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