1 // SPDX-License-Identifier: GPL-2.0+
3 * Menu-driven UEFI Variable maintenance
5 * Copyright (c) 2022 Masahisa Kojima, Linaro Limited
12 #include <efi_loader.h>
13 #include <efi_load_initrd.h>
14 #include <efi_config.h>
15 #include <efi_variable.h>
21 #include <asm/unaligned.h>
22 #include <linux/delay.h>
24 static struct efi_simple_text_input_protocol *cin;
25 const char *eficonfig_menu_desc =
26 " Press UP/DOWN to move, ENTER to select, ESC to quit";
28 static const char *eficonfig_change_boot_order_desc =
29 " Press UP/DOWN to move, +/- to change orde\n"
30 " Press SPACE to activate or deactivate the entry\n"
31 " CTRL+S to save, ESC to quit";
33 static struct efi_simple_text_output_protocol *cout;
36 #define EFICONFIG_DESCRIPTION_MAX 32
37 #define EFICONFIG_OPTIONAL_DATA_MAX 64
38 #define EFICONFIG_MENU_HEADER_ROW_NUM 3
39 #define EFICONFIG_MENU_DESC_ROW_NUM 5
42 * struct eficonfig_filepath_info - structure to be used to store file path
44 * @name: file or directory name
45 * @list: list structure
47 struct eficonfig_filepath_info {
49 struct list_head list;
53 * struct eficonfig_boot_option - structure to be used for updating UEFI boot option
55 * @file_info: user selected file info
56 * @initrd_info: user selected initrd file info
57 * @boot_index: index of the boot option
58 * @description: pointer to the description string
59 * @optional_data: pointer to the optional_data
60 * @edit_completed: flag indicates edit complete
62 struct eficonfig_boot_option {
63 struct eficonfig_select_file_info file_info;
64 struct eficonfig_select_file_info initrd_info;
65 unsigned int boot_index;
72 * struct eficonfig_volume_entry_data - structure to be used to store volume info
74 * @file_info: pointer to file info structure
75 * @v: pointer to the protocol interface
76 * @dp: pointer to the device path
78 struct eficonfig_volume_entry_data {
79 struct eficonfig_select_file_info *file_info;
80 struct efi_simple_file_system_protocol *v;
81 struct efi_device_path *dp;
85 * struct eficonfig_file_entry_data - structure to be used to store file info
87 * @file_info: pointer to file info structure
88 * @is_directory: flag to identify the directory or file
89 * @file_name: name of directory or file
91 struct eficonfig_file_entry_data {
92 struct eficonfig_select_file_info *file_info;
98 * struct eficonfig_boot_selection_data - structure to be used to select the boot option entry
100 * @boot_index: index of the boot option
101 * @selected: pointer to store the selected index in the BootOrder variable
103 struct eficonfig_boot_selection_data {
109 * struct eficonfig_boot_order_data - structure to be used to update BootOrder variable
111 * @boot_index: boot option index
112 * @active: flag to include the boot option into BootOrder variable
114 struct eficonfig_boot_order_data {
120 * struct eficonfig_save_boot_order_data - structure to be used to change boot order
122 * @efi_menu: pointer to efimenu structure
123 * @selected: flag to indicate user selects "Save" entry
125 struct eficonfig_save_boot_order_data {
126 struct efimenu *efi_menu;
131 * struct eficonfig_menu_adjust - update start and end entry index
133 * @efi_menu: pointer to efimenu structure
134 * @add: flag to add or substract the index
136 static void eficonfig_menu_adjust(struct efimenu *efi_menu, bool add)
143 if (add && efi_menu->end < efi_menu->active) {
146 } else if (!add && efi_menu->start > efi_menu->active) {
151 #define eficonfig_menu_up(_a) eficonfig_menu_adjust(_a, false)
152 #define eficonfig_menu_down(_a) eficonfig_menu_adjust(_a, true)
155 * eficonfig_print_msg() - print message
157 * display the message to the user, user proceeds the screen
158 * with any key press.
160 * @items: pointer to the structure of each menu entry
161 * @count: the number of menu entry
162 * @menu_header: pointer to the menu header string
163 * Return: status code
165 void eficonfig_print_msg(char *msg)
171 printf(ANSI_CURSOR_HIDE
174 "%s\n\n Press any key to continue", 3, 4, msg);
180 * eficonfig_print_entry() - print each menu entry
182 * @data: pointer to the data associated with each menu entry
184 void eficonfig_print_entry(void *data)
186 struct eficonfig_entry *entry = data;
187 bool reverse = (entry->efi_menu->active == entry->num);
189 if (entry->efi_menu->start > entry->num || entry->efi_menu->end < entry->num)
192 printf(ANSI_CURSOR_POSITION, (entry->num - entry->efi_menu->start) +
193 EFICONFIG_MENU_HEADER_ROW_NUM + 1, 7);
196 puts(ANSI_COLOR_REVERSE);
198 printf(ANSI_CLEAR_LINE "%s", entry->title);
201 puts(ANSI_COLOR_RESET);
205 * eficonfig_display_statusline() - print status line
207 * @m: pointer to the menu structure
209 void eficonfig_display_statusline(struct menu *m)
211 struct eficonfig_entry *entry;
213 if (menu_default_choice(m, (void *)&entry) < 0)
216 printf(ANSI_CURSOR_POSITION
218 ANSI_CURSOR_POSITION ANSI_CLEAR_LINE ANSI_CURSOR_POSITION
220 ANSI_CLEAR_LINE_TO_END,
221 1, 1, entry->efi_menu->menu_header, avail_row + 4, 1,
222 avail_row + 5, 1, entry->efi_menu->menu_desc);
226 * eficonfig_choice_entry() - user key input handler
228 * @data: pointer to the efimenu structure
229 * Return: key string to identify the selected entry
231 char *eficonfig_choice_entry(void *data)
233 struct cli_ch_state s_cch, *cch = &s_cch;
234 struct list_head *pos, *n;
235 struct eficonfig_entry *entry;
236 enum bootmenu_key key = BKEY_NONE;
237 struct efimenu *efi_menu = data;
242 key = bootmenu_loop((struct bootmenu_data *)efi_menu, cch);
246 if (efi_menu->active > 0)
247 eficonfig_menu_up(efi_menu);
249 /* no menu key selected, regenerate menu */
252 if (efi_menu->active < efi_menu->count - 1)
253 eficonfig_menu_down(efi_menu);
255 /* no menu key selected, regenerate menu */
258 list_for_each_safe(pos, n, &efi_menu->list) {
259 entry = list_entry(pos, struct eficonfig_entry, list);
260 if (entry->num == efi_menu->active)
265 /* Quit by choosing the last entry */
266 entry = list_last_entry(&efi_menu->list, struct eficonfig_entry, list);
269 /* Pressed key is not valid, no need to regenerate the menu */
276 * eficonfig_destroy() - destroy efimenu
278 * @efi_menu: pointer to the efimenu structure
280 void eficonfig_destroy(struct efimenu *efi_menu)
282 struct list_head *pos, *n;
283 struct eficonfig_entry *entry;
288 list_for_each_safe(pos, n, &efi_menu->list) {
289 entry = list_entry(pos, struct eficonfig_entry, list);
291 list_del(&entry->list);
294 free(efi_menu->menu_header);
299 * eficonfig_process_quit() - callback function for "Quit" entry
301 * @data: pointer to the data
302 * Return: status code
304 efi_status_t eficonfig_process_quit(void *data)
310 * eficonfig_append_menu_entry() - append menu item
312 * @efi_menu: pointer to the efimenu structure
313 * @title: pointer to the entry title
314 * @func: callback of each entry
315 * @data: pointer to the data to be passed to each entry callback
316 * Return: status code
318 efi_status_t eficonfig_append_menu_entry(struct efimenu *efi_menu,
319 char *title, eficonfig_entry_func func,
322 struct eficonfig_entry *entry;
324 if (efi_menu->count >= EFICONFIG_ENTRY_NUM_MAX)
325 return EFI_OUT_OF_RESOURCES;
327 entry = calloc(1, sizeof(struct eficonfig_entry));
329 return EFI_OUT_OF_RESOURCES;
331 entry->title = title;
332 sprintf(entry->key, "%d", efi_menu->count);
333 entry->efi_menu = efi_menu;
336 entry->num = efi_menu->count++;
337 list_add_tail(&entry->list, &efi_menu->list);
343 * eficonfig_append_quit_entry() - append quit entry
345 * @efi_menu: pointer to the efimenu structure
346 * Return: status code
348 efi_status_t eficonfig_append_quit_entry(struct efimenu *efi_menu)
353 title = strdup("Quit");
355 return EFI_OUT_OF_RESOURCES;
357 ret = eficonfig_append_menu_entry(efi_menu, title, eficonfig_process_quit, NULL);
358 if (ret != EFI_SUCCESS)
365 * eficonfig_create_fixed_menu() - create fixed entry menu structure
367 * @items: pointer to the menu entry item
368 * @count: the number of menu entry
369 * Return: pointer to the efimenu structure
371 void *eficonfig_create_fixed_menu(const struct eficonfig_item *items, int count)
376 struct efimenu *efi_menu;
377 const struct eficonfig_item *iter = items;
379 efi_menu = calloc(1, sizeof(struct efimenu));
383 INIT_LIST_HEAD(&efi_menu->list);
384 for (i = 0; i < count; i++, iter++) {
385 title = strdup(iter->title);
389 ret = eficonfig_append_menu_entry(efi_menu, title, iter->func, iter->data);
390 if (ret != EFI_SUCCESS) {
398 eficonfig_destroy(efi_menu);
404 * eficonfig_process_common() - main handler for UEFI menu
406 * Construct the structures required to show the menu, then handle
407 * the user input interacting with u-boot menu functions.
409 * @efi_menu: pointer to the efimenu structure
410 * @menu_header: pointer to the menu header string
411 * @menu_desc: pointer to the menu description
412 * @display_statusline: function pointer to draw statusline
413 * @item_data_print: function pointer to draw the menu item
414 * @item_choice: function pointer to handle the key press
415 * Return: status code
417 efi_status_t eficonfig_process_common(struct efimenu *efi_menu,
418 char *menu_header, const char *menu_desc,
419 void (*display_statusline)(struct menu *),
420 void (*item_data_print)(void *),
421 char *(*item_choice)(void *))
425 struct list_head *pos, *n;
426 struct eficonfig_entry *entry;
427 efi_status_t ret = EFI_SUCCESS;
429 if (efi_menu->count > EFICONFIG_ENTRY_NUM_MAX)
430 return EFI_OUT_OF_RESOURCES;
432 efi_menu->delay = -1;
433 efi_menu->active = 0;
435 efi_menu->end = avail_row - 1;
438 efi_menu->menu_header = strdup(menu_header);
439 if (!efi_menu->menu_header)
440 return EFI_OUT_OF_RESOURCES;
443 efi_menu->menu_desc = menu_desc;
445 menu = menu_create(NULL, 0, 1, display_statusline, item_data_print,
446 item_choice, efi_menu);
448 return EFI_INVALID_PARAMETER;
450 list_for_each_safe(pos, n, &efi_menu->list) {
451 entry = list_entry(pos, struct eficonfig_entry, list);
452 if (!menu_item_add(menu, entry->key, entry)) {
453 ret = EFI_INVALID_PARAMETER;
458 entry = list_first_entry_or_null(&efi_menu->list, struct eficonfig_entry, list);
460 menu_default_set(menu, entry->key);
462 printf(ANSI_CURSOR_HIDE
464 ANSI_CURSOR_POSITION, 1, 1);
466 if (menu_get_choice(menu, &choice)) {
469 ret = entry->func(entry->data);
474 printf(ANSI_CLEAR_CONSOLE
476 ANSI_CURSOR_SHOW, 1, 1);
482 * eficonfig_volume_selected() - handler of volume selection
484 * @data: pointer to the data of selected entry
485 * Return: status code
487 static efi_status_t eficonfig_volume_selected(void *data)
489 struct eficonfig_volume_entry_data *info = data;
492 info->file_info->current_volume = info->v;
493 info->file_info->dp_volume = info->dp;
500 * eficonfig_create_device_path() - create device path
502 * @dp_volume: pointer to the volume
503 * @current_path: pointer to the file path u16 string
505 * device path or NULL. Caller must free the returned value
507 struct efi_device_path *eficonfig_create_device_path(struct efi_device_path *dp_volume,
513 struct efi_device_path *dp;
514 struct efi_device_path_file_path *fp;
516 fp_size = sizeof(struct efi_device_path) + u16_strsize(current_path);
517 buf = calloc(1, fp_size + sizeof(END));
522 fp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE,
523 fp->dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH,
524 fp->dp.length = (u16)fp_size;
525 u16_strcpy(fp->str, current_path);
529 *((struct efi_device_path *)p) = END;
531 dp = efi_dp_append(dp_volume, (struct efi_device_path *)buf);
538 * eficonfig_file_selected() - handler of file selection
540 * @data: pointer to the data of selected entry
541 * Return: status code
543 static efi_status_t eficonfig_file_selected(void *data)
546 struct eficonfig_file_entry_data *info = data;
549 return EFI_INVALID_PARAMETER;
551 if (!strcmp(info->file_name, "..\\")) {
552 struct eficonfig_filepath_info *iter;
553 struct list_head *pos, *n;
556 tmp = info->file_info->current_path;
558 memset(info->file_info->current_path, 0, EFICONFIG_FILE_PATH_BUF_SIZE);
559 filepath = calloc(1, EFICONFIG_FILE_PATH_MAX);
561 return EFI_OUT_OF_RESOURCES;
563 list_for_each_safe(pos, n, &info->file_info->filepath_list) {
564 iter = list_entry(pos, struct eficonfig_filepath_info, list);
566 is_last = list_is_last(&iter->list, &info->file_info->filepath_list);
568 list_del(&iter->list);
573 strlcat(filepath, iter->name, EFICONFIG_FILE_PATH_MAX);
575 utf8_utf16_strcpy(&tmp, filepath);
578 struct eficonfig_filepath_info *filepath_info;
580 new_len = u16_strlen(info->file_info->current_path) +
581 strlen(info->file_name);
582 if (new_len >= EFICONFIG_FILE_PATH_MAX) {
583 eficonfig_print_msg("File path is too long!");
584 return EFI_INVALID_PARAMETER;
586 tmp = &info->file_info->current_path[u16_strlen(info->file_info->current_path)];
587 utf8_utf16_strcpy(&tmp, info->file_name);
589 filepath_info = calloc(1, sizeof(struct eficonfig_filepath_info));
591 return EFI_OUT_OF_RESOURCES;
593 filepath_info->name = strdup(info->file_name);
594 if (!filepath_info->name) {
596 return EFI_OUT_OF_RESOURCES;
598 list_add_tail(&filepath_info->list, &info->file_info->filepath_list);
600 if (!info->is_directory)
601 info->file_info->file_selected = true;
608 * eficonfig_select_volume() - construct the volume selection menu
610 * @file_info: pointer to the file selection structure
611 * Return: status code
613 static efi_status_t eficonfig_select_volume(struct eficonfig_select_file_info *file_info)
618 struct efimenu *efi_menu;
619 struct list_head *pos, *n;
620 struct efi_handler *handler;
621 struct eficonfig_entry *entry;
622 struct efi_device_path *device_path;
623 efi_handle_t *volume_handles = NULL;
624 struct efi_simple_file_system_protocol *v;
626 ret = efi_locate_handle_buffer_int(BY_PROTOCOL, &efi_simple_file_system_protocol_guid,
627 NULL, &count, (efi_handle_t **)&volume_handles);
628 if (ret != EFI_SUCCESS) {
629 eficonfig_print_msg("No block device found!");
633 efi_menu = calloc(1, sizeof(struct efimenu));
635 return EFI_OUT_OF_RESOURCES;
637 INIT_LIST_HEAD(&efi_menu->list);
638 for (i = 0; i < count; i++) {
640 struct efi_block_io *block_io;
641 struct eficonfig_volume_entry_data *info;
643 if (efi_menu->count >= EFICONFIG_ENTRY_NUM_MAX - 1)
646 ret = efi_search_protocol(volume_handles[i],
647 &efi_simple_file_system_protocol_guid, &handler);
648 if (ret != EFI_SUCCESS)
650 ret = efi_protocol_open(handler, (void **)&v, efi_root, NULL,
651 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
652 if (ret != EFI_SUCCESS)
655 ret = efi_search_protocol(volume_handles[i], &efi_guid_device_path, &handler);
656 if (ret != EFI_SUCCESS)
658 ret = efi_protocol_open(handler, (void **)&device_path,
659 efi_root, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
660 if (ret != EFI_SUCCESS)
663 ret = efi_search_protocol(volume_handles[i], &efi_block_io_guid, &handler);
664 if (ret != EFI_SUCCESS)
666 ret = efi_protocol_open(handler, (void **)&block_io,
667 efi_root, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
668 if (ret != EFI_SUCCESS)
671 info = calloc(1, sizeof(struct eficonfig_volume_entry_data));
673 ret = EFI_OUT_OF_RESOURCES;
677 devname = calloc(1, BOOTMENU_DEVICE_NAME_MAX);
680 ret = EFI_OUT_OF_RESOURCES;
683 ret = efi_disk_get_device_name(volume_handles[i], devname,
684 BOOTMENU_DEVICE_NAME_MAX);
685 if (ret != EFI_SUCCESS) {
691 info->dp = device_path;
692 info->file_info = file_info;
693 ret = eficonfig_append_menu_entry(efi_menu, devname, eficonfig_volume_selected,
695 if (ret != EFI_SUCCESS) {
701 ret = eficonfig_append_quit_entry(efi_menu);
702 if (ret != EFI_SUCCESS)
705 ret = eficonfig_process_common(efi_menu, " ** Select Volume **",
707 eficonfig_display_statusline,
708 eficonfig_print_entry,
709 eficonfig_choice_entry);
712 efi_free_pool(volume_handles);
713 list_for_each_safe(pos, n, &efi_menu->list) {
714 entry = list_entry(pos, struct eficonfig_entry, list);
717 eficonfig_destroy(efi_menu);
723 * sort_file() - sort the file name in ascii order
725 * @data1: pointer to the file entry data
726 * @data2: pointer to the file entry data
727 * Return: -1 if the data1 file name is less than data2 file name,
728 * 0 if both file name match,
729 * 1 if the data1 file name is greater thant data2 file name.
731 static int sort_file(const void *arg1, const void *arg2)
733 const struct eficonfig_file_entry_data *data1, *data2;
735 data1 = *((const struct eficonfig_file_entry_data **)arg1);
736 data2 = *((const struct eficonfig_file_entry_data **)arg2);
738 return strcasecmp(data1->file_name, data2->file_name);
742 * eficonfig_create_file_entry() - construct the file menu entry
744 * @efi_menu: pointer to the efimenu structure
745 * @count: number of the directory and file
746 * @tmp_infos: pointer to the entry data array
747 * @f: pointer to the file handle
748 * @buf: pointer to the buffer to store the directory information
749 * @file_info: pointer to the file selection structure
750 * Return: status code
753 eficonfig_create_file_entry(struct efimenu *efi_menu, u32 count,
754 struct eficonfig_file_entry_data **tmp_infos,
755 struct efi_file_handle *f, struct efi_file_info *buf,
756 struct eficonfig_select_file_info *file_info)
761 u32 i, entry_num = 0;
762 struct eficonfig_file_entry_data *info;
764 EFI_CALL(f->setpos(f, 0));
765 /* Read directory and construct menu structure */
766 for (i = 0; i < count; i++) {
767 if (entry_num >= EFICONFIG_ENTRY_NUM_MAX - 1)
770 len = sizeof(struct efi_file_info) + EFICONFIG_FILE_PATH_BUF_SIZE;
771 ret = EFI_CALL(f->read(f, &len, buf));
772 if (ret != EFI_SUCCESS || len == 0)
775 info = calloc(1, sizeof(struct eficonfig_file_entry_data));
777 ret = EFI_OUT_OF_RESOURCES;
781 /* append '\\' at the end of directory name */
782 name = calloc(1, utf16_utf8_strlen(buf->file_name) + 2);
784 ret = EFI_OUT_OF_RESOURCES;
789 utf16_utf8_strcpy(&p, buf->file_name);
790 if (buf->attribute & EFI_FILE_DIRECTORY) {
791 /* filter out u'.' */
792 if (!u16_strcmp(buf->file_name, u".")) {
797 name[u16_strlen(buf->file_name)] = '\\';
798 info->is_directory = true;
801 info->file_name = name;
802 info->file_info = file_info;
803 tmp_infos[entry_num++] = info;
806 qsort(tmp_infos, entry_num, sizeof(*tmp_infos),
807 (int (*)(const void *, const void *))sort_file);
809 for (i = 0; i < entry_num; i++) {
810 ret = eficonfig_append_menu_entry(efi_menu, tmp_infos[i]->file_name,
811 eficonfig_file_selected, tmp_infos[i]);
812 if (ret != EFI_SUCCESS)
821 * eficonfig_show_file_selection() - construct the file selection menu
823 * @file_info: pointer to the file selection structure
824 * @root: pointer to the file handle
825 * Return: status code
827 static efi_status_t eficonfig_show_file_selection(struct eficonfig_select_file_info *file_info,
828 struct efi_file_handle *root)
833 struct efimenu *efi_menu;
834 struct efi_file_handle *f;
835 struct efi_file_info *buf;
836 struct eficonfig_file_entry_data **tmp_infos;
838 buf = calloc(1, sizeof(struct efi_file_info) + EFICONFIG_FILE_PATH_BUF_SIZE);
840 return EFI_OUT_OF_RESOURCES;
842 while (!file_info->file_selected) {
843 efi_menu = calloc(1, sizeof(struct efimenu));
845 ret = EFI_OUT_OF_RESOURCES;
848 INIT_LIST_HEAD(&efi_menu->list);
850 ret = EFI_CALL(root->open(root, &f, file_info->current_path,
851 EFI_FILE_MODE_READ, 0));
852 if (ret != EFI_SUCCESS) {
853 eficonfig_print_msg("Reading volume failed!");
859 /* Count the number of directory entries */
861 len = sizeof(struct efi_file_info) + EFICONFIG_FILE_PATH_BUF_SIZE;
862 ret = EFI_CALL(f->read(f, &len, buf));
863 if (ret != EFI_SUCCESS || len == 0)
869 /* allocate array to sort the entry */
870 tmp_infos = calloc(count, sizeof(*tmp_infos));
872 ret = EFI_OUT_OF_RESOURCES;
876 ret = eficonfig_create_file_entry(efi_menu, count, tmp_infos,
878 if (ret != EFI_SUCCESS)
881 ret = eficonfig_append_quit_entry(efi_menu);
882 if (ret != EFI_SUCCESS)
885 ret = eficonfig_process_common(efi_menu, " ** Select File **",
887 eficonfig_display_statusline,
888 eficonfig_print_entry,
889 eficonfig_choice_entry);
891 EFI_CALL(f->close(f));
892 eficonfig_destroy(efi_menu);
895 for (i = 0; i < count; i++)
901 if (ret != EFI_SUCCESS)
912 * handle_user_input() - handle user input
914 * @buf: pointer to the buffer
915 * @buf_size: size of the buffer
916 * @cursor_col: cursor column for user input
917 * @msg: pointer to the string to display
918 * Return: status code
920 static efi_status_t handle_user_input(u16 *buf, int buf_size,
921 int cursor_col, char *msg)
926 printf(ANSI_CLEAR_CONSOLE
930 " Press ENTER to complete, ESC to quit",
933 /* tmp is used to accept user cancel */
934 tmp = calloc(1, buf_size * sizeof(u16));
936 return EFI_OUT_OF_RESOURCES;
938 ret = efi_console_get_u16_string(cin, tmp, buf_size, NULL, 4, cursor_col);
939 if (ret == EFI_SUCCESS)
940 u16_strcpy(buf, tmp);
944 /* to stay the parent menu */
945 ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;
951 * eficonfig_boot_add_enter_description() - handle user input for description
953 * @data: pointer to the internal boot option structure
954 * Return: status code
956 static efi_status_t eficonfig_boot_add_enter_description(void *data)
958 struct eficonfig_boot_option *bo = data;
960 return handle_user_input(bo->description, EFICONFIG_DESCRIPTION_MAX, 22,
961 "\n ** Edit Description **\n"
963 " enter description: ");
967 * eficonfig_boot_add_optional_data() - handle user input for optional data
969 * @data: pointer to the internal boot option structure
970 * Return: status code
972 static efi_status_t eficonfig_boot_add_optional_data(void *data)
974 struct eficonfig_boot_option *bo = data;
976 return handle_user_input(bo->optional_data, EFICONFIG_OPTIONAL_DATA_MAX, 24,
977 "\n ** Edit Optional Data **\n"
979 " enter optional data:");
983 * eficonfig_boot_edit_save() - handler to save the boot option
985 * @data: pointer to the internal boot option structure
986 * Return: status code
988 static efi_status_t eficonfig_boot_edit_save(void *data)
990 struct eficonfig_boot_option *bo = data;
992 if (u16_strlen(bo->description) == 0) {
993 eficonfig_print_msg("Boot Description is empty!");
994 bo->edit_completed = false;
995 return EFI_NOT_READY;
997 if (u16_strlen(bo->file_info.current_path) == 0) {
998 eficonfig_print_msg("File is not selected!");
999 bo->edit_completed = false;
1000 return EFI_NOT_READY;
1003 bo->edit_completed = true;
1009 * eficonfig_process_clear_file_selection() - callback function for "Clear" entry
1011 * @data: pointer to the data
1012 * Return: status code
1014 efi_status_t eficonfig_process_clear_file_selection(void *data)
1016 struct eficonfig_select_file_info *file_info = data;
1018 /* clear the existing file information */
1019 file_info->current_volume = NULL;
1020 file_info->current_path[0] = u'\0';
1021 file_info->dp_volume = NULL;
1026 static struct eficonfig_item select_file_menu_items[] = {
1027 {"Select File", eficonfig_process_select_file},
1028 {"Clear", eficonfig_process_clear_file_selection},
1029 {"Quit", eficonfig_process_quit},
1033 * eficonfig_process_show_file_option() - display select file option
1035 * @file_info: pointer to the file information structure
1036 * Return: status code
1038 efi_status_t eficonfig_process_show_file_option(void *data)
1041 struct efimenu *efi_menu;
1043 select_file_menu_items[0].data = data;
1044 select_file_menu_items[1].data = data;
1045 efi_menu = eficonfig_create_fixed_menu(select_file_menu_items,
1046 ARRAY_SIZE(select_file_menu_items));
1048 return EFI_OUT_OF_RESOURCES;
1050 ret = eficonfig_process_common(efi_menu, " ** Update File **",
1051 eficonfig_menu_desc,
1052 eficonfig_display_statusline,
1053 eficonfig_print_entry,
1054 eficonfig_choice_entry);
1055 if (ret != EFI_SUCCESS) /* User selects "Clear" or "Quit" */
1056 ret = EFI_NOT_READY;
1058 eficonfig_destroy(efi_menu);
1064 * eficonfig_process_select_file() - handle user file selection
1066 * @data: pointer to the data
1067 * Return: status code
1069 efi_status_t eficonfig_process_select_file(void *data)
1073 struct list_head *pos, *n;
1074 struct efi_file_handle *root;
1075 struct eficonfig_filepath_info *item;
1076 struct eficonfig_select_file_info *tmp = NULL;
1077 struct eficonfig_select_file_info *file_info = data;
1079 tmp = calloc(1, sizeof(struct eficonfig_select_file_info));
1081 return EFI_OUT_OF_RESOURCES;
1083 tmp->current_path = calloc(1, EFICONFIG_FILE_PATH_BUF_SIZE);
1084 if (!tmp->current_path) {
1086 return EFI_OUT_OF_RESOURCES;
1088 INIT_LIST_HEAD(&tmp->filepath_list);
1090 while (!tmp->file_selected) {
1091 tmp->current_volume = NULL;
1092 memset(tmp->current_path, 0, EFICONFIG_FILE_PATH_BUF_SIZE);
1094 ret = eficonfig_select_volume(tmp);
1095 if (ret != EFI_SUCCESS)
1098 if (!tmp->current_volume)
1099 return EFI_INVALID_PARAMETER;
1101 ret = EFI_CALL(tmp->current_volume->open_volume(tmp->current_volume, &root));
1102 if (ret != EFI_SUCCESS)
1105 ret = eficonfig_show_file_selection(tmp, root);
1106 if (ret == EFI_ABORTED)
1108 if (ret != EFI_SUCCESS)
1113 if (ret == EFI_SUCCESS) {
1114 len = u16_strlen(tmp->current_path);
1115 len = (len >= EFICONFIG_FILE_PATH_MAX) ? (EFICONFIG_FILE_PATH_MAX - 1) : len;
1116 memcpy(file_info->current_path, tmp->current_path, len * sizeof(u16));
1117 file_info->current_path[len] = u'\0';
1118 file_info->current_volume = tmp->current_volume;
1119 file_info->dp_volume = tmp->dp_volume;
1122 list_for_each_safe(pos, n, &tmp->filepath_list) {
1123 item = list_entry(pos, struct eficonfig_filepath_info, list);
1124 list_del(&item->list);
1128 free(tmp->current_path);
1131 /* to stay the parent menu */
1132 ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;
1138 * eficonfig_get_unused_bootoption() - get unused "Boot####" index
1140 * @buf: pointer to the buffer to store boot option variable name
1141 * @buf_size: buffer size
1142 * @index: pointer to store the index in the BootOrder variable
1143 * Return: status code
1145 efi_status_t eficonfig_get_unused_bootoption(u16 *buf, efi_uintn_t buf_size,
1146 unsigned int *index)
1152 if (buf_size < u16_strsize(u"Boot####"))
1153 return EFI_BUFFER_TOO_SMALL;
1155 for (i = 0; i <= 0xFFFF; i++) {
1157 efi_create_indexed_name(buf, buf_size, "Boot", i);
1158 ret = efi_get_variable_int(buf, &efi_global_variable_guid,
1159 NULL, &size, NULL, NULL);
1160 if (ret == EFI_BUFFER_TOO_SMALL)
1167 return EFI_OUT_OF_RESOURCES;
1175 * eficonfig_set_boot_option() - set boot option
1177 * @varname: pointer to variable name
1178 * @dp: pointer to device path
1179 * @label: pointer to label string
1180 * @optional_data: pointer to optional data
1181 * Return: status code
1183 static efi_status_t eficonfig_set_boot_option(u16 *varname, struct efi_device_path *dp,
1184 efi_uintn_t dp_size, u16 *label, char *optional_data)
1189 struct efi_load_option lo;
1192 lo.file_path_length = dp_size;
1193 lo.attributes = LOAD_OPTION_ACTIVE;
1194 lo.optional_data = optional_data;
1197 size = efi_serialize_load_option(&lo, (u8 **)&p);
1199 return EFI_INVALID_PARAMETER;
1201 ret = efi_set_variable_int(varname, &efi_global_variable_guid,
1202 EFI_VARIABLE_NON_VOLATILE |
1203 EFI_VARIABLE_BOOTSERVICE_ACCESS |
1204 EFI_VARIABLE_RUNTIME_ACCESS,
1212 * eficonfig_append_bootorder() - append new boot option in BootOrder variable
1214 * @index: "Boot####" index to append to BootOrder variable
1215 * Return: status code
1217 efi_status_t eficonfig_append_bootorder(u16 index)
1221 u16 *new_bootorder = NULL;
1222 efi_uintn_t last, size, new_size;
1224 /* append new boot option */
1225 bootorder = efi_get_var(u"BootOrder", &efi_global_variable_guid, &size);
1226 last = size / sizeof(u16);
1227 new_size = size + sizeof(u16);
1228 new_bootorder = calloc(1, new_size);
1229 if (!new_bootorder) {
1230 ret = EFI_OUT_OF_RESOURCES;
1233 memcpy(new_bootorder, bootorder, size);
1234 new_bootorder[last] = index;
1236 ret = efi_set_variable_int(u"BootOrder", &efi_global_variable_guid,
1237 EFI_VARIABLE_NON_VOLATILE |
1238 EFI_VARIABLE_BOOTSERVICE_ACCESS |
1239 EFI_VARIABLE_RUNTIME_ACCESS,
1240 new_size, new_bootorder, false);
1241 if (ret != EFI_SUCCESS)
1246 free(new_bootorder);
1252 * create_boot_option_entry() - create boot option entry
1254 * @efi_menu: pointer to the efimenu structure
1255 * @title: pointer to the entry title
1256 * @val: pointer to boot option label
1257 * @func: callback of each entry
1258 * @data: pointer to the data to be passed to each entry callback
1259 * Return: status code
1261 static efi_status_t create_boot_option_entry(struct efimenu *efi_menu, char *title, u16 *val,
1262 eficonfig_entry_func func, void *data)
1267 len = strlen(title) + 1;
1269 len += utf16_utf8_strlen(val);
1270 buf = calloc(1, len);
1272 return EFI_OUT_OF_RESOURCES;
1276 p = buf + strlen(title);
1277 utf16_utf8_strcpy(&p, val);
1280 return eficonfig_append_menu_entry(efi_menu, buf, func, data);
1284 * prepare_file_selection_entry() - prepare file selection entry
1286 * @efi_menu: pointer to the efimenu structure
1287 * @title: pointer to the title string
1288 * @file_info: pointer to the file info
1289 * Return: status code
1291 static efi_status_t prepare_file_selection_entry(struct efimenu *efi_menu, char *title,
1292 struct eficonfig_select_file_info *file_info)
1296 u16 *file_name = NULL, *p;
1297 efi_handle_t handle;
1300 devname = calloc(1, EFICONFIG_VOLUME_PATH_MAX + 1);
1302 return EFI_OUT_OF_RESOURCES;
1304 /* get the device name only when the user already selected the file path */
1305 handle = efi_dp_find_obj(file_info->dp_volume, NULL, NULL);
1307 ret = efi_disk_get_device_name(handle, devname, EFICONFIG_VOLUME_PATH_MAX);
1308 if (ret != EFI_SUCCESS)
1313 * If the preconfigured volume does not exist in the system, display the text
1314 * converted volume device path instead of U-Boot friendly name(e.g. "usb 0:1").
1316 if (!handle && file_info->dp_volume) {
1320 dp_str = efi_dp_str(file_info->dp_volume);
1322 utf16_utf8_strncpy(&q, dp_str, EFICONFIG_VOLUME_PATH_MAX);
1324 efi_free_pool(dp_str);
1327 /* append u'/' to devname, it is just for display purpose. */
1328 if (file_info->current_path[0] != u'\0' && file_info->current_path[0] != u'/')
1329 strlcat(devname, "/", EFICONFIG_VOLUME_PATH_MAX + 1);
1331 len = strlen(devname);
1332 len += utf16_utf8_strlen(file_info->current_path) + 1;
1333 file_name = calloc(1, len * sizeof(u16));
1335 ret = EFI_OUT_OF_RESOURCES;
1340 utf8_utf16_strcpy(&p, devname);
1341 u16_strlcat(file_name, file_info->current_path, len);
1342 ret = create_boot_option_entry(efi_menu, title, file_name,
1343 eficonfig_process_show_file_option, file_info);
1352 * eficonfig_show_boot_option() - prepare menu entry for editing boot option
1354 * Construct the structures to create edit boot option menu
1356 * @bo: pointer to the boot option
1357 * @header_str: pointer to the header string
1358 * Return: status code
1360 static efi_status_t eficonfig_show_boot_option(struct eficonfig_boot_option *bo,
1364 struct efimenu *efi_menu;
1366 efi_menu = calloc(1, sizeof(struct efimenu));
1368 return EFI_OUT_OF_RESOURCES;
1370 INIT_LIST_HEAD(&efi_menu->list);
1372 ret = create_boot_option_entry(efi_menu, "Description: ", bo->description,
1373 eficonfig_boot_add_enter_description, bo);
1374 if (ret != EFI_SUCCESS)
1377 ret = prepare_file_selection_entry(efi_menu, "File: ", &bo->file_info);
1378 if (ret != EFI_SUCCESS)
1381 ret = prepare_file_selection_entry(efi_menu, "Initrd File: ", &bo->initrd_info);
1382 if (ret != EFI_SUCCESS)
1385 ret = create_boot_option_entry(efi_menu, "Optional Data: ", bo->optional_data,
1386 eficonfig_boot_add_optional_data, bo);
1387 if (ret != EFI_SUCCESS)
1390 ret = create_boot_option_entry(efi_menu, "Save", NULL,
1391 eficonfig_boot_edit_save, bo);
1392 if (ret != EFI_SUCCESS)
1395 ret = create_boot_option_entry(efi_menu, "Quit", NULL,
1396 eficonfig_process_quit, NULL);
1397 if (ret != EFI_SUCCESS)
1400 ret = eficonfig_process_common(efi_menu, header_str,
1401 eficonfig_menu_desc,
1402 eficonfig_display_statusline,
1403 eficonfig_print_entry,
1404 eficonfig_choice_entry);
1407 eficonfig_destroy(efi_menu);
1413 * fill_file_info() - fill the file info from efi_device_path structure
1415 * @dp: pointer to the device path
1416 * @file_info: pointer to the file info structure
1417 * @device_dp: pointer to the volume device path
1419 static void fill_file_info(struct efi_device_path *dp,
1420 struct eficonfig_select_file_info *file_info,
1421 struct efi_device_path *device_dp)
1424 struct efi_device_path *file_dp = NULL;
1426 efi_dp_split_file_path(dp, &device_dp, &file_dp);
1427 file_info->dp_volume = device_dp;
1430 file_str = efi_dp_str(file_dp);
1432 * efi_convert_device_path_to_text() automatically adds u'/' at the
1433 * beginning of file name, remove u'/' before copying to current_path
1439 u16_strcpy(file_info->current_path, p);
1440 efi_free_pool(file_dp);
1441 efi_free_pool(file_str);
1446 * eficonfig_edit_boot_option() - prepare boot option structure for editing
1448 * Construct the boot option structure and copy the existing value
1450 * @varname: pointer to the UEFI variable name
1451 * @bo: pointer to the boot option
1452 * @load_option: pointer to the load option
1453 * @load_option_size: size of the load option
1454 * @header_str: pointer to the header string
1455 * Return : status code
1457 static efi_status_t eficonfig_edit_boot_option(u16 *varname, struct eficonfig_boot_option *bo,
1458 void *load_option, efi_uintn_t load_option_size,
1463 char *tmp = NULL, *p;
1464 struct efi_load_option lo = {0};
1465 efi_uintn_t final_dp_size;
1466 struct efi_device_path *dp = NULL;
1467 efi_uintn_t size = load_option_size;
1468 struct efi_device_path *final_dp = NULL;
1469 struct efi_device_path *device_dp = NULL;
1470 struct efi_device_path *initrd_dp = NULL;
1471 struct efi_device_path *initrd_device_dp = NULL;
1473 const struct efi_initrd_dp id_dp = {
1476 DEVICE_PATH_TYPE_MEDIA_DEVICE,
1477 DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
1478 sizeof(id_dp.vendor),
1480 EFI_INITRD_MEDIA_GUID,
1483 DEVICE_PATH_TYPE_END,
1484 DEVICE_PATH_SUB_TYPE_END,
1489 bo->file_info.current_path = calloc(1, EFICONFIG_FILE_PATH_BUF_SIZE);
1490 if (!bo->file_info.current_path) {
1491 ret = EFI_OUT_OF_RESOURCES;
1495 bo->initrd_info.current_path = calloc(1, EFICONFIG_FILE_PATH_BUF_SIZE);
1496 if (!bo->file_info.current_path) {
1497 ret = EFI_OUT_OF_RESOURCES;
1501 bo->description = calloc(1, EFICONFIG_DESCRIPTION_MAX * sizeof(u16));
1502 if (!bo->description) {
1503 ret = EFI_OUT_OF_RESOURCES;
1507 bo->optional_data = calloc(1, EFICONFIG_OPTIONAL_DATA_MAX * sizeof(u16));
1508 if (!bo->optional_data) {
1509 ret = EFI_OUT_OF_RESOURCES;
1513 /* copy the preset value */
1515 ret = efi_deserialize_load_option(&lo, load_option, &size);
1516 if (ret != EFI_SUCCESS)
1520 ret = EFI_INVALID_PARAMETER;
1523 /* truncate the long label string */
1524 if (u16_strlen(lo.label) >= EFICONFIG_DESCRIPTION_MAX)
1525 lo.label[EFICONFIG_DESCRIPTION_MAX - 1] = u'\0';
1527 u16_strcpy(bo->description, lo.label);
1529 /* EFI image file path is a first instance */
1531 fill_file_info(lo.file_path, &bo->file_info, device_dp);
1533 /* Initrd file path(optional) is placed at second instance. */
1534 initrd_dp = efi_dp_from_lo(&lo, &efi_lf2_initrd_guid);
1536 fill_file_info(initrd_dp, &bo->initrd_info, initrd_device_dp);
1537 efi_free_pool(initrd_dp);
1541 memcpy(bo->optional_data, lo.optional_data, size);
1545 ret = eficonfig_show_boot_option(bo, header_str);
1546 if (ret == EFI_SUCCESS && bo->edit_completed)
1548 if (ret == EFI_NOT_READY)
1550 if (ret != EFI_SUCCESS)
1554 if (bo->initrd_info.dp_volume) {
1555 dp = eficonfig_create_device_path(bo->initrd_info.dp_volume,
1556 bo->initrd_info.current_path);
1558 ret = EFI_OUT_OF_RESOURCES;
1561 initrd_dp = efi_dp_append((const struct efi_device_path *)&id_dp, dp);
1565 dp = eficonfig_create_device_path(bo->file_info.dp_volume, bo->file_info.current_path);
1567 ret = EFI_OUT_OF_RESOURCES;
1570 final_dp_size = efi_dp_size(dp) + sizeof(END);
1572 final_dp = efi_dp_concat(dp, initrd_dp);
1573 final_dp_size += efi_dp_size(initrd_dp) + sizeof(END);
1575 final_dp = efi_dp_dup(dp);
1582 if (utf16_utf8_strlen(bo->optional_data)) {
1583 len = utf16_utf8_strlen(bo->optional_data) + 1;
1584 tmp = calloc(1, len);
1588 utf16_utf8_strncpy(&p, bo->optional_data, u16_strlen(bo->optional_data));
1591 ret = eficonfig_set_boot_option(varname, final_dp, final_dp_size, bo->description, tmp);
1594 free(bo->optional_data);
1595 free(bo->description);
1596 free(bo->file_info.current_path);
1597 free(bo->initrd_info.current_path);
1598 efi_free_pool(device_dp);
1599 efi_free_pool(initrd_device_dp);
1600 efi_free_pool(initrd_dp);
1601 efi_free_pool(final_dp);
1607 * eficonfig_process_add_boot_option() - handler to add boot option
1609 * @data: pointer to the data for each entry
1610 * Return: status code
1612 static efi_status_t eficonfig_process_add_boot_option(void *data)
1616 struct eficonfig_boot_option *bo = NULL;
1618 bo = calloc(1, sizeof(struct eficonfig_boot_option));
1620 return EFI_OUT_OF_RESOURCES;
1622 ret = eficonfig_get_unused_bootoption(varname, sizeof(varname), &bo->boot_index);
1623 if (ret != EFI_SUCCESS)
1626 ret = eficonfig_edit_boot_option(varname, bo, NULL, 0, " ** Add Boot Option ** ");
1627 if (ret != EFI_SUCCESS)
1630 ret = eficonfig_append_bootorder((u16)bo->boot_index);
1631 if (ret != EFI_SUCCESS)
1637 /* to stay the parent menu */
1638 ret = (ret == EFI_ABORTED) ? EFI_SUCCESS : ret;
1644 * eficonfig_process_boot_selected() - handler to select boot option entry
1646 * @data: pointer to the data for each entry
1647 * Return: status code
1649 static efi_status_t eficonfig_process_boot_selected(void *data)
1651 struct eficonfig_boot_selection_data *info = data;
1654 *info->selected = info->boot_index;
1660 * search_bootorder() - search the boot option index in BootOrder
1662 * @bootorder: pointer to the BootOrder variable
1663 * @num: number of BootOrder entry
1664 * @target: target boot option index to search
1665 * @index: pointer to store the index of BootOrder variable
1666 * Return: true if exists, false otherwise
1668 static bool search_bootorder(u16 *bootorder, efi_uintn_t num, u32 target, u32 *index)
1672 for (i = 0; i < num; i++) {
1673 if (target == bootorder[i]) {
1685 * eficonfig_add_boot_selection_entry() - add boot option menu entry
1687 * @efi_menu: pointer to store the efimenu structure
1688 * @boot_index: boot option index to be added
1689 * @selected: pointer to store the selected boot option index
1690 * Return: status code
1692 static efi_status_t eficonfig_add_boot_selection_entry(struct efimenu *efi_menu,
1693 unsigned int boot_index,
1694 unsigned int *selected)
1700 struct efi_load_option lo;
1701 u16 varname[] = u"Boot####";
1702 struct eficonfig_boot_selection_data *info;
1704 efi_create_indexed_name(varname, sizeof(varname), "Boot", boot_index);
1705 load_option = efi_get_var(varname, &efi_global_variable_guid, &size);
1709 ret = efi_deserialize_load_option(&lo, load_option, &size);
1710 if (ret != EFI_SUCCESS) {
1711 log_warning("Invalid load option for %ls\n", varname);
1716 if (size >= sizeof(efi_guid_t) &&
1717 !guidcmp(lo.optional_data, &efi_guid_bootmenu_auto_generated)) {
1719 * auto generated entry has GUID in optional_data,
1720 * skip auto generated entry because it will be generated
1721 * again even if it is edited or deleted.
1727 info = calloc(1, sizeof(struct eficonfig_boot_selection_data));
1730 return EFI_OUT_OF_RESOURCES;
1733 buf = calloc(1, utf16_utf8_strlen(lo.label) + 1);
1737 return EFI_OUT_OF_RESOURCES;
1740 utf16_utf8_strcpy(&p, lo.label);
1741 info->boot_index = boot_index;
1742 info->selected = selected;
1743 ret = eficonfig_append_menu_entry(efi_menu, buf, eficonfig_process_boot_selected, info);
1744 if (ret != EFI_SUCCESS) {
1755 * eficonfig_show_boot_selection() - construct boot option menu entry
1757 * @selected: pointer to store the selected boot option index
1758 * Return: status code
1760 static efi_status_t eficonfig_show_boot_selection(unsigned int *selected)
1765 u16 *var_name16 = NULL;
1766 efi_uintn_t num, size, buf_size;
1767 struct efimenu *efi_menu;
1768 struct list_head *pos, *n;
1769 struct eficonfig_entry *entry;
1771 efi_menu = calloc(1, sizeof(struct efimenu));
1773 return EFI_OUT_OF_RESOURCES;
1775 bootorder = efi_get_var(u"BootOrder", &efi_global_variable_guid, &size);
1777 INIT_LIST_HEAD(&efi_menu->list);
1778 num = size / sizeof(u16);
1779 /* list the load option in the order of BootOrder variable */
1780 for (i = 0; i < num; i++) {
1781 ret = eficonfig_add_boot_selection_entry(efi_menu, bootorder[i], selected);
1782 if (ret != EFI_SUCCESS)
1785 if (efi_menu->count >= EFICONFIG_ENTRY_NUM_MAX - 1)
1789 /* list the remaining load option not included in the BootOrder */
1791 var_name16 = malloc(buf_size);
1793 return EFI_OUT_OF_RESOURCES;
1800 ret = efi_next_variable_name(&buf_size, &var_name16, &guid);
1801 if (ret == EFI_NOT_FOUND)
1803 if (ret != EFI_SUCCESS)
1806 if (efi_varname_is_load_option(var_name16, &index)) {
1807 /* If the index is included in the BootOrder, skip it */
1808 if (search_bootorder(bootorder, num, index, NULL))
1811 ret = eficonfig_add_boot_selection_entry(efi_menu, index, selected);
1812 if (ret != EFI_SUCCESS)
1816 if (efi_menu->count >= EFICONFIG_ENTRY_NUM_MAX - 1)
1820 ret = eficonfig_append_quit_entry(efi_menu);
1821 if (ret != EFI_SUCCESS)
1824 ret = eficonfig_process_common(efi_menu, " ** Select Boot Option **",
1825 eficonfig_menu_desc,
1826 eficonfig_display_statusline,
1827 eficonfig_print_entry,
1828 eficonfig_choice_entry);
1830 list_for_each_safe(pos, n, &efi_menu->list) {
1831 entry = list_entry(pos, struct eficonfig_entry, list);
1834 eficonfig_destroy(efi_menu);
1842 * eficonfig_process_edit_boot_option() - handler to edit boot option
1844 * @data: pointer to the data for each entry
1845 * Return: status code
1847 static efi_status_t eficonfig_process_edit_boot_option(void *data)
1851 struct eficonfig_boot_option *bo = NULL;
1854 unsigned int selected;
1856 u16 varname[] = u"Boot####";
1858 ret = eficonfig_show_boot_selection(&selected);
1859 if (ret != EFI_SUCCESS)
1862 bo = calloc(1, sizeof(struct eficonfig_boot_option));
1864 ret = EFI_OUT_OF_RESOURCES;
1868 bo->boot_index = selected;
1869 efi_create_indexed_name(varname, sizeof(varname), "Boot", selected);
1870 load_option = efi_get_var(varname, &efi_global_variable_guid, &size);
1873 ret = EFI_NOT_FOUND;
1877 ret = eficonfig_edit_boot_option(varname, bo, load_option, size,
1878 " ** Edit Boot Option ** ");
1882 if (ret != EFI_SUCCESS && ret != EFI_ABORTED)
1886 /* to stay the parent menu */
1887 ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;
1893 * eficonfig_print_change_boot_order_entry() - print the boot option entry
1895 * @data: pointer to the data associated with each menu entry
1897 static void eficonfig_print_change_boot_order_entry(void *data)
1899 struct eficonfig_entry *entry = data;
1900 bool reverse = (entry->efi_menu->active == entry->num);
1902 if (entry->efi_menu->start > entry->num || entry->efi_menu->end < entry->num)
1905 printf(ANSI_CURSOR_POSITION ANSI_CLEAR_LINE,
1906 (entry->num - entry->efi_menu->start) + EFICONFIG_MENU_HEADER_ROW_NUM + 1, 7);
1909 puts(ANSI_COLOR_REVERSE);
1911 if (entry->num < entry->efi_menu->count - 2) {
1912 if (((struct eficonfig_boot_order_data *)entry->data)->active)
1918 printf("%s", entry->title);
1921 puts(ANSI_COLOR_RESET);
1925 * eficonfig_choice_change_boot_order() - user key input handler
1927 * @data: pointer to the menu entry
1928 * Return: key string to identify the selected entry
1930 char *eficonfig_choice_change_boot_order(void *data)
1932 struct cli_ch_state s_cch, *cch = &s_cch;
1933 struct list_head *pos, *n;
1934 struct efimenu *efi_menu = data;
1935 enum bootmenu_key key = BKEY_NONE;
1936 struct eficonfig_entry *entry, *tmp;
1940 key = bootmenu_loop(NULL, cch);
1944 if (efi_menu->active > 0 &&
1945 efi_menu->active < efi_menu->count - 2) {
1946 list_for_each_safe(pos, n, &efi_menu->list) {
1947 entry = list_entry(pos, struct eficonfig_entry, list);
1948 if (entry->num == efi_menu->active)
1951 tmp = list_entry(pos->prev, struct eficonfig_entry, list);
1954 list_del(&tmp->list);
1955 list_add(&tmp->list, &entry->list);
1957 eficonfig_menu_up(efi_menu);
1961 if (efi_menu->active > 0)
1962 eficonfig_menu_up(efi_menu);
1966 if (efi_menu->active < efi_menu->count - 3) {
1967 list_for_each_safe(pos, n, &efi_menu->list) {
1968 entry = list_entry(pos, struct eficonfig_entry, list);
1969 if (entry->num == efi_menu->active)
1972 tmp = list_entry(pos->next, struct eficonfig_entry, list);
1975 list_del(&entry->list);
1976 list_add(&entry->list, &tmp->list);
1978 eficonfig_menu_down(efi_menu);
1982 if (efi_menu->active < efi_menu->count - 1)
1983 eficonfig_menu_down(efi_menu);
1987 /* force to select "Save" entry */
1988 efi_menu->active = efi_menu->count - 2;
1992 if (efi_menu->active == efi_menu->count - 2) {
1993 list_for_each_prev_safe(pos, n, &efi_menu->list) {
1994 entry = list_entry(pos, struct eficonfig_entry, list);
1995 if (entry->num == efi_menu->active)
2001 if (efi_menu->active == efi_menu->count - 1) {
2002 entry = list_last_entry(&efi_menu->list,
2003 struct eficonfig_entry,
2007 /* Pressed key is not valid, wait next key press */
2010 if (efi_menu->active < efi_menu->count - 2) {
2011 list_for_each_safe(pos, n, &efi_menu->list) {
2012 entry = list_entry(pos, struct eficonfig_entry, list);
2013 if (entry->num == efi_menu->active) {
2014 struct eficonfig_boot_order_data *data = entry->data;
2016 data->active = !data->active;
2021 /* Pressed key is not valid, wait next key press */
2024 entry = list_last_entry(&efi_menu->list,
2025 struct eficonfig_entry, list);
2028 /* Pressed key is not valid, wait next key press */
2035 * eficonfig_process_save_boot_order() - callback function for "Save" entry
2037 * @data: pointer to the data
2038 * Return: status code
2040 static efi_status_t eficonfig_process_save_boot_order(void *data)
2045 struct list_head *pos, *n;
2047 struct efimenu *efi_menu;
2048 struct eficonfig_entry *entry;
2049 struct eficonfig_save_boot_order_data *save_data = data;
2051 efi_menu = save_data->efi_menu;
2054 * The change boot order menu always has "Save" and "Quit" entries.
2055 * !(efi_menu->count - 2) means there is no user defined boot option.
2057 if (!(efi_menu->count - 2))
2060 new_bootorder = calloc(1, (efi_menu->count - 2) * sizeof(u16));
2061 if (!new_bootorder) {
2062 ret = EFI_OUT_OF_RESOURCES;
2066 /* create new BootOrder */
2068 list_for_each_safe(pos, n, &efi_menu->list) {
2069 struct eficonfig_boot_order_data *data;
2071 entry = list_entry(pos, struct eficonfig_entry, list);
2072 /* exit the loop when iteration reaches "Save" */
2073 if (!strncmp(entry->title, "Save", strlen("Save")))
2078 new_bootorder[count++] = data->boot_index;
2081 size = count * sizeof(u16);
2082 ret = efi_set_variable_int(u"BootOrder", &efi_global_variable_guid,
2083 EFI_VARIABLE_NON_VOLATILE |
2084 EFI_VARIABLE_BOOTSERVICE_ACCESS |
2085 EFI_VARIABLE_RUNTIME_ACCESS,
2086 size, new_bootorder, false);
2088 save_data->selected = true;
2090 free(new_bootorder);
2096 * eficonfig_add_change_boot_order_entry() - add boot order entry
2098 * @efi_menu: pointer to the efimenu structure
2099 * @boot_index: boot option index to be added
2100 * @active: flag to include the boot option into BootOrder
2101 * Return: status code
2103 static efi_status_t eficonfig_add_change_boot_order_entry(struct efimenu *efi_menu,
2104 u32 boot_index, bool active)
2110 struct efi_load_option lo;
2111 u16 varname[] = u"Boot####";
2112 struct eficonfig_boot_order_data *data;
2114 efi_create_indexed_name(varname, sizeof(varname), "Boot", boot_index);
2115 load_option = efi_get_var(varname, &efi_global_variable_guid, &size);
2119 ret = efi_deserialize_load_option(&lo, load_option, &size);
2120 if (ret != EFI_SUCCESS)
2123 data = calloc(1, sizeof(*data));
2125 ret = EFI_OUT_OF_RESOURCES;
2129 title = calloc(1, utf16_utf8_strlen(lo.label) + 1);
2132 ret = EFI_OUT_OF_RESOURCES;
2136 utf16_utf8_strcpy(&p, lo.label);
2138 data->boot_index = boot_index;
2139 data->active = active;
2141 ret = eficonfig_append_menu_entry(efi_menu, title, NULL, data);
2142 if (ret != EFI_SUCCESS) {
2155 * eficonfig_create_change_boot_order_entry() - create boot order entry
2157 * @efi_menu: pointer to the efimenu structure
2158 * @bootorder: pointer to the BootOrder variable
2159 * @num: number of BootOrder entry
2160 * Return: status code
2162 static efi_status_t eficonfig_create_change_boot_order_entry(struct efimenu *efi_menu,
2163 u16 *bootorder, efi_uintn_t num)
2168 u16 *var_name16 = NULL;
2169 efi_uintn_t size, buf_size;
2170 struct eficonfig_save_boot_order_data *save_data;
2172 /* list the load option in the order of BootOrder variable */
2173 for (i = 0; i < num; i++) {
2174 if (efi_menu->count >= EFICONFIG_ENTRY_NUM_MAX - 2)
2177 ret = eficonfig_add_change_boot_order_entry(efi_menu, bootorder[i], true);
2178 if (ret != EFI_SUCCESS)
2182 /* list the remaining load option not included in the BootOrder */
2184 var_name16 = malloc(buf_size);
2186 return EFI_OUT_OF_RESOURCES;
2193 if (efi_menu->count >= EFICONFIG_ENTRY_NUM_MAX - 2)
2197 ret = efi_next_variable_name(&buf_size, &var_name16, &guid);
2198 if (ret == EFI_NOT_FOUND)
2200 if (ret != EFI_SUCCESS)
2203 if (efi_varname_is_load_option(var_name16, &index)) {
2204 /* If the index is included in the BootOrder, skip it */
2205 if (search_bootorder(bootorder, num, index, NULL))
2208 ret = eficonfig_add_change_boot_order_entry(efi_menu, index, false);
2209 if (ret != EFI_SUCCESS)
2214 /* add "Save" and "Quit" entries */
2215 title = strdup("Save");
2217 ret = EFI_OUT_OF_RESOURCES;
2221 save_data = malloc(sizeof(struct eficonfig_save_boot_order_data));
2223 ret = EFI_OUT_OF_RESOURCES;
2226 save_data->efi_menu = efi_menu;
2227 save_data->selected = false;
2229 ret = eficonfig_append_menu_entry(efi_menu, title,
2230 eficonfig_process_save_boot_order,
2232 if (ret != EFI_SUCCESS)
2235 ret = eficonfig_append_quit_entry(efi_menu);
2236 if (ret != EFI_SUCCESS)
2239 efi_menu->active = 0;
2247 * eficonfig_process_change_boot_order() - handler to change boot order
2249 * @data: pointer to the data for each entry
2250 * Return: status code
2252 static efi_status_t eficonfig_process_change_boot_order(void *data)
2256 efi_uintn_t num, size;
2257 struct list_head *pos, *n;
2258 struct eficonfig_entry *entry;
2259 struct efimenu *efi_menu;
2261 efi_menu = calloc(1, sizeof(struct efimenu));
2263 return EFI_OUT_OF_RESOURCES;
2265 bootorder = efi_get_var(u"BootOrder", &efi_global_variable_guid, &size);
2267 INIT_LIST_HEAD(&efi_menu->list);
2268 num = size / sizeof(u16);
2269 ret = eficonfig_create_change_boot_order_entry(efi_menu, bootorder, num);
2270 if (ret != EFI_SUCCESS)
2274 ret = eficonfig_process_common(efi_menu,
2275 " ** Change Boot Order **",
2276 eficonfig_change_boot_order_desc,
2277 eficonfig_display_statusline,
2278 eficonfig_print_change_boot_order_entry,
2279 eficonfig_choice_change_boot_order);
2280 /* exit from the menu if user selects the "Save" entry. */
2281 if (ret == EFI_SUCCESS && efi_menu->active == (efi_menu->count - 2)) {
2282 list_for_each_prev_safe(pos, n, &efi_menu->list) {
2283 entry = list_entry(pos, struct eficonfig_entry, list);
2284 if (entry->num == efi_menu->active)
2287 if (((struct eficonfig_save_boot_order_data *)entry->data)->selected)
2290 if (ret != EFI_SUCCESS)
2295 list_for_each_safe(pos, n, &efi_menu->list) {
2296 entry = list_entry(pos, struct eficonfig_entry, list);
2299 eficonfig_destroy(efi_menu);
2301 /* to stay the parent menu */
2302 ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;
2308 * delete_boot_option() - delete selected boot option
2310 * @boot_index: boot option index to delete
2311 * Return: status code
2313 static efi_status_t delete_boot_option(u16 boot_index)
2319 efi_uintn_t num, size;
2321 efi_create_indexed_name(varname, sizeof(varname),
2322 "Boot", boot_index);
2323 ret = efi_set_variable_int(varname, &efi_global_variable_guid,
2325 if (ret != EFI_SUCCESS) {
2326 log_err("delete boot option(%ls) failed\n", varname);
2330 /* update BootOrder if necessary */
2331 bootorder = efi_get_var(u"BootOrder", &efi_global_variable_guid, &size);
2335 num = size / sizeof(u16);
2336 if (!search_bootorder(bootorder, num, boot_index, &index))
2339 memmove(&bootorder[index], &bootorder[index + 1],
2340 (num - index - 1) * sizeof(u16));
2341 size -= sizeof(u16);
2342 ret = efi_set_variable_int(u"BootOrder", &efi_global_variable_guid,
2343 EFI_VARIABLE_NON_VOLATILE |
2344 EFI_VARIABLE_BOOTSERVICE_ACCESS |
2345 EFI_VARIABLE_RUNTIME_ACCESS,
2346 size, bootorder, false);
2352 * eficonfig_process_delete_boot_option() - handler to delete boot option
2354 * @data: pointer to the data for each entry
2355 * Return: status code
2357 static efi_status_t eficonfig_process_delete_boot_option(void *data)
2360 unsigned int selected;
2363 ret = eficonfig_show_boot_selection(&selected);
2364 if (ret == EFI_SUCCESS)
2365 ret = delete_boot_option(selected);
2367 if (ret != EFI_SUCCESS)
2371 /* to stay the parent menu */
2372 ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;
2378 * eficonfig_enumerate_boot_option() - enumerate the possible bootable media
2380 * @opt: pointer to the media boot option structure
2381 * @volume_handles: pointer to the efi handles
2382 * @count: number of efi handle
2383 * Return: status code
2385 efi_status_t eficonfig_enumerate_boot_option(struct eficonfig_media_boot_option *opt,
2386 efi_handle_t *volume_handles, efi_status_t count)
2389 struct efi_handler *handler;
2390 efi_status_t ret = EFI_SUCCESS;
2392 for (i = 0; i < count; i++) {
2394 u16 dev_name[BOOTMENU_DEVICE_NAME_MAX];
2395 char *optional_data;
2396 struct efi_load_option lo;
2397 char buf[BOOTMENU_DEVICE_NAME_MAX];
2398 struct efi_device_path *device_path;
2400 ret = efi_search_protocol(volume_handles[i], &efi_guid_device_path, &handler);
2401 if (ret != EFI_SUCCESS)
2403 ret = efi_protocol_open(handler, (void **)&device_path,
2404 efi_root, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
2405 if (ret != EFI_SUCCESS)
2408 ret = efi_disk_get_device_name(volume_handles[i], buf, BOOTMENU_DEVICE_NAME_MAX);
2409 if (ret != EFI_SUCCESS)
2413 utf8_utf16_strncpy(&p, buf, strlen(buf));
2415 lo.label = dev_name;
2416 lo.attributes = LOAD_OPTION_ACTIVE;
2417 lo.file_path = device_path;
2418 lo.file_path_length = efi_dp_size(device_path) + sizeof(END);
2420 * Set the dedicated guid to optional_data, it is used to identify
2421 * the boot option that automatically generated by the bootmenu.
2422 * efi_serialize_load_option() expects optional_data is null-terminated
2423 * utf8 string, so set the "1234567" string to allocate enough space
2424 * to store guid, instead of realloc the load_option.
2426 lo.optional_data = "1234567";
2427 opt[i].size = efi_serialize_load_option(&lo, (u8 **)&opt[i].lo);
2429 ret = EFI_OUT_OF_RESOURCES;
2433 optional_data = (char *)opt[i].lo + (opt[i].size - u16_strsize(u"1234567"));
2434 memcpy(optional_data, &efi_guid_bootmenu_auto_generated, sizeof(efi_guid_t));
2442 * eficonfig_delete_invalid_boot_option() - delete non-existing boot option
2444 * @opt: pointer to the media boot option structure
2445 * @count: number of media boot option structure
2446 * Return: status code
2448 efi_status_t eficonfig_delete_invalid_boot_option(struct eficonfig_media_boot_option *opt,
2453 u32 i, list_size = 0;
2454 struct efi_load_option lo;
2455 u16 *var_name16 = NULL;
2456 u16 varname[] = u"Boot####";
2457 efi_status_t ret = EFI_SUCCESS;
2458 u16 *delete_index_list = NULL, *p;
2459 efi_uintn_t buf_size;
2462 var_name16 = malloc(buf_size);
2464 return EFI_OUT_OF_RESOURCES;
2472 ret = efi_next_variable_name(&buf_size, &var_name16, &guid);
2473 if (ret == EFI_NOT_FOUND) {
2475 * EFI_NOT_FOUND indicates we retrieved all EFI variables.
2476 * This should be treated as success.
2481 if (ret != EFI_SUCCESS)
2484 if (!efi_varname_is_load_option(var_name16, &index))
2487 efi_create_indexed_name(varname, sizeof(varname), "Boot", index);
2488 load_option = efi_get_var(varname, &efi_global_variable_guid, &size);
2493 ret = efi_deserialize_load_option(&lo, load_option, &size);
2494 if (ret != EFI_SUCCESS)
2497 if (size >= sizeof(efi_guid_bootmenu_auto_generated) &&
2498 !guidcmp(lo.optional_data, &efi_guid_bootmenu_auto_generated)) {
2499 for (i = 0; i < count; i++) {
2500 if (opt[i].size == tmp &&
2501 memcmp(opt[i].lo, load_option, tmp) == 0) {
2502 opt[i].exist = true;
2508 * The entire list of variables must be retrieved by
2509 * efi_get_next_variable_name_int() before deleting the invalid
2510 * boot option, just save the index here.
2513 p = realloc(delete_index_list, sizeof(u32) *
2516 ret = EFI_OUT_OF_RESOURCES;
2519 delete_index_list = p;
2520 delete_index_list[list_size++] = index;
2527 /* delete all invalid boot options */
2528 for (i = 0; i < list_size; i++) {
2529 ret = delete_boot_option(delete_index_list[i]);
2530 if (ret != EFI_SUCCESS)
2536 free(delete_index_list);
2542 * eficonfig_generate_media_device_boot_option() - generate the media device boot option
2544 * This function enumerates all devices supporting EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
2545 * and generate the bootmenu entries.
2546 * This function also provide the BOOT#### variable maintenance for
2547 * the media device entries.
2548 * - Automatically create the BOOT#### variable for the newly detected device,
2549 * this BOOT#### variable is distinguished by the special GUID
2550 * stored in the EFI_LOAD_OPTION.optional_data
2551 * - If the device is not attached to the system, the associated BOOT#### variable
2552 * is automatically deleted.
2554 * Return: status code
2556 efi_status_t eficonfig_generate_media_device_boot_option(void)
2561 efi_handle_t *volume_handles = NULL;
2562 struct eficonfig_media_boot_option *opt = NULL;
2564 ret = efi_locate_handle_buffer_int(BY_PROTOCOL, &efi_simple_file_system_protocol_guid,
2565 NULL, &count, (efi_handle_t **)&volume_handles);
2566 if (ret != EFI_SUCCESS)
2569 opt = calloc(count, sizeof(struct eficonfig_media_boot_option));
2573 /* enumerate all devices supporting EFI_SIMPLE_FILE_SYSTEM_PROTOCOL */
2574 ret = eficonfig_enumerate_boot_option(opt, volume_handles, count);
2575 if (ret != EFI_SUCCESS)
2579 * System hardware configuration may vary depending on the user setup.
2580 * The boot option is automatically added by the bootmenu.
2581 * If the device is not attached to the system, the boot option needs
2584 ret = eficonfig_delete_invalid_boot_option(opt, count);
2585 if (ret != EFI_SUCCESS)
2588 /* add non-existent boot option */
2589 for (i = 0; i < count; i++) {
2593 if (!opt[i].exist) {
2594 ret = eficonfig_get_unused_bootoption(var_name, sizeof(var_name),
2596 if (ret != EFI_SUCCESS)
2599 ret = efi_set_variable_int(var_name, &efi_global_variable_guid,
2600 EFI_VARIABLE_NON_VOLATILE |
2601 EFI_VARIABLE_BOOTSERVICE_ACCESS |
2602 EFI_VARIABLE_RUNTIME_ACCESS,
2603 opt[i].size, opt[i].lo, false);
2604 if (ret != EFI_SUCCESS)
2607 ret = eficonfig_append_bootorder(boot_index);
2608 if (ret != EFI_SUCCESS) {
2609 efi_set_variable_int(var_name, &efi_global_variable_guid,
2618 for (i = 0; i < count; i++)
2622 efi_free_pool(volume_handles);
2628 * eficonfig_init() - do required initialization for eficonfig command
2630 * Return: status code
2632 static efi_status_t eficonfig_init(void)
2634 efi_status_t ret = EFI_SUCCESS;
2636 struct efi_handler *handler;
2637 unsigned long columns, rows;
2640 ret = efi_search_protocol(efi_root, &efi_guid_text_input_protocol, &handler);
2641 if (ret != EFI_SUCCESS)
2644 ret = efi_protocol_open(handler, (void **)&cin, efi_root, NULL,
2645 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
2646 if (ret != EFI_SUCCESS)
2648 ret = efi_search_protocol(efi_root, &efi_guid_text_output_protocol, &handler);
2649 if (ret != EFI_SUCCESS)
2652 ret = efi_protocol_open(handler, (void **)&cout, efi_root, NULL,
2653 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
2654 if (ret != EFI_SUCCESS)
2657 cout->query_mode(cout, cout->mode->mode, &columns, &rows);
2658 avail_row = rows - (EFICONFIG_MENU_HEADER_ROW_NUM +
2659 EFICONFIG_MENU_DESC_ROW_NUM);
2660 if (avail_row <= 0) {
2661 eficonfig_print_msg("Console size is too small!");
2662 return EFI_INVALID_PARAMETER;
2664 /* TODO: Should we check the minimum column size? */
2672 static const struct eficonfig_item maintenance_menu_items[] = {
2673 {"Add Boot Option", eficonfig_process_add_boot_option},
2674 {"Edit Boot Option", eficonfig_process_edit_boot_option},
2675 {"Change Boot Order", eficonfig_process_change_boot_order},
2676 {"Delete Boot Option", eficonfig_process_delete_boot_option},
2677 #if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT) && IS_ENABLED(CONFIG_EFI_MM_COMM_TEE))
2678 {"Secure Boot Configuration", eficonfig_process_secure_boot_config},
2680 {"Quit", eficonfig_process_quit},
2684 * do_eficonfig() - execute `eficonfig` command
2686 * @cmdtp: table entry describing command
2687 * @flag: bitmap indicating how the command was invoked
2688 * @argc: number of arguments
2689 * @argv: command line arguments
2690 * Return: status code
2692 static int do_eficonfig(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
2695 struct efimenu *efi_menu;
2698 return CMD_RET_USAGE;
2700 ret = efi_init_obj_list();
2701 if (ret != EFI_SUCCESS) {
2702 log_err("Error: Cannot initialize UEFI sub-system, r = %lu\n",
2703 ret & ~EFI_ERROR_MASK);
2705 return CMD_RET_FAILURE;
2708 ret = eficonfig_init();
2709 if (ret != EFI_SUCCESS)
2710 return CMD_RET_FAILURE;
2712 ret = eficonfig_generate_media_device_boot_option();
2713 if (ret != EFI_SUCCESS && ret != EFI_NOT_FOUND)
2717 efi_menu = eficonfig_create_fixed_menu(maintenance_menu_items,
2718 ARRAY_SIZE(maintenance_menu_items));
2720 return CMD_RET_FAILURE;
2722 ret = eficonfig_process_common(efi_menu,
2723 " ** UEFI Maintenance Menu **",
2724 eficonfig_menu_desc,
2725 eficonfig_display_statusline,
2726 eficonfig_print_entry,
2727 eficonfig_choice_entry);
2728 eficonfig_destroy(efi_menu);
2730 if (ret == EFI_ABORTED)
2734 return CMD_RET_SUCCESS;
2738 eficonfig, 1, 0, do_eficonfig,
2739 "provide menu-driven UEFI variable maintenance interface",