efidebug.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104
  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. * @attributes: Attribute value
  358. *
  359. * Print memory map attributes
  360. */
  361. static void print_memory_attributes(u64 attributes)
  362. {
  363. int sep, i;
  364. for (sep = 0, i = 0; i < ARRAY_SIZE(efi_mem_attrs); i++)
  365. if (attributes & efi_mem_attrs[i].bit) {
  366. if (sep) {
  367. putc('|');
  368. } else {
  369. putc(' ');
  370. sep = 1;
  371. }
  372. puts(efi_mem_attrs[i].text);
  373. }
  374. }
  375. #define EFI_PHYS_ADDR_WIDTH (int)(sizeof(efi_physical_addr_t) * 2)
  376. /**
  377. * do_efi_show_memmap() - show UEFI memory map
  378. *
  379. * @cmdtp: Command table
  380. * @flag: Command flag
  381. * @argc: Number of arguments
  382. * @argv: Argument array
  383. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  384. *
  385. * Implement efidebug "memmap" sub-command.
  386. * Show UEFI memory map.
  387. */
  388. static int do_efi_show_memmap(cmd_tbl_t *cmdtp, int flag,
  389. int argc, char * const argv[])
  390. {
  391. struct efi_mem_desc *memmap = NULL, *map;
  392. efi_uintn_t map_size = 0;
  393. const char *type;
  394. int i;
  395. efi_status_t ret;
  396. ret = EFI_CALL(BS->get_memory_map(&map_size, memmap, NULL, NULL, NULL));
  397. if (ret == EFI_BUFFER_TOO_SMALL) {
  398. map_size += sizeof(struct efi_mem_desc); /* for my own */
  399. ret = EFI_CALL(BS->allocate_pool(EFI_LOADER_DATA,
  400. map_size, (void *)&memmap));
  401. if (ret != EFI_SUCCESS)
  402. return CMD_RET_FAILURE;
  403. ret = EFI_CALL(BS->get_memory_map(&map_size, memmap,
  404. NULL, NULL, NULL));
  405. }
  406. if (ret != EFI_SUCCESS) {
  407. EFI_CALL(BS->free_pool(memmap));
  408. return CMD_RET_FAILURE;
  409. }
  410. printf("Type Start%.*s End%.*s Attributes\n",
  411. EFI_PHYS_ADDR_WIDTH - 5, spc, EFI_PHYS_ADDR_WIDTH - 3, spc);
  412. printf("================ %.*s %.*s ==========\n",
  413. EFI_PHYS_ADDR_WIDTH, sep, EFI_PHYS_ADDR_WIDTH, sep);
  414. for (i = 0, map = memmap; i < map_size / sizeof(*map); map++, i++) {
  415. if (map->type < EFI_MAX_MEMORY_TYPE)
  416. type = efi_mem_type_string[map->type];
  417. else
  418. type = "(unknown)";
  419. printf("%-16s %.*llx-%.*llx", type,
  420. EFI_PHYS_ADDR_WIDTH,
  421. map->physical_start,
  422. EFI_PHYS_ADDR_WIDTH,
  423. map->physical_start + map->num_pages * EFI_PAGE_SIZE);
  424. print_memory_attributes(map->attribute);
  425. putc('\n');
  426. }
  427. EFI_CALL(BS->free_pool(memmap));
  428. return CMD_RET_SUCCESS;
  429. }
  430. /**
  431. * do_efi_boot_add() - set UEFI load option
  432. *
  433. * @cmdtp: Command table
  434. * @flag: Command flag
  435. * @argc: Number of arguments
  436. * @argv: Argument array
  437. * Return: CMD_RET_SUCCESS on success,
  438. * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
  439. *
  440. * Implement efidebug "boot add" sub-command.
  441. * Create or change UEFI load option.
  442. * - boot add <id> <label> <interface> <devnum>[:<part>] <file> <options>
  443. */
  444. static int do_efi_boot_add(cmd_tbl_t *cmdtp, int flag,
  445. int argc, char * const argv[])
  446. {
  447. int id;
  448. char *endp;
  449. char var_name[9];
  450. u16 var_name16[9], *p;
  451. efi_guid_t guid;
  452. size_t label_len, label_len16;
  453. u16 *label;
  454. struct efi_device_path *device_path = NULL, *file_path = NULL;
  455. struct efi_load_option lo;
  456. void *data = NULL;
  457. efi_uintn_t size;
  458. int ret;
  459. if (argc < 6 || argc > 7)
  460. return CMD_RET_USAGE;
  461. id = (int)simple_strtoul(argv[1], &endp, 16);
  462. if (*endp != '\0' || id > 0xffff)
  463. return CMD_RET_USAGE;
  464. sprintf(var_name, "Boot%04X", id);
  465. p = var_name16;
  466. utf8_utf16_strncpy(&p, var_name, 9);
  467. guid = efi_global_variable_guid;
  468. /* attributes */
  469. lo.attributes = LOAD_OPTION_ACTIVE; /* always ACTIVE */
  470. /* label */
  471. label_len = strlen(argv[2]);
  472. label_len16 = utf8_utf16_strnlen(argv[2], label_len);
  473. label = malloc((label_len16 + 1) * sizeof(u16));
  474. if (!label)
  475. return CMD_RET_FAILURE;
  476. lo.label = label; /* label will be changed below */
  477. utf8_utf16_strncpy(&label, argv[2], label_len);
  478. /* file path */
  479. ret = efi_dp_from_name(argv[3], argv[4], argv[5], &device_path,
  480. &file_path);
  481. if (ret != EFI_SUCCESS) {
  482. printf("Cannot create device path for \"%s %s\"\n",
  483. argv[3], argv[4]);
  484. ret = CMD_RET_FAILURE;
  485. goto out;
  486. }
  487. lo.file_path = file_path;
  488. lo.file_path_length = efi_dp_size(file_path)
  489. + sizeof(struct efi_device_path); /* for END */
  490. /* optional data */
  491. if (argc < 6)
  492. lo.optional_data = NULL;
  493. else
  494. lo.optional_data = (const u8 *)argv[6];
  495. size = efi_serialize_load_option(&lo, (u8 **)&data);
  496. if (!size) {
  497. ret = CMD_RET_FAILURE;
  498. goto out;
  499. }
  500. ret = EFI_CALL(RT->set_variable(var_name16, &guid,
  501. EFI_VARIABLE_BOOTSERVICE_ACCESS |
  502. EFI_VARIABLE_RUNTIME_ACCESS,
  503. size, data));
  504. ret = (ret == EFI_SUCCESS ? CMD_RET_SUCCESS : CMD_RET_FAILURE);
  505. out:
  506. free(data);
  507. efi_free_pool(device_path);
  508. efi_free_pool(file_path);
  509. free(lo.label);
  510. return ret;
  511. }
  512. /**
  513. * do_efi_boot_rm() - delete UEFI load options
  514. *
  515. * @cmdtp: Command table
  516. * @flag: Command flag
  517. * @argc: Number of arguments
  518. * @argv: Argument array
  519. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  520. *
  521. * Implement efidebug "boot rm" sub-command.
  522. * Delete UEFI load options.
  523. * - boot rm <id> ...
  524. */
  525. static int do_efi_boot_rm(cmd_tbl_t *cmdtp, int flag,
  526. int argc, char * const argv[])
  527. {
  528. efi_guid_t guid;
  529. int id, i;
  530. char *endp;
  531. char var_name[9];
  532. u16 var_name16[9];
  533. efi_status_t ret;
  534. if (argc == 1)
  535. return CMD_RET_USAGE;
  536. guid = efi_global_variable_guid;
  537. for (i = 1; i < argc; i++, argv++) {
  538. id = (int)simple_strtoul(argv[1], &endp, 16);
  539. if (*endp != '\0' || id > 0xffff)
  540. return CMD_RET_FAILURE;
  541. sprintf(var_name, "Boot%04X", id);
  542. utf8_utf16_strncpy((u16 **)&var_name16, var_name, 9);
  543. ret = EFI_CALL(RT->set_variable(var_name16, &guid, 0, 0, NULL));
  544. if (ret) {
  545. printf("cannot remove Boot%04X", id);
  546. return CMD_RET_FAILURE;
  547. }
  548. }
  549. return CMD_RET_SUCCESS;
  550. }
  551. /**
  552. * show_efi_boot_opt_data() - dump UEFI load option
  553. *
  554. * @id: load option number
  555. * @data: value of UEFI load option variable
  556. * @size: size of the boot option
  557. *
  558. * Decode the value of UEFI load option variable and print information.
  559. */
  560. static void show_efi_boot_opt_data(int id, void *data, size_t size)
  561. {
  562. struct efi_load_option lo;
  563. char *label, *p;
  564. size_t label_len16, label_len;
  565. u16 *dp_str;
  566. efi_deserialize_load_option(&lo, data);
  567. label_len16 = u16_strlen(lo.label);
  568. label_len = utf16_utf8_strnlen(lo.label, label_len16);
  569. label = malloc(label_len + 1);
  570. if (!label)
  571. return;
  572. p = label;
  573. utf16_utf8_strncpy(&p, lo.label, label_len16);
  574. printf("Boot%04X:\n", id);
  575. printf(" attributes: %c%c%c (0x%08x)\n",
  576. /* ACTIVE */
  577. lo.attributes & LOAD_OPTION_ACTIVE ? 'A' : '-',
  578. /* FORCE RECONNECT */
  579. lo.attributes & LOAD_OPTION_FORCE_RECONNECT ? 'R' : '-',
  580. /* HIDDEN */
  581. lo.attributes & LOAD_OPTION_HIDDEN ? 'H' : '-',
  582. lo.attributes);
  583. printf(" label: %s\n", label);
  584. dp_str = efi_dp_str(lo.file_path);
  585. printf(" file_path: %ls\n", dp_str);
  586. efi_free_pool(dp_str);
  587. printf(" data:\n");
  588. print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1,
  589. lo.optional_data, size + (u8 *)data -
  590. (u8 *)lo.optional_data, true);
  591. free(label);
  592. }
  593. /**
  594. * show_efi_boot_opt() - dump UEFI load option
  595. *
  596. * @id: Load option number
  597. *
  598. * Dump information defined by UEFI load option.
  599. */
  600. static void show_efi_boot_opt(int id)
  601. {
  602. char var_name[9];
  603. u16 var_name16[9], *p;
  604. efi_guid_t guid;
  605. void *data = NULL;
  606. efi_uintn_t size;
  607. int ret;
  608. sprintf(var_name, "Boot%04X", id);
  609. p = var_name16;
  610. utf8_utf16_strncpy(&p, var_name, 9);
  611. guid = efi_global_variable_guid;
  612. size = 0;
  613. ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size, NULL));
  614. if (ret == (int)EFI_BUFFER_TOO_SMALL) {
  615. data = malloc(size);
  616. ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size,
  617. data));
  618. }
  619. if (ret == EFI_SUCCESS)
  620. show_efi_boot_opt_data(id, data, size);
  621. else if (ret == EFI_NOT_FOUND)
  622. printf("Boot%04X: not found\n", id);
  623. free(data);
  624. }
  625. static int u16_tohex(u16 c)
  626. {
  627. if (c >= '0' && c <= '9')
  628. return c - '0';
  629. if (c >= 'A' && c <= 'F')
  630. return c - 'A' + 10;
  631. /* not hexadecimal */
  632. return -1;
  633. }
  634. /**
  635. * show_efi_boot_dump() - dump all UEFI load options
  636. *
  637. * @cmdtp: Command table
  638. * @flag: Command flag
  639. * @argc: Number of arguments
  640. * @argv: Argument array
  641. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  642. *
  643. * Implement efidebug "boot dump" sub-command.
  644. * Dump information of all UEFI load options defined.
  645. * - boot dump
  646. */
  647. static int do_efi_boot_dump(cmd_tbl_t *cmdtp, int flag,
  648. int argc, char * const argv[])
  649. {
  650. u16 *var_name16, *p;
  651. efi_uintn_t buf_size, size;
  652. efi_guid_t guid;
  653. int id, i, digit;
  654. efi_status_t ret;
  655. if (argc > 1)
  656. return CMD_RET_USAGE;
  657. buf_size = 128;
  658. var_name16 = malloc(buf_size);
  659. if (!var_name16)
  660. return CMD_RET_FAILURE;
  661. var_name16[0] = 0;
  662. for (;;) {
  663. size = buf_size;
  664. ret = EFI_CALL(efi_get_next_variable_name(&size, var_name16,
  665. &guid));
  666. if (ret == EFI_NOT_FOUND)
  667. break;
  668. if (ret == EFI_BUFFER_TOO_SMALL) {
  669. buf_size = size;
  670. p = realloc(var_name16, buf_size);
  671. if (!p) {
  672. free(var_name16);
  673. return CMD_RET_FAILURE;
  674. }
  675. var_name16 = p;
  676. ret = EFI_CALL(efi_get_next_variable_name(&size,
  677. var_name16,
  678. &guid));
  679. }
  680. if (ret != EFI_SUCCESS) {
  681. free(var_name16);
  682. return CMD_RET_FAILURE;
  683. }
  684. if (memcmp(var_name16, L"Boot", 8))
  685. continue;
  686. for (id = 0, i = 0; i < 4; i++) {
  687. digit = u16_tohex(var_name16[4 + i]);
  688. if (digit < 0)
  689. break;
  690. id = (id << 4) + digit;
  691. }
  692. if (i == 4 && !var_name16[8])
  693. show_efi_boot_opt(id);
  694. }
  695. free(var_name16);
  696. return CMD_RET_SUCCESS;
  697. }
  698. /**
  699. * show_efi_boot_order() - show order of UEFI load options
  700. *
  701. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  702. *
  703. * Show order of UEFI load options defined by BootOrder variable.
  704. */
  705. static int show_efi_boot_order(void)
  706. {
  707. efi_guid_t guid;
  708. u16 *bootorder = NULL;
  709. efi_uintn_t size;
  710. int num, i;
  711. char var_name[9];
  712. u16 var_name16[9], *p16;
  713. void *data;
  714. struct efi_load_option lo;
  715. char *label, *p;
  716. size_t label_len16, label_len;
  717. efi_status_t ret;
  718. guid = efi_global_variable_guid;
  719. size = 0;
  720. ret = EFI_CALL(RT->get_variable(L"BootOrder", &guid, NULL, &size,
  721. NULL));
  722. if (ret == EFI_BUFFER_TOO_SMALL) {
  723. bootorder = malloc(size);
  724. ret = EFI_CALL(RT->get_variable(L"BootOrder", &guid, NULL,
  725. &size, bootorder));
  726. }
  727. if (ret == EFI_NOT_FOUND) {
  728. printf("BootOrder not defined\n");
  729. ret = CMD_RET_SUCCESS;
  730. goto out;
  731. } else if (ret != EFI_SUCCESS) {
  732. ret = CMD_RET_FAILURE;
  733. goto out;
  734. }
  735. num = size / sizeof(u16);
  736. for (i = 0; i < num; i++) {
  737. sprintf(var_name, "Boot%04X", bootorder[i]);
  738. p16 = var_name16;
  739. utf8_utf16_strncpy(&p16, var_name, 9);
  740. size = 0;
  741. ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size,
  742. NULL));
  743. if (ret != EFI_BUFFER_TOO_SMALL) {
  744. printf("%2d: Boot%04X: (not defined)\n",
  745. i + 1, bootorder[i]);
  746. continue;
  747. }
  748. data = malloc(size);
  749. if (!data) {
  750. ret = CMD_RET_FAILURE;
  751. goto out;
  752. }
  753. ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size,
  754. data));
  755. if (ret != EFI_SUCCESS) {
  756. free(data);
  757. ret = CMD_RET_FAILURE;
  758. goto out;
  759. }
  760. efi_deserialize_load_option(&lo, data);
  761. label_len16 = u16_strlen(lo.label);
  762. label_len = utf16_utf8_strnlen(lo.label, label_len16);
  763. label = malloc(label_len + 1);
  764. if (!label) {
  765. free(data);
  766. ret = CMD_RET_FAILURE;
  767. goto out;
  768. }
  769. p = label;
  770. utf16_utf8_strncpy(&p, lo.label, label_len16);
  771. printf("%2d: Boot%04X: %s\n", i + 1, bootorder[i], label);
  772. free(label);
  773. free(data);
  774. }
  775. out:
  776. free(bootorder);
  777. return ret;
  778. }
  779. /**
  780. * do_efi_boot_next() - manage UEFI BootNext variable
  781. *
  782. * @cmdtp: Command table
  783. * @flag: Command flag
  784. * @argc: Number of arguments
  785. * @argv: Argument array
  786. * Return: CMD_RET_SUCCESS on success,
  787. * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
  788. *
  789. * Implement efidebug "boot next" sub-command.
  790. * Set BootNext variable.
  791. * - boot next <id>
  792. */
  793. static int do_efi_boot_next(cmd_tbl_t *cmdtp, int flag,
  794. int argc, char * const argv[])
  795. {
  796. u16 bootnext;
  797. efi_uintn_t size;
  798. char *endp;
  799. efi_guid_t guid;
  800. efi_status_t ret;
  801. if (argc != 2)
  802. return CMD_RET_USAGE;
  803. bootnext = (u16)simple_strtoul(argv[1], &endp, 16);
  804. if (*endp != '\0' || bootnext > 0xffff) {
  805. printf("invalid value: %s\n", argv[1]);
  806. ret = CMD_RET_FAILURE;
  807. goto out;
  808. }
  809. guid = efi_global_variable_guid;
  810. size = sizeof(u16);
  811. ret = EFI_CALL(RT->set_variable(L"BootNext", &guid,
  812. EFI_VARIABLE_BOOTSERVICE_ACCESS |
  813. EFI_VARIABLE_RUNTIME_ACCESS,
  814. size, &bootnext));
  815. ret = (ret == EFI_SUCCESS ? CMD_RET_SUCCESS : CMD_RET_FAILURE);
  816. out:
  817. return ret;
  818. }
  819. /**
  820. * do_efi_boot_order() - manage UEFI BootOrder variable
  821. *
  822. * @cmdtp: Command table
  823. * @flag: Command flag
  824. * @argc: Number of arguments
  825. * @argv: Argument array
  826. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  827. *
  828. * Implement efidebug "boot order" sub-command.
  829. * Show order of UEFI load options, or change it in BootOrder variable.
  830. * - boot order [<id> ...]
  831. */
  832. static int do_efi_boot_order(cmd_tbl_t *cmdtp, int flag,
  833. int argc, char * const argv[])
  834. {
  835. u16 *bootorder = NULL;
  836. efi_uintn_t size;
  837. int id, i;
  838. char *endp;
  839. efi_guid_t guid;
  840. efi_status_t ret;
  841. if (argc == 1)
  842. return show_efi_boot_order();
  843. argc--;
  844. argv++;
  845. size = argc * sizeof(u16);
  846. bootorder = malloc(size);
  847. if (!bootorder)
  848. return CMD_RET_FAILURE;
  849. for (i = 0; i < argc; i++) {
  850. id = (int)simple_strtoul(argv[i], &endp, 16);
  851. if (*endp != '\0' || id > 0xffff) {
  852. printf("invalid value: %s\n", argv[i]);
  853. ret = CMD_RET_FAILURE;
  854. goto out;
  855. }
  856. bootorder[i] = (u16)id;
  857. }
  858. guid = efi_global_variable_guid;
  859. ret = EFI_CALL(RT->set_variable(L"BootOrder", &guid,
  860. EFI_VARIABLE_BOOTSERVICE_ACCESS |
  861. EFI_VARIABLE_RUNTIME_ACCESS,
  862. size, bootorder));
  863. ret = (ret == EFI_SUCCESS ? CMD_RET_SUCCESS : CMD_RET_FAILURE);
  864. out:
  865. free(bootorder);
  866. return ret;
  867. }
  868. static cmd_tbl_t cmd_efidebug_boot_sub[] = {
  869. U_BOOT_CMD_MKENT(add, CONFIG_SYS_MAXARGS, 1, do_efi_boot_add, "", ""),
  870. U_BOOT_CMD_MKENT(rm, CONFIG_SYS_MAXARGS, 1, do_efi_boot_rm, "", ""),
  871. U_BOOT_CMD_MKENT(dump, CONFIG_SYS_MAXARGS, 1, do_efi_boot_dump, "", ""),
  872. U_BOOT_CMD_MKENT(next, CONFIG_SYS_MAXARGS, 1, do_efi_boot_next, "", ""),
  873. U_BOOT_CMD_MKENT(order, CONFIG_SYS_MAXARGS, 1, do_efi_boot_order,
  874. "", ""),
  875. };
  876. /**
  877. * do_efi_boot_opt() - manage UEFI load options
  878. *
  879. * @cmdtp: Command table
  880. * @flag: Command flag
  881. * @argc: Number of arguments
  882. * @argv: Argument array
  883. * Return: CMD_RET_SUCCESS on success,
  884. * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
  885. *
  886. * Implement efidebug "boot" sub-command.
  887. * See above for details of sub-commands.
  888. */
  889. static int do_efi_boot_opt(cmd_tbl_t *cmdtp, int flag,
  890. int argc, char * const argv[])
  891. {
  892. cmd_tbl_t *cp;
  893. if (argc < 2)
  894. return CMD_RET_USAGE;
  895. argc--; argv++;
  896. cp = find_cmd_tbl(argv[0], cmd_efidebug_boot_sub,
  897. ARRAY_SIZE(cmd_efidebug_boot_sub));
  898. if (!cp)
  899. return CMD_RET_USAGE;
  900. return cp->cmd(cmdtp, flag, argc, argv);
  901. }
  902. static cmd_tbl_t cmd_efidebug_sub[] = {
  903. U_BOOT_CMD_MKENT(boot, CONFIG_SYS_MAXARGS, 1, do_efi_boot_opt, "", ""),
  904. U_BOOT_CMD_MKENT(devices, CONFIG_SYS_MAXARGS, 1, do_efi_show_devices,
  905. "", ""),
  906. U_BOOT_CMD_MKENT(drivers, CONFIG_SYS_MAXARGS, 1, do_efi_show_drivers,
  907. "", ""),
  908. U_BOOT_CMD_MKENT(dh, CONFIG_SYS_MAXARGS, 1, do_efi_show_handles,
  909. "", ""),
  910. U_BOOT_CMD_MKENT(images, CONFIG_SYS_MAXARGS, 1, do_efi_show_images,
  911. "", ""),
  912. U_BOOT_CMD_MKENT(memmap, CONFIG_SYS_MAXARGS, 1, do_efi_show_memmap,
  913. "", ""),
  914. };
  915. /**
  916. * do_efidebug() - display and configure UEFI environment
  917. *
  918. * @cmdtp: Command table
  919. * @flag: Command flag
  920. * @argc: Number of arguments
  921. * @argv: Argument array
  922. * Return: CMD_RET_SUCCESS on success,
  923. * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
  924. *
  925. * Implement efidebug command which allows us to display and
  926. * configure UEFI environment.
  927. * See above for details of sub-commands.
  928. */
  929. static int do_efidebug(cmd_tbl_t *cmdtp, int flag,
  930. int argc, char * const argv[])
  931. {
  932. cmd_tbl_t *cp;
  933. efi_status_t r;
  934. if (argc < 2)
  935. return CMD_RET_USAGE;
  936. argc--; argv++;
  937. /* Initialize UEFI drivers */
  938. r = efi_init_obj_list();
  939. if (r != EFI_SUCCESS) {
  940. printf("Error: Cannot initialize UEFI sub-system, r = %lu\n",
  941. r & ~EFI_ERROR_MASK);
  942. return CMD_RET_FAILURE;
  943. }
  944. cp = find_cmd_tbl(argv[0], cmd_efidebug_sub,
  945. ARRAY_SIZE(cmd_efidebug_sub));
  946. if (!cp)
  947. return CMD_RET_USAGE;
  948. return cp->cmd(cmdtp, flag, argc, argv);
  949. }
  950. #ifdef CONFIG_SYS_LONGHELP
  951. static char efidebug_help_text[] =
  952. " - UEFI Shell-like interface to configure UEFI environment\n"
  953. "\n"
  954. "efidebug boot add <bootid> <label> <interface> <devnum>[:<part>] <file path> [<load options>]\n"
  955. " - set UEFI BootXXXX variable\n"
  956. " <load options> will be passed to UEFI application\n"
  957. "efidebug boot rm <bootid#1> [<bootid#2> [<bootid#3> [...]]]\n"
  958. " - delete UEFI BootXXXX variables\n"
  959. "efidebug boot dump\n"
  960. " - dump all UEFI BootXXXX variables\n"
  961. "efidebug boot next <bootid>\n"
  962. " - set UEFI BootNext variable\n"
  963. "efidebug boot order [<bootid#1> [<bootid#2> [<bootid#3> [...]]]]\n"
  964. " - set/show UEFI boot order\n"
  965. "\n"
  966. "efidebug devices\n"
  967. " - show uefi devices\n"
  968. "efidebug drivers\n"
  969. " - show uefi drivers\n"
  970. "efidebug dh\n"
  971. " - show uefi handles\n"
  972. "efidebug images\n"
  973. " - show loaded images\n"
  974. "efidebug memmap\n"
  975. " - show uefi memory map\n";
  976. #endif
  977. U_BOOT_CMD(
  978. efidebug, 10, 0, do_efidebug,
  979. "Configure UEFI environment",
  980. efidebug_help_text
  981. );