1 // SPDX-License-Identifier: GPL-2.0
3 * Platform Firmware Runtime Update tool to do Management
4 * Mode code injection/driver update and telemetry retrieval.
6 * This tool uses the interfaces provided by pfr_update and
7 * pfr_telemetry drivers. These interfaces are exposed via
8 * /dev/pfr_update and /dev/pfr_telemetry. Write operation
9 * on the /dev/pfr_update is to load the EFI capsule into
10 * kernel space. Mmap/read operations on /dev/pfr_telemetry
11 * could be used to read the telemetry data to user space.
17 #include <sys/types.h>
22 #include <sys/ioctl.h>
24 #include <uuid/uuid.h>
28 int action, query_cap, log_type, log_level, log_read, log_getinfo,
30 int set_log_level, set_log_type,
31 set_revid, set_log_revid;
39 #define LOG_EXEC_IDX 0
40 #define LOG_HISTORY_IDX 1
44 static int valid_log_level(int level)
46 return level == LOG_ERR || level == LOG_WARN ||
47 level == LOG_INFO || level == LOG_VERB;
50 static int valid_log_type(int type)
52 return type == LOG_EXEC_IDX || type == LOG_HISTORY_IDX;
55 static inline int valid_log_revid(int id)
57 return id == REVID_1 || id == REVID_2;
60 static void help(void)
63 "usage: %s [OPTIONS]\n"
68 " -u, --update [stage and activate]\n"
70 " -d, --revid update\n"
73 " -T, --type(0:execution, 1:history)\n"
74 " -L, --level(0, 1, 2, 4)\n"
80 char *option_string = "l:sauqd:GT:L:RD:h";
81 static struct option long_options[] = {
82 {"load", required_argument, 0, 'l'},
83 {"stage", no_argument, 0, 's'},
84 {"activate", no_argument, 0, 'a'},
85 {"update", no_argument, 0, 'u'},
86 {"query", no_argument, 0, 'q'},
87 {"getloginfo", no_argument, 0, 'G'},
88 {"type", required_argument, 0, 'T'},
89 {"level", required_argument, 0, 'L'},
90 {"read", no_argument, 0, 'R'},
91 {"setrev", required_argument, 0, 'd'},
92 {"setrevlog", required_argument, 0, 'D'},
93 {"help", no_argument, 0, 'h'},
97 static void parse_options(int argc, char **argv)
100 char *pathname, *endptr;
103 pathname = strdup(argv[0]);
104 progname = basename(pathname);
106 while ((opt = getopt_long_only(argc, argv, option_string,
107 long_options, &option_index)) != -1) {
110 capsule_name = optarg;
128 log_type = strtol(optarg, &endptr, 0);
129 if (*endptr || (log_type != 0 && log_type != 1)) {
130 printf("Number expected: type(0:execution, 1:history) - Quit.\n");
137 log_level = strtol(optarg, &endptr, 0);
139 (log_level != 0 && log_level != 1 &&
140 log_level != 2 && log_level != 4)) {
141 printf("Number expected: level(0, 1, 2, 4) - Quit.\n");
151 revid = atoi(optarg);
155 log_revid = atoi(optarg);
167 void print_cap(struct pfru_update_cap_info *cap)
173 perror("Can not allocate uuid buffer\n");
177 uuid_unparse(cap->code_type, uuid);
178 printf("code injection image type:%s\n", uuid);
179 printf("fw_version:%d\n", cap->fw_version);
180 printf("code_rt_version:%d\n", cap->code_rt_version);
182 uuid_unparse(cap->drv_type, uuid);
183 printf("driver update image type:%s\n", uuid);
184 printf("drv_rt_version:%d\n", cap->drv_rt_version);
185 printf("drv_svn:%d\n", cap->drv_svn);
187 uuid_unparse(cap->platform_id, uuid);
188 printf("platform id:%s\n", uuid);
189 uuid_unparse(cap->oem_id, uuid);
190 printf("oem id:%s\n", uuid);
191 printf("oem information length:%d\n", cap->oem_info_len);
196 int main(int argc, char *argv[])
198 int fd_update, fd_update_log, fd_capsule;
199 struct pfrt_log_data_info data_info;
200 struct pfrt_log_info info;
201 struct pfru_update_cap_info cap;
202 void *addr_map_capsule;
208 printf("Please run the tool as root - Exiting.\n");
212 parse_options(argc, argv);
214 fd_update = open("/dev/acpi_pfr_update0", O_RDWR);
216 printf("PFRU device not supported - Quit...\n");
220 fd_update_log = open("/dev/acpi_pfr_telemetry0", O_RDWR);
221 if (fd_update_log < 0) {
222 printf("PFRT device not supported - Quit...\n");
227 ret = ioctl(fd_update, PFRU_IOC_QUERY_CAP, &cap);
229 perror("Query Update Capability info failed.");
234 close(fd_update_log);
240 ret = ioctl(fd_update_log, PFRT_LOG_IOC_GET_DATA_INFO, &data_info);
242 perror("Get telemetry data info failed.");
244 close(fd_update_log);
249 ret = ioctl(fd_update_log, PFRT_LOG_IOC_GET_INFO, &info);
251 perror("Get telemetry info failed.");
253 close(fd_update_log);
258 printf("log_level:%d\n", info.log_level);
259 printf("log_type:%d\n", info.log_type);
260 printf("log_revid:%d\n", info.log_revid);
261 printf("max_data_size:%d\n", data_info.max_data_size);
262 printf("chunk1_size:%d\n", data_info.chunk1_size);
263 printf("chunk2_size:%d\n", data_info.chunk2_size);
264 printf("rollover_cnt:%d\n", data_info.rollover_cnt);
265 printf("reset_cnt:%d\n", data_info.reset_cnt);
275 if (!valid_log_level(log_level)) {
276 printf("Invalid log level %d\n",
279 info.log_level = log_level;
284 if (!valid_log_type(log_type)) {
285 printf("Invalid log type %d\n",
288 info.log_type = log_type;
293 if (!valid_log_revid(log_revid)) {
294 printf("Invalid log revid %d, unchanged.\n",
297 info.log_revid = log_revid;
301 ret = ioctl(fd_update_log, PFRT_LOG_IOC_SET_INFO, &info);
303 perror("Log information set failed.(log_level, log_type, log_revid)");
305 close(fd_update_log);
311 ret = ioctl(fd_update, PFRU_IOC_SET_REV, &revid);
313 perror("pfru update revid set failed");
315 close(fd_update_log);
320 printf("pfru update revid set to %d\n", revid);
324 fd_capsule = open(capsule_name, O_RDONLY);
325 if (fd_capsule < 0) {
326 perror("Can not open capsule file...");
328 close(fd_update_log);
333 if (fstat(fd_capsule, &st) < 0) {
334 perror("Can not fstat capsule file...");
337 close(fd_update_log);
342 addr_map_capsule = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED,
344 if (addr_map_capsule == MAP_FAILED) {
345 perror("Failed to mmap capsule file.");
348 close(fd_update_log);
353 ret = write(fd_update, (char *)addr_map_capsule, st.st_size);
354 printf("Load %d bytes of capsule file into the system\n",
358 perror("Failed to load capsule file");
361 close(fd_update_log);
366 munmap(addr_map_capsule, st.st_size);
368 printf("Load done.\n");
373 ret = ioctl(fd_update, PFRU_IOC_STAGE, NULL);
374 } else if (action == 2) {
375 ret = ioctl(fd_update, PFRU_IOC_ACTIVATE, NULL);
376 } else if (action == 3) {
377 ret = ioctl(fd_update, PFRU_IOC_STAGE_ACTIVATE, NULL);
380 close(fd_update_log);
384 printf("Update finished, return %d\n", ret);
393 ret = ioctl(fd_update_log, PFRT_LOG_IOC_GET_DATA_INFO, &data_info);
395 perror("Get telemetry data info failed.");
396 close(fd_update_log);
401 max_data_sz = data_info.max_data_size;
403 printf("No telemetry data available.\n");
404 close(fd_update_log);
409 log_buf = malloc(max_data_sz + 1);
411 perror("log_buf allocate failed.");
412 close(fd_update_log);
417 p_mmap = mmap(NULL, max_data_sz, PROT_READ, MAP_SHARED, fd_update_log, 0);
418 if (p_mmap == MAP_FAILED) {
419 perror("mmap error.");
420 close(fd_update_log);
425 memcpy(log_buf, p_mmap, max_data_sz);
426 log_buf[max_data_sz] = '\0';
427 printf("%s\n", log_buf);
430 munmap(p_mmap, max_data_sz);
433 close(fd_update_log);