efidebug.c 38 KB

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