efidebug.c 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628
  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_dt_fixup.h>
  11. #include <efi_load_initrd.h>
  12. #include <efi_loader.h>
  13. #include <efi_rng.h>
  14. #include <efi_variable.h>
  15. #include <exports.h>
  16. #include <hexdump.h>
  17. #include <log.h>
  18. #include <malloc.h>
  19. #include <mapmem.h>
  20. #include <part.h>
  21. #include <search.h>
  22. #include <linux/ctype.h>
  23. #include <linux/err.h>
  24. #define BS systab.boottime
  25. #define RT systab.runtime
  26. #ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT
  27. /**
  28. * do_efi_capsule_update() - process a capsule update
  29. *
  30. * @cmdtp: Command table
  31. * @flag: Command flag
  32. * @argc: Number of arguments
  33. * @argv: Argument array
  34. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  35. *
  36. * Implement efidebug "capsule update" sub-command.
  37. * process a capsule update.
  38. *
  39. * efidebug capsule update [-v] <capsule address>
  40. */
  41. static int do_efi_capsule_update(struct cmd_tbl *cmdtp, int flag,
  42. int argc, char * const argv[])
  43. {
  44. struct efi_capsule_header *capsule;
  45. int verbose = 0;
  46. char *endp;
  47. efi_status_t ret;
  48. if (argc != 2 && argc != 3)
  49. return CMD_RET_USAGE;
  50. if (argc == 3) {
  51. if (strcmp(argv[1], "-v"))
  52. return CMD_RET_USAGE;
  53. verbose = 1;
  54. argc--;
  55. argv++;
  56. }
  57. capsule = (typeof(capsule))hextoul(argv[1], &endp);
  58. if (endp == argv[1]) {
  59. printf("Invalid address: %s", argv[1]);
  60. return CMD_RET_FAILURE;
  61. }
  62. if (verbose) {
  63. printf("Capsule guid: %pUl\n", &capsule->capsule_guid);
  64. printf("Capsule flags: 0x%x\n", capsule->flags);
  65. printf("Capsule header size: 0x%x\n", capsule->header_size);
  66. printf("Capsule image size: 0x%x\n",
  67. capsule->capsule_image_size);
  68. }
  69. ret = EFI_CALL(RT->update_capsule(&capsule, 1, 0));
  70. if (ret) {
  71. printf("Cannot handle a capsule at %p", capsule);
  72. return CMD_RET_FAILURE;
  73. }
  74. return CMD_RET_SUCCESS;
  75. }
  76. static int do_efi_capsule_on_disk_update(struct cmd_tbl *cmdtp, int flag,
  77. int argc, char * const argv[])
  78. {
  79. efi_status_t ret;
  80. ret = efi_launch_capsules();
  81. return ret == EFI_SUCCESS ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
  82. }
  83. /**
  84. * do_efi_capsule_show() - show capsule information
  85. *
  86. * @cmdtp: Command table
  87. * @flag: Command flag
  88. * @argc: Number of arguments
  89. * @argv: Argument array
  90. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  91. *
  92. * Implement efidebug "capsule show" sub-command.
  93. * show capsule information.
  94. *
  95. * efidebug capsule show <capsule address>
  96. */
  97. static int do_efi_capsule_show(struct cmd_tbl *cmdtp, int flag,
  98. int argc, char * const argv[])
  99. {
  100. struct efi_capsule_header *capsule;
  101. char *endp;
  102. if (argc != 2)
  103. return CMD_RET_USAGE;
  104. capsule = (typeof(capsule))hextoul(argv[1], &endp);
  105. if (endp == argv[1]) {
  106. printf("Invalid address: %s", argv[1]);
  107. return CMD_RET_FAILURE;
  108. }
  109. printf("Capsule guid: %pUl\n", &capsule->capsule_guid);
  110. printf("Capsule flags: 0x%x\n", capsule->flags);
  111. printf("Capsule header size: 0x%x\n", capsule->header_size);
  112. printf("Capsule image size: 0x%x\n",
  113. capsule->capsule_image_size);
  114. return CMD_RET_SUCCESS;
  115. }
  116. #ifdef CONFIG_EFI_ESRT
  117. #define EFI_ESRT_FW_TYPE_NUM 4
  118. char *efi_fw_type_str[EFI_ESRT_FW_TYPE_NUM] = {"unknown", "system FW", "device FW",
  119. "UEFI driver"};
  120. #define EFI_ESRT_UPDATE_STATUS_NUM 9
  121. char *efi_update_status_str[EFI_ESRT_UPDATE_STATUS_NUM] = {"success", "unsuccessful",
  122. "insufficient resources", "incorrect version", "invalid format",
  123. "auth error", "power event (AC)", "power event (batt)",
  124. "unsatisfied dependencies"};
  125. #define EFI_FW_TYPE_STR_GET(idx) (\
  126. EFI_ESRT_FW_TYPE_NUM > (idx) ? efi_fw_type_str[(idx)] : "error"\
  127. )
  128. #define EFI_FW_STATUS_STR_GET(idx) (\
  129. EFI_ESRT_UPDATE_STATUS_NUM > (idx) ? efi_update_status_str[(idx)] : "error"\
  130. )
  131. /**
  132. * do_efi_capsule_esrt() - manage UEFI capsules
  133. *
  134. * @cmdtp: Command table
  135. * @flag: Command flag
  136. * @argc: Number of arguments
  137. * @argv: Argument array
  138. * Return: CMD_RET_SUCCESS on success,
  139. * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
  140. *
  141. * Implement efidebug "capsule esrt" sub-command.
  142. * The prints the current ESRT table.
  143. *
  144. * efidebug capsule esrt
  145. */
  146. static int do_efi_capsule_esrt(struct cmd_tbl *cmdtp, int flag,
  147. int argc, char * const argv[])
  148. {
  149. struct efi_system_resource_table *esrt = NULL;
  150. if (argc != 1)
  151. return CMD_RET_USAGE;
  152. for (int idx = 0; idx < systab.nr_tables; idx++)
  153. if (!guidcmp(&efi_esrt_guid, &systab.tables[idx].guid))
  154. esrt = (struct efi_system_resource_table *)systab.tables[idx].table;
  155. if (!esrt) {
  156. log_info("ESRT: table not present\n");
  157. return CMD_RET_SUCCESS;
  158. }
  159. printf("========================================\n");
  160. printf("ESRT: fw_resource_count=%d\n", esrt->fw_resource_count);
  161. printf("ESRT: fw_resource_count_max=%d\n", esrt->fw_resource_count_max);
  162. printf("ESRT: fw_resource_version=%lld\n", esrt->fw_resource_version);
  163. for (int idx = 0; idx < esrt->fw_resource_count; idx++) {
  164. printf("[entry %d]==============================\n", idx);
  165. printf("ESRT: fw_class=%pUL\n", &esrt->entries[idx].fw_class);
  166. printf("ESRT: fw_type=%s\n", EFI_FW_TYPE_STR_GET(esrt->entries[idx].fw_type));
  167. printf("ESRT: fw_version=%d\n", esrt->entries[idx].fw_version);
  168. printf("ESRT: lowest_supported_fw_version=%d\n",
  169. esrt->entries[idx].lowest_supported_fw_version);
  170. printf("ESRT: capsule_flags=%d\n",
  171. esrt->entries[idx].capsule_flags);
  172. printf("ESRT: last_attempt_version=%d\n",
  173. esrt->entries[idx].last_attempt_version);
  174. printf("ESRT: last_attempt_status=%s\n",
  175. EFI_FW_STATUS_STR_GET(esrt->entries[idx].last_attempt_status));
  176. }
  177. printf("========================================\n");
  178. return CMD_RET_SUCCESS;
  179. }
  180. #endif /* CONFIG_EFI_ESRT */
  181. /**
  182. * do_efi_capsule_res() - show a capsule update result
  183. *
  184. * @cmdtp: Command table
  185. * @flag: Command flag
  186. * @argc: Number of arguments
  187. * @argv: Argument array
  188. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  189. *
  190. * Implement efidebug "capsule result" sub-command.
  191. * show a capsule update result.
  192. * If result number is not specified, CapsuleLast will be shown.
  193. *
  194. * efidebug capsule result [<capsule result number>]
  195. */
  196. static int do_efi_capsule_res(struct cmd_tbl *cmdtp, int flag,
  197. int argc, char * const argv[])
  198. {
  199. int capsule_id;
  200. char *endp;
  201. u16 var_name16[12];
  202. efi_guid_t guid;
  203. struct efi_capsule_result_variable_header *result = NULL;
  204. efi_uintn_t size;
  205. efi_status_t ret;
  206. if (argc != 1 && argc != 2)
  207. return CMD_RET_USAGE;
  208. guid = efi_guid_capsule_report;
  209. if (argc == 1) {
  210. size = sizeof(var_name16);
  211. ret = efi_get_variable_int(u"CapsuleLast", &guid, NULL,
  212. &size, var_name16, NULL);
  213. if (ret != EFI_SUCCESS) {
  214. if (ret == EFI_NOT_FOUND)
  215. printf("CapsuleLast doesn't exist\n");
  216. else
  217. printf("Failed to get CapsuleLast\n");
  218. return CMD_RET_FAILURE;
  219. }
  220. printf("CapsuleLast is %ls\n", var_name16);
  221. } else {
  222. argc--;
  223. argv++;
  224. capsule_id = hextoul(argv[0], &endp);
  225. if (capsule_id < 0 || capsule_id > 0xffff)
  226. return CMD_RET_USAGE;
  227. efi_create_indexed_name(var_name16, sizeof(var_name16),
  228. "Capsule", capsule_id);
  229. }
  230. size = 0;
  231. ret = efi_get_variable_int(var_name16, &guid, NULL, &size, NULL, NULL);
  232. if (ret == EFI_BUFFER_TOO_SMALL) {
  233. result = malloc(size);
  234. if (!result)
  235. return CMD_RET_FAILURE;
  236. ret = efi_get_variable_int(var_name16, &guid, NULL, &size,
  237. result, NULL);
  238. }
  239. if (ret != EFI_SUCCESS) {
  240. free(result);
  241. printf("Failed to get %ls\n", var_name16);
  242. return CMD_RET_FAILURE;
  243. }
  244. printf("Result total size: 0x%x\n", result->variable_total_size);
  245. printf("Capsule guid: %pUl\n", &result->capsule_guid);
  246. printf("Time processed: %04d-%02d-%02d %02d:%02d:%02d\n",
  247. result->capsule_processed.year, result->capsule_processed.month,
  248. result->capsule_processed.day, result->capsule_processed.hour,
  249. result->capsule_processed.minute,
  250. result->capsule_processed.second);
  251. printf("Capsule status: 0x%lx\n", result->capsule_status);
  252. free(result);
  253. return CMD_RET_SUCCESS;
  254. }
  255. static struct cmd_tbl cmd_efidebug_capsule_sub[] = {
  256. U_BOOT_CMD_MKENT(update, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_update,
  257. "", ""),
  258. U_BOOT_CMD_MKENT(show, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_show,
  259. "", ""),
  260. #ifdef CONFIG_EFI_ESRT
  261. U_BOOT_CMD_MKENT(esrt, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_esrt,
  262. "", ""),
  263. #endif
  264. U_BOOT_CMD_MKENT(disk-update, 0, 0, do_efi_capsule_on_disk_update,
  265. "", ""),
  266. U_BOOT_CMD_MKENT(result, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_res,
  267. "", ""),
  268. };
  269. /**
  270. * do_efi_capsule() - manage UEFI capsules
  271. *
  272. * @cmdtp: Command table
  273. * @flag: Command flag
  274. * @argc: Number of arguments
  275. * @argv: Argument array
  276. * Return: CMD_RET_SUCCESS on success,
  277. * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
  278. *
  279. * Implement efidebug "capsule" sub-command.
  280. */
  281. static int do_efi_capsule(struct cmd_tbl *cmdtp, int flag,
  282. int argc, char * const argv[])
  283. {
  284. struct cmd_tbl *cp;
  285. if (argc < 2)
  286. return CMD_RET_USAGE;
  287. argc--; argv++;
  288. cp = find_cmd_tbl(argv[0], cmd_efidebug_capsule_sub,
  289. ARRAY_SIZE(cmd_efidebug_capsule_sub));
  290. if (!cp)
  291. return CMD_RET_USAGE;
  292. return cp->cmd(cmdtp, flag, argc, argv);
  293. }
  294. #endif /* CONFIG_EFI_HAVE_CAPSULE_SUPPORT */
  295. /**
  296. * efi_get_device_path_text() - get device path text
  297. *
  298. * Return the text representation of the device path of a handle.
  299. *
  300. * @handle: handle of UEFI device
  301. * Return:
  302. * Pointer to the device path text or NULL.
  303. * The caller is responsible for calling FreePool().
  304. */
  305. static u16 *efi_get_device_path_text(efi_handle_t handle)
  306. {
  307. struct efi_handler *handler;
  308. efi_status_t ret;
  309. ret = efi_search_protocol(handle, &efi_guid_device_path, &handler);
  310. if (ret == EFI_SUCCESS && handler->protocol_interface) {
  311. struct efi_device_path *dp = handler->protocol_interface;
  312. return efi_dp_str(dp);
  313. } else {
  314. return NULL;
  315. }
  316. }
  317. #define EFI_HANDLE_WIDTH ((int)sizeof(efi_handle_t) * 2)
  318. static const char spc[] = " ";
  319. static const char sep[] = "================";
  320. /**
  321. * do_efi_show_devices() - show UEFI devices
  322. *
  323. * @cmdtp: Command table
  324. * @flag: Command flag
  325. * @argc: Number of arguments
  326. * @argv: Argument array
  327. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  328. *
  329. * Implement efidebug "devices" sub-command.
  330. * Show all UEFI devices and their information.
  331. */
  332. static int do_efi_show_devices(struct cmd_tbl *cmdtp, int flag,
  333. int argc, char *const argv[])
  334. {
  335. efi_handle_t *handles;
  336. efi_uintn_t num, i;
  337. u16 *dev_path_text;
  338. efi_status_t ret;
  339. ret = EFI_CALL(efi_locate_handle_buffer(ALL_HANDLES, NULL, NULL,
  340. &num, &handles));
  341. if (ret != EFI_SUCCESS)
  342. return CMD_RET_FAILURE;
  343. if (!num)
  344. return CMD_RET_SUCCESS;
  345. printf("Device%.*s Device Path\n", EFI_HANDLE_WIDTH - 6, spc);
  346. printf("%.*s ====================\n", EFI_HANDLE_WIDTH, sep);
  347. for (i = 0; i < num; i++) {
  348. dev_path_text = efi_get_device_path_text(handles[i]);
  349. if (dev_path_text) {
  350. printf("%p %ls\n", handles[i], dev_path_text);
  351. efi_free_pool(dev_path_text);
  352. }
  353. }
  354. efi_free_pool(handles);
  355. return CMD_RET_SUCCESS;
  356. }
  357. /**
  358. * efi_get_driver_handle_info() - get information of UEFI driver
  359. *
  360. * @handle: Handle of UEFI device
  361. * @driver_name: Driver name
  362. * @image_path: Pointer to text of device path
  363. * Return: 0 on success, -1 on failure
  364. *
  365. * Currently return no useful information as all UEFI drivers are
  366. * built-in..
  367. */
  368. static int efi_get_driver_handle_info(efi_handle_t handle, u16 **driver_name,
  369. u16 **image_path)
  370. {
  371. struct efi_handler *handler;
  372. struct efi_loaded_image *image;
  373. efi_status_t ret;
  374. /*
  375. * driver name
  376. * TODO: support EFI_COMPONENT_NAME2_PROTOCOL
  377. */
  378. *driver_name = NULL;
  379. /* image name */
  380. ret = efi_search_protocol(handle, &efi_guid_loaded_image, &handler);
  381. if (ret != EFI_SUCCESS) {
  382. *image_path = NULL;
  383. return 0;
  384. }
  385. image = handler->protocol_interface;
  386. *image_path = efi_dp_str(image->file_path);
  387. return 0;
  388. }
  389. /**
  390. * do_efi_show_drivers() - show UEFI drivers
  391. *
  392. * @cmdtp: Command table
  393. * @flag: Command flag
  394. * @argc: Number of arguments
  395. * @argv: Argument array
  396. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  397. *
  398. * Implement efidebug "drivers" sub-command.
  399. * Show all UEFI drivers and their information.
  400. */
  401. static int do_efi_show_drivers(struct cmd_tbl *cmdtp, int flag,
  402. int argc, char *const argv[])
  403. {
  404. efi_handle_t *handles;
  405. efi_uintn_t num, i;
  406. u16 *driver_name, *image_path_text;
  407. efi_status_t ret;
  408. ret = EFI_CALL(efi_locate_handle_buffer(
  409. BY_PROTOCOL, &efi_guid_driver_binding_protocol,
  410. NULL, &num, &handles));
  411. if (ret != EFI_SUCCESS)
  412. return CMD_RET_FAILURE;
  413. if (!num)
  414. return CMD_RET_SUCCESS;
  415. printf("Driver%.*s Name Image Path\n",
  416. EFI_HANDLE_WIDTH - 6, spc);
  417. printf("%.*s ==================== ====================\n",
  418. EFI_HANDLE_WIDTH, sep);
  419. for (i = 0; i < num; i++) {
  420. if (!efi_get_driver_handle_info(handles[i], &driver_name,
  421. &image_path_text)) {
  422. if (image_path_text)
  423. printf("%p %-20ls %ls\n", handles[i],
  424. driver_name, image_path_text);
  425. else
  426. printf("%p %-20ls <built-in>\n",
  427. handles[i], driver_name);
  428. efi_free_pool(driver_name);
  429. efi_free_pool(image_path_text);
  430. }
  431. }
  432. efi_free_pool(handles);
  433. return CMD_RET_SUCCESS;
  434. }
  435. /**
  436. * do_efi_show_handles() - show UEFI handles
  437. *
  438. * @cmdtp: Command table
  439. * @flag: Command flag
  440. * @argc: Number of arguments
  441. * @argv: Argument array
  442. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  443. *
  444. * Implement efidebug "dh" sub-command.
  445. * Show all UEFI handles and their information, currently all protocols
  446. * added to handle.
  447. */
  448. static int do_efi_show_handles(struct cmd_tbl *cmdtp, int flag,
  449. int argc, char *const argv[])
  450. {
  451. efi_handle_t *handles;
  452. efi_guid_t **guid;
  453. efi_uintn_t num, count, i, j;
  454. efi_status_t ret;
  455. ret = EFI_CALL(efi_locate_handle_buffer(ALL_HANDLES, NULL, NULL,
  456. &num, &handles));
  457. if (ret != EFI_SUCCESS)
  458. return CMD_RET_FAILURE;
  459. if (!num)
  460. return CMD_RET_SUCCESS;
  461. printf("Handle%.*s Protocols\n", EFI_HANDLE_WIDTH - 6, spc);
  462. printf("%.*s ====================\n", EFI_HANDLE_WIDTH, sep);
  463. for (i = 0; i < num; i++) {
  464. printf("%p", handles[i]);
  465. ret = EFI_CALL(BS->protocols_per_handle(handles[i], &guid,
  466. &count));
  467. if (ret || !count) {
  468. putc('\n');
  469. continue;
  470. }
  471. for (j = 0; j < count; j++) {
  472. if (j)
  473. printf(", ");
  474. else
  475. putc(' ');
  476. printf("%pUs", guid[j]);
  477. }
  478. putc('\n');
  479. }
  480. efi_free_pool(handles);
  481. return CMD_RET_SUCCESS;
  482. }
  483. /**
  484. * do_efi_show_images() - show UEFI images
  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, CMD_RET_RET_FAILURE on failure
  491. *
  492. * Implement efidebug "images" sub-command.
  493. * Show all UEFI loaded images and their information.
  494. */
  495. static int do_efi_show_images(struct cmd_tbl *cmdtp, int flag,
  496. int argc, char *const argv[])
  497. {
  498. efi_print_image_infos(NULL);
  499. return CMD_RET_SUCCESS;
  500. }
  501. static const char * const efi_mem_type_string[] = {
  502. [EFI_RESERVED_MEMORY_TYPE] = "RESERVED",
  503. [EFI_LOADER_CODE] = "LOADER CODE",
  504. [EFI_LOADER_DATA] = "LOADER DATA",
  505. [EFI_BOOT_SERVICES_CODE] = "BOOT CODE",
  506. [EFI_BOOT_SERVICES_DATA] = "BOOT DATA",
  507. [EFI_RUNTIME_SERVICES_CODE] = "RUNTIME CODE",
  508. [EFI_RUNTIME_SERVICES_DATA] = "RUNTIME DATA",
  509. [EFI_CONVENTIONAL_MEMORY] = "CONVENTIONAL",
  510. [EFI_UNUSABLE_MEMORY] = "UNUSABLE MEM",
  511. [EFI_ACPI_RECLAIM_MEMORY] = "ACPI RECLAIM MEM",
  512. [EFI_ACPI_MEMORY_NVS] = "ACPI NVS",
  513. [EFI_MMAP_IO] = "IO",
  514. [EFI_MMAP_IO_PORT] = "IO PORT",
  515. [EFI_PAL_CODE] = "PAL",
  516. [EFI_PERSISTENT_MEMORY_TYPE] = "PERSISTENT",
  517. };
  518. static const struct efi_mem_attrs {
  519. const u64 bit;
  520. const char *text;
  521. } efi_mem_attrs[] = {
  522. {EFI_MEMORY_UC, "UC"},
  523. {EFI_MEMORY_UC, "UC"},
  524. {EFI_MEMORY_WC, "WC"},
  525. {EFI_MEMORY_WT, "WT"},
  526. {EFI_MEMORY_WB, "WB"},
  527. {EFI_MEMORY_UCE, "UCE"},
  528. {EFI_MEMORY_WP, "WP"},
  529. {EFI_MEMORY_RP, "RP"},
  530. {EFI_MEMORY_XP, "WP"},
  531. {EFI_MEMORY_NV, "NV"},
  532. {EFI_MEMORY_MORE_RELIABLE, "REL"},
  533. {EFI_MEMORY_RO, "RO"},
  534. {EFI_MEMORY_SP, "SP"},
  535. {EFI_MEMORY_RUNTIME, "RT"},
  536. };
  537. /**
  538. * print_memory_attributes() - print memory map attributes
  539. *
  540. * @attributes: Attribute value
  541. *
  542. * Print memory map attributes
  543. */
  544. static void print_memory_attributes(u64 attributes)
  545. {
  546. int sep, i;
  547. for (sep = 0, i = 0; i < ARRAY_SIZE(efi_mem_attrs); i++)
  548. if (attributes & efi_mem_attrs[i].bit) {
  549. if (sep) {
  550. putc('|');
  551. } else {
  552. putc(' ');
  553. sep = 1;
  554. }
  555. puts(efi_mem_attrs[i].text);
  556. }
  557. }
  558. #define EFI_PHYS_ADDR_WIDTH (int)(sizeof(efi_physical_addr_t) * 2)
  559. /**
  560. * do_efi_show_memmap() - show UEFI memory map
  561. *
  562. * @cmdtp: Command table
  563. * @flag: Command flag
  564. * @argc: Number of arguments
  565. * @argv: Argument array
  566. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  567. *
  568. * Implement efidebug "memmap" sub-command.
  569. * Show UEFI memory map.
  570. */
  571. static int do_efi_show_memmap(struct cmd_tbl *cmdtp, int flag,
  572. int argc, char *const argv[])
  573. {
  574. struct efi_mem_desc *memmap = NULL, *map;
  575. efi_uintn_t map_size = 0;
  576. const char *type;
  577. int i;
  578. efi_status_t ret;
  579. ret = efi_get_memory_map(&map_size, memmap, NULL, NULL, NULL);
  580. if (ret == EFI_BUFFER_TOO_SMALL) {
  581. map_size += sizeof(struct efi_mem_desc); /* for my own */
  582. ret = efi_allocate_pool(EFI_LOADER_DATA, map_size,
  583. (void *)&memmap);
  584. if (ret != EFI_SUCCESS)
  585. return CMD_RET_FAILURE;
  586. ret = efi_get_memory_map(&map_size, memmap, NULL, NULL, NULL);
  587. }
  588. if (ret != EFI_SUCCESS) {
  589. efi_free_pool(memmap);
  590. return CMD_RET_FAILURE;
  591. }
  592. printf("Type Start%.*s End%.*s Attributes\n",
  593. EFI_PHYS_ADDR_WIDTH - 5, spc, EFI_PHYS_ADDR_WIDTH - 3, spc);
  594. printf("================ %.*s %.*s ==========\n",
  595. EFI_PHYS_ADDR_WIDTH, sep, EFI_PHYS_ADDR_WIDTH, sep);
  596. /*
  597. * Coverity check: dereferencing null pointer "map."
  598. * This is a false positive as memmap will always be
  599. * populated by allocate_pool() above.
  600. */
  601. for (i = 0, map = memmap; i < map_size / sizeof(*map); map++, i++) {
  602. if (map->type < ARRAY_SIZE(efi_mem_type_string))
  603. type = efi_mem_type_string[map->type];
  604. else
  605. type = "(unknown)";
  606. printf("%-16s %.*llx-%.*llx", type,
  607. EFI_PHYS_ADDR_WIDTH,
  608. (u64)map_to_sysmem((void *)(uintptr_t)
  609. map->physical_start),
  610. EFI_PHYS_ADDR_WIDTH,
  611. (u64)map_to_sysmem((void *)(uintptr_t)
  612. (map->physical_start +
  613. map->num_pages * EFI_PAGE_SIZE)));
  614. print_memory_attributes(map->attribute);
  615. putc('\n');
  616. }
  617. efi_free_pool(memmap);
  618. return CMD_RET_SUCCESS;
  619. }
  620. /**
  621. * do_efi_show_tables() - show UEFI configuration tables
  622. *
  623. * @cmdtp: Command table
  624. * @flag: Command flag
  625. * @argc: Number of arguments
  626. * @argv: Argument array
  627. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  628. *
  629. * Implement efidebug "tables" sub-command.
  630. * Show UEFI configuration tables.
  631. */
  632. static int do_efi_show_tables(struct cmd_tbl *cmdtp, int flag,
  633. int argc, char *const argv[])
  634. {
  635. efi_uintn_t i;
  636. for (i = 0; i < systab.nr_tables; ++i)
  637. printf("%pUl (%pUs)\n",
  638. &systab.tables[i].guid, &systab.tables[i].guid);
  639. return CMD_RET_SUCCESS;
  640. }
  641. /**
  642. * create_initrd_dp() - Create a special device for our Boot### option
  643. *
  644. * @dev: Device
  645. * @part: Disk partition
  646. * @file: Filename
  647. * Return: Pointer to the device path or ERR_PTR
  648. *
  649. */
  650. static
  651. struct efi_device_path *create_initrd_dp(const char *dev, const char *part,
  652. const char *file)
  653. {
  654. struct efi_device_path *tmp_dp = NULL, *tmp_fp = NULL;
  655. struct efi_device_path *initrd_dp = NULL;
  656. efi_status_t ret;
  657. const struct efi_initrd_dp id_dp = {
  658. .vendor = {
  659. {
  660. DEVICE_PATH_TYPE_MEDIA_DEVICE,
  661. DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
  662. sizeof(id_dp.vendor),
  663. },
  664. EFI_INITRD_MEDIA_GUID,
  665. },
  666. .end = {
  667. DEVICE_PATH_TYPE_END,
  668. DEVICE_PATH_SUB_TYPE_END,
  669. sizeof(id_dp.end),
  670. }
  671. };
  672. ret = efi_dp_from_name(dev, part, file, &tmp_dp, &tmp_fp);
  673. if (ret != EFI_SUCCESS) {
  674. printf("Cannot create device path for \"%s %s\"\n", part, file);
  675. goto out;
  676. }
  677. initrd_dp = efi_dp_append((const struct efi_device_path *)&id_dp,
  678. tmp_fp);
  679. out:
  680. efi_free_pool(tmp_dp);
  681. efi_free_pool(tmp_fp);
  682. return initrd_dp;
  683. }
  684. /**
  685. * do_efi_boot_add() - set UEFI load option
  686. *
  687. * @cmdtp: Command table
  688. * @flag: Command flag
  689. * @argc: Number of arguments
  690. * @argv: Argument array
  691. * Return: CMD_RET_SUCCESS on success,
  692. * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
  693. *
  694. * Implement efidebug "boot add" sub-command. Create or change UEFI load option.
  695. *
  696. * efidebug boot add -b <id> <label> <interface> <devnum>[:<part>] <file>
  697. * -i <file> <interface2> <devnum2>[:<part>] <initrd>
  698. * -s '<options>'
  699. */
  700. static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag,
  701. int argc, char *const argv[])
  702. {
  703. int id;
  704. char *endp;
  705. u16 var_name16[9];
  706. efi_guid_t guid;
  707. size_t label_len, label_len16;
  708. u16 *label;
  709. struct efi_device_path *device_path = NULL, *file_path = NULL;
  710. struct efi_device_path *final_fp = NULL;
  711. struct efi_device_path *initrd_dp = NULL;
  712. struct efi_load_option lo;
  713. void *data = NULL;
  714. efi_uintn_t size;
  715. efi_uintn_t fp_size = 0;
  716. efi_status_t ret;
  717. int r = CMD_RET_SUCCESS;
  718. guid = efi_global_variable_guid;
  719. /* attributes */
  720. lo.attributes = LOAD_OPTION_ACTIVE; /* always ACTIVE */
  721. lo.optional_data = NULL;
  722. lo.label = NULL;
  723. argc--;
  724. argv++; /* 'add' */
  725. for (; argc > 0; argc--, argv++) {
  726. if (!strcmp(argv[0], "-b")) {
  727. if (argc < 5 || lo.label) {
  728. r = CMD_RET_USAGE;
  729. goto out;
  730. }
  731. id = (int)hextoul(argv[1], &endp);
  732. if (*endp != '\0' || id > 0xffff)
  733. return CMD_RET_USAGE;
  734. efi_create_indexed_name(var_name16, sizeof(var_name16),
  735. "Boot", id);
  736. /* label */
  737. label_len = strlen(argv[2]);
  738. label_len16 = utf8_utf16_strnlen(argv[2], label_len);
  739. label = malloc((label_len16 + 1) * sizeof(u16));
  740. if (!label)
  741. return CMD_RET_FAILURE;
  742. lo.label = label; /* label will be changed below */
  743. utf8_utf16_strncpy(&label, argv[2], label_len);
  744. /* file path */
  745. ret = efi_dp_from_name(argv[3], argv[4], argv[5],
  746. &device_path, &file_path);
  747. if (ret != EFI_SUCCESS) {
  748. printf("Cannot create device path for \"%s %s\"\n",
  749. argv[3], argv[4]);
  750. r = CMD_RET_FAILURE;
  751. goto out;
  752. }
  753. fp_size += efi_dp_size(file_path) +
  754. sizeof(struct efi_device_path);
  755. argc -= 5;
  756. argv += 5;
  757. } else if (!strcmp(argv[0], "-i")) {
  758. if (argc < 3 || initrd_dp) {
  759. r = CMD_RET_USAGE;
  760. goto out;
  761. }
  762. initrd_dp = create_initrd_dp(argv[1], argv[2], argv[3]);
  763. if (!initrd_dp) {
  764. printf("Cannot add an initrd\n");
  765. r = CMD_RET_FAILURE;
  766. goto out;
  767. }
  768. argc -= 3;
  769. argv += 3;
  770. fp_size += efi_dp_size(initrd_dp) +
  771. sizeof(struct efi_device_path);
  772. } else if (!strcmp(argv[0], "-s")) {
  773. if (argc < 1 || lo.optional_data) {
  774. r = CMD_RET_USAGE;
  775. goto out;
  776. }
  777. lo.optional_data = (const u8 *)argv[1];
  778. argc -= 1;
  779. argv += 1;
  780. } else {
  781. r = CMD_RET_USAGE;
  782. goto out;
  783. }
  784. }
  785. if (!file_path) {
  786. printf("Missing binary\n");
  787. r = CMD_RET_USAGE;
  788. goto out;
  789. }
  790. final_fp = efi_dp_concat(file_path, initrd_dp);
  791. if (!final_fp) {
  792. printf("Cannot create final device path\n");
  793. r = CMD_RET_FAILURE;
  794. goto out;
  795. }
  796. lo.file_path = final_fp;
  797. lo.file_path_length = fp_size;
  798. size = efi_serialize_load_option(&lo, (u8 **)&data);
  799. if (!size) {
  800. r = CMD_RET_FAILURE;
  801. goto out;
  802. }
  803. ret = efi_set_variable_int(var_name16, &guid,
  804. EFI_VARIABLE_NON_VOLATILE |
  805. EFI_VARIABLE_BOOTSERVICE_ACCESS |
  806. EFI_VARIABLE_RUNTIME_ACCESS,
  807. size, data, false);
  808. if (ret != EFI_SUCCESS) {
  809. printf("Cannot set %ls\n", var_name16);
  810. r = CMD_RET_FAILURE;
  811. }
  812. out:
  813. free(data);
  814. efi_free_pool(final_fp);
  815. efi_free_pool(initrd_dp);
  816. efi_free_pool(device_path);
  817. efi_free_pool(file_path);
  818. free(lo.label);
  819. return r;
  820. }
  821. /**
  822. * do_efi_boot_rm() - delete UEFI load options
  823. *
  824. * @cmdtp: Command table
  825. * @flag: Command flag
  826. * @argc: Number of arguments
  827. * @argv: Argument array
  828. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  829. *
  830. * Implement efidebug "boot rm" sub-command.
  831. * Delete UEFI load options.
  832. *
  833. * efidebug boot rm <id> ...
  834. */
  835. static int do_efi_boot_rm(struct cmd_tbl *cmdtp, int flag,
  836. int argc, char *const argv[])
  837. {
  838. efi_guid_t guid;
  839. int id, i;
  840. char *endp;
  841. u16 var_name16[9];
  842. efi_status_t ret;
  843. if (argc == 1)
  844. return CMD_RET_USAGE;
  845. guid = efi_global_variable_guid;
  846. for (i = 1; i < argc; i++, argv++) {
  847. id = (int)hextoul(argv[1], &endp);
  848. if (*endp != '\0' || id > 0xffff)
  849. return CMD_RET_FAILURE;
  850. efi_create_indexed_name(var_name16, sizeof(var_name16),
  851. "Boot", id);
  852. ret = efi_set_variable_int(var_name16, &guid, 0, 0, NULL,
  853. false);
  854. if (ret) {
  855. printf("Cannot remove %ls\n", var_name16);
  856. return CMD_RET_FAILURE;
  857. }
  858. }
  859. return CMD_RET_SUCCESS;
  860. }
  861. /**
  862. * show_efi_boot_opt_data() - dump UEFI load option
  863. *
  864. * @varname16: variable name
  865. * @data: value of UEFI load option variable
  866. * @size: size of the boot option
  867. *
  868. * Decode the value of UEFI load option variable and print information.
  869. */
  870. static void show_efi_boot_opt_data(u16 *varname16, void *data, size_t *size)
  871. {
  872. struct efi_device_path *initrd_path = NULL;
  873. struct efi_load_option lo;
  874. efi_status_t ret;
  875. ret = efi_deserialize_load_option(&lo, data, size);
  876. if (ret != EFI_SUCCESS) {
  877. printf("%ls: invalid load option\n", varname16);
  878. return;
  879. }
  880. printf("%ls:\nattributes: %c%c%c (0x%08x)\n",
  881. varname16,
  882. /* ACTIVE */
  883. lo.attributes & LOAD_OPTION_ACTIVE ? 'A' : '-',
  884. /* FORCE RECONNECT */
  885. lo.attributes & LOAD_OPTION_FORCE_RECONNECT ? 'R' : '-',
  886. /* HIDDEN */
  887. lo.attributes & LOAD_OPTION_HIDDEN ? 'H' : '-',
  888. lo.attributes);
  889. printf(" label: %ls\n", lo.label);
  890. printf(" file_path: %pD\n", lo.file_path);
  891. initrd_path = efi_dp_from_lo(&lo, &efi_lf2_initrd_guid);
  892. if (initrd_path) {
  893. printf(" initrd_path: %pD\n", initrd_path);
  894. efi_free_pool(initrd_path);
  895. }
  896. printf(" data:\n");
  897. print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1,
  898. lo.optional_data, *size, true);
  899. }
  900. /**
  901. * show_efi_boot_opt() - dump UEFI load option
  902. *
  903. * @varname16: variable name
  904. *
  905. * Dump information defined by UEFI load option.
  906. */
  907. static void show_efi_boot_opt(u16 *varname16)
  908. {
  909. void *data;
  910. efi_uintn_t size;
  911. efi_status_t ret;
  912. size = 0;
  913. ret = EFI_CALL(efi_get_variable(varname16, &efi_global_variable_guid,
  914. NULL, &size, NULL));
  915. if (ret == EFI_BUFFER_TOO_SMALL) {
  916. data = malloc(size);
  917. if (!data) {
  918. printf("ERROR: Out of memory\n");
  919. return;
  920. }
  921. ret = EFI_CALL(efi_get_variable(varname16,
  922. &efi_global_variable_guid,
  923. NULL, &size, data));
  924. if (ret == EFI_SUCCESS)
  925. show_efi_boot_opt_data(varname16, data, &size);
  926. free(data);
  927. }
  928. }
  929. static int u16_tohex(u16 c)
  930. {
  931. if (c >= '0' && c <= '9')
  932. return c - '0';
  933. if (c >= 'A' && c <= 'F')
  934. return c - 'A' + 10;
  935. /* not hexadecimal */
  936. return -1;
  937. }
  938. /**
  939. * show_efi_boot_dump() - dump all UEFI load options
  940. *
  941. * @cmdtp: Command table
  942. * @flag: Command flag
  943. * @argc: Number of arguments
  944. * @argv: Argument array
  945. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  946. *
  947. * Implement efidebug "boot dump" sub-command.
  948. * Dump information of all UEFI load options defined.
  949. *
  950. * efidebug boot dump
  951. */
  952. static int do_efi_boot_dump(struct cmd_tbl *cmdtp, int flag,
  953. int argc, char *const argv[])
  954. {
  955. u16 *var_name16, *p;
  956. efi_uintn_t buf_size, size;
  957. efi_guid_t guid;
  958. int id, i, digit;
  959. efi_status_t ret;
  960. if (argc > 1)
  961. return CMD_RET_USAGE;
  962. buf_size = 128;
  963. var_name16 = malloc(buf_size);
  964. if (!var_name16)
  965. return CMD_RET_FAILURE;
  966. var_name16[0] = 0;
  967. for (;;) {
  968. size = buf_size;
  969. ret = EFI_CALL(efi_get_next_variable_name(&size, var_name16,
  970. &guid));
  971. if (ret == EFI_NOT_FOUND)
  972. break;
  973. if (ret == EFI_BUFFER_TOO_SMALL) {
  974. buf_size = size;
  975. p = realloc(var_name16, buf_size);
  976. if (!p) {
  977. free(var_name16);
  978. return CMD_RET_FAILURE;
  979. }
  980. var_name16 = p;
  981. ret = EFI_CALL(efi_get_next_variable_name(&size,
  982. var_name16,
  983. &guid));
  984. }
  985. if (ret != EFI_SUCCESS) {
  986. free(var_name16);
  987. return CMD_RET_FAILURE;
  988. }
  989. if (memcmp(var_name16, u"Boot", 8))
  990. continue;
  991. for (id = 0, i = 0; i < 4; i++) {
  992. digit = u16_tohex(var_name16[4 + i]);
  993. if (digit < 0)
  994. break;
  995. id = (id << 4) + digit;
  996. }
  997. if (i == 4 && !var_name16[8])
  998. show_efi_boot_opt(var_name16);
  999. }
  1000. free(var_name16);
  1001. return CMD_RET_SUCCESS;
  1002. }
  1003. /**
  1004. * show_efi_boot_order() - show order of UEFI load options
  1005. *
  1006. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  1007. *
  1008. * Show order of UEFI load options defined by BootOrder variable.
  1009. */
  1010. static int show_efi_boot_order(void)
  1011. {
  1012. u16 *bootorder;
  1013. efi_uintn_t size;
  1014. int num, i;
  1015. u16 var_name16[9];
  1016. void *data;
  1017. struct efi_load_option lo;
  1018. efi_status_t ret;
  1019. size = 0;
  1020. ret = EFI_CALL(efi_get_variable(u"BootOrder", &efi_global_variable_guid,
  1021. NULL, &size, NULL));
  1022. if (ret != EFI_BUFFER_TOO_SMALL) {
  1023. if (ret == EFI_NOT_FOUND) {
  1024. printf("BootOrder not defined\n");
  1025. return CMD_RET_SUCCESS;
  1026. } else {
  1027. return CMD_RET_FAILURE;
  1028. }
  1029. }
  1030. bootorder = malloc(size);
  1031. if (!bootorder) {
  1032. printf("ERROR: Out of memory\n");
  1033. return CMD_RET_FAILURE;
  1034. }
  1035. ret = EFI_CALL(efi_get_variable(u"BootOrder", &efi_global_variable_guid,
  1036. NULL, &size, bootorder));
  1037. if (ret != EFI_SUCCESS) {
  1038. ret = CMD_RET_FAILURE;
  1039. goto out;
  1040. }
  1041. num = size / sizeof(u16);
  1042. for (i = 0; i < num; i++) {
  1043. efi_create_indexed_name(var_name16, sizeof(var_name16),
  1044. "Boot", bootorder[i]);
  1045. size = 0;
  1046. ret = EFI_CALL(efi_get_variable(var_name16,
  1047. &efi_global_variable_guid, NULL,
  1048. &size, NULL));
  1049. if (ret != EFI_BUFFER_TOO_SMALL) {
  1050. printf("%2d: %ls: (not defined)\n", i + 1, var_name16);
  1051. continue;
  1052. }
  1053. data = malloc(size);
  1054. if (!data) {
  1055. ret = CMD_RET_FAILURE;
  1056. goto out;
  1057. }
  1058. ret = EFI_CALL(efi_get_variable(var_name16,
  1059. &efi_global_variable_guid, NULL,
  1060. &size, data));
  1061. if (ret != EFI_SUCCESS) {
  1062. free(data);
  1063. ret = CMD_RET_FAILURE;
  1064. goto out;
  1065. }
  1066. ret = efi_deserialize_load_option(&lo, data, &size);
  1067. if (ret != EFI_SUCCESS) {
  1068. printf("%ls: invalid load option\n", var_name16);
  1069. ret = CMD_RET_FAILURE;
  1070. goto out;
  1071. }
  1072. printf("%2d: %ls: %ls\n", i + 1, var_name16, lo.label);
  1073. free(data);
  1074. }
  1075. out:
  1076. free(bootorder);
  1077. return ret;
  1078. }
  1079. /**
  1080. * do_efi_boot_next() - manage UEFI BootNext variable
  1081. *
  1082. * @cmdtp: Command table
  1083. * @flag: Command flag
  1084. * @argc: Number of arguments
  1085. * @argv: Argument array
  1086. * Return: CMD_RET_SUCCESS on success,
  1087. * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
  1088. *
  1089. * Implement efidebug "boot next" sub-command.
  1090. * Set BootNext variable.
  1091. *
  1092. * efidebug boot next <id>
  1093. */
  1094. static int do_efi_boot_next(struct cmd_tbl *cmdtp, int flag,
  1095. int argc, char *const argv[])
  1096. {
  1097. u16 bootnext;
  1098. efi_uintn_t size;
  1099. char *endp;
  1100. efi_guid_t guid;
  1101. efi_status_t ret;
  1102. int r = CMD_RET_SUCCESS;
  1103. if (argc != 2)
  1104. return CMD_RET_USAGE;
  1105. bootnext = (u16)hextoul(argv[1], &endp);
  1106. if (*endp) {
  1107. printf("invalid value: %s\n", argv[1]);
  1108. r = CMD_RET_FAILURE;
  1109. goto out;
  1110. }
  1111. guid = efi_global_variable_guid;
  1112. size = sizeof(u16);
  1113. ret = efi_set_variable_int(u"BootNext", &guid,
  1114. EFI_VARIABLE_NON_VOLATILE |
  1115. EFI_VARIABLE_BOOTSERVICE_ACCESS |
  1116. EFI_VARIABLE_RUNTIME_ACCESS,
  1117. size, &bootnext, false);
  1118. if (ret != EFI_SUCCESS) {
  1119. printf("Cannot set BootNext\n");
  1120. r = CMD_RET_FAILURE;
  1121. }
  1122. out:
  1123. return r;
  1124. }
  1125. /**
  1126. * do_efi_boot_order() - manage UEFI BootOrder variable
  1127. *
  1128. * @cmdtp: Command table
  1129. * @flag: Command flag
  1130. * @argc: Number of arguments
  1131. * @argv: Argument array
  1132. * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
  1133. *
  1134. * Implement efidebug "boot order" sub-command.
  1135. * Show order of UEFI load options, or change it in BootOrder variable.
  1136. *
  1137. * efidebug boot order [<id> ...]
  1138. */
  1139. static int do_efi_boot_order(struct cmd_tbl *cmdtp, int flag,
  1140. int argc, char *const argv[])
  1141. {
  1142. u16 *bootorder = NULL;
  1143. efi_uintn_t size;
  1144. int id, i;
  1145. char *endp;
  1146. efi_guid_t guid;
  1147. efi_status_t ret;
  1148. int r = CMD_RET_SUCCESS;
  1149. if (argc == 1)
  1150. return show_efi_boot_order();
  1151. argc--;
  1152. argv++;
  1153. size = argc * sizeof(u16);
  1154. bootorder = malloc(size);
  1155. if (!bootorder)
  1156. return CMD_RET_FAILURE;
  1157. for (i = 0; i < argc; i++) {
  1158. id = (int)hextoul(argv[i], &endp);
  1159. if (*endp != '\0' || id > 0xffff) {
  1160. printf("invalid value: %s\n", argv[i]);
  1161. r = CMD_RET_FAILURE;
  1162. goto out;
  1163. }
  1164. bootorder[i] = (u16)id;
  1165. }
  1166. guid = efi_global_variable_guid;
  1167. ret = efi_set_variable_int(u"BootOrder", &guid,
  1168. EFI_VARIABLE_NON_VOLATILE |
  1169. EFI_VARIABLE_BOOTSERVICE_ACCESS |
  1170. EFI_VARIABLE_RUNTIME_ACCESS,
  1171. size, bootorder, true);
  1172. if (ret != EFI_SUCCESS) {
  1173. printf("Cannot set BootOrder\n");
  1174. r = CMD_RET_FAILURE;
  1175. }
  1176. out:
  1177. free(bootorder);
  1178. return r;
  1179. }
  1180. static struct cmd_tbl cmd_efidebug_boot_sub[] = {
  1181. U_BOOT_CMD_MKENT(add, CONFIG_SYS_MAXARGS, 1, do_efi_boot_add, "", ""),
  1182. U_BOOT_CMD_MKENT(rm, CONFIG_SYS_MAXARGS, 1, do_efi_boot_rm, "", ""),
  1183. U_BOOT_CMD_MKENT(dump, CONFIG_SYS_MAXARGS, 1, do_efi_boot_dump, "", ""),
  1184. U_BOOT_CMD_MKENT(next, CONFIG_SYS_MAXARGS, 1, do_efi_boot_next, "", ""),
  1185. U_BOOT_CMD_MKENT(order, CONFIG_SYS_MAXARGS, 1, do_efi_boot_order,
  1186. "", ""),
  1187. };
  1188. /**
  1189. * do_efi_boot_opt() - manage UEFI load options
  1190. *
  1191. * @cmdtp: Command table
  1192. * @flag: Command flag
  1193. * @argc: Number of arguments
  1194. * @argv: Argument array
  1195. * Return: CMD_RET_SUCCESS on success,
  1196. * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
  1197. *
  1198. * Implement efidebug "boot" sub-command.
  1199. */
  1200. static int do_efi_boot_opt(struct cmd_tbl *cmdtp, int flag,
  1201. int argc, char *const argv[])
  1202. {
  1203. struct cmd_tbl *cp;
  1204. if (argc < 2)
  1205. return CMD_RET_USAGE;
  1206. argc--; argv++;
  1207. cp = find_cmd_tbl(argv[0], cmd_efidebug_boot_sub,
  1208. ARRAY_SIZE(cmd_efidebug_boot_sub));
  1209. if (!cp)
  1210. return CMD_RET_USAGE;
  1211. return cp->cmd(cmdtp, flag, argc, argv);
  1212. }
  1213. /**
  1214. * do_efi_test_bootmgr() - run simple bootmgr for test
  1215. *
  1216. * @cmdtp: Command table
  1217. * @flag: Command flag
  1218. * @argc: Number of arguments
  1219. * @argv: Argument array
  1220. * Return: CMD_RET_SUCCESS on success,
  1221. * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
  1222. *
  1223. * Implement efidebug "test bootmgr" sub-command.
  1224. * Run simple bootmgr for test.
  1225. *
  1226. * efidebug test bootmgr
  1227. */
  1228. static __maybe_unused int do_efi_test_bootmgr(struct cmd_tbl *cmdtp, int flag,
  1229. int argc, char * const argv[])
  1230. {
  1231. efi_handle_t image;
  1232. efi_uintn_t exit_data_size = 0;
  1233. u16 *exit_data = NULL;
  1234. efi_status_t ret;
  1235. void *load_options = NULL;
  1236. ret = efi_bootmgr_load(&image, &load_options);
  1237. printf("efi_bootmgr_load() returned: %ld\n", ret & ~EFI_ERROR_MASK);
  1238. /* We call efi_start_image() even if error for test purpose. */
  1239. ret = EFI_CALL(efi_start_image(image, &exit_data_size, &exit_data));
  1240. printf("efi_start_image() returned: %ld\n", ret & ~EFI_ERROR_MASK);
  1241. if (ret && exit_data)
  1242. efi_free_pool(exit_data);
  1243. efi_restore_gd();
  1244. free(load_options);
  1245. return CMD_RET_SUCCESS;
  1246. }
  1247. static struct cmd_tbl cmd_efidebug_test_sub[] = {
  1248. #ifdef CONFIG_CMD_BOOTEFI_BOOTMGR
  1249. U_BOOT_CMD_MKENT(bootmgr, CONFIG_SYS_MAXARGS, 1, do_efi_test_bootmgr,
  1250. "", ""),
  1251. #endif
  1252. };
  1253. /**
  1254. * do_efi_test() - manage UEFI load options
  1255. *
  1256. * @cmdtp: Command table
  1257. * @flag: Command flag
  1258. * @argc: Number of arguments
  1259. * @argv: Argument array
  1260. * Return: CMD_RET_SUCCESS on success,
  1261. * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
  1262. *
  1263. * Implement efidebug "test" sub-command.
  1264. */
  1265. static int do_efi_test(struct cmd_tbl *cmdtp, int flag,
  1266. int argc, char * const argv[])
  1267. {
  1268. struct cmd_tbl *cp;
  1269. if (argc < 2)
  1270. return CMD_RET_USAGE;
  1271. argc--; argv++;
  1272. cp = find_cmd_tbl(argv[0], cmd_efidebug_test_sub,
  1273. ARRAY_SIZE(cmd_efidebug_test_sub));
  1274. if (!cp)
  1275. return CMD_RET_USAGE;
  1276. return cp->cmd(cmdtp, flag, argc, argv);
  1277. }
  1278. /**
  1279. * do_efi_query_info() - QueryVariableInfo EFI service
  1280. *
  1281. * @cmdtp: Command table
  1282. * @flag: Command flag
  1283. * @argc: Number of arguments
  1284. * @argv: Argument array
  1285. * Return: CMD_RET_SUCCESS on success,
  1286. * CMD_RET_USAGE or CMD_RET_FAILURE on failure
  1287. *
  1288. * Implement efidebug "test" sub-command.
  1289. */
  1290. static int do_efi_query_info(struct cmd_tbl *cmdtp, int flag,
  1291. int argc, char * const argv[])
  1292. {
  1293. efi_status_t ret;
  1294. u32 attr = 0;
  1295. u64 max_variable_storage_size;
  1296. u64 remain_variable_storage_size;
  1297. u64 max_variable_size;
  1298. int i;
  1299. for (i = 1; i < argc; i++) {
  1300. if (!strcmp(argv[i], "-bs"))
  1301. attr |= EFI_VARIABLE_BOOTSERVICE_ACCESS;
  1302. else if (!strcmp(argv[i], "-rt"))
  1303. attr |= EFI_VARIABLE_RUNTIME_ACCESS;
  1304. else if (!strcmp(argv[i], "-nv"))
  1305. attr |= EFI_VARIABLE_NON_VOLATILE;
  1306. else if (!strcmp(argv[i], "-at"))
  1307. attr |=
  1308. EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
  1309. }
  1310. ret = EFI_CALL(efi_query_variable_info(attr,
  1311. &max_variable_storage_size,
  1312. &remain_variable_storage_size,
  1313. &max_variable_size));
  1314. if (ret != EFI_SUCCESS) {
  1315. printf("Error: Cannot query UEFI variables, r = %lu\n",
  1316. ret & ~EFI_ERROR_MASK);
  1317. return CMD_RET_FAILURE;
  1318. }
  1319. printf("Max storage size %llu\n", max_variable_storage_size);
  1320. printf("Remaining storage size %llu\n", remain_variable_storage_size);
  1321. printf("Max variable size %llu\n", max_variable_size);
  1322. return CMD_RET_SUCCESS;
  1323. }
  1324. static struct cmd_tbl cmd_efidebug_sub[] = {
  1325. U_BOOT_CMD_MKENT(boot, CONFIG_SYS_MAXARGS, 1, do_efi_boot_opt, "", ""),
  1326. #ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT
  1327. U_BOOT_CMD_MKENT(capsule, CONFIG_SYS_MAXARGS, 1, do_efi_capsule,
  1328. "", ""),
  1329. #endif
  1330. U_BOOT_CMD_MKENT(devices, CONFIG_SYS_MAXARGS, 1, do_efi_show_devices,
  1331. "", ""),
  1332. U_BOOT_CMD_MKENT(drivers, CONFIG_SYS_MAXARGS, 1, do_efi_show_drivers,
  1333. "", ""),
  1334. U_BOOT_CMD_MKENT(dh, CONFIG_SYS_MAXARGS, 1, do_efi_show_handles,
  1335. "", ""),
  1336. U_BOOT_CMD_MKENT(images, CONFIG_SYS_MAXARGS, 1, do_efi_show_images,
  1337. "", ""),
  1338. U_BOOT_CMD_MKENT(memmap, CONFIG_SYS_MAXARGS, 1, do_efi_show_memmap,
  1339. "", ""),
  1340. U_BOOT_CMD_MKENT(tables, CONFIG_SYS_MAXARGS, 1, do_efi_show_tables,
  1341. "", ""),
  1342. U_BOOT_CMD_MKENT(test, CONFIG_SYS_MAXARGS, 1, do_efi_test,
  1343. "", ""),
  1344. U_BOOT_CMD_MKENT(query, CONFIG_SYS_MAXARGS, 1, do_efi_query_info,
  1345. "", ""),
  1346. };
  1347. /**
  1348. * do_efidebug() - display and configure UEFI environment
  1349. *
  1350. * @cmdtp: Command table
  1351. * @flag: Command flag
  1352. * @argc: Number of arguments
  1353. * @argv: Argument array
  1354. * Return: CMD_RET_SUCCESS on success,
  1355. * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
  1356. *
  1357. * Implement efidebug command which allows us to display and
  1358. * configure UEFI environment.
  1359. */
  1360. static int do_efidebug(struct cmd_tbl *cmdtp, int flag,
  1361. int argc, char *const argv[])
  1362. {
  1363. struct cmd_tbl *cp;
  1364. efi_status_t r;
  1365. if (argc < 2)
  1366. return CMD_RET_USAGE;
  1367. argc--; argv++;
  1368. /* Initialize UEFI drivers */
  1369. r = efi_init_obj_list();
  1370. if (r != EFI_SUCCESS) {
  1371. printf("Error: Cannot initialize UEFI sub-system, r = %lu\n",
  1372. r & ~EFI_ERROR_MASK);
  1373. return CMD_RET_FAILURE;
  1374. }
  1375. cp = find_cmd_tbl(argv[0], cmd_efidebug_sub,
  1376. ARRAY_SIZE(cmd_efidebug_sub));
  1377. if (!cp)
  1378. return CMD_RET_USAGE;
  1379. return cp->cmd(cmdtp, flag, argc, argv);
  1380. }
  1381. #ifdef CONFIG_SYS_LONGHELP
  1382. static char efidebug_help_text[] =
  1383. " - UEFI Shell-like interface to configure UEFI environment\n"
  1384. "\n"
  1385. "efidebug boot add "
  1386. "-b <bootid> <label> <interface> <devnum>[:<part>] <file path> "
  1387. "-i <interface> <devnum>[:<part>] <initrd file path> "
  1388. "-s '<optional data>'\n"
  1389. " - set UEFI BootXXXX variable\n"
  1390. " <load options> will be passed to UEFI application\n"
  1391. "efidebug boot rm <bootid#1> [<bootid#2> [<bootid#3> [...]]]\n"
  1392. " - delete UEFI BootXXXX variables\n"
  1393. "efidebug boot dump\n"
  1394. " - dump all UEFI BootXXXX variables\n"
  1395. "efidebug boot next <bootid>\n"
  1396. " - set UEFI BootNext variable\n"
  1397. "efidebug boot order [<bootid#1> [<bootid#2> [<bootid#3> [...]]]]\n"
  1398. " - set/show UEFI boot order\n"
  1399. "\n"
  1400. #ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT
  1401. "efidebug capsule update [-v] <capsule address>\n"
  1402. " - process a capsule\n"
  1403. "efidebug capsule disk-update\n"
  1404. " - update a capsule from disk\n"
  1405. "efidebug capsule show <capsule address>\n"
  1406. " - show capsule information\n"
  1407. "efidebug capsule result [<capsule result var>]\n"
  1408. " - show a capsule update result\n"
  1409. #ifdef CONFIG_EFI_ESRT
  1410. "efidebug capsule esrt\n"
  1411. " - print the ESRT\n"
  1412. #endif
  1413. "\n"
  1414. #endif
  1415. "efidebug devices\n"
  1416. " - show UEFI devices\n"
  1417. "efidebug drivers\n"
  1418. " - show UEFI drivers\n"
  1419. "efidebug dh\n"
  1420. " - show UEFI handles\n"
  1421. "efidebug images\n"
  1422. " - show loaded images\n"
  1423. "efidebug memmap\n"
  1424. " - show UEFI memory map\n"
  1425. "efidebug tables\n"
  1426. " - show UEFI configuration tables\n"
  1427. #ifdef CONFIG_CMD_BOOTEFI_BOOTMGR
  1428. "efidebug test bootmgr\n"
  1429. " - run simple bootmgr for test\n"
  1430. #endif
  1431. "efidebug query [-nv][-bs][-rt][-at]\n"
  1432. " - show size of UEFI variables store\n";
  1433. #endif
  1434. U_BOOT_CMD(
  1435. efidebug, CONFIG_SYS_MAXARGS, 0, do_efidebug,
  1436. "Configure UEFI environment",
  1437. efidebug_help_text
  1438. );