efidebug.c 29 KB

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