Merge branch '2022-11-23-assorted-fixes'
[platform/kernel/u-boot.git] / cmd / eficonfig.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  *  Menu-driven UEFI Variable maintenance
4  *
5  *  Copyright (c) 2022 Masahisa Kojima, Linaro Limited
6  */
7
8 #include <ansi.h>
9 #include <common.h>
10 #include <charset.h>
11 #include <efi_loader.h>
12 #include <efi_load_initrd.h>
13 #include <efi_config.h>
14 #include <efi_variable.h>
15 #include <log.h>
16 #include <malloc.h>
17 #include <menu.h>
18 #include <sort.h>
19 #include <watchdog.h>
20 #include <asm/unaligned.h>
21 #include <linux/delay.h>
22
23 static struct efi_simple_text_input_protocol *cin;
24
25 #define EFICONFIG_DESCRIPTION_MAX 32
26 #define EFICONFIG_OPTIONAL_DATA_MAX 64
27
28 /**
29  * struct eficonfig_filepath_info - structure to be used to store file path
30  *
31  * @name:       file or directory name
32  * @list:       list structure
33  */
34 struct eficonfig_filepath_info {
35         char *name;
36         struct list_head list;
37 };
38
39 /**
40  * struct eficonfig_boot_option - structure to be used for updating UEFI boot option
41  *
42  * @file_info:          user selected file info
43  * @initrd_info:        user selected initrd file info
44  * @boot_index:         index of the boot option
45  * @description:        pointer to the description string
46  * @optional_data:      pointer to the optional_data
47  * @edit_completed:     flag indicates edit complete
48  */
49 struct eficonfig_boot_option {
50         struct eficonfig_select_file_info file_info;
51         struct eficonfig_select_file_info initrd_info;
52         unsigned int boot_index;
53         u16 *description;
54         u16 *optional_data;
55         bool edit_completed;
56 };
57
58 /**
59  * struct eficonfig_volume_entry_data - structure to be used to store volume info
60  *
61  * @file_info:  pointer to file info structure
62  * @v:          pointer to the protocol interface
63  * @dp:         pointer to the device path
64  */
65 struct eficonfig_volume_entry_data {
66         struct eficonfig_select_file_info *file_info;
67         struct efi_simple_file_system_protocol *v;
68         struct efi_device_path *dp;
69 };
70
71 /**
72  * struct eficonfig_file_entry_data - structure to be used to store file info
73  *
74  * @file_info:          pointer to file info structure
75  * @is_directory:       flag to identify the directory or file
76  * @file_name:          name of directory or file
77  */
78 struct eficonfig_file_entry_data {
79         struct eficonfig_select_file_info *file_info;
80         bool is_directory;
81         char *file_name;
82 };
83
84 /**
85  * struct eficonfig_boot_selection_data - structure to be used to select the boot option entry
86  *
87  * @boot_index: index of the boot option
88  * @selected:           pointer to store the selected index in the BootOrder variable
89  */
90 struct eficonfig_boot_selection_data {
91         u16 boot_index;
92         int *selected;
93 };
94
95 /**
96  * struct eficonfig_boot_order_data - structure to be used to update BootOrder variable
97  *
98  * @boot_index:         boot option index
99  * @active:             flag to include the boot option into BootOrder variable
100  */
101 struct eficonfig_boot_order_data {
102         u32 boot_index;
103         bool active;
104 };
105
106 /**
107  * eficonfig_print_msg() - print message
108  *
109  * display the message to the user, user proceeds the screen
110  * with any key press.
111  *
112  * @items:              pointer to the structure of each menu entry
113  * @count:              the number of menu entry
114  * @menu_header:        pointer to the menu header string
115  * Return:      status code
116  */
117 void eficonfig_print_msg(char *msg)
118 {
119         /* Flush input */
120         while (tstc())
121                 getchar();
122
123         printf(ANSI_CURSOR_HIDE
124                ANSI_CLEAR_CONSOLE
125                ANSI_CURSOR_POSITION
126                "%s\n\n  Press any key to continue", 3, 4, msg);
127
128         getchar();
129 }
130
131 /**
132  * eficonfig_print_entry() - print each menu entry
133  *
134  * @data:       pointer to the data associated with each menu entry
135  */
136 static void eficonfig_print_entry(void *data)
137 {
138         struct eficonfig_entry *entry = data;
139         int reverse = (entry->efi_menu->active == entry->num);
140
141         /* TODO: support scroll or page for many entries */
142
143         /*
144          * Move cursor to line where the entry will be drawn (entry->num)
145          * First 3 lines(menu header) + 1 empty line
146          */
147         printf(ANSI_CURSOR_POSITION, entry->num + 4, 7);
148
149         if (reverse)
150                 puts(ANSI_COLOR_REVERSE);
151
152         printf("%s", entry->title);
153
154         if (reverse)
155                 puts(ANSI_COLOR_RESET);
156 }
157
158 /**
159  * eficonfig_display_statusline() - print status line
160  *
161  * @m:  pointer to the menu structure
162  */
163 static void eficonfig_display_statusline(struct menu *m)
164 {
165         struct eficonfig_entry *entry;
166
167         if (menu_default_choice(m, (void *)&entry) < 0)
168                 return;
169
170         printf(ANSI_CURSOR_POSITION
171               "\n%s\n"
172                ANSI_CURSOR_POSITION ANSI_CLEAR_LINE ANSI_CURSOR_POSITION
173                "  Press UP/DOWN to move, ENTER to select, ESC/CTRL+C to quit"
174                ANSI_CLEAR_LINE_TO_END ANSI_CURSOR_POSITION ANSI_CLEAR_LINE,
175                1, 1, entry->efi_menu->menu_header, entry->efi_menu->count + 5, 1,
176                entry->efi_menu->count + 6, 1, entry->efi_menu->count + 7, 1);
177 }
178
179 /**
180  * eficonfig_choice_entry() - user key input handler
181  *
182  * @data:       pointer to the efimenu structure
183  * Return:      key string to identify the selected entry
184  */
185 static char *eficonfig_choice_entry(void *data)
186 {
187         int esc = 0;
188         struct list_head *pos, *n;
189         struct eficonfig_entry *entry;
190         enum bootmenu_key key = KEY_NONE;
191         struct efimenu *efi_menu = data;
192
193         while (1) {
194                 bootmenu_loop((struct bootmenu_data *)efi_menu, &key, &esc);
195
196                 switch (key) {
197                 case KEY_UP:
198                         if (efi_menu->active > 0)
199                                 --efi_menu->active;
200                         /* no menu key selected, regenerate menu */
201                         return NULL;
202                 case KEY_DOWN:
203                         if (efi_menu->active < efi_menu->count - 1)
204                                 ++efi_menu->active;
205                         /* no menu key selected, regenerate menu */
206                         return NULL;
207                 case KEY_SELECT:
208                         list_for_each_safe(pos, n, &efi_menu->list) {
209                                 entry = list_entry(pos, struct eficonfig_entry, list);
210                                 if (entry->num == efi_menu->active)
211                                         return entry->key;
212                         }
213                         break;
214                 case KEY_QUIT:
215                         /* Quit by choosing the last entry */
216                         entry = list_last_entry(&efi_menu->list, struct eficonfig_entry, list);
217                         return entry->key;
218                 default:
219                         /* Pressed key is not valid, no need to regenerate the menu */
220                         break;
221                 }
222         }
223 }
224
225 /**
226  * eficonfig_destroy() - destroy efimenu
227  *
228  * @efi_menu:   pointer to the efimenu structure
229  */
230 void eficonfig_destroy(struct efimenu *efi_menu)
231 {
232         struct list_head *pos, *n;
233         struct eficonfig_entry *entry;
234
235         if (!efi_menu)
236                 return;
237
238         list_for_each_safe(pos, n, &efi_menu->list) {
239                 entry = list_entry(pos, struct eficonfig_entry, list);
240                 free(entry->title);
241                 list_del(&entry->list);
242                 free(entry);
243         }
244         free(efi_menu->menu_header);
245         free(efi_menu);
246 }
247
248 /**
249  * eficonfig_process_quit() - callback function for "Quit" entry
250  *
251  * @data:       pointer to the data
252  * Return:      status code
253  */
254 efi_status_t eficonfig_process_quit(void *data)
255 {
256         return EFI_ABORTED;
257 }
258
259 /**
260  * eficonfig_append_menu_entry() - append menu item
261  *
262  * @efi_menu:   pointer to the efimenu structure
263  * @title:      pointer to the entry title
264  * @func:       callback of each entry
265  * @data:       pointer to the data to be passed to each entry callback
266  * Return:      status code
267  */
268 efi_status_t eficonfig_append_menu_entry(struct efimenu *efi_menu,
269                                          char *title, eficonfig_entry_func func,
270                                          void *data)
271 {
272         struct eficonfig_entry *entry;
273
274         if (efi_menu->count >= EFICONFIG_ENTRY_NUM_MAX)
275                 return EFI_OUT_OF_RESOURCES;
276
277         entry = calloc(1, sizeof(struct eficonfig_entry));
278         if (!entry)
279                 return EFI_OUT_OF_RESOURCES;
280
281         entry->title = title;
282         sprintf(entry->key, "%d", efi_menu->count);
283         entry->efi_menu = efi_menu;
284         entry->func = func;
285         entry->data = data;
286         entry->num = efi_menu->count++;
287         list_add_tail(&entry->list, &efi_menu->list);
288
289         return EFI_SUCCESS;
290 }
291
292 /**
293  * eficonfig_append_quit_entry() - append quit entry
294  *
295  * @efi_menu:   pointer to the efimenu structure
296  * Return:      status code
297  */
298 efi_status_t eficonfig_append_quit_entry(struct efimenu *efi_menu)
299 {
300         char *title;
301         efi_status_t ret;
302
303         title = strdup("Quit");
304         if (!title)
305                 return EFI_OUT_OF_RESOURCES;
306
307         ret = eficonfig_append_menu_entry(efi_menu, title, eficonfig_process_quit, NULL);
308         if (ret != EFI_SUCCESS)
309                 free(title);
310
311         return ret;
312 }
313
314 /**
315  * eficonfig_create_fixed_menu() - create fixed entry menu structure
316  *
317  * @items:      pointer to the menu entry item
318  * @count:      the number of menu entry
319  * Return:      pointer to the efimenu structure
320  */
321 void *eficonfig_create_fixed_menu(const struct eficonfig_item *items, int count)
322 {
323         u32 i;
324         char *title;
325         efi_status_t ret;
326         struct efimenu *efi_menu;
327         const struct eficonfig_item *iter = items;
328
329         efi_menu = calloc(1, sizeof(struct efimenu));
330         if (!efi_menu)
331                 return NULL;
332
333         INIT_LIST_HEAD(&efi_menu->list);
334         for (i = 0; i < count; i++, iter++) {
335                 title = strdup(iter->title);
336                 if (!title)
337                         goto out;
338
339                 ret = eficonfig_append_menu_entry(efi_menu, title, iter->func, iter->data);
340                 if (ret != EFI_SUCCESS) {
341                         free(title);
342                         goto out;
343                 }
344         }
345
346         return efi_menu;
347 out:
348         eficonfig_destroy(efi_menu);
349
350         return NULL;
351 }
352
353 /**
354  * eficonfig_process_common() - main handler for UEFI menu
355  *
356  * Construct the structures required to show the menu, then handle
357  * the user input interacting with u-boot menu functions.
358  *
359  * @efi_menu:           pointer to the efimenu structure
360  * @menu_header:        pointer to the menu header string
361  * Return:              status code
362  */
363 efi_status_t eficonfig_process_common(struct efimenu *efi_menu, char *menu_header)
364 {
365         struct menu *menu;
366         void *choice = NULL;
367         struct list_head *pos, *n;
368         struct eficonfig_entry *entry;
369         efi_status_t ret = EFI_SUCCESS;
370
371         if (efi_menu->count > EFICONFIG_ENTRY_NUM_MAX)
372                 return EFI_OUT_OF_RESOURCES;
373
374         efi_menu->delay = -1;
375         efi_menu->active = 0;
376
377         if (menu_header) {
378                 efi_menu->menu_header = strdup(menu_header);
379                 if (!efi_menu->menu_header)
380                         return EFI_OUT_OF_RESOURCES;
381         }
382
383         menu = menu_create(NULL, 0, 1, eficonfig_display_statusline,
384                            eficonfig_print_entry, eficonfig_choice_entry,
385                            efi_menu);
386         if (!menu)
387                 return EFI_INVALID_PARAMETER;
388
389         list_for_each_safe(pos, n, &efi_menu->list) {
390                 entry = list_entry(pos, struct eficonfig_entry, list);
391                 if (!menu_item_add(menu, entry->key, entry)) {
392                         ret = EFI_INVALID_PARAMETER;
393                         goto out;
394                 }
395         }
396
397         entry = list_first_entry_or_null(&efi_menu->list, struct eficonfig_entry, list);
398         if (entry)
399                 menu_default_set(menu, entry->key);
400
401         printf(ANSI_CURSOR_HIDE
402                ANSI_CLEAR_CONSOLE
403                ANSI_CURSOR_POSITION, 1, 1);
404
405         if (menu_get_choice(menu, &choice)) {
406                 entry = choice;
407                 if (entry->func)
408                         ret = entry->func(entry->data);
409         }
410 out:
411         menu_destroy(menu);
412
413         printf(ANSI_CLEAR_CONSOLE
414                ANSI_CURSOR_POSITION
415                ANSI_CURSOR_SHOW, 1, 1);
416
417         return ret;
418 }
419
420 /**
421  * eficonfig_volume_selected() - handler of volume selection
422  *
423  * @data:       pointer to the data of selected entry
424  * Return:      status code
425  */
426 static efi_status_t eficonfig_volume_selected(void *data)
427 {
428         struct eficonfig_volume_entry_data *info = data;
429
430         if (info) {
431                 info->file_info->current_volume = info->v;
432                 info->file_info->dp_volume = info->dp;
433         }
434
435         return EFI_SUCCESS;
436 }
437
438 /**
439  * eficonfig_create_device_path() - create device path
440  *
441  * @dp_volume:  pointer to the volume
442  * @current_path: pointer to the file path u16 string
443  * Return:
444  * device path or NULL. Caller must free the returned value
445  */
446 struct efi_device_path *eficonfig_create_device_path(struct efi_device_path *dp_volume,
447                                                      u16 *current_path)
448 {
449         char *p;
450         void *buf;
451         efi_uintn_t fp_size;
452         struct efi_device_path *dp;
453         struct efi_device_path_file_path *fp;
454
455         fp_size = sizeof(struct efi_device_path) +
456                   ((u16_strlen(current_path) + 1) * sizeof(u16));
457         buf = calloc(1, fp_size + sizeof(END));
458         if (!buf)
459                 return NULL;
460
461         fp = buf;
462         fp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE,
463         fp->dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH,
464         fp->dp.length = (u16)fp_size;
465         u16_strcpy(fp->str, current_path);
466
467         p = buf;
468         p += fp_size;
469         *((struct efi_device_path *)p) = END;
470
471         dp = efi_dp_append(dp_volume, (struct efi_device_path *)buf);
472         free(buf);
473
474         return dp;
475 }
476
477 /**
478  * eficonfig_file_selected() - handler of file selection
479  *
480  * @data:       pointer to the data of selected entry
481  * Return:      status code
482  */
483 static efi_status_t eficonfig_file_selected(void *data)
484 {
485         u16 *tmp;
486         struct eficonfig_file_entry_data *info = data;
487
488         if (!info)
489                 return EFI_INVALID_PARAMETER;
490
491         if (!strcmp(info->file_name, "..")) {
492                 struct eficonfig_filepath_info *iter;
493                 struct list_head *pos, *n;
494                 int is_last;
495                 char *filepath;
496                 tmp = info->file_info->current_path;
497
498                 memset(info->file_info->current_path, 0, EFICONFIG_FILE_PATH_BUF_SIZE);
499                 filepath = calloc(1, EFICONFIG_FILE_PATH_MAX);
500                 if (!filepath)
501                         return EFI_OUT_OF_RESOURCES;
502
503                 list_for_each_safe(pos, n, &info->file_info->filepath_list) {
504                         iter = list_entry(pos, struct eficonfig_filepath_info, list);
505
506                         is_last = list_is_last(&iter->list, &info->file_info->filepath_list);
507                         if (is_last) {
508                                 list_del(&iter->list);
509                                 free(iter->name);
510                                 free(iter);
511                                 break;
512                         }
513                         strlcat(filepath, iter->name, EFICONFIG_FILE_PATH_MAX);
514                 }
515                 utf8_utf16_strcpy(&tmp, filepath);
516         } else {
517                 size_t new_len;
518                 struct eficonfig_filepath_info *filepath_info;
519
520                 new_len = u16_strlen(info->file_info->current_path) +
521                                      strlen(info->file_name);
522                 if (new_len >= EFICONFIG_FILE_PATH_MAX) {
523                         eficonfig_print_msg("File path is too long!");
524                         return EFI_INVALID_PARAMETER;
525                 }
526                 tmp = &info->file_info->current_path[u16_strlen(info->file_info->current_path)];
527                 utf8_utf16_strcpy(&tmp, info->file_name);
528
529                 filepath_info = calloc(1, sizeof(struct eficonfig_filepath_info));
530                 if (!filepath_info)
531                         return EFI_OUT_OF_RESOURCES;
532
533                 filepath_info->name = strdup(info->file_name);
534                 if (!filepath_info->name) {
535                         free(filepath_info);
536                         return EFI_OUT_OF_RESOURCES;
537                 }
538                 list_add_tail(&filepath_info->list, &info->file_info->filepath_list);
539
540                 if (!info->is_directory)
541                         info->file_info->file_selected = true;
542         }
543
544         return EFI_SUCCESS;
545 }
546
547 /**
548  * eficonfig_select_volume() - construct the volume selection menu
549  *
550  * @file_info:  pointer to the file selection structure
551  * Return:      status code
552  */
553 static efi_status_t eficonfig_select_volume(struct eficonfig_select_file_info *file_info)
554 {
555         u32 i;
556         efi_status_t ret;
557         efi_uintn_t count;
558         struct efimenu *efi_menu;
559         struct list_head *pos, *n;
560         struct efi_handler *handler;
561         struct eficonfig_entry *entry;
562         struct efi_device_path *device_path;
563         efi_handle_t *volume_handles = NULL;
564         struct efi_simple_file_system_protocol *v;
565
566         ret = efi_locate_handle_buffer_int(BY_PROTOCOL, &efi_simple_file_system_protocol_guid,
567                                            NULL, &count, (efi_handle_t **)&volume_handles);
568         if (ret != EFI_SUCCESS) {
569                 eficonfig_print_msg("No block device found!");
570                 return ret;
571         }
572
573         efi_menu = calloc(1, sizeof(struct efimenu));
574         if (!efi_menu)
575                 return EFI_OUT_OF_RESOURCES;
576
577         INIT_LIST_HEAD(&efi_menu->list);
578         for (i = 0; i < count; i++) {
579                 char *devname;
580                 struct efi_block_io *block_io;
581                 struct eficonfig_volume_entry_data *info;
582
583                 if (efi_menu->count >= EFICONFIG_ENTRY_NUM_MAX - 1)
584                         break;
585
586                 ret = efi_search_protocol(volume_handles[i],
587                                           &efi_simple_file_system_protocol_guid, &handler);
588                 if (ret != EFI_SUCCESS)
589                         continue;
590                 ret = efi_protocol_open(handler, (void **)&v, efi_root, NULL,
591                                         EFI_OPEN_PROTOCOL_GET_PROTOCOL);
592                 if (ret != EFI_SUCCESS)
593                         continue;
594
595                 ret = efi_search_protocol(volume_handles[i], &efi_guid_device_path, &handler);
596                 if (ret != EFI_SUCCESS)
597                         continue;
598                 ret = efi_protocol_open(handler, (void **)&device_path,
599                                         efi_root, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
600                 if (ret != EFI_SUCCESS)
601                         continue;
602
603                 ret = efi_search_protocol(volume_handles[i], &efi_block_io_guid, &handler);
604                 if (ret != EFI_SUCCESS)
605                         continue;
606                 ret = efi_protocol_open(handler, (void **)&block_io,
607                                         efi_root, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
608                 if (ret != EFI_SUCCESS)
609                         continue;
610
611                 info = calloc(1, sizeof(struct eficonfig_volume_entry_data));
612                 if (!info) {
613                         ret = EFI_OUT_OF_RESOURCES;
614                         goto out;
615                 }
616
617                 devname = calloc(1, BOOTMENU_DEVICE_NAME_MAX);
618                 if (!devname) {
619                         free(info);
620                         ret = EFI_OUT_OF_RESOURCES;
621                         goto out;
622                 }
623                 ret = efi_disk_get_device_name(volume_handles[i], devname,
624                                                BOOTMENU_DEVICE_NAME_MAX);
625                 if (ret != EFI_SUCCESS) {
626                         free(info);
627                         goto out;
628                 }
629
630                 info->v = v;
631                 info->dp = device_path;
632                 info->file_info = file_info;
633                 ret = eficonfig_append_menu_entry(efi_menu, devname, eficonfig_volume_selected,
634                                                   info);
635                 if (ret != EFI_SUCCESS) {
636                         free(info);
637                         goto out;
638                 }
639         }
640
641         ret = eficonfig_append_quit_entry(efi_menu);
642         if (ret != EFI_SUCCESS)
643                 goto out;
644
645         ret = eficonfig_process_common(efi_menu, "  ** Select Volume **");
646 out:
647         efi_free_pool(volume_handles);
648         list_for_each_safe(pos, n, &efi_menu->list) {
649                 entry = list_entry(pos, struct eficonfig_entry, list);
650                 free(entry->data);
651         }
652         eficonfig_destroy(efi_menu);
653
654         return ret;
655 }
656
657 /**
658  * sort_file() - sort the file name in ascii order
659  *
660  * @data1:      pointer to the file entry data
661  * @data2:      pointer to the file entry data
662  * Return:      -1 if the data1 file name is less than data2 file name,
663  *              0 if both file name match,
664  *              1 if the data1 file name is greater thant data2 file name.
665  */
666 static int sort_file(const void *arg1, const void *arg2)
667 {
668         const struct eficonfig_file_entry_data *data1, *data2;
669
670         data1 = *((const struct eficonfig_file_entry_data **)arg1);
671         data2 = *((const struct eficonfig_file_entry_data **)arg2);
672
673         return strcasecmp(data1->file_name, data2->file_name);
674 }
675
676 /**
677  * eficonfig_create_file_entry() - construct the file menu entry
678  *
679  * @efi_menu:   pointer to the efimenu structure
680  * @count:      number of the directory and file
681  * @tmp_infos:  pointer to the entry data array
682  * @f:          pointer to the file handle
683  * @buf:        pointer to the buffer to store the directory information
684  * @file_info:  pointer to the file selection structure
685  * Return:      status code
686  */
687 static efi_status_t
688 eficonfig_create_file_entry(struct efimenu *efi_menu, u32 count,
689                             struct eficonfig_file_entry_data **tmp_infos,
690                             struct efi_file_handle *f, struct efi_file_info *buf,
691                             struct eficonfig_select_file_info *file_info)
692 {
693         char *name, *p;
694         efi_uintn_t len;
695         efi_status_t ret;
696         u32 i, entry_num = 0;
697         struct eficonfig_file_entry_data *info;
698
699         EFI_CALL(f->setpos(f, 0));
700         /* Read directory and construct menu structure */
701         for (i = 0; i < count; i++) {
702                 if (entry_num >= EFICONFIG_ENTRY_NUM_MAX - 1)
703                         break;
704
705                 len = sizeof(struct efi_file_info) + EFICONFIG_FILE_PATH_BUF_SIZE;
706                 ret = EFI_CALL(f->read(f, &len, buf));
707                 if (ret != EFI_SUCCESS || len == 0)
708                         break;
709
710                 info = calloc(1, sizeof(struct eficonfig_file_entry_data));
711                 if (!info) {
712                         ret = EFI_OUT_OF_RESOURCES;
713                         goto out;
714                 }
715
716                 /* append '\\' at the end of directory name */
717                 name = calloc(1, utf16_utf8_strlen(buf->file_name) + 2);
718                 if (!name) {
719                         ret = EFI_OUT_OF_RESOURCES;
720                         free(info);
721                         goto out;
722                 }
723                 p = name;
724                 utf16_utf8_strcpy(&p, buf->file_name);
725                 if (buf->attribute & EFI_FILE_DIRECTORY) {
726                         /* filter out u'.' */
727                         if (!u16_strcmp(buf->file_name, u".")) {
728                                 free(info);
729                                 free(name);
730                                 continue;
731                         }
732                         name[u16_strlen(buf->file_name)] = '\\';
733                         info->is_directory = true;
734                 }
735
736                 info->file_name = name;
737                 info->file_info = file_info;
738                 tmp_infos[entry_num++] = info;
739         }
740
741         qsort(tmp_infos, entry_num, sizeof(*tmp_infos),
742               (int (*)(const void *, const void *))sort_file);
743
744         for (i = 0; i < entry_num; i++) {
745                 ret = eficonfig_append_menu_entry(efi_menu, tmp_infos[i]->file_name,
746                                                   eficonfig_file_selected, tmp_infos[i]);
747                 if (ret != EFI_SUCCESS)
748                         goto out;
749         }
750
751 out:
752         return ret;
753 }
754
755 /**
756  * eficonfig_show_file_selection() - construct the file selection menu
757  *
758  * @file_info:  pointer to the file selection structure
759  * @root:       pointer to the file handle
760  * Return:      status code
761  */
762 static efi_status_t eficonfig_show_file_selection(struct eficonfig_select_file_info *file_info,
763                                                   struct efi_file_handle *root)
764 {
765         u32 count = 0, i;
766         efi_uintn_t len;
767         efi_status_t ret;
768         struct efimenu *efi_menu;
769         struct efi_file_handle *f;
770         struct efi_file_info *buf;
771         struct eficonfig_file_entry_data **tmp_infos;
772
773         buf = calloc(1, sizeof(struct efi_file_info) + EFICONFIG_FILE_PATH_BUF_SIZE);
774         if (!buf)
775                 return EFI_OUT_OF_RESOURCES;
776
777         while (!file_info->file_selected) {
778                 efi_menu = calloc(1, sizeof(struct efimenu));
779                 if (!efi_menu) {
780                         ret = EFI_OUT_OF_RESOURCES;
781                         goto out;
782                 }
783                 INIT_LIST_HEAD(&efi_menu->list);
784
785                 ret = EFI_CALL(root->open(root, &f, file_info->current_path,
786                                           EFI_FILE_MODE_READ, 0));
787                 if (ret != EFI_SUCCESS) {
788                         eficonfig_print_msg("Reading volume failed!");
789                         free(efi_menu);
790                         ret = EFI_ABORTED;
791                         goto out;
792                 }
793
794                 /* Count the number of directory entries */
795                 for (;;) {
796                         len = sizeof(struct efi_file_info) + EFICONFIG_FILE_PATH_BUF_SIZE;
797                         ret = EFI_CALL(f->read(f, &len, buf));
798                         if (ret != EFI_SUCCESS || len == 0)
799                                 break;
800
801                         count++;
802                 }
803
804                 /* allocate array to sort the entry */
805                 tmp_infos = calloc(count, sizeof(*tmp_infos));
806                 if (!tmp_infos) {
807                         ret = EFI_OUT_OF_RESOURCES;
808                         goto err;
809                 }
810
811                 ret = eficonfig_create_file_entry(efi_menu, count, tmp_infos,
812                                                   f, buf, file_info);
813                 if (ret != EFI_SUCCESS)
814                         goto err;
815
816                 ret = eficonfig_append_quit_entry(efi_menu);
817                 if (ret != EFI_SUCCESS)
818                         goto err;
819
820                 ret = eficonfig_process_common(efi_menu, "  ** Select File **");
821 err:
822                 EFI_CALL(f->close(f));
823                 eficonfig_destroy(efi_menu);
824
825                 if (tmp_infos) {
826                         for (i = 0; i < count; i++)
827                                 free(tmp_infos[i]);
828                 }
829
830                 free(tmp_infos);
831
832                 if (ret != EFI_SUCCESS)
833                         break;
834         }
835
836 out:
837         free(buf);
838
839         return ret;
840 }
841
842 /**
843  * handle_user_input() - handle user input
844  *
845  * @buf:        pointer to the buffer
846  * @buf_size:   size of the buffer
847  * @cursor_col: cursor column for user input
848  * @msg:        pointer to the string to display
849  * Return:      status code
850  */
851 static efi_status_t handle_user_input(u16 *buf, int buf_size,
852                                       int cursor_col, char *msg)
853 {
854         u16 *tmp;
855         efi_status_t ret;
856
857         printf(ANSI_CLEAR_CONSOLE
858                ANSI_CURSOR_POSITION
859                "%s"
860                ANSI_CURSOR_POSITION
861                "  Press ENTER to complete, ESC/CTRL+C to quit",
862                0, 1, msg, 8, 1);
863
864         /* tmp is used to accept user cancel */
865         tmp = calloc(1, buf_size * sizeof(u16));
866         if (!tmp)
867                 return EFI_OUT_OF_RESOURCES;
868
869         ret = efi_console_get_u16_string(cin, tmp, buf_size, NULL, 4, cursor_col);
870         if (ret == EFI_SUCCESS)
871                 u16_strcpy(buf, tmp);
872
873         free(tmp);
874
875         /* to stay the parent menu */
876         ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;
877
878         return ret;
879 }
880
881 /**
882  * eficonfig_boot_add_enter_description() - handle user input for description
883  *
884  * @data:       pointer to the internal boot option structure
885  * Return:      status code
886  */
887 static efi_status_t eficonfig_boot_add_enter_description(void *data)
888 {
889         struct eficonfig_boot_option *bo = data;
890
891         return handle_user_input(bo->description, EFICONFIG_DESCRIPTION_MAX, 22,
892                                  "\n  ** Edit Description **\n"
893                                  "\n"
894                                  "  enter description: ");
895 }
896
897 /**
898  * eficonfig_boot_add_optional_data() - handle user input for optional data
899  *
900  * @data:       pointer to the internal boot option structure
901  * Return:      status code
902  */
903 static efi_status_t eficonfig_boot_add_optional_data(void *data)
904 {
905         struct eficonfig_boot_option *bo = data;
906
907         return handle_user_input(bo->optional_data, EFICONFIG_OPTIONAL_DATA_MAX, 24,
908                                  "\n  ** Edit Optional Data **\n"
909                                  "\n"
910                                  "  enter optional data:");
911 }
912
913 /**
914  * eficonfig_boot_edit_save() - handler to save the boot option
915  *
916  * @data:       pointer to the internal boot option structure
917  * Return:      status code
918  */
919 static efi_status_t eficonfig_boot_edit_save(void *data)
920 {
921         struct eficonfig_boot_option *bo = data;
922
923         if (u16_strlen(bo->description) == 0) {
924                 eficonfig_print_msg("Boot Description is empty!");
925                 bo->edit_completed = false;
926                 return EFI_NOT_READY;
927         }
928         if (u16_strlen(bo->file_info.current_path) == 0) {
929                 eficonfig_print_msg("File is not selected!");
930                 bo->edit_completed = false;
931                 return EFI_NOT_READY;
932         }
933
934         bo->edit_completed = true;
935
936         return EFI_SUCCESS;
937 }
938
939 /**
940  * eficonfig_process_clear_file_selection() - callback function for "Clear" entry
941  *
942  * @data:       pointer to the data
943  * Return:      status code
944  */
945 efi_status_t eficonfig_process_clear_file_selection(void *data)
946 {
947         struct eficonfig_select_file_info *file_info = data;
948
949         /* clear the existing file information */
950         file_info->current_volume = NULL;
951         file_info->current_path[0] = u'\0';
952         file_info->dp_volume = NULL;
953
954         return EFI_ABORTED;
955 }
956
957 static struct eficonfig_item select_file_menu_items[] = {
958         {"Select File", eficonfig_process_select_file},
959         {"Clear", eficonfig_process_clear_file_selection},
960         {"Quit", eficonfig_process_quit},
961 };
962
963 /**
964  * eficonfig_process_show_file_option() - display select file option
965  *
966  * @file_info:  pointer to the file information structure
967  * Return:      status code
968  */
969 efi_status_t eficonfig_process_show_file_option(void *data)
970 {
971         efi_status_t ret;
972         struct efimenu *efi_menu;
973
974         select_file_menu_items[0].data = data;
975         select_file_menu_items[1].data = data;
976         efi_menu = eficonfig_create_fixed_menu(select_file_menu_items,
977                                                ARRAY_SIZE(select_file_menu_items));
978         if (!efi_menu)
979                 return EFI_OUT_OF_RESOURCES;
980
981         ret = eficonfig_process_common(efi_menu, "  ** Update File **");
982         if (ret != EFI_SUCCESS) /* User selects "Clear" or "Quit" */
983                 ret = EFI_NOT_READY;
984
985         eficonfig_destroy(efi_menu);
986
987         return ret;
988 }
989
990 /**
991  * eficonfig_process_select_file() - handle user file selection
992  *
993  * @data:       pointer to the data
994  * Return:      status code
995  */
996 efi_status_t eficonfig_process_select_file(void *data)
997 {
998         size_t len;
999         efi_status_t ret;
1000         struct list_head *pos, *n;
1001         struct efi_file_handle *root;
1002         struct eficonfig_filepath_info *item;
1003         struct eficonfig_select_file_info *tmp = NULL;
1004         struct eficonfig_select_file_info *file_info = data;
1005
1006         tmp = calloc(1, sizeof(struct eficonfig_select_file_info));
1007         if (!tmp)
1008                 return EFI_OUT_OF_RESOURCES;
1009
1010         tmp->current_path = calloc(1, EFICONFIG_FILE_PATH_BUF_SIZE);
1011         if (!tmp->current_path) {
1012                 free(tmp);
1013                 return EFI_OUT_OF_RESOURCES;
1014         }
1015         INIT_LIST_HEAD(&tmp->filepath_list);
1016
1017         while (!tmp->file_selected) {
1018                 tmp->current_volume = NULL;
1019                 memset(tmp->current_path, 0, EFICONFIG_FILE_PATH_BUF_SIZE);
1020
1021                 ret = eficonfig_select_volume(tmp);
1022                 if (ret != EFI_SUCCESS)
1023                         goto out;
1024
1025                 if (!tmp->current_volume)
1026                         return EFI_INVALID_PARAMETER;
1027
1028                 ret = EFI_CALL(tmp->current_volume->open_volume(tmp->current_volume, &root));
1029                 if (ret != EFI_SUCCESS)
1030                         goto out;
1031
1032                 ret = eficonfig_show_file_selection(tmp, root);
1033                 if (ret == EFI_ABORTED)
1034                         continue;
1035                 if (ret != EFI_SUCCESS)
1036                         goto out;
1037         }
1038
1039 out:
1040         if (ret == EFI_SUCCESS) {
1041                 len = u16_strlen(tmp->current_path);
1042                 len = (len >= EFICONFIG_FILE_PATH_MAX) ? (EFICONFIG_FILE_PATH_MAX - 1) : len;
1043                 memcpy(file_info->current_path, tmp->current_path, len * sizeof(u16));
1044                 file_info->current_path[len] = u'\0';
1045                 file_info->current_volume = tmp->current_volume;
1046                 file_info->dp_volume = tmp->dp_volume;
1047         }
1048
1049         list_for_each_safe(pos, n, &tmp->filepath_list) {
1050                 item = list_entry(pos, struct eficonfig_filepath_info, list);
1051                 list_del(&item->list);
1052                 free(item->name);
1053                 free(item);
1054         }
1055         free(tmp->current_path);
1056         free(tmp);
1057
1058         /* to stay the parent menu */
1059         ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;
1060
1061         return ret;
1062 }
1063
1064 /**
1065  * eficonfig_get_unused_bootoption() - get unused "Boot####" index
1066  *
1067  * @buf:        pointer to the buffer to store boot option variable name
1068  * @buf_size:   buffer size
1069  * @index:      pointer to store the index in the BootOrder variable
1070  * Return:      status code
1071  */
1072 efi_status_t eficonfig_get_unused_bootoption(u16 *buf, efi_uintn_t buf_size,
1073                                              unsigned int *index)
1074 {
1075         u32 i;
1076         efi_status_t ret;
1077         efi_uintn_t size;
1078
1079         if (buf_size < u16_strsize(u"Boot####"))
1080                 return EFI_BUFFER_TOO_SMALL;
1081
1082         for (i = 0; i <= 0xFFFF; i++) {
1083                 size = 0;
1084                 efi_create_indexed_name(buf, buf_size, "Boot", i);
1085                 ret = efi_get_variable_int(buf, &efi_global_variable_guid,
1086                                            NULL, &size, NULL, NULL);
1087                 if (ret == EFI_BUFFER_TOO_SMALL)
1088                         continue;
1089                 else
1090                         break;
1091         }
1092
1093         if (i > 0xFFFF)
1094                 return EFI_OUT_OF_RESOURCES;
1095
1096         *index = i;
1097
1098         return EFI_SUCCESS;
1099 }
1100
1101 /**
1102  * eficonfig_set_boot_option() - set boot option
1103  *
1104  * @varname:            pointer to variable name
1105  * @dp:                 pointer to device path
1106  * @label:              pointer to label string
1107  * @optional_data:      pointer to optional data
1108  * Return:              status code
1109  */
1110 static efi_status_t eficonfig_set_boot_option(u16 *varname, struct efi_device_path *dp,
1111                                               efi_uintn_t dp_size, u16 *label, char *optional_data)
1112 {
1113         void *p = NULL;
1114         efi_status_t ret;
1115         efi_uintn_t size;
1116         struct efi_load_option lo;
1117
1118         lo.file_path = dp;
1119         lo.file_path_length = dp_size;
1120         lo.attributes = LOAD_OPTION_ACTIVE;
1121         lo.optional_data = optional_data;
1122         lo.label = label;
1123
1124         size = efi_serialize_load_option(&lo, (u8 **)&p);
1125         if (!size)
1126                 return EFI_INVALID_PARAMETER;
1127
1128         ret = efi_set_variable_int(varname, &efi_global_variable_guid,
1129                                    EFI_VARIABLE_NON_VOLATILE |
1130                                    EFI_VARIABLE_BOOTSERVICE_ACCESS |
1131                                    EFI_VARIABLE_RUNTIME_ACCESS,
1132                                    size, p, false);
1133         free(p);
1134
1135         return ret;
1136 }
1137
1138 /**
1139  * eficonfig_append_bootorder() - append new boot option in BootOrder variable
1140  *
1141  * @index:      "Boot####" index to append to BootOrder variable
1142  * Return:      status code
1143  */
1144 efi_status_t eficonfig_append_bootorder(u16 index)
1145 {
1146         u16 *bootorder;
1147         efi_status_t ret;
1148         u16 *new_bootorder = NULL;
1149         efi_uintn_t last, size, new_size;
1150
1151         /* append new boot option */
1152         bootorder = efi_get_var(u"BootOrder", &efi_global_variable_guid, &size);
1153         last = size / sizeof(u16);
1154         new_size = size + sizeof(u16);
1155         new_bootorder = calloc(1, new_size);
1156         if (!new_bootorder) {
1157                 ret = EFI_OUT_OF_RESOURCES;
1158                 goto out;
1159         }
1160         memcpy(new_bootorder, bootorder, size);
1161         new_bootorder[last] = index;
1162
1163         ret = efi_set_variable_int(u"BootOrder", &efi_global_variable_guid,
1164                                    EFI_VARIABLE_NON_VOLATILE |
1165                                    EFI_VARIABLE_BOOTSERVICE_ACCESS |
1166                                    EFI_VARIABLE_RUNTIME_ACCESS,
1167                                    new_size, new_bootorder, false);
1168         if (ret != EFI_SUCCESS)
1169                 goto out;
1170
1171 out:
1172         free(bootorder);
1173         free(new_bootorder);
1174
1175         return ret;
1176 }
1177
1178 /**
1179  * create_boot_option_entry() - create boot option entry
1180  *
1181  * @efi_menu:   pointer to the efimenu structure
1182  * @title:      pointer to the entry title
1183  * @val:        pointer to boot option label
1184  * @func:       callback of each entry
1185  * @data:       pointer to the data to be passed to each entry callback
1186  * Return:      status code
1187  */
1188 static efi_status_t create_boot_option_entry(struct efimenu *efi_menu, char *title, u16 *val,
1189                                              eficonfig_entry_func func, void *data)
1190 {
1191         u32 len;
1192         char *p, *buf;
1193
1194         len = strlen(title) + 1;
1195         if (val)
1196                 len += utf16_utf8_strlen(val);
1197         buf = calloc(1, len);
1198         if (!buf)
1199                 return EFI_OUT_OF_RESOURCES;
1200
1201         strcpy(buf, title);
1202         if (val) {
1203                 p = buf + strlen(title);
1204                 utf16_utf8_strcpy(&p, val);
1205         }
1206
1207         return eficonfig_append_menu_entry(efi_menu, buf, func, data);
1208 }
1209
1210 /**
1211  * prepare_file_selection_entry() - prepare file selection entry
1212  *
1213  * @efi_menu:   pointer to the efimenu structure
1214  * @title:      pointer to the title string
1215  * @file_info:  pointer to the file info
1216  * Return:      status code
1217  */
1218 static efi_status_t prepare_file_selection_entry(struct efimenu *efi_menu, char *title,
1219                                                  struct eficonfig_select_file_info *file_info)
1220 {
1221         u32 len;
1222         efi_status_t ret;
1223         u16 *file_name = NULL, *p;
1224         efi_handle_t handle;
1225         char *devname;
1226
1227         devname = calloc(1, EFICONFIG_VOLUME_PATH_MAX + 1);
1228         if (!devname)
1229                 return EFI_OUT_OF_RESOURCES;
1230
1231         /* get the device name only when the user already selected the file path */
1232         handle = efi_dp_find_obj(file_info->dp_volume, NULL, NULL);
1233         if (handle) {
1234                 ret = efi_disk_get_device_name(handle, devname, EFICONFIG_VOLUME_PATH_MAX);
1235                 if (ret != EFI_SUCCESS)
1236                         goto out;
1237         }
1238
1239         /*
1240          * If the preconfigured volume does not exist in the system, display the text
1241          * converted volume device path instead of U-Boot friendly name(e.g. "usb 0:1").
1242          */
1243         if (!handle && file_info->dp_volume) {
1244                 u16 *dp_str;
1245                 char *q = devname;
1246
1247                 dp_str = efi_dp_str(file_info->dp_volume);
1248                 if (dp_str)
1249                         utf16_utf8_strncpy(&q, dp_str, EFICONFIG_VOLUME_PATH_MAX);
1250
1251                 efi_free_pool(dp_str);
1252         }
1253
1254         /* append u'/' to devname, it is just for display purpose. */
1255         if (file_info->current_path[0] != u'\0' && file_info->current_path[0] != u'/')
1256                 strlcat(devname, "/", EFICONFIG_VOLUME_PATH_MAX + 1);
1257
1258         len = strlen(devname);
1259         len += utf16_utf8_strlen(file_info->current_path) + 1;
1260         file_name = calloc(1, len * sizeof(u16));
1261         if (!file_name) {
1262                 ret = EFI_OUT_OF_RESOURCES;
1263                 goto out;
1264         }
1265
1266         p = file_name;
1267         utf8_utf16_strcpy(&p, devname);
1268         u16_strlcat(file_name, file_info->current_path, len);
1269         ret = create_boot_option_entry(efi_menu, title, file_name,
1270                                        eficonfig_process_show_file_option, file_info);
1271 out:
1272         free(devname);
1273         free(file_name);
1274
1275         return ret;
1276 }
1277
1278 /**
1279  * eficonfig_show_boot_option() - prepare menu entry for editing boot option
1280  *
1281  * Construct the structures to create edit boot option menu
1282  *
1283  * @bo:         pointer to the boot option
1284  * @header_str: pointer to the header string
1285  * Return:      status code
1286  */
1287 static efi_status_t eficonfig_show_boot_option(struct eficonfig_boot_option *bo,
1288                                                char *header_str)
1289 {
1290         efi_status_t ret;
1291         struct efimenu *efi_menu;
1292
1293         efi_menu = calloc(1, sizeof(struct efimenu));
1294         if (!efi_menu)
1295                 return EFI_OUT_OF_RESOURCES;
1296
1297         INIT_LIST_HEAD(&efi_menu->list);
1298
1299         ret = create_boot_option_entry(efi_menu, "Description: ", bo->description,
1300                                        eficonfig_boot_add_enter_description, bo);
1301         if (ret != EFI_SUCCESS)
1302                 goto out;
1303
1304         ret = prepare_file_selection_entry(efi_menu, "File: ", &bo->file_info);
1305         if (ret != EFI_SUCCESS)
1306                 goto out;
1307
1308         ret = prepare_file_selection_entry(efi_menu, "Initrd File: ", &bo->initrd_info);
1309         if (ret != EFI_SUCCESS)
1310                 goto out;
1311
1312         ret = create_boot_option_entry(efi_menu, "Optional Data: ", bo->optional_data,
1313                                        eficonfig_boot_add_optional_data, bo);
1314         if (ret != EFI_SUCCESS)
1315                 goto out;
1316
1317         ret = create_boot_option_entry(efi_menu, "Save", NULL,
1318                                        eficonfig_boot_edit_save, bo);
1319         if (ret != EFI_SUCCESS)
1320                 goto out;
1321
1322         ret = create_boot_option_entry(efi_menu, "Quit", NULL,
1323                                        eficonfig_process_quit, NULL);
1324         if (ret != EFI_SUCCESS)
1325                 goto out;
1326
1327         ret = eficonfig_process_common(efi_menu, header_str);
1328 out:
1329         eficonfig_destroy(efi_menu);
1330
1331         return ret;
1332 }
1333
1334 /**
1335  * fill_file_info() - fill the file info from efi_device_path structure
1336  *
1337  * @dp:         pointer to the device path
1338  * @file_info:  pointer to the file info structure
1339  * @device_dp:  pointer to the volume device path
1340  */
1341 static void fill_file_info(struct efi_device_path *dp,
1342                            struct eficonfig_select_file_info *file_info,
1343                            struct efi_device_path *device_dp)
1344 {
1345         u16 *file_str, *p;
1346         struct efi_device_path *file_dp = NULL;
1347
1348         efi_dp_split_file_path(dp, &device_dp, &file_dp);
1349         file_info->dp_volume = device_dp;
1350
1351         if (file_dp) {
1352                 file_str = efi_dp_str(file_dp);
1353                 /*
1354                  * efi_convert_device_path_to_text() automatically adds u'/' at the
1355                  * beginning of file name, remove u'/' before copying to current_path
1356                  */
1357                 p = file_str;
1358                 if (p[0] == u'/')
1359                         p++;
1360
1361                 u16_strcpy(file_info->current_path, p);
1362                 efi_free_pool(file_dp);
1363                 efi_free_pool(file_str);
1364         }
1365 }
1366
1367 /**
1368  * eficonfig_edit_boot_option() - prepare boot option structure for editing
1369  *
1370  * Construct the boot option structure and copy the existing value
1371  *
1372  * @varname:            pointer to the UEFI variable name
1373  * @bo:                 pointer to the boot option
1374  * @load_option:        pointer to the load option
1375  * @load_option_size:   size of the load option
1376  * @header_str:         pointer to the header string
1377  * Return       :       status code
1378  */
1379 static efi_status_t eficonfig_edit_boot_option(u16 *varname, struct eficonfig_boot_option *bo,
1380                                                void *load_option, efi_uintn_t load_option_size,
1381                                                char *header_str)
1382 {
1383         size_t len;
1384         efi_status_t ret;
1385         char *tmp = NULL, *p;
1386         struct efi_load_option lo = {0};
1387         efi_uintn_t final_dp_size;
1388         struct efi_device_path *dp = NULL;
1389         efi_uintn_t size = load_option_size;
1390         struct efi_device_path *final_dp = NULL;
1391         struct efi_device_path *device_dp = NULL;
1392         struct efi_device_path *initrd_dp = NULL;
1393         struct efi_device_path *initrd_device_dp = NULL;
1394
1395         const struct efi_initrd_dp id_dp = {
1396                 .vendor = {
1397                         {
1398                         DEVICE_PATH_TYPE_MEDIA_DEVICE,
1399                         DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
1400                         sizeof(id_dp.vendor),
1401                         },
1402                         EFI_INITRD_MEDIA_GUID,
1403                 },
1404                 .end = {
1405                         DEVICE_PATH_TYPE_END,
1406                         DEVICE_PATH_SUB_TYPE_END,
1407                         sizeof(id_dp.end),
1408                 }
1409         };
1410
1411         bo->file_info.current_path = calloc(1, EFICONFIG_FILE_PATH_BUF_SIZE);
1412         if (!bo->file_info.current_path) {
1413                 ret =  EFI_OUT_OF_RESOURCES;
1414                 goto out;
1415         }
1416
1417         bo->initrd_info.current_path = calloc(1, EFICONFIG_FILE_PATH_BUF_SIZE);
1418         if (!bo->file_info.current_path) {
1419                 ret =  EFI_OUT_OF_RESOURCES;
1420                 goto out;
1421         }
1422
1423         bo->description = calloc(1, EFICONFIG_DESCRIPTION_MAX * sizeof(u16));
1424         if (!bo->description) {
1425                 ret =  EFI_OUT_OF_RESOURCES;
1426                 goto out;
1427         }
1428
1429         bo->optional_data = calloc(1, EFICONFIG_OPTIONAL_DATA_MAX * sizeof(u16));
1430         if (!bo->optional_data) {
1431                 ret =  EFI_OUT_OF_RESOURCES;
1432                 goto out;
1433         }
1434
1435         /* copy the preset value */
1436         if (load_option) {
1437                 ret = efi_deserialize_load_option(&lo, load_option, &size);
1438                 if (ret != EFI_SUCCESS)
1439                         goto out;
1440
1441                 if (!lo.label) {
1442                         ret = EFI_INVALID_PARAMETER;
1443                         goto out;
1444                 }
1445                 /* truncate the long label string */
1446                 if (u16_strlen(lo.label) >= EFICONFIG_DESCRIPTION_MAX)
1447                         lo.label[EFICONFIG_DESCRIPTION_MAX - 1] = u'\0';
1448
1449                 u16_strcpy(bo->description, lo.label);
1450
1451                 /* EFI image file path is a first instance */
1452                 if (lo.file_path)
1453                         fill_file_info(lo.file_path, &bo->file_info, device_dp);
1454
1455                 /* Initrd file path(optional) is placed at second instance. */
1456                 initrd_dp = efi_dp_from_lo(&lo, &efi_lf2_initrd_guid);
1457                 if (initrd_dp) {
1458                         fill_file_info(initrd_dp, &bo->initrd_info, initrd_device_dp);
1459                         efi_free_pool(initrd_dp);
1460                 }
1461
1462                 if (size > 0)
1463                         memcpy(bo->optional_data, lo.optional_data, size);
1464         }
1465
1466         while (1) {
1467                 ret = eficonfig_show_boot_option(bo, header_str);
1468                 if (ret == EFI_SUCCESS && bo->edit_completed)
1469                         break;
1470                 if (ret == EFI_NOT_READY)
1471                         continue;
1472                 if (ret != EFI_SUCCESS)
1473                         goto out;
1474         }
1475
1476         if (bo->initrd_info.dp_volume) {
1477                 dp = eficonfig_create_device_path(bo->initrd_info.dp_volume,
1478                                                  bo->initrd_info.current_path);
1479                 if (!dp) {
1480                         ret = EFI_OUT_OF_RESOURCES;
1481                         goto out;
1482                 }
1483                 initrd_dp = efi_dp_append((const struct efi_device_path *)&id_dp, dp);
1484                 efi_free_pool(dp);
1485         }
1486
1487         dp = eficonfig_create_device_path(bo->file_info.dp_volume, bo->file_info.current_path);
1488         if (!dp) {
1489                 ret = EFI_OUT_OF_RESOURCES;
1490                 goto out;
1491         }
1492         final_dp_size = efi_dp_size(dp) + sizeof(END);
1493         if (initrd_dp) {
1494                 final_dp = efi_dp_concat(dp, initrd_dp);
1495                 final_dp_size += efi_dp_size(initrd_dp) + sizeof(END);
1496         } else {
1497                 final_dp = efi_dp_dup(dp);
1498         }
1499         efi_free_pool(dp);
1500
1501         if (!final_dp)
1502                 goto out;
1503
1504         if (utf16_utf8_strlen(bo->optional_data)) {
1505                 len = utf16_utf8_strlen(bo->optional_data) + 1;
1506                 tmp = calloc(1, len);
1507                 if (!tmp)
1508                         goto out;
1509                 p = tmp;
1510                 utf16_utf8_strncpy(&p, bo->optional_data, u16_strlen(bo->optional_data));
1511         }
1512
1513         ret = eficonfig_set_boot_option(varname, final_dp, final_dp_size, bo->description, tmp);
1514 out:
1515         free(tmp);
1516         free(bo->optional_data);
1517         free(bo->description);
1518         free(bo->file_info.current_path);
1519         free(bo->initrd_info.current_path);
1520         efi_free_pool(device_dp);
1521         efi_free_pool(initrd_device_dp);
1522         efi_free_pool(initrd_dp);
1523         efi_free_pool(final_dp);
1524
1525         return ret;
1526 }
1527
1528 /**
1529  * eficonfig_process_add_boot_option() - handler to add boot option
1530  *
1531  * @data:       pointer to the data for each entry
1532  * Return:      status code
1533  */
1534 static efi_status_t eficonfig_process_add_boot_option(void *data)
1535 {
1536         u16 varname[9];
1537         efi_status_t ret;
1538         struct eficonfig_boot_option *bo = NULL;
1539
1540         bo = calloc(1, sizeof(struct eficonfig_boot_option));
1541         if (!bo)
1542                 return EFI_OUT_OF_RESOURCES;
1543
1544         ret = eficonfig_get_unused_bootoption(varname, sizeof(varname), &bo->boot_index);
1545         if (ret != EFI_SUCCESS)
1546                 return ret;
1547
1548         ret = eficonfig_edit_boot_option(varname, bo, NULL, 0,  "  ** Add Boot Option ** ");
1549         if (ret != EFI_SUCCESS)
1550                 goto out;
1551
1552         ret = eficonfig_append_bootorder((u16)bo->boot_index);
1553         if (ret != EFI_SUCCESS)
1554                 goto out;
1555
1556 out:
1557         free(bo);
1558
1559         /* to stay the parent menu */
1560         ret = (ret == EFI_ABORTED) ? EFI_SUCCESS : ret;
1561
1562         return ret;
1563 }
1564
1565 /**
1566  * eficonfig_process_boot_selected() - handler to select boot option entry
1567  *
1568  * @data:       pointer to the data for each entry
1569  * Return:      status code
1570  */
1571 static efi_status_t eficonfig_process_boot_selected(void *data)
1572 {
1573         struct eficonfig_boot_selection_data *info = data;
1574
1575         if (info)
1576                 *info->selected = info->boot_index;
1577
1578         return EFI_SUCCESS;
1579 }
1580
1581 /**
1582  * search_bootorder() - search the boot option index in BootOrder
1583  *
1584  * @bootorder:  pointer to the BootOrder variable
1585  * @num:        number of BootOrder entry
1586  * @target:     target boot option index to search
1587  * @index:      pointer to store the index of BootOrder variable
1588  * Return:      true if exists, false otherwise
1589  */
1590 static bool search_bootorder(u16 *bootorder, efi_uintn_t num, u32 target, u32 *index)
1591 {
1592         u32 i;
1593
1594         for (i = 0; i < num; i++) {
1595                 if (target == bootorder[i]) {
1596                         if (index)
1597                                 *index = i;
1598
1599                         return true;
1600                 }
1601         }
1602
1603         return false;
1604 }
1605
1606 /**
1607  * eficonfig_add_boot_selection_entry() - add boot option menu entry
1608  *
1609  * @efi_menu:   pointer to store the efimenu structure
1610  * @boot_index: boot option index to be added
1611  * @selected:   pointer to store the selected boot option index
1612  * Return:      status code
1613  */
1614 static efi_status_t eficonfig_add_boot_selection_entry(struct efimenu *efi_menu,
1615                                                        unsigned int boot_index,
1616                                                        unsigned int *selected)
1617 {
1618         char *buf, *p;
1619         efi_status_t ret;
1620         efi_uintn_t size;
1621         void *load_option;
1622         struct efi_load_option lo;
1623         u16 varname[] = u"Boot####";
1624         struct eficonfig_boot_selection_data *info;
1625
1626         efi_create_indexed_name(varname, sizeof(varname), "Boot", boot_index);
1627         load_option = efi_get_var(varname, &efi_global_variable_guid, &size);
1628         if (!load_option)
1629                 return EFI_SUCCESS;
1630
1631         ret = efi_deserialize_load_option(&lo, load_option, &size);
1632         if (ret != EFI_SUCCESS) {
1633                 log_warning("Invalid load option for %ls\n", varname);
1634                 free(load_option);
1635                 return ret;
1636         }
1637
1638         if (size >= sizeof(efi_guid_t) &&
1639             !guidcmp(lo.optional_data, &efi_guid_bootmenu_auto_generated)) {
1640                 /*
1641                  * auto generated entry has GUID in optional_data,
1642                  * skip auto generated entry because it will be generated
1643                  * again even if it is edited or deleted.
1644                  */
1645                 free(load_option);
1646                 return EFI_SUCCESS;
1647         }
1648
1649         info = calloc(1, sizeof(struct eficonfig_boot_selection_data));
1650         if (!info) {
1651                 free(load_option);
1652                 return EFI_OUT_OF_RESOURCES;
1653         }
1654
1655         buf = calloc(1, utf16_utf8_strlen(lo.label) + 1);
1656         if (!buf) {
1657                 free(load_option);
1658                 free(info);
1659                 return EFI_OUT_OF_RESOURCES;
1660         }
1661         p = buf;
1662         utf16_utf8_strcpy(&p, lo.label);
1663         info->boot_index = boot_index;
1664         info->selected = selected;
1665         ret = eficonfig_append_menu_entry(efi_menu, buf, eficonfig_process_boot_selected, info);
1666         if (ret != EFI_SUCCESS) {
1667                 free(load_option);
1668                 free(info);
1669                 return ret;
1670         }
1671         free(load_option);
1672
1673         return EFI_SUCCESS;
1674 }
1675
1676 /**
1677  * eficonfig_show_boot_selection() - construct boot option menu entry
1678  *
1679  * @selected:   pointer to store the selected boot option index
1680  * Return:      status code
1681  */
1682 static efi_status_t eficonfig_show_boot_selection(unsigned int *selected)
1683 {
1684         u32 i;
1685         u16 *bootorder;
1686         efi_status_t ret;
1687         efi_uintn_t num, size;
1688         struct efimenu *efi_menu;
1689         struct list_head *pos, *n;
1690         struct eficonfig_entry *entry;
1691
1692         efi_menu = calloc(1, sizeof(struct efimenu));
1693         if (!efi_menu)
1694                 return EFI_OUT_OF_RESOURCES;
1695
1696         bootorder = efi_get_var(u"BootOrder", &efi_global_variable_guid, &size);
1697
1698         INIT_LIST_HEAD(&efi_menu->list);
1699         num = size / sizeof(u16);
1700         /* list the load option in the order of BootOrder variable */
1701         for (i = 0; i < num; i++) {
1702                 ret = eficonfig_add_boot_selection_entry(efi_menu, bootorder[i], selected);
1703                 if (ret != EFI_SUCCESS)
1704                         goto out;
1705
1706                 if (efi_menu->count >= EFICONFIG_ENTRY_NUM_MAX - 1)
1707                         break;
1708         }
1709
1710         /* list the remaining load option not included in the BootOrder */
1711         for (i = 0; i <= 0xFFFF; i++) {
1712                 /* If the index is included in the BootOrder, skip it */
1713                 if (search_bootorder(bootorder, num, i, NULL))
1714                         continue;
1715
1716                 ret = eficonfig_add_boot_selection_entry(efi_menu, i, selected);
1717                 if (ret != EFI_SUCCESS)
1718                         goto out;
1719
1720                 if (efi_menu->count >= EFICONFIG_ENTRY_NUM_MAX - 1)
1721                         break;
1722         }
1723
1724         ret = eficonfig_append_quit_entry(efi_menu);
1725         if (ret != EFI_SUCCESS)
1726                 goto out;
1727
1728         ret = eficonfig_process_common(efi_menu, "  ** Select Boot Option **");
1729 out:
1730         list_for_each_safe(pos, n, &efi_menu->list) {
1731                 entry = list_entry(pos, struct eficonfig_entry, list);
1732                 free(entry->data);
1733         }
1734         eficonfig_destroy(efi_menu);
1735
1736         return ret;
1737 }
1738
1739 /**
1740  * eficonfig_process_edit_boot_option() - handler to edit boot option
1741  *
1742  * @data:       pointer to the data for each entry
1743  * Return:      status code
1744  */
1745 static efi_status_t eficonfig_process_edit_boot_option(void *data)
1746 {
1747         efi_status_t ret;
1748         efi_uintn_t size;
1749         struct eficonfig_boot_option *bo = NULL;
1750
1751         while (1) {
1752                 unsigned int selected;
1753                 void *load_option;
1754                 u16 varname[] = u"Boot####";
1755
1756                 ret = eficonfig_show_boot_selection(&selected);
1757                 if (ret != EFI_SUCCESS)
1758                         break;
1759
1760                 bo = calloc(1, sizeof(struct eficonfig_boot_option));
1761                 if (!bo) {
1762                         ret = EFI_OUT_OF_RESOURCES;
1763                         goto out;
1764                 }
1765
1766                 bo->boot_index = selected;
1767                 efi_create_indexed_name(varname, sizeof(varname), "Boot", selected);
1768                 load_option = efi_get_var(varname, &efi_global_variable_guid, &size);
1769                 if (!load_option) {
1770                         free(bo);
1771                         ret = EFI_NOT_FOUND;
1772                         goto out;
1773                 }
1774
1775                 ret = eficonfig_edit_boot_option(varname, bo, load_option, size,
1776                                                  "  ** Edit Boot Option ** ");
1777
1778                 free(load_option);
1779                 free(bo);
1780                 if (ret != EFI_SUCCESS && ret != EFI_ABORTED)
1781                         break;
1782         }
1783 out:
1784         /* to stay the parent menu */
1785         ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;
1786
1787         return ret;
1788 }
1789
1790 /**
1791  * eficonfig_display_change_boot_order() - display the BootOrder list
1792  *
1793  * @efi_menu:   pointer to the efimenu structure
1794  * Return:      status code
1795  */
1796 static void eficonfig_display_change_boot_order(struct efimenu *efi_menu)
1797 {
1798         bool reverse;
1799         struct list_head *pos, *n;
1800         struct eficonfig_entry *entry;
1801
1802         printf(ANSI_CLEAR_CONSOLE ANSI_CURSOR_POSITION
1803                "\n  ** Change Boot Order **\n"
1804                ANSI_CURSOR_POSITION
1805                "  Press UP/DOWN to move, +/- to change order"
1806                ANSI_CURSOR_POSITION
1807                "  Press SPACE to activate or deactivate the entry"
1808                ANSI_CURSOR_POSITION
1809                "  Select [Save] to complete, ESC/CTRL+C to quit"
1810                ANSI_CURSOR_POSITION ANSI_CLEAR_LINE,
1811                1, 1, efi_menu->count + 5, 1, efi_menu->count + 6, 1,
1812                efi_menu->count + 7, 1,  efi_menu->count + 8, 1);
1813
1814         /* draw boot option list */
1815         list_for_each_safe(pos, n, &efi_menu->list) {
1816                 entry = list_entry(pos, struct eficonfig_entry, list);
1817                 reverse = (entry->num == efi_menu->active);
1818
1819                 printf(ANSI_CURSOR_POSITION, entry->num + 4, 7);
1820
1821                 if (reverse)
1822                         puts(ANSI_COLOR_REVERSE);
1823
1824                 if (entry->num < efi_menu->count - 2) {
1825                         if (((struct eficonfig_boot_order_data *)entry->data)->active)
1826                                 printf("[*]  ");
1827                         else
1828                                 printf("[ ]  ");
1829                 }
1830
1831                 printf("%s", entry->title);
1832
1833                 if (reverse)
1834                         puts(ANSI_COLOR_RESET);
1835         }
1836 }
1837
1838 /**
1839  * eficonfig_choice_change_boot_order() - handle the BootOrder update
1840  *
1841  * @efi_menu:   pointer to the efimenu structure
1842  * Return:      status code
1843  */
1844 static efi_status_t eficonfig_choice_change_boot_order(struct efimenu *efi_menu)
1845 {
1846         int esc = 0;
1847         struct list_head *pos, *n;
1848         enum bootmenu_key key = KEY_NONE;
1849         struct eficonfig_entry *entry, *tmp;
1850
1851         while (1) {
1852                 bootmenu_loop(NULL, &key, &esc);
1853
1854                 switch (key) {
1855                 case KEY_PLUS:
1856                         if (efi_menu->active > 0) {
1857                                 list_for_each_safe(pos, n, &efi_menu->list) {
1858                                         entry = list_entry(pos, struct eficonfig_entry, list);
1859                                         if (entry->num == efi_menu->active)
1860                                                 break;
1861                                 }
1862                                 tmp = list_entry(pos->prev, struct eficonfig_entry, list);
1863                                 entry->num--;
1864                                 tmp->num++;
1865                                 list_del(&tmp->list);
1866                                 list_add(&tmp->list, &entry->list);
1867                         }
1868                         fallthrough;
1869                 case KEY_UP:
1870                         if (efi_menu->active > 0)
1871                                 --efi_menu->active;
1872                         return EFI_NOT_READY;
1873                 case KEY_MINUS:
1874                         if (efi_menu->active < efi_menu->count - 3) {
1875                                 list_for_each_safe(pos, n, &efi_menu->list) {
1876                                         entry = list_entry(pos, struct eficonfig_entry, list);
1877                                         if (entry->num == efi_menu->active)
1878                                                 break;
1879                                 }
1880                                 tmp = list_entry(pos->next, struct eficonfig_entry, list);
1881                                 entry->num++;
1882                                 tmp->num--;
1883                                 list_del(&entry->list);
1884                                 list_add(&entry->list, &tmp->list);
1885
1886                                 ++efi_menu->active;
1887                         }
1888                         return EFI_NOT_READY;
1889                 case KEY_DOWN:
1890                         if (efi_menu->active < efi_menu->count - 1)
1891                                 ++efi_menu->active;
1892                         return EFI_NOT_READY;
1893                 case KEY_SELECT:
1894                         /* "Save" */
1895                         if (efi_menu->active == efi_menu->count - 2)
1896                                 return EFI_SUCCESS;
1897
1898                         /* "Quit" */
1899                         if (efi_menu->active == efi_menu->count - 1)
1900                                 return EFI_ABORTED;
1901
1902                         break;
1903                 case KEY_SPACE:
1904                         if (efi_menu->active < efi_menu->count - 2) {
1905                                 list_for_each_safe(pos, n, &efi_menu->list) {
1906                                         entry = list_entry(pos, struct eficonfig_entry, list);
1907                                         if (entry->num == efi_menu->active) {
1908                                                 struct eficonfig_boot_order_data *data = entry->data;
1909
1910                                                 data->active = !data->active;
1911                                                 return EFI_NOT_READY;
1912                                         }
1913                                 }
1914                         }
1915                         break;
1916                 case KEY_QUIT:
1917                         return EFI_ABORTED;
1918                 default:
1919                         /* Pressed key is not valid, no need to regenerate the menu */
1920                         break;
1921                 }
1922         }
1923 }
1924
1925 /**
1926  * eficonfig_add_change_boot_order_entry() - add boot order entry
1927  *
1928  * @efi_menu:   pointer to the efimenu structure
1929  * @boot_index: boot option index to be added
1930  * @active:     flag to include the boot option into BootOrder
1931  * Return:      status code
1932  */
1933 static efi_status_t eficonfig_add_change_boot_order_entry(struct efimenu *efi_menu,
1934                                                           u32 boot_index, bool active)
1935 {
1936         char *title, *p;
1937         efi_status_t ret;
1938         efi_uintn_t size;
1939         void *load_option;
1940         struct efi_load_option lo;
1941         u16 varname[] = u"Boot####";
1942         struct eficonfig_boot_order_data *data;
1943
1944         efi_create_indexed_name(varname, sizeof(varname), "Boot", boot_index);
1945         load_option = efi_get_var(varname, &efi_global_variable_guid, &size);
1946         if (!load_option)
1947                 return EFI_SUCCESS;
1948
1949         ret = efi_deserialize_load_option(&lo, load_option, &size);
1950         if (ret != EFI_SUCCESS)
1951                 goto out;
1952
1953         data = calloc(1, sizeof(*data));
1954         if (!data) {
1955                 ret = EFI_OUT_OF_RESOURCES;
1956                 goto out;
1957         }
1958
1959         title = calloc(1, utf16_utf8_strlen(lo.label) + 1);
1960         if (!title) {
1961                 free(data);
1962                 ret = EFI_OUT_OF_RESOURCES;
1963                 goto out;
1964         }
1965         p = title;
1966         utf16_utf8_strcpy(&p, lo.label);
1967
1968         data->boot_index = boot_index;
1969         data->active = active;
1970
1971         ret = eficonfig_append_menu_entry(efi_menu, title, NULL, data);
1972         if (ret != EFI_SUCCESS) {
1973                 free(data);
1974                 free(title);
1975                 goto out;
1976         }
1977
1978 out:
1979         free(load_option);
1980
1981         return ret;
1982 }
1983
1984 /**
1985  * eficonfig_create_change_boot_order_entry() - create boot order entry
1986  *
1987  * @efi_menu:   pointer to the efimenu structure
1988  * @bootorder:  pointer to the BootOrder variable
1989  * @num:        number of BootOrder entry
1990  * Return:      status code
1991  */
1992 static efi_status_t eficonfig_create_change_boot_order_entry(struct efimenu *efi_menu,
1993                                                              u16 *bootorder, efi_uintn_t num)
1994 {
1995         u32 i;
1996         char *title;
1997         efi_status_t ret;
1998
1999         /* list the load option in the order of BootOrder variable */
2000         for (i = 0; i < num; i++) {
2001                 if (efi_menu->count >= EFICONFIG_ENTRY_NUM_MAX - 2)
2002                         break;
2003
2004                 ret = eficonfig_add_change_boot_order_entry(efi_menu, bootorder[i], true);
2005                 if (ret != EFI_SUCCESS)
2006                         goto out;
2007         }
2008
2009         /* list the remaining load option not included in the BootOrder */
2010         for (i = 0; i < 0xFFFF; i++) {
2011                 if (efi_menu->count >= EFICONFIG_ENTRY_NUM_MAX - 2)
2012                         break;
2013
2014                 /* If the index is included in the BootOrder, skip it */
2015                 if (search_bootorder(bootorder, num, i, NULL))
2016                         continue;
2017
2018                 ret = eficonfig_add_change_boot_order_entry(efi_menu, i, false);
2019                 if (ret != EFI_SUCCESS)
2020                         goto out;
2021         }
2022
2023         /* add "Save" and "Quit" entries */
2024         title = strdup("Save");
2025         if (!title) {
2026                 ret = EFI_OUT_OF_RESOURCES;
2027                 goto out;
2028         }
2029
2030         ret = eficonfig_append_menu_entry(efi_menu, title, NULL, NULL);
2031         if (ret != EFI_SUCCESS)
2032                 goto out;
2033
2034         ret = eficonfig_append_quit_entry(efi_menu);
2035         if (ret != EFI_SUCCESS)
2036                 goto out;
2037
2038         efi_menu->active = 0;
2039
2040         return EFI_SUCCESS;
2041 out:
2042         return ret;
2043 }
2044
2045 /**
2046  * eficonfig_process_change_boot_order() - handler to change boot order
2047  *
2048  * @data:       pointer to the data for each entry
2049  * Return:      status code
2050  */
2051 static efi_status_t eficonfig_process_change_boot_order(void *data)
2052 {
2053         u32 count;
2054         u16 *bootorder;
2055         efi_status_t ret;
2056         efi_uintn_t num, size;
2057         struct list_head *pos, *n;
2058         struct eficonfig_entry *entry;
2059         struct efimenu *efi_menu;
2060
2061         efi_menu = calloc(1, sizeof(struct efimenu));
2062         if (!efi_menu)
2063                 return EFI_OUT_OF_RESOURCES;
2064
2065         bootorder = efi_get_var(u"BootOrder", &efi_global_variable_guid, &size);
2066
2067         INIT_LIST_HEAD(&efi_menu->list);
2068         num = size / sizeof(u16);
2069         ret = eficonfig_create_change_boot_order_entry(efi_menu, bootorder, num);
2070         if (ret != EFI_SUCCESS)
2071                 goto out;
2072
2073         while (1) {
2074                 eficonfig_display_change_boot_order(efi_menu);
2075
2076                 ret = eficonfig_choice_change_boot_order(efi_menu);
2077                 if (ret == EFI_SUCCESS) {
2078                         u16 *new_bootorder;
2079
2080                         new_bootorder = calloc(1, (efi_menu->count - 2) * sizeof(u16));
2081                         if (!new_bootorder) {
2082                                 ret = EFI_OUT_OF_RESOURCES;
2083                                 goto out;
2084                         }
2085
2086                         /* create new BootOrder  */
2087                         count = 0;
2088                         list_for_each_safe(pos, n, &efi_menu->list) {
2089                                 struct eficonfig_boot_order_data *data;
2090
2091                                 entry = list_entry(pos, struct eficonfig_entry, list);
2092                                 /* exit the loop when iteration reaches "Save" */
2093                                 if (!strncmp(entry->title, "Save", strlen("Save")))
2094                                         break;
2095
2096                                 data = entry->data;
2097                                 if (data->active)
2098                                         new_bootorder[count++] = data->boot_index;
2099                         }
2100
2101                         size = count * sizeof(u16);
2102                         ret = efi_set_variable_int(u"BootOrder", &efi_global_variable_guid,
2103                                                    EFI_VARIABLE_NON_VOLATILE |
2104                                                    EFI_VARIABLE_BOOTSERVICE_ACCESS |
2105                                                    EFI_VARIABLE_RUNTIME_ACCESS,
2106                                                    size, new_bootorder, false);
2107
2108                         free(new_bootorder);
2109                         goto out;
2110                 } else if (ret == EFI_NOT_READY) {
2111                         continue;
2112                 } else {
2113                         goto out;
2114                 }
2115         }
2116 out:
2117         free(bootorder);
2118         list_for_each_safe(pos, n, &efi_menu->list) {
2119                 entry = list_entry(pos, struct eficonfig_entry, list);
2120                 free(entry->data);
2121         }
2122         eficonfig_destroy(efi_menu);
2123
2124         /* to stay the parent menu */
2125         ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;
2126
2127         return ret;
2128 }
2129
2130 /**
2131  * delete_boot_option() - delete selected boot option
2132  *
2133  * @boot_index: boot option index to delete
2134  * Return:      status code
2135  */
2136 static efi_status_t delete_boot_option(u16 boot_index)
2137 {
2138         u16 *bootorder;
2139         u16 varname[9];
2140         efi_status_t ret;
2141         unsigned int index;
2142         efi_uintn_t num, size;
2143
2144         efi_create_indexed_name(varname, sizeof(varname),
2145                                 "Boot", boot_index);
2146         ret = efi_set_variable_int(varname, &efi_global_variable_guid,
2147                                    0, 0, NULL, false);
2148         if (ret != EFI_SUCCESS) {
2149                 log_err("delete boot option(%ls) failed\n", varname);
2150                 return ret;
2151         }
2152
2153         /* update BootOrder if necessary */
2154         bootorder = efi_get_var(u"BootOrder", &efi_global_variable_guid, &size);
2155         if (!bootorder)
2156                 return EFI_SUCCESS;
2157
2158         num = size / sizeof(u16);
2159         if (!search_bootorder(bootorder, num, boot_index, &index))
2160                 return EFI_SUCCESS;
2161
2162         memmove(&bootorder[index], &bootorder[index + 1],
2163                 (num - index - 1) * sizeof(u16));
2164         size -= sizeof(u16);
2165         ret = efi_set_variable_int(u"BootOrder", &efi_global_variable_guid,
2166                                    EFI_VARIABLE_NON_VOLATILE |
2167                                    EFI_VARIABLE_BOOTSERVICE_ACCESS |
2168                                    EFI_VARIABLE_RUNTIME_ACCESS,
2169                                    size, bootorder, false);
2170
2171         return ret;
2172 }
2173
2174 /**
2175  * eficonfig_process_delete_boot_option() - handler to delete boot option
2176  *
2177  * @data:       pointer to the data for each entry
2178  * Return:      status code
2179  */
2180 static efi_status_t eficonfig_process_delete_boot_option(void *data)
2181 {
2182         efi_status_t ret;
2183         unsigned int selected;
2184
2185         while (1) {
2186                 ret = eficonfig_show_boot_selection(&selected);
2187                 if (ret == EFI_SUCCESS)
2188                         ret = delete_boot_option(selected);
2189
2190                 if (ret != EFI_SUCCESS)
2191                         break;
2192         }
2193
2194         /* to stay the parent menu */
2195         ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;
2196
2197         return ret;
2198 }
2199
2200 /**
2201  * eficonfig_enumerate_boot_option() - enumerate the possible bootable media
2202  *
2203  * @opt:                pointer to the media boot option structure
2204  * @volume_handles:     pointer to the efi handles
2205  * @count:              number of efi handle
2206  * Return:              status code
2207  */
2208 efi_status_t eficonfig_enumerate_boot_option(struct eficonfig_media_boot_option *opt,
2209                                              efi_handle_t *volume_handles, efi_status_t count)
2210 {
2211         u32 i;
2212         struct efi_handler *handler;
2213         efi_status_t ret = EFI_SUCCESS;
2214
2215         for (i = 0; i < count; i++) {
2216                 u16 *p;
2217                 u16 dev_name[BOOTMENU_DEVICE_NAME_MAX];
2218                 char *optional_data;
2219                 struct efi_load_option lo;
2220                 char buf[BOOTMENU_DEVICE_NAME_MAX];
2221                 struct efi_device_path *device_path;
2222
2223                 ret = efi_search_protocol(volume_handles[i], &efi_guid_device_path, &handler);
2224                 if (ret != EFI_SUCCESS)
2225                         continue;
2226                 ret = efi_protocol_open(handler, (void **)&device_path,
2227                                         efi_root, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
2228                 if (ret != EFI_SUCCESS)
2229                         continue;
2230
2231                 ret = efi_disk_get_device_name(volume_handles[i], buf, BOOTMENU_DEVICE_NAME_MAX);
2232                 if (ret != EFI_SUCCESS)
2233                         continue;
2234
2235                 p = dev_name;
2236                 utf8_utf16_strncpy(&p, buf, strlen(buf));
2237
2238                 lo.label = dev_name;
2239                 lo.attributes = LOAD_OPTION_ACTIVE;
2240                 lo.file_path = device_path;
2241                 lo.file_path_length = efi_dp_size(device_path) + sizeof(END);
2242                 /*
2243                  * Set the dedicated guid to optional_data, it is used to identify
2244                  * the boot option that automatically generated by the bootmenu.
2245                  * efi_serialize_load_option() expects optional_data is null-terminated
2246                  * utf8 string, so set the "1234567" string to allocate enough space
2247                  * to store guid, instead of realloc the load_option.
2248                  */
2249                 lo.optional_data = "1234567";
2250                 opt[i].size = efi_serialize_load_option(&lo, (u8 **)&opt[i].lo);
2251                 if (!opt[i].size) {
2252                         ret = EFI_OUT_OF_RESOURCES;
2253                         goto out;
2254                 }
2255                 /* set the guid */
2256                 optional_data = (char *)opt[i].lo + (opt[i].size - u16_strsize(u"1234567"));
2257                 memcpy(optional_data, &efi_guid_bootmenu_auto_generated, sizeof(efi_guid_t));
2258         }
2259
2260 out:
2261         return ret;
2262 }
2263
2264 /**
2265  * eficonfig_delete_invalid_boot_option() - delete non-existing boot option
2266  *
2267  * @opt:                pointer to the media boot option structure
2268  * @count:              number of media boot option structure
2269  * Return:              status code
2270  */
2271 efi_status_t eficonfig_delete_invalid_boot_option(struct eficonfig_media_boot_option *opt,
2272                                                   efi_status_t count)
2273 {
2274         u32 i, j;
2275         efi_uintn_t size;
2276         void *load_option;
2277         struct efi_load_option lo;
2278         u16 varname[] = u"Boot####";
2279         efi_status_t ret = EFI_SUCCESS;
2280
2281         for (i = 0; i <= 0xFFFF; i++) {
2282                 efi_uintn_t tmp;
2283
2284                 efi_create_indexed_name(varname, sizeof(varname), "Boot", i);
2285                 load_option = efi_get_var(varname, &efi_global_variable_guid, &size);
2286                 if (!load_option)
2287                         continue;
2288
2289                 tmp = size;
2290                 ret = efi_deserialize_load_option(&lo, load_option, &size);
2291                 if (ret != EFI_SUCCESS)
2292                         goto next;
2293
2294                 if (size >= sizeof(efi_guid_bootmenu_auto_generated)) {
2295                         if (guidcmp(lo.optional_data, &efi_guid_bootmenu_auto_generated) == 0) {
2296                                 for (j = 0; j < count; j++) {
2297                                         if (opt[j].size == tmp &&
2298                                             memcmp(opt[j].lo, load_option, tmp) == 0) {
2299                                                 opt[j].exist = true;
2300                                                 break;
2301                                         }
2302                                 }
2303
2304                                 if (j == count) {
2305                                         ret = delete_boot_option(i);
2306                                         if (ret != EFI_SUCCESS) {
2307                                                 free(load_option);
2308                                                 goto out;
2309                                         }
2310                                 }
2311                         }
2312                 }
2313 next:
2314                 free(load_option);
2315         }
2316
2317 out:
2318         return ret;
2319 }
2320
2321 /**
2322  * eficonfig_generate_media_device_boot_option() - generate the media device boot option
2323  *
2324  * This function enumerates all devices supporting EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
2325  * and generate the bootmenu entries.
2326  * This function also provide the BOOT#### variable maintenance for
2327  * the media device entries.
2328  *   - Automatically create the BOOT#### variable for the newly detected device,
2329  *     this BOOT#### variable is distinguished by the special GUID
2330  *     stored in the EFI_LOAD_OPTION.optional_data
2331  *   - If the device is not attached to the system, the associated BOOT#### variable
2332  *     is automatically deleted.
2333  *
2334  * Return:      status code
2335  */
2336 efi_status_t eficonfig_generate_media_device_boot_option(void)
2337 {
2338         u32 i;
2339         efi_status_t ret;
2340         efi_uintn_t count;
2341         efi_handle_t *volume_handles = NULL;
2342         struct eficonfig_media_boot_option *opt = NULL;
2343
2344         ret = efi_locate_handle_buffer_int(BY_PROTOCOL, &efi_simple_file_system_protocol_guid,
2345                                            NULL, &count, (efi_handle_t **)&volume_handles);
2346         if (ret != EFI_SUCCESS)
2347                 return ret;
2348
2349         opt = calloc(count, sizeof(struct eficonfig_media_boot_option));
2350         if (!opt)
2351                 goto out;
2352
2353         /* enumerate all devices supporting EFI_SIMPLE_FILE_SYSTEM_PROTOCOL */
2354         ret = eficonfig_enumerate_boot_option(opt, volume_handles, count);
2355         if (ret != EFI_SUCCESS)
2356                 goto out;
2357
2358         /*
2359          * System hardware configuration may vary depending on the user setup.
2360          * The boot option is automatically added by the bootmenu.
2361          * If the device is not attached to the system, the boot option needs
2362          * to be deleted.
2363          */
2364         ret = eficonfig_delete_invalid_boot_option(opt, count);
2365         if (ret != EFI_SUCCESS)
2366                 goto out;
2367
2368         /* add non-existent boot option */
2369         for (i = 0; i < count; i++) {
2370                 u32 boot_index;
2371                 u16 var_name[9];
2372
2373                 if (!opt[i].exist) {
2374                         ret = eficonfig_get_unused_bootoption(var_name, sizeof(var_name),
2375                                                               &boot_index);
2376                         if (ret != EFI_SUCCESS)
2377                                 goto out;
2378
2379                         ret = efi_set_variable_int(var_name, &efi_global_variable_guid,
2380                                                    EFI_VARIABLE_NON_VOLATILE |
2381                                                    EFI_VARIABLE_BOOTSERVICE_ACCESS |
2382                                                    EFI_VARIABLE_RUNTIME_ACCESS,
2383                                                    opt[i].size, opt[i].lo, false);
2384                         if (ret != EFI_SUCCESS)
2385                                 goto out;
2386
2387                         ret = eficonfig_append_bootorder(boot_index);
2388                         if (ret != EFI_SUCCESS) {
2389                                 efi_set_variable_int(var_name, &efi_global_variable_guid,
2390                                                      0, 0, NULL, false);
2391                                 goto out;
2392                         }
2393                 }
2394         }
2395
2396 out:
2397         if (opt) {
2398                 for (i = 0; i < count; i++)
2399                         free(opt[i].lo);
2400         }
2401         free(opt);
2402         efi_free_pool(volume_handles);
2403
2404         return ret;
2405 }
2406
2407 /**
2408  * eficonfig_init() - do required initialization for eficonfig command
2409  *
2410  * Return:      status code
2411  */
2412 static efi_status_t eficonfig_init(void)
2413 {
2414         efi_status_t ret = EFI_SUCCESS;
2415         static bool init;
2416         struct efi_handler *handler;
2417
2418         if (!init) {
2419                 ret = efi_search_protocol(efi_root, &efi_guid_text_input_protocol, &handler);
2420                 if (ret != EFI_SUCCESS)
2421                         return ret;
2422
2423                 ret = efi_protocol_open(handler, (void **)&cin, efi_root, NULL,
2424                                         EFI_OPEN_PROTOCOL_GET_PROTOCOL);
2425                 if (ret != EFI_SUCCESS)
2426                         return ret;
2427         }
2428
2429         init = true;
2430
2431         return ret;
2432 }
2433
2434 static const struct eficonfig_item maintenance_menu_items[] = {
2435         {"Add Boot Option", eficonfig_process_add_boot_option},
2436         {"Edit Boot Option", eficonfig_process_edit_boot_option},
2437         {"Change Boot Order", eficonfig_process_change_boot_order},
2438         {"Delete Boot Option", eficonfig_process_delete_boot_option},
2439 #if (CONFIG_IS_ENABLED(EFI_SECURE_BOOT) && CONFIG_IS_ENABLED(EFI_MM_COMM_TEE))
2440         {"Secure Boot Configuration", eficonfig_process_secure_boot_config},
2441 #endif
2442         {"Quit", eficonfig_process_quit},
2443 };
2444
2445 /**
2446  * do_eficonfig() - execute `eficonfig` command
2447  *
2448  * @cmdtp:      table entry describing command
2449  * @flag:       bitmap indicating how the command was invoked
2450  * @argc:       number of arguments
2451  * @argv:       command line arguments
2452  * Return:      status code
2453  */
2454 static int do_eficonfig(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
2455 {
2456         efi_status_t ret;
2457         struct efimenu *efi_menu;
2458
2459         if (argc > 1)
2460                 return CMD_RET_USAGE;
2461
2462         ret = efi_init_obj_list();
2463         if (ret != EFI_SUCCESS) {
2464                 log_err("Error: Cannot initialize UEFI sub-system, r = %lu\n",
2465                         ret & ~EFI_ERROR_MASK);
2466
2467                 return CMD_RET_FAILURE;
2468         }
2469
2470         ret = eficonfig_init();
2471         if (ret != EFI_SUCCESS)
2472                 return CMD_RET_FAILURE;
2473
2474         ret = eficonfig_generate_media_device_boot_option();
2475         if (ret != EFI_SUCCESS && ret != EFI_NOT_FOUND)
2476                 return ret;
2477
2478         while (1) {
2479                 efi_menu = eficonfig_create_fixed_menu(maintenance_menu_items,
2480                                                        ARRAY_SIZE(maintenance_menu_items));
2481                 if (!efi_menu)
2482                         return CMD_RET_FAILURE;
2483
2484                 ret = eficonfig_process_common(efi_menu, "  ** UEFI Maintenance Menu **");
2485                 eficonfig_destroy(efi_menu);
2486
2487                 if (ret == EFI_ABORTED)
2488                         break;
2489         }
2490
2491         return CMD_RET_SUCCESS;
2492 }
2493
2494 U_BOOT_CMD(
2495         eficonfig, 1, 0, do_eficonfig,
2496         "provide menu-driven UEFI variable maintenance interface",
2497         ""
2498 );