efidebug.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182
  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 <exports.h>
  12. #include <hexdump.h>
  13. #include <malloc.h>
  14. #include <mapmem.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. "Load File2",
  225. EFI_LOAD_FILE2_PROTOCOL_GUID,
  226. },
  227. {
  228. "Simple Network",
  229. EFI_SIMPLE_NETWORK_PROTOCOL_GUID,
  230. },
  231. {
  232. "PXE Base Code",
  233. EFI_PXE_BASE_CODE_PROTOCOL_GUID,
  234. },
  235. /* Configuration table GUIDs */
  236. {
  237. "ACPI table",
  238. EFI_ACPI_TABLE_GUID,
  239. },
  240. {
  241. "device tree",
  242. EFI_FDT_GUID,
  243. },
  244. {
  245. "SMBIOS table",
  246. SMBIOS_TABLE_GUID,
  247. },
  248. {
  249. "Runtime properties",
  250. EFI_RT_PROPERTIES_TABLE_GUID,
  251. },
  252. };
  253. /**
  254. * get_guid_text - get string of GUID
  255. *
  256. * Return description of GUID.
  257. *
  258. * @guid: GUID
  259. * Return: description of GUID or NULL
  260. */
  261. static const char *get_guid_text(const void *guid)
  262. {
  263. int i;
  264. for (i = 0; i < ARRAY_SIZE(guid_list); i++) {
  265. /*
  266. * As guidcmp uses memcmp() we can safely accept unaligned
  267. * GUIDs.
  268. */
  269. if (!guidcmp(&guid_list[i].guid, guid))
  270. return guid_list[i].text;
  271. }
  272. return NULL;
  273. }
  274. /**
  275. * do_efi_show_handles() - show UEFI handles
  276. *
  277. * @cmdtp: Command table
  278. * @flag: Command flag
  279. * @argc: Number of arguments
  280. * @argv: Argument array
  281. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  282. *
  283. * Implement efidebug "dh" sub-command.
  284. * Show all UEFI handles and their information, currently all protocols
  285. * added to handle.
  286. */
  287. static int do_efi_show_handles(cmd_tbl_t *cmdtp, int flag,
  288. int argc, char * const argv[])
  289. {
  290. efi_handle_t *handles;
  291. efi_guid_t **guid;
  292. efi_uintn_t num, count, i, j;
  293. const char *guid_text;
  294. efi_status_t ret;
  295. ret = EFI_CALL(BS->locate_handle_buffer(ALL_HANDLES, NULL, NULL,
  296. &num, &handles));
  297. if (ret != EFI_SUCCESS)
  298. return CMD_RET_FAILURE;
  299. if (!num)
  300. return CMD_RET_SUCCESS;
  301. printf("Handle%.*s Protocols\n", EFI_HANDLE_WIDTH - 6, spc);
  302. printf("%.*s ====================\n", EFI_HANDLE_WIDTH, sep);
  303. for (i = 0; i < num; i++) {
  304. printf("%p", handles[i]);
  305. ret = EFI_CALL(BS->protocols_per_handle(handles[i], &guid,
  306. &count));
  307. if (ret || !count) {
  308. putc('\n');
  309. continue;
  310. }
  311. for (j = 0; j < count; j++) {
  312. if (j)
  313. printf(", ");
  314. else
  315. putc(' ');
  316. guid_text = get_guid_text(guid[j]);
  317. if (guid_text)
  318. puts(guid_text);
  319. else
  320. printf("%pUl", guid[j]);
  321. }
  322. putc('\n');
  323. }
  324. EFI_CALL(BS->free_pool(handles));
  325. return CMD_RET_SUCCESS;
  326. }
  327. /**
  328. * do_efi_show_images() - show UEFI images
  329. *
  330. * @cmdtp: Command table
  331. * @flag: Command flag
  332. * @argc: Number of arguments
  333. * @argv: Argument array
  334. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  335. *
  336. * Implement efidebug "images" sub-command.
  337. * Show all UEFI loaded images and their information.
  338. */
  339. static int do_efi_show_images(cmd_tbl_t *cmdtp, int flag,
  340. int argc, char * const argv[])
  341. {
  342. efi_print_image_infos(NULL);
  343. return CMD_RET_SUCCESS;
  344. }
  345. static const char * const efi_mem_type_string[] = {
  346. [EFI_RESERVED_MEMORY_TYPE] = "RESERVED",
  347. [EFI_LOADER_CODE] = "LOADER CODE",
  348. [EFI_LOADER_DATA] = "LOADER DATA",
  349. [EFI_BOOT_SERVICES_CODE] = "BOOT CODE",
  350. [EFI_BOOT_SERVICES_DATA] = "BOOT DATA",
  351. [EFI_RUNTIME_SERVICES_CODE] = "RUNTIME CODE",
  352. [EFI_RUNTIME_SERVICES_DATA] = "RUNTIME DATA",
  353. [EFI_CONVENTIONAL_MEMORY] = "CONVENTIONAL",
  354. [EFI_UNUSABLE_MEMORY] = "UNUSABLE MEM",
  355. [EFI_ACPI_RECLAIM_MEMORY] = "ACPI RECLAIM MEM",
  356. [EFI_ACPI_MEMORY_NVS] = "ACPI NVS",
  357. [EFI_MMAP_IO] = "IO",
  358. [EFI_MMAP_IO_PORT] = "IO PORT",
  359. [EFI_PAL_CODE] = "PAL",
  360. };
  361. static const struct efi_mem_attrs {
  362. const u64 bit;
  363. const char *text;
  364. } efi_mem_attrs[] = {
  365. {EFI_MEMORY_UC, "UC"},
  366. {EFI_MEMORY_UC, "UC"},
  367. {EFI_MEMORY_WC, "WC"},
  368. {EFI_MEMORY_WT, "WT"},
  369. {EFI_MEMORY_WB, "WB"},
  370. {EFI_MEMORY_UCE, "UCE"},
  371. {EFI_MEMORY_WP, "WP"},
  372. {EFI_MEMORY_RP, "RP"},
  373. {EFI_MEMORY_XP, "WP"},
  374. {EFI_MEMORY_NV, "NV"},
  375. {EFI_MEMORY_MORE_RELIABLE, "REL"},
  376. {EFI_MEMORY_RO, "RO"},
  377. {EFI_MEMORY_RUNTIME, "RT"},
  378. };
  379. /**
  380. * print_memory_attributes() - print memory map attributes
  381. *
  382. * @attributes: Attribute value
  383. *
  384. * Print memory map attributes
  385. */
  386. static void print_memory_attributes(u64 attributes)
  387. {
  388. int sep, i;
  389. for (sep = 0, i = 0; i < ARRAY_SIZE(efi_mem_attrs); i++)
  390. if (attributes & efi_mem_attrs[i].bit) {
  391. if (sep) {
  392. putc('|');
  393. } else {
  394. putc(' ');
  395. sep = 1;
  396. }
  397. puts(efi_mem_attrs[i].text);
  398. }
  399. }
  400. #define EFI_PHYS_ADDR_WIDTH (int)(sizeof(efi_physical_addr_t) * 2)
  401. /**
  402. * do_efi_show_memmap() - show UEFI memory map
  403. *
  404. * @cmdtp: Command table
  405. * @flag: Command flag
  406. * @argc: Number of arguments
  407. * @argv: Argument array
  408. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  409. *
  410. * Implement efidebug "memmap" sub-command.
  411. * Show UEFI memory map.
  412. */
  413. static int do_efi_show_memmap(cmd_tbl_t *cmdtp, int flag,
  414. int argc, char * const argv[])
  415. {
  416. struct efi_mem_desc *memmap = NULL, *map;
  417. efi_uintn_t map_size = 0;
  418. const char *type;
  419. int i;
  420. efi_status_t ret;
  421. ret = EFI_CALL(BS->get_memory_map(&map_size, memmap, NULL, NULL, NULL));
  422. if (ret == EFI_BUFFER_TOO_SMALL) {
  423. map_size += sizeof(struct efi_mem_desc); /* for my own */
  424. ret = EFI_CALL(BS->allocate_pool(EFI_LOADER_DATA,
  425. map_size, (void *)&memmap));
  426. if (ret != EFI_SUCCESS)
  427. return CMD_RET_FAILURE;
  428. ret = EFI_CALL(BS->get_memory_map(&map_size, memmap,
  429. NULL, NULL, NULL));
  430. }
  431. if (ret != EFI_SUCCESS) {
  432. EFI_CALL(BS->free_pool(memmap));
  433. return CMD_RET_FAILURE;
  434. }
  435. printf("Type Start%.*s End%.*s Attributes\n",
  436. EFI_PHYS_ADDR_WIDTH - 5, spc, EFI_PHYS_ADDR_WIDTH - 3, spc);
  437. printf("================ %.*s %.*s ==========\n",
  438. EFI_PHYS_ADDR_WIDTH, sep, EFI_PHYS_ADDR_WIDTH, sep);
  439. for (i = 0, map = memmap; i < map_size / sizeof(*map); map++, i++) {
  440. if (map->type < EFI_MAX_MEMORY_TYPE)
  441. type = efi_mem_type_string[map->type];
  442. else
  443. type = "(unknown)";
  444. printf("%-16s %.*llx-%.*llx", type,
  445. EFI_PHYS_ADDR_WIDTH,
  446. (u64)map_to_sysmem((void *)(uintptr_t)
  447. map->physical_start),
  448. EFI_PHYS_ADDR_WIDTH,
  449. (u64)map_to_sysmem((void *)(uintptr_t)
  450. (map->physical_start +
  451. map->num_pages * EFI_PAGE_SIZE)));
  452. print_memory_attributes(map->attribute);
  453. putc('\n');
  454. }
  455. EFI_CALL(BS->free_pool(memmap));
  456. return CMD_RET_SUCCESS;
  457. }
  458. /**
  459. * do_efi_show_tables() - show UEFI configuration tables
  460. *
  461. * @cmdtp: Command table
  462. * @flag: Command flag
  463. * @argc: Number of arguments
  464. * @argv: Argument array
  465. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  466. *
  467. * Implement efidebug "tables" sub-command.
  468. * Show UEFI configuration tables.
  469. */
  470. static int do_efi_show_tables(cmd_tbl_t *cmdtp, int flag,
  471. int argc, char * const argv[])
  472. {
  473. efi_uintn_t i;
  474. const char *guid_str;
  475. for (i = 0; i < systab.nr_tables; ++i) {
  476. guid_str = get_guid_text(&systab.tables[i].guid);
  477. if (!guid_str)
  478. guid_str = "";
  479. printf("%pUl %s\n", &systab.tables[i].guid, guid_str);
  480. }
  481. return CMD_RET_SUCCESS;
  482. }
  483. /**
  484. * do_efi_boot_add() - set UEFI load option
  485. *
  486. * @cmdtp: Command table
  487. * @flag: Command flag
  488. * @argc: Number of arguments
  489. * @argv: Argument array
  490. * Return: CMD_RET_SUCCESS on success,
  491. * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
  492. *
  493. * Implement efidebug "boot add" sub-command. Create or change UEFI load option.
  494. *
  495. * efidebug boot add <id> <label> <interface> <devnum>[:<part>] <file> <options>
  496. */
  497. static int do_efi_boot_add(cmd_tbl_t *cmdtp, int flag,
  498. int argc, char * const argv[])
  499. {
  500. int id;
  501. char *endp;
  502. char var_name[9];
  503. u16 var_name16[9], *p;
  504. efi_guid_t guid;
  505. size_t label_len, label_len16;
  506. u16 *label;
  507. struct efi_device_path *device_path = NULL, *file_path = NULL;
  508. struct efi_load_option lo;
  509. void *data = NULL;
  510. efi_uintn_t size;
  511. efi_status_t ret;
  512. int r = CMD_RET_SUCCESS;
  513. if (argc < 6 || argc > 7)
  514. return CMD_RET_USAGE;
  515. id = (int)simple_strtoul(argv[1], &endp, 16);
  516. if (*endp != '\0' || id > 0xffff)
  517. return CMD_RET_USAGE;
  518. sprintf(var_name, "Boot%04X", id);
  519. p = var_name16;
  520. utf8_utf16_strncpy(&p, var_name, 9);
  521. guid = efi_global_variable_guid;
  522. /* attributes */
  523. lo.attributes = LOAD_OPTION_ACTIVE; /* always ACTIVE */
  524. /* label */
  525. label_len = strlen(argv[2]);
  526. label_len16 = utf8_utf16_strnlen(argv[2], label_len);
  527. label = malloc((label_len16 + 1) * sizeof(u16));
  528. if (!label)
  529. return CMD_RET_FAILURE;
  530. lo.label = label; /* label will be changed below */
  531. utf8_utf16_strncpy(&label, argv[2], label_len);
  532. /* file path */
  533. ret = efi_dp_from_name(argv[3], argv[4], argv[5], &device_path,
  534. &file_path);
  535. if (ret != EFI_SUCCESS) {
  536. printf("Cannot create device path for \"%s %s\"\n",
  537. argv[3], argv[4]);
  538. r = CMD_RET_FAILURE;
  539. goto out;
  540. }
  541. lo.file_path = file_path;
  542. lo.file_path_length = efi_dp_size(file_path)
  543. + sizeof(struct efi_device_path); /* for END */
  544. /* optional data */
  545. if (argc < 6)
  546. lo.optional_data = NULL;
  547. else
  548. lo.optional_data = (const u8 *)argv[6];
  549. size = efi_serialize_load_option(&lo, (u8 **)&data);
  550. if (!size) {
  551. r = CMD_RET_FAILURE;
  552. goto out;
  553. }
  554. ret = EFI_CALL(RT->set_variable(var_name16, &guid,
  555. EFI_VARIABLE_NON_VOLATILE |
  556. EFI_VARIABLE_BOOTSERVICE_ACCESS |
  557. EFI_VARIABLE_RUNTIME_ACCESS,
  558. size, data));
  559. if (ret != EFI_SUCCESS) {
  560. printf("Cannot set %ls\n", var_name16);
  561. r = CMD_RET_FAILURE;
  562. }
  563. out:
  564. free(data);
  565. efi_free_pool(device_path);
  566. efi_free_pool(file_path);
  567. free(lo.label);
  568. return r;
  569. }
  570. /**
  571. * do_efi_boot_rm() - delete UEFI load options
  572. *
  573. * @cmdtp: Command table
  574. * @flag: Command flag
  575. * @argc: Number of arguments
  576. * @argv: Argument array
  577. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  578. *
  579. * Implement efidebug "boot rm" sub-command.
  580. * Delete UEFI load options.
  581. *
  582. * efidebug boot rm <id> ...
  583. */
  584. static int do_efi_boot_rm(cmd_tbl_t *cmdtp, int flag,
  585. int argc, char * const argv[])
  586. {
  587. efi_guid_t guid;
  588. int id, i;
  589. char *endp;
  590. char var_name[9];
  591. u16 var_name16[9], *p;
  592. efi_status_t ret;
  593. if (argc == 1)
  594. return CMD_RET_USAGE;
  595. guid = efi_global_variable_guid;
  596. for (i = 1; i < argc; i++, argv++) {
  597. id = (int)simple_strtoul(argv[1], &endp, 16);
  598. if (*endp != '\0' || id > 0xffff)
  599. return CMD_RET_FAILURE;
  600. sprintf(var_name, "Boot%04X", id);
  601. p = var_name16;
  602. utf8_utf16_strncpy(&p, var_name, 9);
  603. ret = EFI_CALL(RT->set_variable(var_name16, &guid, 0, 0, NULL));
  604. if (ret) {
  605. printf("Cannot remove %ls\n", var_name16);
  606. return CMD_RET_FAILURE;
  607. }
  608. }
  609. return CMD_RET_SUCCESS;
  610. }
  611. /**
  612. * show_efi_boot_opt_data() - dump UEFI load option
  613. *
  614. * @id: load option number
  615. * @data: value of UEFI load option variable
  616. * @size: size of the boot option
  617. *
  618. * Decode the value of UEFI load option variable and print information.
  619. */
  620. static void show_efi_boot_opt_data(int id, void *data, size_t size)
  621. {
  622. struct efi_load_option lo;
  623. char *label, *p;
  624. size_t label_len16, label_len;
  625. u16 *dp_str;
  626. efi_deserialize_load_option(&lo, data);
  627. label_len16 = u16_strlen(lo.label);
  628. label_len = utf16_utf8_strnlen(lo.label, label_len16);
  629. label = malloc(label_len + 1);
  630. if (!label)
  631. return;
  632. p = label;
  633. utf16_utf8_strncpy(&p, lo.label, label_len16);
  634. printf("Boot%04X:\n", id);
  635. printf(" attributes: %c%c%c (0x%08x)\n",
  636. /* ACTIVE */
  637. lo.attributes & LOAD_OPTION_ACTIVE ? 'A' : '-',
  638. /* FORCE RECONNECT */
  639. lo.attributes & LOAD_OPTION_FORCE_RECONNECT ? 'R' : '-',
  640. /* HIDDEN */
  641. lo.attributes & LOAD_OPTION_HIDDEN ? 'H' : '-',
  642. lo.attributes);
  643. printf(" label: %s\n", label);
  644. dp_str = efi_dp_str(lo.file_path);
  645. printf(" file_path: %ls\n", dp_str);
  646. efi_free_pool(dp_str);
  647. printf(" data:\n");
  648. print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1,
  649. lo.optional_data, size + (u8 *)data -
  650. (u8 *)lo.optional_data, true);
  651. free(label);
  652. }
  653. /**
  654. * show_efi_boot_opt() - dump UEFI load option
  655. *
  656. * @id: Load option number
  657. *
  658. * Dump information defined by UEFI load option.
  659. */
  660. static void show_efi_boot_opt(int id)
  661. {
  662. char var_name[9];
  663. u16 var_name16[9], *p;
  664. efi_guid_t guid;
  665. void *data = NULL;
  666. efi_uintn_t size;
  667. efi_status_t ret;
  668. sprintf(var_name, "Boot%04X", id);
  669. p = var_name16;
  670. utf8_utf16_strncpy(&p, var_name, 9);
  671. guid = efi_global_variable_guid;
  672. size = 0;
  673. ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size, NULL));
  674. if (ret == EFI_BUFFER_TOO_SMALL) {
  675. data = malloc(size);
  676. ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size,
  677. data));
  678. }
  679. if (ret == EFI_SUCCESS)
  680. show_efi_boot_opt_data(id, data, size);
  681. else if (ret == EFI_NOT_FOUND)
  682. printf("Boot%04X: not found\n", id);
  683. free(data);
  684. }
  685. static int u16_tohex(u16 c)
  686. {
  687. if (c >= '0' && c <= '9')
  688. return c - '0';
  689. if (c >= 'A' && c <= 'F')
  690. return c - 'A' + 10;
  691. /* not hexadecimal */
  692. return -1;
  693. }
  694. /**
  695. * show_efi_boot_dump() - dump all UEFI load options
  696. *
  697. * @cmdtp: Command table
  698. * @flag: Command flag
  699. * @argc: Number of arguments
  700. * @argv: Argument array
  701. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  702. *
  703. * Implement efidebug "boot dump" sub-command.
  704. * Dump information of all UEFI load options defined.
  705. *
  706. * efidebug boot dump
  707. */
  708. static int do_efi_boot_dump(cmd_tbl_t *cmdtp, int flag,
  709. int argc, char * const argv[])
  710. {
  711. u16 *var_name16, *p;
  712. efi_uintn_t buf_size, size;
  713. efi_guid_t guid;
  714. int id, i, digit;
  715. efi_status_t ret;
  716. if (argc > 1)
  717. return CMD_RET_USAGE;
  718. buf_size = 128;
  719. var_name16 = malloc(buf_size);
  720. if (!var_name16)
  721. return CMD_RET_FAILURE;
  722. var_name16[0] = 0;
  723. for (;;) {
  724. size = buf_size;
  725. ret = EFI_CALL(efi_get_next_variable_name(&size, var_name16,
  726. &guid));
  727. if (ret == EFI_NOT_FOUND)
  728. break;
  729. if (ret == EFI_BUFFER_TOO_SMALL) {
  730. buf_size = size;
  731. p = realloc(var_name16, buf_size);
  732. if (!p) {
  733. free(var_name16);
  734. return CMD_RET_FAILURE;
  735. }
  736. var_name16 = p;
  737. ret = EFI_CALL(efi_get_next_variable_name(&size,
  738. var_name16,
  739. &guid));
  740. }
  741. if (ret != EFI_SUCCESS) {
  742. free(var_name16);
  743. return CMD_RET_FAILURE;
  744. }
  745. if (memcmp(var_name16, L"Boot", 8))
  746. continue;
  747. for (id = 0, i = 0; i < 4; i++) {
  748. digit = u16_tohex(var_name16[4 + i]);
  749. if (digit < 0)
  750. break;
  751. id = (id << 4) + digit;
  752. }
  753. if (i == 4 && !var_name16[8])
  754. show_efi_boot_opt(id);
  755. }
  756. free(var_name16);
  757. return CMD_RET_SUCCESS;
  758. }
  759. /**
  760. * show_efi_boot_order() - show order of UEFI load options
  761. *
  762. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  763. *
  764. * Show order of UEFI load options defined by BootOrder variable.
  765. */
  766. static int show_efi_boot_order(void)
  767. {
  768. efi_guid_t guid;
  769. u16 *bootorder = NULL;
  770. efi_uintn_t size;
  771. int num, i;
  772. char var_name[9];
  773. u16 var_name16[9], *p16;
  774. void *data;
  775. struct efi_load_option lo;
  776. char *label, *p;
  777. size_t label_len16, label_len;
  778. efi_status_t ret;
  779. guid = efi_global_variable_guid;
  780. size = 0;
  781. ret = EFI_CALL(RT->get_variable(L"BootOrder", &guid, NULL, &size,
  782. NULL));
  783. if (ret == EFI_BUFFER_TOO_SMALL) {
  784. bootorder = malloc(size);
  785. ret = EFI_CALL(RT->get_variable(L"BootOrder", &guid, NULL,
  786. &size, bootorder));
  787. }
  788. if (ret == EFI_NOT_FOUND) {
  789. printf("BootOrder not defined\n");
  790. ret = CMD_RET_SUCCESS;
  791. goto out;
  792. } else if (ret != EFI_SUCCESS) {
  793. ret = CMD_RET_FAILURE;
  794. goto out;
  795. }
  796. num = size / sizeof(u16);
  797. for (i = 0; i < num; i++) {
  798. sprintf(var_name, "Boot%04X", bootorder[i]);
  799. p16 = var_name16;
  800. utf8_utf16_strncpy(&p16, var_name, 9);
  801. size = 0;
  802. ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size,
  803. NULL));
  804. if (ret != EFI_BUFFER_TOO_SMALL) {
  805. printf("%2d: Boot%04X: (not defined)\n",
  806. i + 1, bootorder[i]);
  807. continue;
  808. }
  809. data = malloc(size);
  810. if (!data) {
  811. ret = CMD_RET_FAILURE;
  812. goto out;
  813. }
  814. ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size,
  815. data));
  816. if (ret != EFI_SUCCESS) {
  817. free(data);
  818. ret = CMD_RET_FAILURE;
  819. goto out;
  820. }
  821. efi_deserialize_load_option(&lo, data);
  822. label_len16 = u16_strlen(lo.label);
  823. label_len = utf16_utf8_strnlen(lo.label, label_len16);
  824. label = malloc(label_len + 1);
  825. if (!label) {
  826. free(data);
  827. ret = CMD_RET_FAILURE;
  828. goto out;
  829. }
  830. p = label;
  831. utf16_utf8_strncpy(&p, lo.label, label_len16);
  832. printf("%2d: Boot%04X: %s\n", i + 1, bootorder[i], label);
  833. free(label);
  834. free(data);
  835. }
  836. out:
  837. free(bootorder);
  838. return ret;
  839. }
  840. /**
  841. * do_efi_boot_next() - manage UEFI BootNext variable
  842. *
  843. * @cmdtp: Command table
  844. * @flag: Command flag
  845. * @argc: Number of arguments
  846. * @argv: Argument array
  847. * Return: CMD_RET_SUCCESS on success,
  848. * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
  849. *
  850. * Implement efidebug "boot next" sub-command.
  851. * Set BootNext variable.
  852. *
  853. * efidebug boot next <id>
  854. */
  855. static int do_efi_boot_next(cmd_tbl_t *cmdtp, int flag,
  856. int argc, char * const argv[])
  857. {
  858. u16 bootnext;
  859. efi_uintn_t size;
  860. char *endp;
  861. efi_guid_t guid;
  862. efi_status_t ret;
  863. int r = CMD_RET_SUCCESS;
  864. if (argc != 2)
  865. return CMD_RET_USAGE;
  866. bootnext = (u16)simple_strtoul(argv[1], &endp, 16);
  867. if (*endp != '\0' || bootnext > 0xffff) {
  868. printf("invalid value: %s\n", argv[1]);
  869. r = CMD_RET_FAILURE;
  870. goto out;
  871. }
  872. guid = efi_global_variable_guid;
  873. size = sizeof(u16);
  874. ret = EFI_CALL(RT->set_variable(L"BootNext", &guid,
  875. EFI_VARIABLE_NON_VOLATILE |
  876. EFI_VARIABLE_BOOTSERVICE_ACCESS |
  877. EFI_VARIABLE_RUNTIME_ACCESS,
  878. size, &bootnext));
  879. if (ret != EFI_SUCCESS) {
  880. printf("Cannot set BootNext\n");
  881. r = CMD_RET_FAILURE;
  882. }
  883. out:
  884. return r;
  885. }
  886. /**
  887. * do_efi_boot_order() - manage UEFI BootOrder variable
  888. *
  889. * @cmdtp: Command table
  890. * @flag: Command flag
  891. * @argc: Number of arguments
  892. * @argv: Argument array
  893. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  894. *
  895. * Implement efidebug "boot order" sub-command.
  896. * Show order of UEFI load options, or change it in BootOrder variable.
  897. *
  898. * efidebug boot order [<id> ...]
  899. */
  900. static int do_efi_boot_order(cmd_tbl_t *cmdtp, int flag,
  901. int argc, char * const argv[])
  902. {
  903. u16 *bootorder = NULL;
  904. efi_uintn_t size;
  905. int id, i;
  906. char *endp;
  907. efi_guid_t guid;
  908. efi_status_t ret;
  909. int r = CMD_RET_SUCCESS;
  910. if (argc == 1)
  911. return show_efi_boot_order();
  912. argc--;
  913. argv++;
  914. size = argc * sizeof(u16);
  915. bootorder = malloc(size);
  916. if (!bootorder)
  917. return CMD_RET_FAILURE;
  918. for (i = 0; i < argc; i++) {
  919. id = (int)simple_strtoul(argv[i], &endp, 16);
  920. if (*endp != '\0' || id > 0xffff) {
  921. printf("invalid value: %s\n", argv[i]);
  922. r = CMD_RET_FAILURE;
  923. goto out;
  924. }
  925. bootorder[i] = (u16)id;
  926. }
  927. guid = efi_global_variable_guid;
  928. ret = EFI_CALL(RT->set_variable(L"BootOrder", &guid,
  929. EFI_VARIABLE_NON_VOLATILE |
  930. EFI_VARIABLE_BOOTSERVICE_ACCESS |
  931. EFI_VARIABLE_RUNTIME_ACCESS,
  932. size, bootorder));
  933. if (ret != EFI_SUCCESS) {
  934. printf("Cannot set BootOrder\n");
  935. r = CMD_RET_FAILURE;
  936. }
  937. out:
  938. free(bootorder);
  939. return r;
  940. }
  941. static cmd_tbl_t cmd_efidebug_boot_sub[] = {
  942. U_BOOT_CMD_MKENT(add, CONFIG_SYS_MAXARGS, 1, do_efi_boot_add, "", ""),
  943. U_BOOT_CMD_MKENT(rm, CONFIG_SYS_MAXARGS, 1, do_efi_boot_rm, "", ""),
  944. U_BOOT_CMD_MKENT(dump, CONFIG_SYS_MAXARGS, 1, do_efi_boot_dump, "", ""),
  945. U_BOOT_CMD_MKENT(next, CONFIG_SYS_MAXARGS, 1, do_efi_boot_next, "", ""),
  946. U_BOOT_CMD_MKENT(order, CONFIG_SYS_MAXARGS, 1, do_efi_boot_order,
  947. "", ""),
  948. };
  949. /**
  950. * do_efi_boot_opt() - manage UEFI load options
  951. *
  952. * @cmdtp: Command table
  953. * @flag: Command flag
  954. * @argc: Number of arguments
  955. * @argv: Argument array
  956. * Return: CMD_RET_SUCCESS on success,
  957. * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
  958. *
  959. * Implement efidebug "boot" sub-command.
  960. */
  961. static int do_efi_boot_opt(cmd_tbl_t *cmdtp, int flag,
  962. int argc, char * const argv[])
  963. {
  964. cmd_tbl_t *cp;
  965. if (argc < 2)
  966. return CMD_RET_USAGE;
  967. argc--; argv++;
  968. cp = find_cmd_tbl(argv[0], cmd_efidebug_boot_sub,
  969. ARRAY_SIZE(cmd_efidebug_boot_sub));
  970. if (!cp)
  971. return CMD_RET_USAGE;
  972. return cp->cmd(cmdtp, flag, argc, argv);
  973. }
  974. static cmd_tbl_t cmd_efidebug_sub[] = {
  975. U_BOOT_CMD_MKENT(boot, CONFIG_SYS_MAXARGS, 1, do_efi_boot_opt, "", ""),
  976. U_BOOT_CMD_MKENT(devices, CONFIG_SYS_MAXARGS, 1, do_efi_show_devices,
  977. "", ""),
  978. U_BOOT_CMD_MKENT(drivers, CONFIG_SYS_MAXARGS, 1, do_efi_show_drivers,
  979. "", ""),
  980. U_BOOT_CMD_MKENT(dh, CONFIG_SYS_MAXARGS, 1, do_efi_show_handles,
  981. "", ""),
  982. U_BOOT_CMD_MKENT(images, CONFIG_SYS_MAXARGS, 1, do_efi_show_images,
  983. "", ""),
  984. U_BOOT_CMD_MKENT(memmap, CONFIG_SYS_MAXARGS, 1, do_efi_show_memmap,
  985. "", ""),
  986. U_BOOT_CMD_MKENT(tables, CONFIG_SYS_MAXARGS, 1, do_efi_show_tables,
  987. "", ""),
  988. };
  989. /**
  990. * do_efidebug() - display and configure UEFI environment
  991. *
  992. * @cmdtp: Command table
  993. * @flag: Command flag
  994. * @argc: Number of arguments
  995. * @argv: Argument array
  996. * Return: CMD_RET_SUCCESS on success,
  997. * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
  998. *
  999. * Implement efidebug command which allows us to display and
  1000. * configure UEFI environment.
  1001. */
  1002. static int do_efidebug(cmd_tbl_t *cmdtp, int flag,
  1003. int argc, char * const argv[])
  1004. {
  1005. cmd_tbl_t *cp;
  1006. efi_status_t r;
  1007. if (argc < 2)
  1008. return CMD_RET_USAGE;
  1009. argc--; argv++;
  1010. /* Initialize UEFI drivers */
  1011. r = efi_init_obj_list();
  1012. if (r != EFI_SUCCESS) {
  1013. printf("Error: Cannot initialize UEFI sub-system, r = %lu\n",
  1014. r & ~EFI_ERROR_MASK);
  1015. return CMD_RET_FAILURE;
  1016. }
  1017. cp = find_cmd_tbl(argv[0], cmd_efidebug_sub,
  1018. ARRAY_SIZE(cmd_efidebug_sub));
  1019. if (!cp)
  1020. return CMD_RET_USAGE;
  1021. return cp->cmd(cmdtp, flag, argc, argv);
  1022. }
  1023. #ifdef CONFIG_SYS_LONGHELP
  1024. static char efidebug_help_text[] =
  1025. " - UEFI Shell-like interface to configure UEFI environment\n"
  1026. "\n"
  1027. "efidebug boot add <bootid> <label> <interface> <devnum>[:<part>] <file path> [<load options>]\n"
  1028. " - set UEFI BootXXXX variable\n"
  1029. " <load options> will be passed to UEFI application\n"
  1030. "efidebug boot rm <bootid#1> [<bootid#2> [<bootid#3> [...]]]\n"
  1031. " - delete UEFI BootXXXX variables\n"
  1032. "efidebug boot dump\n"
  1033. " - dump all UEFI BootXXXX variables\n"
  1034. "efidebug boot next <bootid>\n"
  1035. " - set UEFI BootNext variable\n"
  1036. "efidebug boot order [<bootid#1> [<bootid#2> [<bootid#3> [...]]]]\n"
  1037. " - set/show UEFI boot order\n"
  1038. "\n"
  1039. "efidebug devices\n"
  1040. " - show UEFI devices\n"
  1041. "efidebug drivers\n"
  1042. " - show UEFI drivers\n"
  1043. "efidebug dh\n"
  1044. " - show UEFI handles\n"
  1045. "efidebug images\n"
  1046. " - show loaded images\n"
  1047. "efidebug memmap\n"
  1048. " - show UEFI memory map\n"
  1049. "efidebug tables\n"
  1050. " - show UEFI configuration tables\n";
  1051. #endif
  1052. U_BOOT_CMD(
  1053. efidebug, 10, 0, do_efidebug,
  1054. "Configure UEFI environment",
  1055. efidebug_help_text
  1056. );