efidebug.c 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * UEFI Shell-like command
  4. *
  5. * Copyright (c) 2018 AKASHI Takahiro, Linaro Limited
  6. */
  7. #include <charset.h>
  8. #include <common.h>
  9. #include <command.h>
  10. #include <efi_loader.h>
  11. #include <environment.h>
  12. #include <exports.h>
  13. #include <hexdump.h>
  14. #include <malloc.h>
  15. #include <search.h>
  16. #include <linux/ctype.h>
  17. #define BS systab.boottime
  18. #define RT systab.runtime
  19. /**
  20. * efi_get_device_handle_info() - get information of UEFI device
  21. *
  22. * @handle: Handle of UEFI device
  23. * @dev_path_text: Pointer to text of device path
  24. * Return: 0 on success, -1 on failure
  25. *
  26. * Currently return a formatted text of device path.
  27. */
  28. static int efi_get_device_handle_info(efi_handle_t handle, u16 **dev_path_text)
  29. {
  30. struct efi_device_path *dp;
  31. efi_status_t ret;
  32. ret = EFI_CALL(BS->open_protocol(handle, &efi_guid_device_path,
  33. (void **)&dp, NULL /* FIXME */, NULL,
  34. EFI_OPEN_PROTOCOL_GET_PROTOCOL));
  35. if (ret == EFI_SUCCESS) {
  36. *dev_path_text = efi_dp_str(dp);
  37. return 0;
  38. } else {
  39. return -1;
  40. }
  41. }
  42. #define EFI_HANDLE_WIDTH ((int)sizeof(efi_handle_t) * 2)
  43. static const char spc[] = " ";
  44. static const char sep[] = "================";
  45. /**
  46. * do_efi_show_devices() - show UEFI devices
  47. *
  48. * @cmdtp: Command table
  49. * @flag: Command flag
  50. * @argc: Number of arguments
  51. * @argv: Argument array
  52. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  53. *
  54. * Implement efidebug "devices" sub-command.
  55. * Show all UEFI devices and their information.
  56. */
  57. static int do_efi_show_devices(cmd_tbl_t *cmdtp, int flag,
  58. int argc, char * const argv[])
  59. {
  60. efi_handle_t *handles;
  61. efi_uintn_t num, i;
  62. u16 *dev_path_text;
  63. efi_status_t ret;
  64. ret = EFI_CALL(BS->locate_handle_buffer(ALL_HANDLES, NULL, NULL,
  65. &num, &handles));
  66. if (ret != EFI_SUCCESS)
  67. return CMD_RET_FAILURE;
  68. if (!num)
  69. return CMD_RET_SUCCESS;
  70. printf("Device%.*s Device Path\n", EFI_HANDLE_WIDTH - 6, spc);
  71. printf("%.*s ====================\n", EFI_HANDLE_WIDTH, sep);
  72. for (i = 0; i < num; i++) {
  73. if (!efi_get_device_handle_info(handles[i], &dev_path_text)) {
  74. printf("%p %ls\n", handles[i], dev_path_text);
  75. efi_free_pool(dev_path_text);
  76. }
  77. }
  78. EFI_CALL(BS->free_pool(handles));
  79. return CMD_RET_SUCCESS;
  80. }
  81. /**
  82. * efi_get_driver_handle_info() - get information of UEFI driver
  83. *
  84. * @handle: Handle of UEFI device
  85. * @driver_name: Driver name
  86. * @image_path: Pointer to text of device path
  87. * Return: 0 on success, -1 on failure
  88. *
  89. * Currently return no useful information as all UEFI drivers are
  90. * built-in..
  91. */
  92. static int efi_get_driver_handle_info(efi_handle_t handle, u16 **driver_name,
  93. u16 **image_path)
  94. {
  95. struct efi_handler *handler;
  96. struct efi_loaded_image *image;
  97. efi_status_t ret;
  98. /*
  99. * driver name
  100. * TODO: support EFI_COMPONENT_NAME2_PROTOCOL
  101. */
  102. *driver_name = NULL;
  103. /* image name */
  104. ret = efi_search_protocol(handle, &efi_guid_loaded_image, &handler);
  105. if (ret != EFI_SUCCESS) {
  106. *image_path = NULL;
  107. return 0;
  108. }
  109. image = handler->protocol_interface;
  110. *image_path = efi_dp_str(image->file_path);
  111. return 0;
  112. }
  113. /**
  114. * do_efi_show_drivers() - show UEFI drivers
  115. *
  116. * @cmdtp: Command table
  117. * @flag: Command flag
  118. * @argc: Number of arguments
  119. * @argv: Argument array
  120. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  121. *
  122. * Implement efidebug "drivers" sub-command.
  123. * Show all UEFI drivers and their information.
  124. */
  125. static int do_efi_show_drivers(cmd_tbl_t *cmdtp, int flag,
  126. int argc, char * const argv[])
  127. {
  128. efi_handle_t *handles;
  129. efi_uintn_t num, i;
  130. u16 *driver_name, *image_path_text;
  131. efi_status_t ret;
  132. ret = EFI_CALL(BS->locate_handle_buffer(
  133. BY_PROTOCOL, &efi_guid_driver_binding_protocol,
  134. NULL, &num, &handles));
  135. if (ret != EFI_SUCCESS)
  136. return CMD_RET_FAILURE;
  137. if (!num)
  138. return CMD_RET_SUCCESS;
  139. printf("Driver%.*s Name Image Path\n",
  140. EFI_HANDLE_WIDTH - 6, spc);
  141. printf("%.*s ==================== ====================\n",
  142. EFI_HANDLE_WIDTH, sep);
  143. for (i = 0; i < num; i++) {
  144. if (!efi_get_driver_handle_info(handles[i], &driver_name,
  145. &image_path_text)) {
  146. if (image_path_text)
  147. printf("%p %-20ls %ls\n", handles[i],
  148. driver_name, image_path_text);
  149. else
  150. printf("%p %-20ls <built-in>\n",
  151. handles[i], driver_name);
  152. EFI_CALL(BS->free_pool(driver_name));
  153. EFI_CALL(BS->free_pool(image_path_text));
  154. }
  155. }
  156. EFI_CALL(BS->free_pool(handles));
  157. return CMD_RET_SUCCESS;
  158. }
  159. static const struct {
  160. const char *text;
  161. const efi_guid_t guid;
  162. } guid_list[] = {
  163. {
  164. "Device Path",
  165. EFI_DEVICE_PATH_PROTOCOL_GUID,
  166. },
  167. {
  168. "Device Path To Text",
  169. EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID,
  170. },
  171. {
  172. "Device Path Utilities",
  173. EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID,
  174. },
  175. {
  176. "Unicode Collation 2",
  177. EFI_UNICODE_COLLATION_PROTOCOL2_GUID,
  178. },
  179. {
  180. "Driver Binding",
  181. EFI_DRIVER_BINDING_PROTOCOL_GUID,
  182. },
  183. {
  184. "Simple Text Input",
  185. EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID,
  186. },
  187. {
  188. "Simple Text Input Ex",
  189. EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID,
  190. },
  191. {
  192. "Simple Text Output",
  193. EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID,
  194. },
  195. {
  196. "Block IO",
  197. EFI_BLOCK_IO_PROTOCOL_GUID,
  198. },
  199. {
  200. "Simple File System",
  201. EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID,
  202. },
  203. {
  204. "Loaded Image",
  205. EFI_LOADED_IMAGE_PROTOCOL_GUID,
  206. },
  207. {
  208. "Graphics Output",
  209. EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID,
  210. },
  211. {
  212. "HII String",
  213. EFI_HII_STRING_PROTOCOL_GUID,
  214. },
  215. {
  216. "HII Database",
  217. EFI_HII_DATABASE_PROTOCOL_GUID,
  218. },
  219. {
  220. "HII Config Routing",
  221. EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID,
  222. },
  223. {
  224. "Simple Network",
  225. EFI_SIMPLE_NETWORK_PROTOCOL_GUID,
  226. },
  227. {
  228. "PXE Base Code",
  229. EFI_PXE_BASE_CODE_PROTOCOL_GUID,
  230. },
  231. };
  232. /**
  233. * get_guid_text - get string of protocol guid
  234. * @guid: Protocol guid
  235. * Return: String
  236. *
  237. * Return string for display to represent the protocol.
  238. */
  239. static const char *get_guid_text(const efi_guid_t *guid)
  240. {
  241. int i;
  242. for (i = 0; i < ARRAY_SIZE(guid_list); i++)
  243. if (!guidcmp(&guid_list[i].guid, guid))
  244. break;
  245. if (i != ARRAY_SIZE(guid_list))
  246. return guid_list[i].text;
  247. else
  248. return NULL;
  249. }
  250. /**
  251. * do_efi_show_handles() - show UEFI handles
  252. *
  253. * @cmdtp: Command table
  254. * @flag: Command flag
  255. * @argc: Number of arguments
  256. * @argv: Argument array
  257. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  258. *
  259. * Implement efidebug "dh" sub-command.
  260. * Show all UEFI handles and their information, currently all protocols
  261. * added to handle.
  262. */
  263. static int do_efi_show_handles(cmd_tbl_t *cmdtp, int flag,
  264. int argc, char * const argv[])
  265. {
  266. efi_handle_t *handles;
  267. efi_guid_t **guid;
  268. efi_uintn_t num, count, i, j;
  269. const char *guid_text;
  270. efi_status_t ret;
  271. ret = EFI_CALL(BS->locate_handle_buffer(ALL_HANDLES, NULL, NULL,
  272. &num, &handles));
  273. if (ret != EFI_SUCCESS)
  274. return CMD_RET_FAILURE;
  275. if (!num)
  276. return CMD_RET_SUCCESS;
  277. printf("Handle%.*s Protocols\n", EFI_HANDLE_WIDTH - 6, spc);
  278. printf("%.*s ====================\n", EFI_HANDLE_WIDTH, sep);
  279. for (i = 0; i < num; i++) {
  280. printf("%p", handles[i]);
  281. ret = EFI_CALL(BS->protocols_per_handle(handles[i], &guid,
  282. &count));
  283. if (ret || !count) {
  284. putc('\n');
  285. continue;
  286. }
  287. for (j = 0; j < count; j++) {
  288. if (j)
  289. printf(", ");
  290. else
  291. putc(' ');
  292. guid_text = get_guid_text(guid[j]);
  293. if (guid_text)
  294. puts(guid_text);
  295. else
  296. printf("%pUl", guid[j]);
  297. }
  298. putc('\n');
  299. }
  300. EFI_CALL(BS->free_pool(handles));
  301. return CMD_RET_SUCCESS;
  302. }
  303. /**
  304. * do_efi_show_images() - show UEFI images
  305. *
  306. * @cmdtp: Command table
  307. * @flag: Command flag
  308. * @argc: Number of arguments
  309. * @argv: Argument array
  310. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  311. *
  312. * Implement efidebug "images" sub-command.
  313. * Show all UEFI loaded images and their information.
  314. */
  315. static int do_efi_show_images(cmd_tbl_t *cmdtp, int flag,
  316. int argc, char * const argv[])
  317. {
  318. efi_print_image_infos(NULL);
  319. return CMD_RET_SUCCESS;
  320. }
  321. static const char * const efi_mem_type_string[] = {
  322. [EFI_RESERVED_MEMORY_TYPE] = "RESERVED",
  323. [EFI_LOADER_CODE] = "LOADER CODE",
  324. [EFI_LOADER_DATA] = "LOADER DATA",
  325. [EFI_BOOT_SERVICES_CODE] = "BOOT CODE",
  326. [EFI_BOOT_SERVICES_DATA] = "BOOT DATA",
  327. [EFI_RUNTIME_SERVICES_CODE] = "RUNTIME CODE",
  328. [EFI_RUNTIME_SERVICES_DATA] = "RUNTIME DATA",
  329. [EFI_CONVENTIONAL_MEMORY] = "CONVENTIONAL",
  330. [EFI_UNUSABLE_MEMORY] = "UNUSABLE MEM",
  331. [EFI_ACPI_RECLAIM_MEMORY] = "ACPI RECLAIM MEM",
  332. [EFI_ACPI_MEMORY_NVS] = "ACPI NVS",
  333. [EFI_MMAP_IO] = "IO",
  334. [EFI_MMAP_IO_PORT] = "IO PORT",
  335. [EFI_PAL_CODE] = "PAL",
  336. };
  337. static const struct efi_mem_attrs {
  338. const u64 bit;
  339. const char *text;
  340. } efi_mem_attrs[] = {
  341. {EFI_MEMORY_UC, "UC"},
  342. {EFI_MEMORY_UC, "UC"},
  343. {EFI_MEMORY_WC, "WC"},
  344. {EFI_MEMORY_WT, "WT"},
  345. {EFI_MEMORY_WB, "WB"},
  346. {EFI_MEMORY_UCE, "UCE"},
  347. {EFI_MEMORY_WP, "WP"},
  348. {EFI_MEMORY_RP, "RP"},
  349. {EFI_MEMORY_XP, "WP"},
  350. {EFI_MEMORY_NV, "NV"},
  351. {EFI_MEMORY_MORE_RELIABLE, "REL"},
  352. {EFI_MEMORY_RO, "RO"},
  353. {EFI_MEMORY_RUNTIME, "RT"},
  354. };
  355. /**
  356. * print_memory_attributes() - print memory map attributes
  357. *
  358. * @attributes: Attribute value
  359. *
  360. * Print memory map attributes
  361. */
  362. static void print_memory_attributes(u64 attributes)
  363. {
  364. int sep, i;
  365. for (sep = 0, i = 0; i < ARRAY_SIZE(efi_mem_attrs); i++)
  366. if (attributes & efi_mem_attrs[i].bit) {
  367. if (sep) {
  368. putc('|');
  369. } else {
  370. putc(' ');
  371. sep = 1;
  372. }
  373. puts(efi_mem_attrs[i].text);
  374. }
  375. }
  376. #define EFI_PHYS_ADDR_WIDTH (int)(sizeof(efi_physical_addr_t) * 2)
  377. /**
  378. * do_efi_show_memmap() - show UEFI memory map
  379. *
  380. * @cmdtp: Command table
  381. * @flag: Command flag
  382. * @argc: Number of arguments
  383. * @argv: Argument array
  384. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  385. *
  386. * Implement efidebug "memmap" sub-command.
  387. * Show UEFI memory map.
  388. */
  389. static int do_efi_show_memmap(cmd_tbl_t *cmdtp, int flag,
  390. int argc, char * const argv[])
  391. {
  392. struct efi_mem_desc *memmap = NULL, *map;
  393. efi_uintn_t map_size = 0;
  394. const char *type;
  395. int i;
  396. efi_status_t ret;
  397. ret = EFI_CALL(BS->get_memory_map(&map_size, memmap, NULL, NULL, NULL));
  398. if (ret == EFI_BUFFER_TOO_SMALL) {
  399. map_size += sizeof(struct efi_mem_desc); /* for my own */
  400. ret = EFI_CALL(BS->allocate_pool(EFI_LOADER_DATA,
  401. map_size, (void *)&memmap));
  402. if (ret != EFI_SUCCESS)
  403. return CMD_RET_FAILURE;
  404. ret = EFI_CALL(BS->get_memory_map(&map_size, memmap,
  405. NULL, NULL, NULL));
  406. }
  407. if (ret != EFI_SUCCESS) {
  408. EFI_CALL(BS->free_pool(memmap));
  409. return CMD_RET_FAILURE;
  410. }
  411. printf("Type Start%.*s End%.*s Attributes\n",
  412. EFI_PHYS_ADDR_WIDTH - 5, spc, EFI_PHYS_ADDR_WIDTH - 3, spc);
  413. printf("================ %.*s %.*s ==========\n",
  414. EFI_PHYS_ADDR_WIDTH, sep, EFI_PHYS_ADDR_WIDTH, sep);
  415. for (i = 0, map = memmap; i < map_size / sizeof(*map); map++, i++) {
  416. if (map->type < EFI_MAX_MEMORY_TYPE)
  417. type = efi_mem_type_string[map->type];
  418. else
  419. type = "(unknown)";
  420. printf("%-16s %.*llx-%.*llx", type,
  421. EFI_PHYS_ADDR_WIDTH,
  422. map->physical_start,
  423. EFI_PHYS_ADDR_WIDTH,
  424. map->physical_start + map->num_pages * EFI_PAGE_SIZE);
  425. print_memory_attributes(map->attribute);
  426. putc('\n');
  427. }
  428. EFI_CALL(BS->free_pool(memmap));
  429. return CMD_RET_SUCCESS;
  430. }
  431. /**
  432. * do_efi_boot_add() - set UEFI load option
  433. *
  434. * @cmdtp: Command table
  435. * @flag: Command flag
  436. * @argc: Number of arguments
  437. * @argv: Argument array
  438. * Return: CMD_RET_SUCCESS on success,
  439. * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
  440. *
  441. * Implement efidebug "boot add" sub-command. Create or change UEFI load option.
  442. *
  443. * efidebug boot add <id> <label> <interface> <devnum>[:<part>] <file> <options>
  444. */
  445. static int do_efi_boot_add(cmd_tbl_t *cmdtp, int flag,
  446. int argc, char * const argv[])
  447. {
  448. int id;
  449. char *endp;
  450. char var_name[9];
  451. u16 var_name16[9], *p;
  452. efi_guid_t guid;
  453. size_t label_len, label_len16;
  454. u16 *label;
  455. struct efi_device_path *device_path = NULL, *file_path = NULL;
  456. struct efi_load_option lo;
  457. void *data = NULL;
  458. efi_uintn_t size;
  459. efi_status_t ret;
  460. int r = CMD_RET_SUCCESS;
  461. if (argc < 6 || argc > 7)
  462. return CMD_RET_USAGE;
  463. id = (int)simple_strtoul(argv[1], &endp, 16);
  464. if (*endp != '\0' || id > 0xffff)
  465. return CMD_RET_USAGE;
  466. sprintf(var_name, "Boot%04X", id);
  467. p = var_name16;
  468. utf8_utf16_strncpy(&p, var_name, 9);
  469. guid = efi_global_variable_guid;
  470. /* attributes */
  471. lo.attributes = LOAD_OPTION_ACTIVE; /* always ACTIVE */
  472. /* label */
  473. label_len = strlen(argv[2]);
  474. label_len16 = utf8_utf16_strnlen(argv[2], label_len);
  475. label = malloc((label_len16 + 1) * sizeof(u16));
  476. if (!label)
  477. return CMD_RET_FAILURE;
  478. lo.label = label; /* label will be changed below */
  479. utf8_utf16_strncpy(&label, argv[2], label_len);
  480. /* file path */
  481. ret = efi_dp_from_name(argv[3], argv[4], argv[5], &device_path,
  482. &file_path);
  483. if (ret != EFI_SUCCESS) {
  484. printf("Cannot create device path for \"%s %s\"\n",
  485. argv[3], argv[4]);
  486. r = CMD_RET_FAILURE;
  487. goto out;
  488. }
  489. lo.file_path = file_path;
  490. lo.file_path_length = efi_dp_size(file_path)
  491. + sizeof(struct efi_device_path); /* for END */
  492. /* optional data */
  493. if (argc < 6)
  494. lo.optional_data = NULL;
  495. else
  496. lo.optional_data = (const u8 *)argv[6];
  497. size = efi_serialize_load_option(&lo, (u8 **)&data);
  498. if (!size) {
  499. r = CMD_RET_FAILURE;
  500. goto out;
  501. }
  502. ret = EFI_CALL(RT->set_variable(var_name16, &guid,
  503. EFI_VARIABLE_NON_VOLATILE |
  504. EFI_VARIABLE_BOOTSERVICE_ACCESS |
  505. EFI_VARIABLE_RUNTIME_ACCESS,
  506. size, data));
  507. if (ret != EFI_SUCCESS) {
  508. printf("Cannot set %ls\n", var_name16);
  509. r = CMD_RET_FAILURE;
  510. }
  511. out:
  512. free(data);
  513. efi_free_pool(device_path);
  514. efi_free_pool(file_path);
  515. free(lo.label);
  516. return r;
  517. }
  518. /**
  519. * do_efi_boot_rm() - delete UEFI load options
  520. *
  521. * @cmdtp: Command table
  522. * @flag: Command flag
  523. * @argc: Number of arguments
  524. * @argv: Argument array
  525. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  526. *
  527. * Implement efidebug "boot rm" sub-command.
  528. * Delete UEFI load options.
  529. *
  530. * efidebug boot rm <id> ...
  531. */
  532. static int do_efi_boot_rm(cmd_tbl_t *cmdtp, int flag,
  533. int argc, char * const argv[])
  534. {
  535. efi_guid_t guid;
  536. int id, i;
  537. char *endp;
  538. char var_name[9];
  539. u16 var_name16[9];
  540. efi_status_t ret;
  541. if (argc == 1)
  542. return CMD_RET_USAGE;
  543. guid = efi_global_variable_guid;
  544. for (i = 1; i < argc; i++, argv++) {
  545. id = (int)simple_strtoul(argv[1], &endp, 16);
  546. if (*endp != '\0' || id > 0xffff)
  547. return CMD_RET_FAILURE;
  548. sprintf(var_name, "Boot%04X", id);
  549. utf8_utf16_strncpy((u16 **)&var_name16, var_name, 9);
  550. ret = EFI_CALL(RT->set_variable(var_name16, &guid, 0, 0, NULL));
  551. if (ret) {
  552. printf("Cannot remove Boot%04X", id);
  553. return CMD_RET_FAILURE;
  554. }
  555. }
  556. return CMD_RET_SUCCESS;
  557. }
  558. /**
  559. * show_efi_boot_opt_data() - dump UEFI load option
  560. *
  561. * @id: load option number
  562. * @data: value of UEFI load option variable
  563. * @size: size of the boot option
  564. *
  565. * Decode the value of UEFI load option variable and print information.
  566. */
  567. static void show_efi_boot_opt_data(int id, void *data, size_t size)
  568. {
  569. struct efi_load_option lo;
  570. char *label, *p;
  571. size_t label_len16, label_len;
  572. u16 *dp_str;
  573. efi_deserialize_load_option(&lo, data);
  574. label_len16 = u16_strlen(lo.label);
  575. label_len = utf16_utf8_strnlen(lo.label, label_len16);
  576. label = malloc(label_len + 1);
  577. if (!label)
  578. return;
  579. p = label;
  580. utf16_utf8_strncpy(&p, lo.label, label_len16);
  581. printf("Boot%04X:\n", id);
  582. printf(" attributes: %c%c%c (0x%08x)\n",
  583. /* ACTIVE */
  584. lo.attributes & LOAD_OPTION_ACTIVE ? 'A' : '-',
  585. /* FORCE RECONNECT */
  586. lo.attributes & LOAD_OPTION_FORCE_RECONNECT ? 'R' : '-',
  587. /* HIDDEN */
  588. lo.attributes & LOAD_OPTION_HIDDEN ? 'H' : '-',
  589. lo.attributes);
  590. printf(" label: %s\n", label);
  591. dp_str = efi_dp_str(lo.file_path);
  592. printf(" file_path: %ls\n", dp_str);
  593. efi_free_pool(dp_str);
  594. printf(" data:\n");
  595. print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1,
  596. lo.optional_data, size + (u8 *)data -
  597. (u8 *)lo.optional_data, true);
  598. free(label);
  599. }
  600. /**
  601. * show_efi_boot_opt() - dump UEFI load option
  602. *
  603. * @id: Load option number
  604. *
  605. * Dump information defined by UEFI load option.
  606. */
  607. static void show_efi_boot_opt(int id)
  608. {
  609. char var_name[9];
  610. u16 var_name16[9], *p;
  611. efi_guid_t guid;
  612. void *data = NULL;
  613. efi_uintn_t size;
  614. int ret;
  615. sprintf(var_name, "Boot%04X", id);
  616. p = var_name16;
  617. utf8_utf16_strncpy(&p, var_name, 9);
  618. guid = efi_global_variable_guid;
  619. size = 0;
  620. ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size, NULL));
  621. if (ret == (int)EFI_BUFFER_TOO_SMALL) {
  622. data = malloc(size);
  623. ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size,
  624. data));
  625. }
  626. if (ret == EFI_SUCCESS)
  627. show_efi_boot_opt_data(id, data, size);
  628. else if (ret == EFI_NOT_FOUND)
  629. printf("Boot%04X: not found\n", id);
  630. free(data);
  631. }
  632. static int u16_tohex(u16 c)
  633. {
  634. if (c >= '0' && c <= '9')
  635. return c - '0';
  636. if (c >= 'A' && c <= 'F')
  637. return c - 'A' + 10;
  638. /* not hexadecimal */
  639. return -1;
  640. }
  641. /**
  642. * show_efi_boot_dump() - dump all UEFI load options
  643. *
  644. * @cmdtp: Command table
  645. * @flag: Command flag
  646. * @argc: Number of arguments
  647. * @argv: Argument array
  648. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  649. *
  650. * Implement efidebug "boot dump" sub-command.
  651. * Dump information of all UEFI load options defined.
  652. * - boot dump
  653. */
  654. static int do_efi_boot_dump(cmd_tbl_t *cmdtp, int flag,
  655. int argc, char * const argv[])
  656. {
  657. u16 *var_name16, *p;
  658. efi_uintn_t buf_size, size;
  659. efi_guid_t guid;
  660. int id, i, digit;
  661. efi_status_t ret;
  662. if (argc > 1)
  663. return CMD_RET_USAGE;
  664. buf_size = 128;
  665. var_name16 = malloc(buf_size);
  666. if (!var_name16)
  667. return CMD_RET_FAILURE;
  668. var_name16[0] = 0;
  669. for (;;) {
  670. size = buf_size;
  671. ret = EFI_CALL(efi_get_next_variable_name(&size, var_name16,
  672. &guid));
  673. if (ret == EFI_NOT_FOUND)
  674. break;
  675. if (ret == EFI_BUFFER_TOO_SMALL) {
  676. buf_size = size;
  677. p = realloc(var_name16, buf_size);
  678. if (!p) {
  679. free(var_name16);
  680. return CMD_RET_FAILURE;
  681. }
  682. var_name16 = p;
  683. ret = EFI_CALL(efi_get_next_variable_name(&size,
  684. var_name16,
  685. &guid));
  686. }
  687. if (ret != EFI_SUCCESS) {
  688. free(var_name16);
  689. return CMD_RET_FAILURE;
  690. }
  691. if (memcmp(var_name16, L"Boot", 8))
  692. continue;
  693. for (id = 0, i = 0; i < 4; i++) {
  694. digit = u16_tohex(var_name16[4 + i]);
  695. if (digit < 0)
  696. break;
  697. id = (id << 4) + digit;
  698. }
  699. if (i == 4 && !var_name16[8])
  700. show_efi_boot_opt(id);
  701. }
  702. free(var_name16);
  703. return CMD_RET_SUCCESS;
  704. }
  705. /**
  706. * show_efi_boot_order() - show order of UEFI load options
  707. *
  708. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  709. *
  710. * Show order of UEFI load options defined by BootOrder variable.
  711. */
  712. static int show_efi_boot_order(void)
  713. {
  714. efi_guid_t guid;
  715. u16 *bootorder = NULL;
  716. efi_uintn_t size;
  717. int num, i;
  718. char var_name[9];
  719. u16 var_name16[9], *p16;
  720. void *data;
  721. struct efi_load_option lo;
  722. char *label, *p;
  723. size_t label_len16, label_len;
  724. efi_status_t ret;
  725. guid = efi_global_variable_guid;
  726. size = 0;
  727. ret = EFI_CALL(RT->get_variable(L"BootOrder", &guid, NULL, &size,
  728. NULL));
  729. if (ret == EFI_BUFFER_TOO_SMALL) {
  730. bootorder = malloc(size);
  731. ret = EFI_CALL(RT->get_variable(L"BootOrder", &guid, NULL,
  732. &size, bootorder));
  733. }
  734. if (ret == EFI_NOT_FOUND) {
  735. printf("BootOrder not defined\n");
  736. ret = CMD_RET_SUCCESS;
  737. goto out;
  738. } else if (ret != EFI_SUCCESS) {
  739. ret = CMD_RET_FAILURE;
  740. goto out;
  741. }
  742. num = size / sizeof(u16);
  743. for (i = 0; i < num; i++) {
  744. sprintf(var_name, "Boot%04X", bootorder[i]);
  745. p16 = var_name16;
  746. utf8_utf16_strncpy(&p16, var_name, 9);
  747. size = 0;
  748. ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size,
  749. NULL));
  750. if (ret != EFI_BUFFER_TOO_SMALL) {
  751. printf("%2d: Boot%04X: (not defined)\n",
  752. i + 1, bootorder[i]);
  753. continue;
  754. }
  755. data = malloc(size);
  756. if (!data) {
  757. ret = CMD_RET_FAILURE;
  758. goto out;
  759. }
  760. ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size,
  761. data));
  762. if (ret != EFI_SUCCESS) {
  763. free(data);
  764. ret = CMD_RET_FAILURE;
  765. goto out;
  766. }
  767. efi_deserialize_load_option(&lo, data);
  768. label_len16 = u16_strlen(lo.label);
  769. label_len = utf16_utf8_strnlen(lo.label, label_len16);
  770. label = malloc(label_len + 1);
  771. if (!label) {
  772. free(data);
  773. ret = CMD_RET_FAILURE;
  774. goto out;
  775. }
  776. p = label;
  777. utf16_utf8_strncpy(&p, lo.label, label_len16);
  778. printf("%2d: Boot%04X: %s\n", i + 1, bootorder[i], label);
  779. free(label);
  780. free(data);
  781. }
  782. out:
  783. free(bootorder);
  784. return ret;
  785. }
  786. /**
  787. * do_efi_boot_next() - manage UEFI BootNext variable
  788. *
  789. * @cmdtp: Command table
  790. * @flag: Command flag
  791. * @argc: Number of arguments
  792. * @argv: Argument array
  793. * Return: CMD_RET_SUCCESS on success,
  794. * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
  795. *
  796. * Implement efidebug "boot next" sub-command.
  797. * Set BootNext variable.
  798. *
  799. * efidebug boot next <id>
  800. */
  801. static int do_efi_boot_next(cmd_tbl_t *cmdtp, int flag,
  802. int argc, char * const argv[])
  803. {
  804. u16 bootnext;
  805. efi_uintn_t size;
  806. char *endp;
  807. efi_guid_t guid;
  808. efi_status_t ret;
  809. int r = CMD_RET_SUCCESS;
  810. if (argc != 2)
  811. return CMD_RET_USAGE;
  812. bootnext = (u16)simple_strtoul(argv[1], &endp, 16);
  813. if (*endp != '\0' || bootnext > 0xffff) {
  814. printf("invalid value: %s\n", argv[1]);
  815. r = CMD_RET_FAILURE;
  816. goto out;
  817. }
  818. guid = efi_global_variable_guid;
  819. size = sizeof(u16);
  820. ret = EFI_CALL(RT->set_variable(L"BootNext", &guid,
  821. EFI_VARIABLE_NON_VOLATILE |
  822. EFI_VARIABLE_BOOTSERVICE_ACCESS |
  823. EFI_VARIABLE_RUNTIME_ACCESS,
  824. size, &bootnext));
  825. if (ret != EFI_SUCCESS) {
  826. printf("Cannot set BootNext\n");
  827. r = CMD_RET_FAILURE;
  828. }
  829. out:
  830. return r;
  831. }
  832. /**
  833. * do_efi_boot_order() - manage UEFI BootOrder variable
  834. *
  835. * @cmdtp: Command table
  836. * @flag: Command flag
  837. * @argc: Number of arguments
  838. * @argv: Argument array
  839. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  840. *
  841. * Implement efidebug "boot order" sub-command.
  842. * Show order of UEFI load options, or change it in BootOrder variable.
  843. *
  844. * efidebug boot order [<id> ...]
  845. */
  846. static int do_efi_boot_order(cmd_tbl_t *cmdtp, int flag,
  847. int argc, char * const argv[])
  848. {
  849. u16 *bootorder = NULL;
  850. efi_uintn_t size;
  851. int id, i;
  852. char *endp;
  853. efi_guid_t guid;
  854. efi_status_t ret;
  855. int r = CMD_RET_SUCCESS;
  856. if (argc == 1)
  857. return show_efi_boot_order();
  858. argc--;
  859. argv++;
  860. size = argc * sizeof(u16);
  861. bootorder = malloc(size);
  862. if (!bootorder)
  863. return CMD_RET_FAILURE;
  864. for (i = 0; i < argc; i++) {
  865. id = (int)simple_strtoul(argv[i], &endp, 16);
  866. if (*endp != '\0' || id > 0xffff) {
  867. printf("invalid value: %s\n", argv[i]);
  868. r = CMD_RET_FAILURE;
  869. goto out;
  870. }
  871. bootorder[i] = (u16)id;
  872. }
  873. guid = efi_global_variable_guid;
  874. ret = EFI_CALL(RT->set_variable(L"BootOrder", &guid,
  875. EFI_VARIABLE_NON_VOLATILE |
  876. EFI_VARIABLE_BOOTSERVICE_ACCESS |
  877. EFI_VARIABLE_RUNTIME_ACCESS,
  878. size, bootorder));
  879. if (ret != EFI_SUCCESS) {
  880. printf("Cannot set BootOrder\n");
  881. r = CMD_RET_FAILURE;
  882. }
  883. out:
  884. free(bootorder);
  885. return r;
  886. }
  887. static cmd_tbl_t cmd_efidebug_boot_sub[] = {
  888. U_BOOT_CMD_MKENT(add, CONFIG_SYS_MAXARGS, 1, do_efi_boot_add, "", ""),
  889. U_BOOT_CMD_MKENT(rm, CONFIG_SYS_MAXARGS, 1, do_efi_boot_rm, "", ""),
  890. U_BOOT_CMD_MKENT(dump, CONFIG_SYS_MAXARGS, 1, do_efi_boot_dump, "", ""),
  891. U_BOOT_CMD_MKENT(next, CONFIG_SYS_MAXARGS, 1, do_efi_boot_next, "", ""),
  892. U_BOOT_CMD_MKENT(order, CONFIG_SYS_MAXARGS, 1, do_efi_boot_order,
  893. "", ""),
  894. };
  895. /**
  896. * do_efi_boot_opt() - manage UEFI load options
  897. *
  898. * @cmdtp: Command table
  899. * @flag: Command flag
  900. * @argc: Number of arguments
  901. * @argv: Argument array
  902. * Return: CMD_RET_SUCCESS on success,
  903. * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
  904. *
  905. * Implement efidebug "boot" sub-command.
  906. * See above for details of sub-commands.
  907. */
  908. static int do_efi_boot_opt(cmd_tbl_t *cmdtp, int flag,
  909. int argc, char * const argv[])
  910. {
  911. cmd_tbl_t *cp;
  912. if (argc < 2)
  913. return CMD_RET_USAGE;
  914. argc--; argv++;
  915. cp = find_cmd_tbl(argv[0], cmd_efidebug_boot_sub,
  916. ARRAY_SIZE(cmd_efidebug_boot_sub));
  917. if (!cp)
  918. return CMD_RET_USAGE;
  919. return cp->cmd(cmdtp, flag, argc, argv);
  920. }
  921. static cmd_tbl_t cmd_efidebug_sub[] = {
  922. U_BOOT_CMD_MKENT(boot, CONFIG_SYS_MAXARGS, 1, do_efi_boot_opt, "", ""),
  923. U_BOOT_CMD_MKENT(devices, CONFIG_SYS_MAXARGS, 1, do_efi_show_devices,
  924. "", ""),
  925. U_BOOT_CMD_MKENT(drivers, CONFIG_SYS_MAXARGS, 1, do_efi_show_drivers,
  926. "", ""),
  927. U_BOOT_CMD_MKENT(dh, CONFIG_SYS_MAXARGS, 1, do_efi_show_handles,
  928. "", ""),
  929. U_BOOT_CMD_MKENT(images, CONFIG_SYS_MAXARGS, 1, do_efi_show_images,
  930. "", ""),
  931. U_BOOT_CMD_MKENT(memmap, CONFIG_SYS_MAXARGS, 1, do_efi_show_memmap,
  932. "", ""),
  933. };
  934. /**
  935. * do_efidebug() - display and configure UEFI environment
  936. *
  937. * @cmdtp: Command table
  938. * @flag: Command flag
  939. * @argc: Number of arguments
  940. * @argv: Argument array
  941. * Return: CMD_RET_SUCCESS on success,
  942. * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
  943. *
  944. * Implement efidebug command which allows us to display and
  945. * configure UEFI environment.
  946. * See above for details of sub-commands.
  947. */
  948. static int do_efidebug(cmd_tbl_t *cmdtp, int flag,
  949. int argc, char * const argv[])
  950. {
  951. cmd_tbl_t *cp;
  952. efi_status_t r;
  953. if (argc < 2)
  954. return CMD_RET_USAGE;
  955. argc--; argv++;
  956. /* Initialize UEFI drivers */
  957. r = efi_init_obj_list();
  958. if (r != EFI_SUCCESS) {
  959. printf("Error: Cannot initialize UEFI sub-system, r = %lu\n",
  960. r & ~EFI_ERROR_MASK);
  961. return CMD_RET_FAILURE;
  962. }
  963. cp = find_cmd_tbl(argv[0], cmd_efidebug_sub,
  964. ARRAY_SIZE(cmd_efidebug_sub));
  965. if (!cp)
  966. return CMD_RET_USAGE;
  967. return cp->cmd(cmdtp, flag, argc, argv);
  968. }
  969. #ifdef CONFIG_SYS_LONGHELP
  970. static char efidebug_help_text[] =
  971. " - UEFI Shell-like interface to configure UEFI environment\n"
  972. "\n"
  973. "efidebug boot add <bootid> <label> <interface> <devnum>[:<part>] <file path> [<load options>]\n"
  974. " - set UEFI BootXXXX variable\n"
  975. " <load options> will be passed to UEFI application\n"
  976. "efidebug boot rm <bootid#1> [<bootid#2> [<bootid#3> [...]]]\n"
  977. " - delete UEFI BootXXXX variables\n"
  978. "efidebug boot dump\n"
  979. " - dump all UEFI BootXXXX variables\n"
  980. "efidebug boot next <bootid>\n"
  981. " - set UEFI BootNext variable\n"
  982. "efidebug boot order [<bootid#1> [<bootid#2> [<bootid#3> [...]]]]\n"
  983. " - set/show UEFI boot order\n"
  984. "\n"
  985. "efidebug devices\n"
  986. " - show uefi devices\n"
  987. "efidebug drivers\n"
  988. " - show uefi drivers\n"
  989. "efidebug dh\n"
  990. " - show uefi handles\n"
  991. "efidebug images\n"
  992. " - show loaded images\n"
  993. "efidebug memmap\n"
  994. " - show uefi memory map\n";
  995. #endif
  996. U_BOOT_CMD(
  997. efidebug, 10, 0, do_efidebug,
  998. "Configure UEFI environment",
  999. efidebug_help_text
  1000. );