Pull request for efi next
UEFI: Implement a command eficonfig to maintain Load Options and boot order via menus. -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEbcT5xx8ppvoGt20zxIHbvCwFGsQFAmMh/kQACgkQxIHbvCwF GsSYVhAAlhyCiAQudBJtrOyAA0HDPMio/Fx9F3YV1Laay//6+xHhEh5H94fMr7jP BHOrpE+IDKQTiQ8X3FpJpm3FzgQBzu0s4gQ+8fCKwkXCkaPTtWhs3s5SdHN0TWmv qGlNbuPdoU+4i7PeBWw87EvOCzh4+snn+l3t+npMxUlZJInGy+6xj0irnSEXTvXV lpDRw2UDq3/smAS8tAcR+zriTH5o1Lx+0qPIO9Hw8BSDHOcvZD+S9d6cd6j+M+Wz rWk1Bshol6anIZWS5Gnx14ddKF8SQcSiPsDXg2Uj2DvFg7lWepKxAbDJD5CVF9R9 aEu6THCurc+769A/IHAS9M0EDNnWoUGFSxe0JuEHdYVuGj30RRfzSaciKkNxsxUZ UGvDnQ+zdRoj6bTVi4Zf8SeZUTm/04lWMoIF05uhZFDiwxidbMowoNsk9FeKria/ 4vXybfj/IhRwbiAhOUqyDjGuoLj8iVeOAyzin4FnDvBwdshIkSsB+4y1sX1aQv02 HQbP6WXkiYoYNkw5i9E9ZChioxkzMrn2za3GxWhkTBMJArDw6xSuHMdQsgwWWoqU fCKjwe+D96lHq5cKt3DmGTvGxQtx9ckSJGK5r+US5y1udzotjOKc1jqMkMvS3Jyg ureTj0wvLYSx+/UirVAZ4IDviDMBVEar79VS2xi+SYBMLeQPy3I= =P89S -----END PGP SIGNATURE----- Merge tag 'efi-next-2022-09-14' of https://source.denx.de/u-boot/custodians/u-boot-efi into next Pull request for efi next UEFI: Implement a command eficonfig to maintain Load Options and boot order via menus.
This commit is contained in:
		
						commit
						1520af3f84
					
				|  | @ -1928,6 +1928,13 @@ config CMD_EFIDEBUG | ||||||
| 	  particularly for managing boot parameters as  well as examining | 	  particularly for managing boot parameters as  well as examining | ||||||
| 	  various EFI status for debugging. | 	  various EFI status for debugging. | ||||||
| 
 | 
 | ||||||
|  | config CMD_EFICONFIG | ||||||
|  | 	bool "eficonfig - provide menu-driven uefi variables maintenance interface" | ||||||
|  | 	depends on CMD_BOOTEFI_BOOTMGR | ||||||
|  | 	help | ||||||
|  | 	  Enable the 'eficonfig' command which provides the menu-driven UEFI | ||||||
|  | 	  variable maintenance interface. | ||||||
|  | 
 | ||||||
| config CMD_EXCEPTION | config CMD_EXCEPTION | ||||||
| 	bool "exception - raise exception" | 	bool "exception - raise exception" | ||||||
| 	depends on ARM || RISCV || SANDBOX || X86 | 	depends on ARM || RISCV || SANDBOX || X86 | ||||||
|  |  | ||||||
|  | @ -64,6 +64,7 @@ obj-$(CONFIG_ENV_IS_IN_EEPROM) += eeprom.o | ||||||
| obj-$(CONFIG_CMD_EEPROM) += eeprom.o | obj-$(CONFIG_CMD_EEPROM) += eeprom.o | ||||||
| obj-$(CONFIG_EFI) += efi.o | obj-$(CONFIG_EFI) += efi.o | ||||||
| obj-$(CONFIG_CMD_EFIDEBUG) += efidebug.o | obj-$(CONFIG_CMD_EFIDEBUG) += efidebug.o | ||||||
|  | obj-$(CONFIG_CMD_EFICONFIG) += eficonfig.o | ||||||
| obj-$(CONFIG_CMD_ELF) += elf.o | obj-$(CONFIG_CMD_ELF) += elf.o | ||||||
| obj-$(CONFIG_CMD_EROFS) += erofs.o | obj-$(CONFIG_CMD_EROFS) += erofs.o | ||||||
| obj-$(CONFIG_HUSH_PARSER) += exit.o | obj-$(CONFIG_HUSH_PARSER) += exit.o | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ | ||||||
| #include <common.h> | #include <common.h> | ||||||
| #include <command.h> | #include <command.h> | ||||||
| #include <ansi.h> | #include <ansi.h> | ||||||
| #include <efi_loader.h> | #include <efi_config.h> | ||||||
| #include <efi_variable.h> | #include <efi_variable.h> | ||||||
| #include <env.h> | #include <env.h> | ||||||
| #include <log.h> | #include <log.h> | ||||||
|  | @ -220,7 +220,7 @@ static int prepare_bootmenu_entry(struct bootmenu_data *menu, | ||||||
| 	return 1; | 	return 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #if (CONFIG_IS_ENABLED(CMD_BOOTEFI_BOOTMGR)) | #if (CONFIG_IS_ENABLED(CMD_BOOTEFI_BOOTMGR)) && (CONFIG_IS_ENABLED(CMD_EFICONFIG)) | ||||||
| /**
 | /**
 | ||||||
|  * prepare_uefi_bootorder_entry() - generate the uefi bootmenu entries |  * prepare_uefi_bootorder_entry() - generate the uefi bootmenu entries | ||||||
|  * |  * | ||||||
|  | @ -340,11 +340,21 @@ static struct bootmenu_data *bootmenu_create(int delay) | ||||||
| 	if (ret < 0) | 	if (ret < 0) | ||||||
| 		goto cleanup; | 		goto cleanup; | ||||||
| 
 | 
 | ||||||
| #if (CONFIG_IS_ENABLED(CMD_BOOTEFI_BOOTMGR)) | #if (CONFIG_IS_ENABLED(CMD_BOOTEFI_BOOTMGR)) && (CONFIG_IS_ENABLED(CMD_EFICONFIG)) | ||||||
| 	if (i < MAX_COUNT - 1) { | 	if (i < MAX_COUNT - 1) { | ||||||
| 			ret = prepare_uefi_bootorder_entry(menu, &iter, &i); | 		efi_status_t efi_ret; | ||||||
| 			if (ret < 0 && ret != -ENOENT) | 
 | ||||||
| 				goto cleanup; | 		/*
 | ||||||
|  | 		 * UEFI specification requires booting from removal media using | ||||||
|  | 		 * a architecture-specific default image name such as BOOTAA64.EFI. | ||||||
|  | 		 */ | ||||||
|  | 		efi_ret = eficonfig_generate_media_device_boot_option(); | ||||||
|  | 		if (efi_ret != EFI_SUCCESS && efi_ret != EFI_NOT_FOUND) | ||||||
|  | 			goto cleanup; | ||||||
|  | 
 | ||||||
|  | 		ret = prepare_uefi_bootorder_entry(menu, &iter, &i); | ||||||
|  | 		if (ret < 0 && ret != -ENOENT) | ||||||
|  | 			goto cleanup; | ||||||
| 	} | 	} | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -548,4 +548,13 @@ void bootmenu_loop(struct bootmenu_data *menu, | ||||||
| 	/* ^C was pressed */ | 	/* ^C was pressed */ | ||||||
| 	if (c == 0x3) | 	if (c == 0x3) | ||||||
| 		*key = KEY_QUIT; | 		*key = KEY_QUIT; | ||||||
|  | 
 | ||||||
|  | 	if (c == '+') | ||||||
|  | 		*key = KEY_PLUS; | ||||||
|  | 
 | ||||||
|  | 	if (c == '-') | ||||||
|  | 		*key = KEY_MINUS; | ||||||
|  | 
 | ||||||
|  | 	if (c == ' ') | ||||||
|  | 		*key = KEY_SPACE; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -93,6 +93,7 @@ CONFIG_CMD_LINK_LOCAL=y | ||||||
| CONFIG_CMD_ETHSW=y | CONFIG_CMD_ETHSW=y | ||||||
| CONFIG_CMD_BMP=y | CONFIG_CMD_BMP=y | ||||||
| CONFIG_CMD_BOOTCOUNT=y | CONFIG_CMD_BOOTCOUNT=y | ||||||
|  | CONFIG_CMD_EFICONFIG=y | ||||||
| CONFIG_CMD_EFIDEBUG=y | CONFIG_CMD_EFIDEBUG=y | ||||||
| CONFIG_CMD_RTC=y | CONFIG_CMD_RTC=y | ||||||
| CONFIG_CMD_TIME=y | CONFIG_CMD_TIME=y | ||||||
|  |  | ||||||
|  | @ -4,6 +4,15 @@ | ||||||
| bootmenu command | bootmenu command | ||||||
| ================ | ================ | ||||||
| 
 | 
 | ||||||
|  | Synopsis | ||||||
|  | -------- | ||||||
|  | :: | ||||||
|  | 
 | ||||||
|  |     bootmenu [delay] | ||||||
|  | 
 | ||||||
|  | Description | ||||||
|  | ----------- | ||||||
|  | 
 | ||||||
| The "bootmenu" command uses U-Boot menu interfaces and provides | The "bootmenu" command uses U-Boot menu interfaces and provides | ||||||
| a simple mechanism for creating menus with different boot items. | a simple mechanism for creating menus with different boot items. | ||||||
| The cursor keys "Up" and "Down" are used for navigation through | The cursor keys "Up" and "Down" are used for navigation through | ||||||
|  | @ -79,6 +88,55 @@ The above example will be rendered as below:: | ||||||
| The selected menu entry will be highlighted - it will have inverted | The selected menu entry will be highlighted - it will have inverted | ||||||
| background and text colors. | background and text colors. | ||||||
| 
 | 
 | ||||||
|  | UEFI boot variable enumeration | ||||||
|  | '''''''''''''''''''''''''''''' | ||||||
|  | If enabled, the bootmenu command will automatically generate and add | ||||||
|  | UEFI-related boot menu entries for the following items. | ||||||
|  | 
 | ||||||
|  |  * possible bootable media with default file names | ||||||
|  |  * user-defined UEFI boot options | ||||||
|  | 
 | ||||||
|  | The bootmenu automatically enumerates the possible bootable | ||||||
|  | media devices supporting EFI_SIMPLE_FILE_SYSTEM_PROTOCOL. | ||||||
|  | This auto generated entry is named as "<interface> <devnum>:<part>" format. | ||||||
|  | (e.g. "usb 0:1") | ||||||
|  | 
 | ||||||
|  | The bootmenu displays the UEFI-related menu entries in order of "BootOrder". | ||||||
|  | When the user selects the UEFI boot menu entry, the bootmenu sets | ||||||
|  | the selected boot variable index to "BootNext" without non-volatile attribute, | ||||||
|  | then call the uefi boot manager with the command "bootefi bootmgr". | ||||||
|  | 
 | ||||||
|  | Example bootmenu is as below:: | ||||||
|  | 
 | ||||||
|  |     *** U-Boot Boot Menu *** | ||||||
|  | 
 | ||||||
|  |        mmc 0:1 | ||||||
|  |        mmc 0:2 | ||||||
|  |        debian | ||||||
|  |        nvme 0:1 | ||||||
|  |        ubuntu | ||||||
|  |        nvme 0:2 | ||||||
|  |        usb 0:2 | ||||||
|  |        U-Boot console | ||||||
|  | 
 | ||||||
|  | Default behavior when user exits from the bootmenu | ||||||
|  | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
|  | User can exit from bootmenu by selecting the last entry | ||||||
|  | "U-Boot console"/"Quit" or ESC/CTRL+C key. | ||||||
|  | 
 | ||||||
|  | When the CONFIG_BOOTMENU_DISABLE_UBOOT_CONSOLE is disabled, | ||||||
|  | user exits from the bootmenu and returns to the U-Boot console. | ||||||
|  | 
 | ||||||
|  | When the CONFIG_BOOTMENU_DISABLE_UBOOT_CONSOLE is enabled, user can not | ||||||
|  | enter the U-Boot console. When the user exits from the bootmenu, | ||||||
|  | the bootmenu invokes the following default behavior. | ||||||
|  | 
 | ||||||
|  |  * if CONFIG_CMD_BOOTEFI_BOOTMGR is enabled, execute "bootefi bootmgr" command | ||||||
|  |  * "bootefi bootmgr" fails or is not enabled, then execute "run bootcmd" command. | ||||||
|  | 
 | ||||||
|  | Configuration | ||||||
|  | ------------- | ||||||
|  | 
 | ||||||
| The "bootmenu" command is enabled by:: | The "bootmenu" command is enabled by:: | ||||||
| 
 | 
 | ||||||
|     CONFIG_CMD_BOOTMENU=y |     CONFIG_CMD_BOOTMENU=y | ||||||
|  | @ -88,3 +146,19 @@ To run the bootmenu at startup add these additional settings:: | ||||||
|     CONFIG_AUTOBOOT_KEYED=y |     CONFIG_AUTOBOOT_KEYED=y | ||||||
|     CONFIG_BOOTDELAY=30 |     CONFIG_BOOTDELAY=30 | ||||||
|     CONFIG_AUTOBOOT_MENU_SHOW=y |     CONFIG_AUTOBOOT_MENU_SHOW=y | ||||||
|  | 
 | ||||||
|  | UEFI boot variable enumeration is enabled by:: | ||||||
|  | 
 | ||||||
|  |     CONFIG_CMD_BOOTEFI_BOOTMGR=y | ||||||
|  | 
 | ||||||
|  | To improve the product security, entering U-Boot console from bootmenu | ||||||
|  | can be disabled by:: | ||||||
|  | 
 | ||||||
|  |     CONFIG_BOOTMENU_DISABLE_UBOOT_CONSOLE=y | ||||||
|  | 
 | ||||||
|  | To scan the discoverable devices connected to the buses such as | ||||||
|  | USB and PCIe prior to bootmenu showing up, CONFIG_PREBOOT can be | ||||||
|  | used to run the command before showing the bootmenu, i.e.:: | ||||||
|  | 
 | ||||||
|  |     CONFIG_USE_PREBOOT=y | ||||||
|  |     CONFIG_PREBOOT="pci enum; usb start; scsi scan; nvme scan; virtio scan" | ||||||
|  |  | ||||||
|  | @ -0,0 +1,71 @@ | ||||||
|  | .. SPDX-License-Identifier: GPL-2.0+ | ||||||
|  | .. (C) Copyright 2022, Masahisa Kojima <masahisa.kojima@linaro.org> | ||||||
|  | 
 | ||||||
|  | eficonfig command | ||||||
|  | ================= | ||||||
|  | 
 | ||||||
|  | Synopsis | ||||||
|  | -------- | ||||||
|  | :: | ||||||
|  | 
 | ||||||
|  |     eficonfig | ||||||
|  | 
 | ||||||
|  | Description | ||||||
|  | ----------- | ||||||
|  | 
 | ||||||
|  | The "eficonfig" command uses U-Boot menu interface and provides | ||||||
|  | a menu-driven UEFI variable maintenance feature. | ||||||
|  | The "eficonfig" has the following menu entries. | ||||||
|  | 
 | ||||||
|  | Add Boot Option | ||||||
|  |     Add new UEFI Boot Option. | ||||||
|  |     User can edit description, file path, and optional_data. | ||||||
|  | 
 | ||||||
|  | Edit Boot Option | ||||||
|  |     Edit the existing UEFI Boot Option | ||||||
|  |     User can edit description, file path, and optional_data. | ||||||
|  | 
 | ||||||
|  | Change Boot Order | ||||||
|  |     Change the order of UEFI BootOrder variable. | ||||||
|  | 
 | ||||||
|  | Delete Boot Option | ||||||
|  |     Delete the UEFI Boot Option | ||||||
|  | 
 | ||||||
|  | Configuration | ||||||
|  | ------------- | ||||||
|  | 
 | ||||||
|  | The "eficonfig" command is enabled by:: | ||||||
|  | 
 | ||||||
|  |     CONFIG_CMD_EFICONFIG=y | ||||||
|  | 
 | ||||||
|  | If CONFIG_BOOTMENU_DISABLE_UBOOT_CONSOLE is enabled, user can not enter | ||||||
|  | U-Boot console. In this case, bootmenu can be used to invoke "eficonfig":: | ||||||
|  | 
 | ||||||
|  |     CONFIG_USE_PREBOOT=y | ||||||
|  |     CONFIG_PREBOOT="setenv bootmenu_0 UEFI Maintenance Menu=eficonfig" | ||||||
|  | 
 | ||||||
|  | How to boot the system with newly added UEFI Boot Option | ||||||
|  | '''''''''''''''''''''''''''''''''''''''''''''''''''''''' | ||||||
|  | 
 | ||||||
|  | "eficonfig" command is responsible for configuring the UEFI variables, | ||||||
|  | not directly handle the system boot. | ||||||
|  | The new Boot Option added by "eficonfig" is appended at the last entry | ||||||
|  | of UEFI BootOrder variable, user may want to change the boot order | ||||||
|  | through "Change Boot Order". | ||||||
|  | If the bootmenu is enabled, CONFIG_BOOTMENU_DISABLE_UBOOT_CONSOLE is enabled, | ||||||
|  | and "eficonfig" is configured as preboot command, the newly added Boot Options | ||||||
|  | are enumerated in the bootmenu when user exits from the eficonfig menu. | ||||||
|  | User may select the entry in the bootmenu to boot the system, or follow | ||||||
|  | the U-Boot configuration the system already has. | ||||||
|  | 
 | ||||||
|  | Auto boot with the UEFI Boot Option | ||||||
|  | ''''''''''''''''''''''''''''''''''' | ||||||
|  | 
 | ||||||
|  | To do auto boot according to the UEFI BootOrder variable, | ||||||
|  | add "bootefi bootmgr" entry as a default or first bootmenu entry:: | ||||||
|  | 
 | ||||||
|  |     CONFIG_PREBOOT="setenv bootmenu_0 UEFI Boot Manager=bootefi bootmgr; setenv bootmenu_1 UEFI Maintenance Menu=eficonfig" | ||||||
|  | 
 | ||||||
|  | See also | ||||||
|  | -------- | ||||||
|  | * :doc:`bootmenu<bootmenu>` provides a simple mechanism for creating menus with different boot items | ||||||
|  | @ -36,6 +36,7 @@ Shell commands | ||||||
|    cmd/cyclic |    cmd/cyclic | ||||||
|    cmd/dm |    cmd/dm | ||||||
|    cmd/echo |    cmd/echo | ||||||
|  |    cmd/eficonfig | ||||||
|    cmd/env |    cmd/env | ||||||
|    cmd/event |    cmd/event | ||||||
|    cmd/exception |    cmd/exception | ||||||
|  |  | ||||||
|  | @ -0,0 +1,98 @@ | ||||||
|  | /* SPDX-License-Identifier: GPL-2.0+ */ | ||||||
|  | /*
 | ||||||
|  |  *  Menu-driven UEFI Variable maintenance | ||||||
|  |  * | ||||||
|  |  *  Copyright (c) 2022 Masahisa Kojima, Linaro Limited | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef _EFI_CONFIG_H | ||||||
|  | #define _EFI_CONFIG_H | ||||||
|  | 
 | ||||||
|  | #include <efi_loader.h> | ||||||
|  | 
 | ||||||
|  | #define EFICONFIG_ENTRY_NUM_MAX 99 | ||||||
|  | #define EFICONFIG_VOLUME_PATH_MAX 512 | ||||||
|  | #define EFICONFIG_FILE_PATH_MAX 512 | ||||||
|  | #define EFICONFIG_FILE_PATH_BUF_SIZE (EFICONFIG_FILE_PATH_MAX * sizeof(u16)) | ||||||
|  | 
 | ||||||
|  | typedef efi_status_t (*eficonfig_entry_func)(void *data); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * struct eficonfig_entry - menu entry structure | ||||||
|  |  * | ||||||
|  |  * @num:	menu entry index | ||||||
|  |  * @title:	title of entry | ||||||
|  |  * @key:	unique key | ||||||
|  |  * @efi_menu:	pointer to the menu structure | ||||||
|  |  * @func:	callback function to be called when this entry is selected | ||||||
|  |  * @data:	data to be passed to the callback function, caller must free() this pointer | ||||||
|  |  * @list:	list structure | ||||||
|  |  */ | ||||||
|  | struct eficonfig_entry { | ||||||
|  | 	u32 num; | ||||||
|  | 	char *title; | ||||||
|  | 	char key[3]; | ||||||
|  | 	struct efimenu *efi_menu; | ||||||
|  | 	eficonfig_entry_func func; | ||||||
|  | 	void *data; | ||||||
|  | 	struct list_head list; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * struct efimenu - efi menu structure | ||||||
|  |  * | ||||||
|  |  * @delay:		delay for autoboot | ||||||
|  |  * @active:		active menu entry index | ||||||
|  |  * @count:		total count of menu entry | ||||||
|  |  * @menu_header:	menu header string | ||||||
|  |  * @list:		menu entry list structure | ||||||
|  |  */ | ||||||
|  | struct efimenu { | ||||||
|  | 	int delay; | ||||||
|  | 	int active; | ||||||
|  | 	int count; | ||||||
|  | 	char *menu_header; | ||||||
|  | 	struct list_head list; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * struct eficonfig_item - structure to construct eficonfig_entry | ||||||
|  |  * | ||||||
|  |  * @title:	title of entry | ||||||
|  |  * @func:	callback function to be called when this entry is selected | ||||||
|  |  * @data:	data to be passed to the callback function | ||||||
|  |  */ | ||||||
|  | struct eficonfig_item { | ||||||
|  | 	char *title; | ||||||
|  | 	eficonfig_entry_func func; | ||||||
|  | 	void *data; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * struct eficonfig_select_file_info - structure to be used for file selection | ||||||
|  |  * | ||||||
|  |  * @current_volume:	pointer to the efi_simple_file_system_protocol | ||||||
|  |  * @dp_volume:		pointer to device path of the selected device | ||||||
|  |  * @current_path:	pointer to the selected file path string | ||||||
|  |  * @filepath_list:	list_head structure for file path list | ||||||
|  |  * @file_selectred:	flag indicates file selecting status | ||||||
|  |  */ | ||||||
|  | struct eficonfig_select_file_info { | ||||||
|  | 	struct efi_simple_file_system_protocol *current_volume; | ||||||
|  | 	struct efi_device_path *dp_volume; | ||||||
|  | 	u16 *current_path; | ||||||
|  | 	struct list_head filepath_list; | ||||||
|  | 	bool file_selected; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void eficonfig_print_msg(char *msg); | ||||||
|  | void eficonfig_destroy(struct efimenu *efi_menu); | ||||||
|  | efi_status_t eficonfig_process_quit(void *data); | ||||||
|  | efi_status_t eficonfig_process_common(struct efimenu *efi_menu, char *menu_header); | ||||||
|  | efi_status_t eficonfig_select_file_handler(void *data); | ||||||
|  | efi_status_t eficonfig_get_unused_bootoption(u16 *buf, | ||||||
|  | 					     efi_uintn_t buf_size, u32 *index); | ||||||
|  | efi_status_t eficonfig_append_bootorder(u16 index); | ||||||
|  | efi_status_t eficonfig_generate_media_device_boot_option(void); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | @ -142,6 +142,11 @@ static inline efi_status_t efi_launch_capsules(void) | ||||||
| 	EFI_GUID(0x63293792, 0xadf5, 0x9325, \ | 	EFI_GUID(0x63293792, 0xadf5, 0x9325, \ | ||||||
| 		 0xb9, 0x9f, 0x4e, 0x0e, 0x45, 0x5c, 0x1b, 0x1e) | 		 0xb9, 0x9f, 0x4e, 0x0e, 0x45, 0x5c, 0x1b, 0x1e) | ||||||
| 
 | 
 | ||||||
|  | /* GUID for the auto generated boot menu entry */ | ||||||
|  | #define EFICONFIG_AUTO_GENERATED_ENTRY_GUID \ | ||||||
|  | 	EFI_GUID(0x38c1acc1, 0x9fc0, 0x41f0, \ | ||||||
|  | 		 0xb9, 0x01, 0xfa, 0x74, 0xd6, 0xd6, 0xe4, 0xde) | ||||||
|  | 
 | ||||||
| /* Use internal device tree when starting UEFI application */ | /* Use internal device tree when starting UEFI application */ | ||||||
| #define EFI_FDT_USE_INTERNAL NULL | #define EFI_FDT_USE_INTERNAL NULL | ||||||
| 
 | 
 | ||||||
|  | @ -226,6 +231,9 @@ const char *__efi_nesting_dec(void); | ||||||
| #define EFI_CACHELINE_SIZE 128 | #define EFI_CACHELINE_SIZE 128 | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | /* max bootmenu title size for volume selection */ | ||||||
|  | #define BOOTMENU_DEVICE_NAME_MAX 16 | ||||||
|  | 
 | ||||||
| /* Key identifying current memory map */ | /* Key identifying current memory map */ | ||||||
| extern efi_uintn_t efi_memory_map_key; | extern efi_uintn_t efi_memory_map_key; | ||||||
| 
 | 
 | ||||||
|  | @ -249,6 +257,9 @@ extern const struct efi_hii_string_protocol efi_hii_string; | ||||||
| 
 | 
 | ||||||
| uint16_t *efi_dp_str(struct efi_device_path *dp); | uint16_t *efi_dp_str(struct efi_device_path *dp); | ||||||
| 
 | 
 | ||||||
|  | /* GUID for the auto generated boot menu entry */ | ||||||
|  | extern const efi_guid_t efi_guid_bootmenu_auto_generated; | ||||||
|  | 
 | ||||||
| /* GUID of the U-Boot root node */ | /* GUID of the U-Boot root node */ | ||||||
| extern const efi_guid_t efi_u_boot_guid; | extern const efi_guid_t efi_u_boot_guid; | ||||||
| #ifdef CONFIG_SANDBOX | #ifdef CONFIG_SANDBOX | ||||||
|  | @ -314,6 +325,8 @@ extern const efi_guid_t efi_guid_firmware_management_protocol; | ||||||
| extern const efi_guid_t efi_esrt_guid; | extern const efi_guid_t efi_esrt_guid; | ||||||
| /* GUID of the SMBIOS table */ | /* GUID of the SMBIOS table */ | ||||||
| extern const efi_guid_t smbios_guid; | extern const efi_guid_t smbios_guid; | ||||||
|  | /*GUID of console */ | ||||||
|  | extern const efi_guid_t efi_guid_text_input_protocol; | ||||||
| 
 | 
 | ||||||
| extern char __efi_runtime_start[], __efi_runtime_stop[]; | extern char __efi_runtime_start[], __efi_runtime_stop[]; | ||||||
| extern char __efi_runtime_rel_start[], __efi_runtime_rel_stop[]; | extern char __efi_runtime_rel_start[], __efi_runtime_rel_stop[]; | ||||||
|  | @ -940,6 +953,22 @@ struct efi_signature_store { | ||||||
| struct x509_certificate; | struct x509_certificate; | ||||||
| struct pkcs7_message; | struct pkcs7_message; | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * struct eficonfig_media_boot_option - boot option for (removable) media device | ||||||
|  |  * | ||||||
|  |  * This structure is used to enumerate possible boot option | ||||||
|  |  * | ||||||
|  |  * @lo:		Serialized load option data | ||||||
|  |  * @size:	Size of serialized load option data | ||||||
|  |  * @exist:	Flag to indicate the load option already exists | ||||||
|  |  *		in Non-volatile load option | ||||||
|  |  */ | ||||||
|  | struct eficonfig_media_boot_option { | ||||||
|  | 	void *lo; | ||||||
|  | 	efi_uintn_t size; | ||||||
|  | 	bool exist; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| bool efi_hash_regions(struct image_region *regs, int count, | bool efi_hash_regions(struct image_region *regs, int count, | ||||||
| 		      void **hash, const char *hash_algo, int *len); | 		      void **hash, const char *hash_algo, int *len); | ||||||
| bool efi_signature_lookup_digest(struct efi_image_regions *regs, | bool efi_signature_lookup_digest(struct efi_image_regions *regs, | ||||||
|  | @ -1064,4 +1093,28 @@ efi_status_t efi_esrt_populate(void); | ||||||
| efi_status_t efi_load_capsule_drivers(void); | efi_status_t efi_load_capsule_drivers(void); | ||||||
| 
 | 
 | ||||||
| efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr, u32 *sz); | efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr, u32 *sz); | ||||||
|  | 
 | ||||||
|  | efi_status_t efi_locate_handle_buffer_int(enum efi_locate_search_type search_type, | ||||||
|  | 					  const efi_guid_t *protocol, void *search_key, | ||||||
|  | 					  efi_uintn_t *no_handles, efi_handle_t **buffer); | ||||||
|  | 
 | ||||||
|  | efi_status_t efi_open_volume_int(struct efi_simple_file_system_protocol *this, | ||||||
|  | 				 struct efi_file_handle **root); | ||||||
|  | efi_status_t efi_file_open_int(struct efi_file_handle *this, | ||||||
|  | 			       struct efi_file_handle **new_handle, | ||||||
|  | 			       u16 *file_name, u64 open_mode, | ||||||
|  | 			       u64 attributes); | ||||||
|  | efi_status_t efi_file_close_int(struct efi_file_handle *file); | ||||||
|  | efi_status_t efi_file_read_int(struct efi_file_handle *this, | ||||||
|  | 			       efi_uintn_t *buffer_size, void *buffer); | ||||||
|  | efi_status_t efi_file_setpos_int(struct efi_file_handle *file, u64 pos); | ||||||
|  | 
 | ||||||
|  | typedef efi_status_t (*efi_console_filter_func)(struct efi_input_key *key); | ||||||
|  | efi_status_t efi_console_get_u16_string | ||||||
|  | 		(struct efi_simple_text_input_protocol *cin, | ||||||
|  | 		 u16 *buf, efi_uintn_t count, efi_console_filter_func filer_func, | ||||||
|  | 		 int row, int col); | ||||||
|  | 
 | ||||||
|  | efi_status_t efi_disk_get_device_name(const efi_handle_t handle, char *buf, int size); | ||||||
|  | 
 | ||||||
| #endif /* _EFI_LOADER_H */ | #endif /* _EFI_LOADER_H */ | ||||||
|  |  | ||||||
|  | @ -48,6 +48,9 @@ enum bootmenu_key { | ||||||
| 	KEY_DOWN, | 	KEY_DOWN, | ||||||
| 	KEY_SELECT, | 	KEY_SELECT, | ||||||
| 	KEY_QUIT, | 	KEY_QUIT, | ||||||
|  | 	KEY_PLUS, | ||||||
|  | 	KEY_MINUS, | ||||||
|  | 	KEY_SPACE, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void bootmenu_autoboot_loop(struct bootmenu_data *menu, | void bootmenu_autoboot_loop(struct bootmenu_data *menu, | ||||||
|  |  | ||||||
|  | @ -19,6 +19,9 @@ | ||||||
| static const struct efi_boot_services *bs; | static const struct efi_boot_services *bs; | ||||||
| static const struct efi_runtime_services *rs; | static const struct efi_runtime_services *rs; | ||||||
| 
 | 
 | ||||||
|  | const efi_guid_t efi_guid_bootmenu_auto_generated = | ||||||
|  | 		EFICONFIG_AUTO_GENERATED_ENTRY_GUID; | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * bootmgr implements the logic of trying to find a payload to boot |  * bootmgr implements the logic of trying to find a payload to boot | ||||||
|  * based on the BootOrder + BootXXXX variables, and then loading it. |  * based on the BootOrder + BootXXXX variables, and then loading it. | ||||||
|  | @ -243,6 +246,10 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Set load options */ | 	/* Set load options */ | ||||||
|  | 	if (size >= sizeof(efi_guid_t) && | ||||||
|  | 	    !guidcmp(lo.optional_data, &efi_guid_bootmenu_auto_generated)) | ||||||
|  | 		size = 0; | ||||||
|  | 
 | ||||||
| 	if (size) { | 	if (size) { | ||||||
| 		*load_options = malloc(size); | 		*load_options = malloc(size); | ||||||
| 		if (!*load_options) { | 		if (!*load_options) { | ||||||
|  |  | ||||||
|  | @ -2453,6 +2453,35 @@ static efi_status_t EFIAPI efi_protocols_per_handle( | ||||||
| 	return EFI_EXIT(EFI_SUCCESS); | 	return EFI_EXIT(EFI_SUCCESS); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | efi_status_t efi_locate_handle_buffer_int(enum efi_locate_search_type search_type, | ||||||
|  | 					  const efi_guid_t *protocol, void *search_key, | ||||||
|  | 					  efi_uintn_t *no_handles, efi_handle_t **buffer) | ||||||
|  | { | ||||||
|  | 	efi_status_t r; | ||||||
|  | 	efi_uintn_t buffer_size = 0; | ||||||
|  | 
 | ||||||
|  | 	if (!no_handles || !buffer) { | ||||||
|  | 		r = EFI_INVALID_PARAMETER; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 	*no_handles = 0; | ||||||
|  | 	*buffer = NULL; | ||||||
|  | 	r = efi_locate_handle(search_type, protocol, search_key, &buffer_size, | ||||||
|  | 			      *buffer); | ||||||
|  | 	if (r != EFI_BUFFER_TOO_SMALL) | ||||||
|  | 		goto out; | ||||||
|  | 	r = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, buffer_size, | ||||||
|  | 			      (void **)buffer); | ||||||
|  | 	if (r != EFI_SUCCESS) | ||||||
|  | 		goto out; | ||||||
|  | 	r = efi_locate_handle(search_type, protocol, search_key, &buffer_size, | ||||||
|  | 			      *buffer); | ||||||
|  | 	if (r == EFI_SUCCESS) | ||||||
|  | 		*no_handles = buffer_size / sizeof(efi_handle_t); | ||||||
|  | out: | ||||||
|  | 	return r; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * efi_locate_handle_buffer() - locate handles implementing a protocol |  * efi_locate_handle_buffer() - locate handles implementing a protocol | ||||||
|  * @search_type: selection criterion |  * @search_type: selection criterion | ||||||
|  | @ -2474,30 +2503,13 @@ efi_status_t EFIAPI efi_locate_handle_buffer( | ||||||
| 			efi_uintn_t *no_handles, efi_handle_t **buffer) | 			efi_uintn_t *no_handles, efi_handle_t **buffer) | ||||||
| { | { | ||||||
| 	efi_status_t r; | 	efi_status_t r; | ||||||
| 	efi_uintn_t buffer_size = 0; |  | ||||||
| 
 | 
 | ||||||
| 	EFI_ENTRY("%d, %pUs, %p, %p, %p", search_type, protocol, search_key, | 	EFI_ENTRY("%d, %pUs, %p, %p, %p", search_type, protocol, search_key, | ||||||
| 		  no_handles, buffer); | 		  no_handles, buffer); | ||||||
| 
 | 
 | ||||||
| 	if (!no_handles || !buffer) { | 	r = efi_locate_handle_buffer_int(search_type, protocol, search_key, | ||||||
| 		r = EFI_INVALID_PARAMETER; | 					 no_handles, buffer); | ||||||
| 		goto out; | 
 | ||||||
| 	} |  | ||||||
| 	*no_handles = 0; |  | ||||||
| 	*buffer = NULL; |  | ||||||
| 	r = efi_locate_handle(search_type, protocol, search_key, &buffer_size, |  | ||||||
| 			      *buffer); |  | ||||||
| 	if (r != EFI_BUFFER_TOO_SMALL) |  | ||||||
| 		goto out; |  | ||||||
| 	r = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, buffer_size, |  | ||||||
| 			      (void **)buffer); |  | ||||||
| 	if (r != EFI_SUCCESS) |  | ||||||
| 		goto out; |  | ||||||
| 	r = efi_locate_handle(search_type, protocol, search_key, &buffer_size, |  | ||||||
| 			      *buffer); |  | ||||||
| 	if (r == EFI_SUCCESS) |  | ||||||
| 		*no_handles = buffer_size / sizeof(efi_handle_t); |  | ||||||
| out: |  | ||||||
| 	return EFI_EXIT(r); | 	return EFI_EXIT(r); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ | ||||||
| 
 | 
 | ||||||
| #define LOG_CATEGORY LOGC_EFI | #define LOG_CATEGORY LOGC_EFI | ||||||
| 
 | 
 | ||||||
|  | #include <ansi.h> | ||||||
| #include <common.h> | #include <common.h> | ||||||
| #include <charset.h> | #include <charset.h> | ||||||
| #include <malloc.h> | #include <malloc.h> | ||||||
|  | @ -1318,3 +1319,72 @@ out_of_memory: | ||||||
| 	printf("ERROR: Out of memory\n"); | 	printf("ERROR: Out of memory\n"); | ||||||
| 	return r; | 	return r; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * efi_console_get_u16_string() - get user input string | ||||||
|  |  * | ||||||
|  |  * @cin:		protocol interface to EFI_SIMPLE_TEXT_INPUT_PROTOCOL | ||||||
|  |  * @buf:		buffer to store user input string in UTF16 | ||||||
|  |  * @count:		number of u16 string including NULL terminator that buf has | ||||||
|  |  * @filter_func:	callback to filter user input | ||||||
|  |  * @row:		row number to locate user input form | ||||||
|  |  * @col:		column number to locate user input form | ||||||
|  |  * Return:		status code | ||||||
|  |  */ | ||||||
|  | efi_status_t efi_console_get_u16_string(struct efi_simple_text_input_protocol *cin, | ||||||
|  | 					u16 *buf, efi_uintn_t count, | ||||||
|  | 					efi_console_filter_func filter_func, | ||||||
|  | 					int row, int col) | ||||||
|  | { | ||||||
|  | 	efi_status_t ret; | ||||||
|  | 	efi_uintn_t len = 0; | ||||||
|  | 	struct efi_input_key key; | ||||||
|  | 
 | ||||||
|  | 	printf(ANSI_CURSOR_POSITION | ||||||
|  | 	       ANSI_CLEAR_LINE_TO_END | ||||||
|  | 	       ANSI_CURSOR_SHOW, row, col); | ||||||
|  | 
 | ||||||
|  | 	ret = EFI_CALL(cin->reset(cin, false)); | ||||||
|  | 	if (ret != EFI_SUCCESS) | ||||||
|  | 		return ret; | ||||||
|  | 
 | ||||||
|  | 	for (;;) { | ||||||
|  | 		do { | ||||||
|  | 			ret = EFI_CALL(cin->read_key_stroke(cin, &key)); | ||||||
|  | 			mdelay(10); | ||||||
|  | 		} while (ret == EFI_NOT_READY); | ||||||
|  | 
 | ||||||
|  | 		if (key.unicode_char == u'\b') { | ||||||
|  | 			if (len > 0) | ||||||
|  | 				buf[--len] = u'\0'; | ||||||
|  | 
 | ||||||
|  | 			printf(ANSI_CURSOR_POSITION | ||||||
|  | 			       "%ls" | ||||||
|  | 			       ANSI_CLEAR_LINE_TO_END, row, col, buf); | ||||||
|  | 			continue; | ||||||
|  | 		} else if (key.unicode_char == u'\r') { | ||||||
|  | 			buf[len] = u'\0'; | ||||||
|  | 			return EFI_SUCCESS; | ||||||
|  | 		} else if (key.unicode_char == 0x3 || key.scan_code == 23) { | ||||||
|  | 			return EFI_ABORTED; | ||||||
|  | 		} else if (key.unicode_char < 0x20) { | ||||||
|  | 			/* ignore control codes other than Ctrl+C, '\r' and '\b' */ | ||||||
|  | 			continue; | ||||||
|  | 		} else if (key.scan_code != 0) { | ||||||
|  | 			/* only accept single ESC press for cancel */ | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (filter_func) { | ||||||
|  | 			if (filter_func(&key) != EFI_SUCCESS) | ||||||
|  | 				continue; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (len >= (count - 1)) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		buf[len] = key.unicode_char; | ||||||
|  | 		len++; | ||||||
|  | 		printf(ANSI_CURSOR_POSITION "%ls", row, col, buf); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -760,3 +760,53 @@ efi_status_t efi_disk_init(void) | ||||||
| 
 | 
 | ||||||
| 	return EFI_SUCCESS; | 	return EFI_SUCCESS; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * efi_disk_get_device_name() - get U-Boot device name associated with EFI handle | ||||||
|  |  * | ||||||
|  |  * @handle:	pointer to the EFI handle | ||||||
|  |  * @buf:	pointer to the buffer to store the string | ||||||
|  |  * @size:	size of buffer | ||||||
|  |  * Return:	status code | ||||||
|  |  */ | ||||||
|  | efi_status_t efi_disk_get_device_name(const efi_handle_t handle, char *buf, int size) | ||||||
|  | { | ||||||
|  | 	int count; | ||||||
|  | 	int diskid; | ||||||
|  | 	enum uclass_id id; | ||||||
|  | 	unsigned int part; | ||||||
|  | 	struct udevice *dev; | ||||||
|  | 	struct blk_desc *desc; | ||||||
|  | 	const char *if_typename; | ||||||
|  | 	bool is_partition = false; | ||||||
|  | 	struct disk_part *part_data; | ||||||
|  | 
 | ||||||
|  | 	if (!handle || !buf || !size) | ||||||
|  | 		return EFI_INVALID_PARAMETER; | ||||||
|  | 
 | ||||||
|  | 	dev = handle->dev; | ||||||
|  | 	id = device_get_uclass_id(dev); | ||||||
|  | 	if (id == UCLASS_BLK) { | ||||||
|  | 		desc = dev_get_uclass_plat(dev); | ||||||
|  | 	} else if (id == UCLASS_PARTITION) { | ||||||
|  | 		desc = dev_get_uclass_plat(dev_get_parent(dev)); | ||||||
|  | 		is_partition = true; | ||||||
|  | 	} else { | ||||||
|  | 		return EFI_INVALID_PARAMETER; | ||||||
|  | 	} | ||||||
|  | 	if_typename = blk_get_if_type_name(desc->if_type); | ||||||
|  | 	diskid = desc->devnum; | ||||||
|  | 
 | ||||||
|  | 	if (is_partition) { | ||||||
|  | 		part_data = dev_get_uclass_plat(dev); | ||||||
|  | 		part = part_data->partnum; | ||||||
|  | 		count = snprintf(buf, size, "%s %d:%d", if_typename, diskid, part); | ||||||
|  | 	} else { | ||||||
|  | 		count = snprintf(buf, size, "%s %d", if_typename, diskid); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (count < 0 || (count + 1) > size) | ||||||
|  | 		return EFI_INVALID_PARAMETER; | ||||||
|  | 
 | ||||||
|  | 	return EFI_SUCCESS; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -246,10 +246,10 @@ error: | ||||||
| 	return NULL; | 	return NULL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static efi_status_t efi_file_open_int(struct efi_file_handle *this, | efi_status_t efi_file_open_int(struct efi_file_handle *this, | ||||||
| 				      struct efi_file_handle **new_handle, | 			       struct efi_file_handle **new_handle, | ||||||
| 				      u16 *file_name, u64 open_mode, | 			       u16 *file_name, u64 open_mode, | ||||||
| 				      u64 attributes) | 			       u64 attributes) | ||||||
| { | { | ||||||
| 	struct file_handle *fh = to_fh(this); | 	struct file_handle *fh = to_fh(this); | ||||||
| 	efi_status_t ret; | 	efi_status_t ret; | ||||||
|  | @ -369,11 +369,17 @@ static efi_status_t file_close(struct file_handle *fh) | ||||||
| 	return EFI_SUCCESS; | 	return EFI_SUCCESS; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static efi_status_t EFIAPI efi_file_close(struct efi_file_handle *file) | efi_status_t efi_file_close_int(struct efi_file_handle *file) | ||||||
| { | { | ||||||
| 	struct file_handle *fh = to_fh(file); | 	struct file_handle *fh = to_fh(file); | ||||||
|  | 
 | ||||||
|  | 	return file_close(fh); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static efi_status_t EFIAPI efi_file_close(struct efi_file_handle *file) | ||||||
|  | { | ||||||
| 	EFI_ENTRY("%p", file); | 	EFI_ENTRY("%p", file); | ||||||
| 	return EFI_EXIT(file_close(fh)); | 	return EFI_EXIT(efi_file_close_int(file)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static efi_status_t EFIAPI efi_file_delete(struct efi_file_handle *file) | static efi_status_t EFIAPI efi_file_delete(struct efi_file_handle *file) | ||||||
|  | @ -562,8 +568,8 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size, | ||||||
| 	return EFI_SUCCESS; | 	return EFI_SUCCESS; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static efi_status_t efi_file_read_int(struct efi_file_handle *this, | efi_status_t efi_file_read_int(struct efi_file_handle *this, | ||||||
| 				      efi_uintn_t *buffer_size, void *buffer) | 			       efi_uintn_t *buffer_size, void *buffer) | ||||||
| { | { | ||||||
| 	struct file_handle *fh = to_fh(this); | 	struct file_handle *fh = to_fh(this); | ||||||
| 	efi_status_t ret = EFI_SUCCESS; | 	efi_status_t ret = EFI_SUCCESS; | ||||||
|  | @ -773,24 +779,11 @@ out: | ||||||
| 	return EFI_EXIT(ret); | 	return EFI_EXIT(ret); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | efi_status_t efi_file_setpos_int(struct efi_file_handle *file, u64 pos) | ||||||
|  * efi_file_setpos() - set current position in file |  | ||||||
|  * |  | ||||||
|  * This function implements the SetPosition service of the EFI file protocol. |  | ||||||
|  * See the UEFI spec for details. |  | ||||||
|  * |  | ||||||
|  * @file:	file handle |  | ||||||
|  * @pos:	new file position |  | ||||||
|  * Return:	status code |  | ||||||
|  */ |  | ||||||
| static efi_status_t EFIAPI efi_file_setpos(struct efi_file_handle *file, |  | ||||||
| 					   u64 pos) |  | ||||||
| { | { | ||||||
| 	struct file_handle *fh = to_fh(file); | 	struct file_handle *fh = to_fh(file); | ||||||
| 	efi_status_t ret = EFI_SUCCESS; | 	efi_status_t ret = EFI_SUCCESS; | ||||||
| 
 | 
 | ||||||
| 	EFI_ENTRY("%p, %llu", file, pos); |  | ||||||
| 
 |  | ||||||
| 	if (fh->isdir) { | 	if (fh->isdir) { | ||||||
| 		if (pos != 0) { | 		if (pos != 0) { | ||||||
| 			ret = EFI_UNSUPPORTED; | 			ret = EFI_UNSUPPORTED; | ||||||
|  | @ -812,6 +805,28 @@ static efi_status_t EFIAPI efi_file_setpos(struct efi_file_handle *file, | ||||||
| 	fh->offset = pos; | 	fh->offset = pos; | ||||||
| 
 | 
 | ||||||
| error: | error: | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * efi_file_setpos() - set current position in file | ||||||
|  |  * | ||||||
|  |  * This function implements the SetPosition service of the EFI file protocol. | ||||||
|  |  * See the UEFI spec for details. | ||||||
|  |  * | ||||||
|  |  * @file:	file handle | ||||||
|  |  * @pos:	new file position | ||||||
|  |  * Return:	status code | ||||||
|  |  */ | ||||||
|  | static efi_status_t EFIAPI efi_file_setpos(struct efi_file_handle *file, | ||||||
|  | 					   u64 pos) | ||||||
|  | { | ||||||
|  | 	efi_status_t ret = EFI_SUCCESS; | ||||||
|  | 
 | ||||||
|  | 	EFI_ENTRY("%p, %llu", file, pos); | ||||||
|  | 
 | ||||||
|  | 	ret = efi_file_setpos_int(file, pos); | ||||||
|  | 
 | ||||||
| 	return EFI_EXIT(ret); | 	return EFI_EXIT(ret); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1138,17 +1153,23 @@ struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp) | ||||||
| 	return f; | 	return f; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | efi_status_t efi_open_volume_int(struct efi_simple_file_system_protocol *this, | ||||||
|  | 				 struct efi_file_handle **root) | ||||||
|  | { | ||||||
|  | 	struct file_system *fs = to_fs(this); | ||||||
|  | 
 | ||||||
|  | 	*root = file_open(fs, NULL, NULL, 0, 0); | ||||||
|  | 
 | ||||||
|  | 	return EFI_SUCCESS; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static efi_status_t EFIAPI | static efi_status_t EFIAPI | ||||||
| efi_open_volume(struct efi_simple_file_system_protocol *this, | efi_open_volume(struct efi_simple_file_system_protocol *this, | ||||||
| 		struct efi_file_handle **root) | 		struct efi_file_handle **root) | ||||||
| { | { | ||||||
| 	struct file_system *fs = to_fs(this); |  | ||||||
| 
 |  | ||||||
| 	EFI_ENTRY("%p, %p", this, root); | 	EFI_ENTRY("%p, %p", this, root); | ||||||
| 
 | 
 | ||||||
| 	*root = file_open(fs, NULL, NULL, 0, 0); | 	return EFI_EXIT(efi_open_volume_int(this, root)); | ||||||
| 
 |  | ||||||
| 	return EFI_EXIT(EFI_SUCCESS); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct efi_simple_file_system_protocol * | struct efi_simple_file_system_protocol * | ||||||
|  |  | ||||||
|  | @ -0,0 +1,40 @@ | ||||||
|  | # SPDX-License-Identifier:      GPL-2.0+ | ||||||
|  | 
 | ||||||
|  | """Fixture for UEFI eficonfig test | ||||||
|  | """ | ||||||
|  | 
 | ||||||
|  | import os | ||||||
|  | import shutil | ||||||
|  | from subprocess import check_call | ||||||
|  | import pytest | ||||||
|  | 
 | ||||||
|  | @pytest.fixture(scope='session') | ||||||
|  | def efi_eficonfig_data(u_boot_config): | ||||||
|  |     """Set up a file system to be used in UEFI "eficonfig" command | ||||||
|  |        tests | ||||||
|  | 
 | ||||||
|  |     Args: | ||||||
|  |         u_boot_config -- U-boot configuration. | ||||||
|  | 
 | ||||||
|  |     Return: | ||||||
|  |         A path to disk image to be used for testing | ||||||
|  |     """ | ||||||
|  |     mnt_point = u_boot_config.persistent_data_dir + '/test_efi_eficonfig' | ||||||
|  |     image_path = u_boot_config.persistent_data_dir + '/efi_eficonfig.img' | ||||||
|  | 
 | ||||||
|  |     shutil.rmtree(mnt_point, ignore_errors=True) | ||||||
|  |     os.mkdir(mnt_point, mode = 0o755) | ||||||
|  | 
 | ||||||
|  |     with open(mnt_point + '/initrd-1.img', 'w', encoding = 'ascii') as file: | ||||||
|  |         file.write("initrd 1") | ||||||
|  | 
 | ||||||
|  |     with open(mnt_point + '/initrd-2.img', 'w', encoding = 'ascii') as file: | ||||||
|  |         file.write("initrd 2") | ||||||
|  | 
 | ||||||
|  |     shutil.copyfile(u_boot_config.build_dir + '/lib/efi_loader/initrddump.efi', | ||||||
|  |                     mnt_point + '/initrddump.efi') | ||||||
|  | 
 | ||||||
|  |     check_call(f'virt-make-fs --partition=gpt --size=+1M --type=vfat {mnt_point} {image_path}', | ||||||
|  |                shell=True) | ||||||
|  | 
 | ||||||
|  |     return image_path | ||||||
|  | @ -0,0 +1,354 @@ | ||||||
|  | # SPDX-License-Identifier:      GPL-2.0+ | ||||||
|  | """ Unit test for UEFI menu-driven configuration | ||||||
|  | """ | ||||||
|  | 
 | ||||||
|  | import pytest | ||||||
|  | import time | ||||||
|  | 
 | ||||||
|  | @pytest.mark.boardspec('sandbox') | ||||||
|  | @pytest.mark.buildconfigspec('cmd_eficonfig') | ||||||
|  | @pytest.mark.buildconfigspec('cmd_bootefi_bootmgr') | ||||||
|  | def test_efi_eficonfig(u_boot_console, efi_eficonfig_data): | ||||||
|  | 
 | ||||||
|  |     def send_user_input_and_wait(user_str, expect_str): | ||||||
|  |         time.sleep(0.1) # TODO: does not work correctly without sleep | ||||||
|  |         u_boot_console.run_command(cmd=user_str, wait_for_prompt=False, | ||||||
|  |                                    wait_for_echo=True, send_nl=False) | ||||||
|  |         u_boot_console.run_command(cmd='\x0d', wait_for_prompt=False, | ||||||
|  |                                    wait_for_echo=False, send_nl=False) | ||||||
|  |         if expect_str is not None: | ||||||
|  |             for i in expect_str: | ||||||
|  |                 u_boot_console.p.expect([i]) | ||||||
|  | 
 | ||||||
|  |     def press_up_down_enter_and_wait(up_count, down_count, enter, expect_str): | ||||||
|  |         # press UP key | ||||||
|  |         for i in range(up_count): | ||||||
|  |             u_boot_console.run_command(cmd='\x1b\x5b\x41', wait_for_prompt=False, | ||||||
|  |                                        wait_for_echo=False, send_nl=False) | ||||||
|  |         # press DOWN key | ||||||
|  |         for i in range(down_count): | ||||||
|  |             u_boot_console.run_command(cmd='\x1b\x5b\x42', wait_for_prompt=False, | ||||||
|  |                                        wait_for_echo=False, send_nl=False) | ||||||
|  |         # press ENTER if requested | ||||||
|  |         if enter: | ||||||
|  |             u_boot_console.run_command(cmd='\x0d', wait_for_prompt=False, | ||||||
|  |                                        wait_for_echo=False, send_nl=False) | ||||||
|  |         # wait expected output | ||||||
|  |         if expect_str is not None: | ||||||
|  |             for i in expect_str: | ||||||
|  |                 u_boot_console.p.expect([i]) | ||||||
|  | 
 | ||||||
|  |     def press_escape_key(wait_prompt): | ||||||
|  |         u_boot_console.run_command(cmd='\x1b', wait_for_prompt=wait_prompt, wait_for_echo=False, send_nl=False) | ||||||
|  | 
 | ||||||
|  |     def press_enter_key(wait_prompt): | ||||||
|  |         u_boot_console.run_command(cmd='\x0d', wait_for_prompt=wait_prompt, | ||||||
|  |                                    wait_for_echo=False, send_nl=False) | ||||||
|  | 
 | ||||||
|  |     def check_current_is_maintenance_menu(): | ||||||
|  |         for i in ('UEFI Maintenance Menu', 'Add Boot Option', 'Edit Boot Option', | ||||||
|  |                   'Change Boot Order', 'Delete Boot Option', 'Quit'): | ||||||
|  |             u_boot_console.p.expect([i]) | ||||||
|  | 
 | ||||||
|  |     """ Unit test for "eficonfig" command | ||||||
|  |     The menu-driven interface is used to set up UEFI load options. | ||||||
|  |     The bootefi bootmgr loads initrddump.efi as a payload. | ||||||
|  |     The crc32 of the loaded initrd.img is checked | ||||||
|  | 
 | ||||||
|  |     Args: | ||||||
|  |         u_boot_console -- U-Boot console | ||||||
|  |         efi__data -- Path to the disk image used for testing. | ||||||
|  |                      Test disk image has following files. | ||||||
|  |                          initrd-1.img | ||||||
|  |                          initrd-2.img | ||||||
|  |                          initrddump.efi | ||||||
|  | 
 | ||||||
|  |     """ | ||||||
|  | 
 | ||||||
|  |     # Restart the system to clean the previous state | ||||||
|  |     u_boot_console.restart_uboot() | ||||||
|  | 
 | ||||||
|  |     with u_boot_console.temporary_timeout(500): | ||||||
|  |         # | ||||||
|  |         # Test Case 1: Check the menu is displayed | ||||||
|  |         # | ||||||
|  |         u_boot_console.run_command('eficonfig', wait_for_prompt=False) | ||||||
|  |         for i in ('UEFI Maintenance Menu', 'Add Boot Option', 'Edit Boot Option', | ||||||
|  |                   'Change Boot Order', 'Delete Boot Option', 'Quit'): | ||||||
|  |             u_boot_console.p.expect([i]) | ||||||
|  |         # Select "Add Boot Option" | ||||||
|  |         press_enter_key(False) | ||||||
|  |         for i in ('Add Boot Option', 'Description:', 'File', 'Initrd File', 'Optional Data', | ||||||
|  |                   'Save', 'Quit'): | ||||||
|  |             u_boot_console.p.expect([i]) | ||||||
|  |         press_escape_key(False) | ||||||
|  |         check_current_is_maintenance_menu() | ||||||
|  |         # return to U-Boot console | ||||||
|  |         press_escape_key(True) | ||||||
|  | 
 | ||||||
|  |         # | ||||||
|  |         # Test Case 2: check auto generated media device entry | ||||||
|  |         # | ||||||
|  | 
 | ||||||
|  |         # bind the test disk image for succeeding tests | ||||||
|  |         u_boot_console.run_command(cmd = f'host bind 0 {efi_eficonfig_data}') | ||||||
|  | 
 | ||||||
|  |         u_boot_console.run_command('eficonfig', wait_for_prompt=False) | ||||||
|  | 
 | ||||||
|  |         # Change the Boot Order | ||||||
|  |         press_up_down_enter_and_wait(0, 2, True, 'Quit') | ||||||
|  |         for i in ('host 0:1', 'Save', 'Quit'): | ||||||
|  |             u_boot_console.p.expect([i]) | ||||||
|  |         # disable auto generated boot option for succeeding test | ||||||
|  |         u_boot_console.run_command(cmd=' ', wait_for_prompt=False, | ||||||
|  |                                        wait_for_echo=False, send_nl=False) | ||||||
|  |         # Save the BootOrder | ||||||
|  |         press_up_down_enter_and_wait(0, 1, True, None) | ||||||
|  |         check_current_is_maintenance_menu() | ||||||
|  | 
 | ||||||
|  |         # | ||||||
|  |         # Test Case 3: Add first Boot Option and load it | ||||||
|  |         # | ||||||
|  | 
 | ||||||
|  |         # Select 'Add Boot Option' | ||||||
|  |         press_up_down_enter_and_wait(0, 0, True, 'Quit') | ||||||
|  | 
 | ||||||
|  |         # Press the enter key to select 'Description:' entry, then enter Description | ||||||
|  |         press_up_down_enter_and_wait(0, 0, True, 'enter description:') | ||||||
|  |         # Send Description user input, press ENTER key to complete | ||||||
|  |         send_user_input_and_wait('test 1', 'Quit') | ||||||
|  | 
 | ||||||
|  |         # Set EFI image(initrddump.efi) | ||||||
|  |         press_up_down_enter_and_wait(0, 1, True, 'Quit') | ||||||
|  |         press_up_down_enter_and_wait(0, 0, True, 'host 0:1') | ||||||
|  |         # Select 'host 0:1' | ||||||
|  |         press_up_down_enter_and_wait(0, 0, True, 'Quit') | ||||||
|  |         # Press down key to select "initrddump.efi" entry followed by the enter key | ||||||
|  |         press_up_down_enter_and_wait(0, 2, True, 'Quit') | ||||||
|  | 
 | ||||||
|  |         # Set Initrd file(initrd-1.img) | ||||||
|  |         press_up_down_enter_and_wait(0, 2, True, 'Quit') | ||||||
|  |         press_up_down_enter_and_wait(0, 0, True, 'host 0:1') | ||||||
|  |         # Select 'host 0:1' | ||||||
|  |         press_up_down_enter_and_wait(0, 0, True, 'Quit') | ||||||
|  |         # Press down key to select "initrd-1.img" entry followed by the enter key | ||||||
|  |         press_up_down_enter_and_wait(0, 0, True, 'Quit') | ||||||
|  | 
 | ||||||
|  |         # Set optional_data | ||||||
|  |         press_up_down_enter_and_wait(0, 3, True, 'Optional Data:') | ||||||
|  |         # Send Description user input, press ENTER key to complete | ||||||
|  |         send_user_input_and_wait('nocolor', None) | ||||||
|  |         for i in ('Description: test 1', 'File: host 0:1/initrddump.efi', | ||||||
|  |                   'Initrd File: host 0:1/initrd-1.img', 'Optional Data: nocolor', 'Save', 'Quit'): | ||||||
|  |             u_boot_console.p.expect([i]) | ||||||
|  | 
 | ||||||
|  |         # Save the Boot Option | ||||||
|  |         press_up_down_enter_and_wait(0, 4, True, None) | ||||||
|  |         check_current_is_maintenance_menu() | ||||||
|  | 
 | ||||||
|  |         # Check the newly added Boot Option is handled correctly | ||||||
|  |         # Return to U-Boot console | ||||||
|  |         press_escape_key(True) | ||||||
|  |         u_boot_console.run_command(cmd = 'bootefi bootmgr') | ||||||
|  |         response = u_boot_console.run_command(cmd = 'load', wait_for_echo=False) | ||||||
|  |         assert 'crc32: 0x181464af' in response | ||||||
|  |         u_boot_console.run_command(cmd = 'exit', wait_for_echo=False) | ||||||
|  | 
 | ||||||
|  |         # | ||||||
|  |         # Test Case 4: Add second Boot Option and load it | ||||||
|  |         # | ||||||
|  |         u_boot_console.run_command('eficonfig', wait_for_prompt=False) | ||||||
|  | 
 | ||||||
|  |         # Select 'Add Boot Option' | ||||||
|  |         press_up_down_enter_and_wait(0, 0, True, 'Quit') | ||||||
|  | 
 | ||||||
|  |         # Press the enter key to select 'Description:' entry, then enter Description | ||||||
|  |         press_up_down_enter_and_wait(0, 0, True, 'enter description:') | ||||||
|  |         # Send Description user input, press ENTER key to complete | ||||||
|  |         send_user_input_and_wait('test 2', 'Quit') | ||||||
|  | 
 | ||||||
|  |         # Set EFI image(initrddump.efi) | ||||||
|  |         press_up_down_enter_and_wait(0, 1, True, 'Quit') | ||||||
|  |         press_up_down_enter_and_wait(0, 0, True, 'host 0:1') | ||||||
|  |         # Select 'host 0:1' | ||||||
|  |         press_up_down_enter_and_wait(0, 0, True, 'Quit') | ||||||
|  |         # Press down key to select "initrddump.efi" entry followed by the enter key | ||||||
|  |         press_up_down_enter_and_wait(0, 2, True, 'Quit') | ||||||
|  | 
 | ||||||
|  |         # Set Initrd file(initrd-2.img) | ||||||
|  |         press_up_down_enter_and_wait(0, 2, True, 'Quit') | ||||||
|  |         press_up_down_enter_and_wait(0, 0, True, 'host 0:1') | ||||||
|  |         # Select 'host 0:1' | ||||||
|  |         press_up_down_enter_and_wait(0, 0, True, 'Quit') | ||||||
|  |         # Press down key to select "initrd-2.img" entry followed by the enter key | ||||||
|  |         press_up_down_enter_and_wait(0, 1, True, 'Quit') | ||||||
|  | 
 | ||||||
|  |         # Set optional_data | ||||||
|  |         press_up_down_enter_and_wait(0, 3, True, 'Optional Data:') | ||||||
|  |         # Send Description user input, press ENTER key to complete | ||||||
|  |         send_user_input_and_wait('nocolor', None) | ||||||
|  |         for i in ('Description: test 2', 'File: host 0:1/initrddump.efi', | ||||||
|  |                   'Initrd File: host 0:1/initrd-2.img', 'Optional Data: nocolor', 'Save', 'Quit'): | ||||||
|  |             u_boot_console.p.expect([i]) | ||||||
|  | 
 | ||||||
|  |         # Save the Boot Option | ||||||
|  |         press_up_down_enter_and_wait(0, 4, True, 'Quit') | ||||||
|  | 
 | ||||||
|  |         # Change the Boot Order | ||||||
|  |         press_up_down_enter_and_wait(0, 2, True, 'Quit') | ||||||
|  |         press_up_down_enter_and_wait(0, 1, False, 'Quit') | ||||||
|  |         # move 'test 1' to the second entry | ||||||
|  |         u_boot_console.run_command(cmd='+', wait_for_prompt=False, | ||||||
|  |                                        wait_for_echo=False, send_nl=False) | ||||||
|  |         for i in ('test 2', 'test 1', 'host 0:1', 'Save', 'Quit'): | ||||||
|  |             u_boot_console.p.expect([i]) | ||||||
|  |         # Save the BootOrder | ||||||
|  |         press_up_down_enter_and_wait(0, 3, True, None) | ||||||
|  |         check_current_is_maintenance_menu() | ||||||
|  | 
 | ||||||
|  |         # Check the newly added Boot Option is handled correctly | ||||||
|  |         # Return to U-Boot console | ||||||
|  |         press_escape_key(True) | ||||||
|  |         u_boot_console.run_command(cmd = 'bootefi bootmgr') | ||||||
|  |         response = u_boot_console.run_command(cmd = 'load', wait_for_echo=False) | ||||||
|  |         assert 'crc32: 0x811d3515' in response | ||||||
|  |         u_boot_console.run_command(cmd = 'exit', wait_for_echo=False) | ||||||
|  | 
 | ||||||
|  |         # | ||||||
|  |         # Test Case 5: Change BootOrder and load it | ||||||
|  |         # | ||||||
|  |         u_boot_console.run_command('eficonfig', wait_for_prompt=False) | ||||||
|  | 
 | ||||||
|  |         # Change the Boot Order | ||||||
|  |         press_up_down_enter_and_wait(0, 2, True, None) | ||||||
|  |         # Check the curren BootOrder | ||||||
|  |         for i in ('test 2', 'test 1', 'host 0:1', 'Save', 'Quit'): | ||||||
|  |             u_boot_console.p.expect([i]) | ||||||
|  |         # move 'test 2' to the second entry | ||||||
|  |         u_boot_console.run_command(cmd='-', wait_for_prompt=False, | ||||||
|  |                                        wait_for_echo=False, send_nl=False) | ||||||
|  |         for i in ('test 1', 'test 2', 'host 0:1', 'Save', 'Quit'): | ||||||
|  |             u_boot_console.p.expect([i]) | ||||||
|  |         # Save the BootOrder | ||||||
|  |         press_up_down_enter_and_wait(0, 2, True, None) | ||||||
|  |         check_current_is_maintenance_menu() | ||||||
|  | 
 | ||||||
|  |         # Return to U-Boot console | ||||||
|  |         press_escape_key(True) | ||||||
|  |         u_boot_console.run_command(cmd = 'bootefi bootmgr') | ||||||
|  |         response = u_boot_console.run_command(cmd = 'load', wait_for_echo=False) | ||||||
|  |         assert 'crc32: 0x181464af' in response | ||||||
|  |         u_boot_console.run_command(cmd = 'exit', wait_for_echo=False) | ||||||
|  | 
 | ||||||
|  |         # | ||||||
|  |         # Test Case 6: Delete Boot Option(label:test 2) | ||||||
|  |         # | ||||||
|  |         u_boot_console.run_command('eficonfig', wait_for_prompt=False) | ||||||
|  | 
 | ||||||
|  |         # Select 'Delete Boot Option' | ||||||
|  |         press_up_down_enter_and_wait(0, 3, True, None) | ||||||
|  |         # Check the current BootOrder | ||||||
|  |         for i in ('test 1', 'test 2', 'Quit'): | ||||||
|  |             u_boot_console.p.expect([i]) | ||||||
|  | 
 | ||||||
|  |         # Delete 'test 2' | ||||||
|  |         press_up_down_enter_and_wait(0, 1, True, None) | ||||||
|  |         for i in ('test 1', 'Quit'): | ||||||
|  |             u_boot_console.p.expect([i]) | ||||||
|  |         press_escape_key(False) | ||||||
|  |         check_current_is_maintenance_menu() | ||||||
|  |         # Return to U-Boot console | ||||||
|  |         press_escape_key(True) | ||||||
|  | 
 | ||||||
|  |         # | ||||||
|  |         # Test Case 7: Edit Boot Option | ||||||
|  |         # | ||||||
|  |         u_boot_console.run_command('eficonfig', wait_for_prompt=False) | ||||||
|  |         # Select 'Edit Boot Option' | ||||||
|  |         press_up_down_enter_and_wait(0, 1, True, None) | ||||||
|  |         # Check the curren BootOrder | ||||||
|  |         for i in ('test 1', 'Quit'): | ||||||
|  |             u_boot_console.p.expect([i]) | ||||||
|  |         press_up_down_enter_and_wait(0, 0, True, None) | ||||||
|  |         for i in ('Description: test 1', 'File: host 0:1/initrddump.efi', | ||||||
|  |                   'Initrd File: host 0:1/initrd-1.img', 'Optional Data: nocolor', 'Save', 'Quit'): | ||||||
|  |             u_boot_console.p.expect([i]) | ||||||
|  | 
 | ||||||
|  |         # Press the enter key to select 'Description:' entry, then enter Description | ||||||
|  |         press_up_down_enter_and_wait(0, 0, True, 'enter description:') | ||||||
|  |         # Send Description user input, press ENTER key to complete | ||||||
|  |         send_user_input_and_wait('test 3', 'Quit') | ||||||
|  | 
 | ||||||
|  |         # Set EFI image(initrddump.efi) | ||||||
|  |         press_up_down_enter_and_wait(0, 1, True, 'Quit') | ||||||
|  |         press_up_down_enter_and_wait(0, 0, True, 'host 0:1') | ||||||
|  |         # Select 'host 0:1' | ||||||
|  |         press_up_down_enter_and_wait(0, 0, True, 'Quit') | ||||||
|  |         # Press down key to select "initrddump.efi" entry followed by the enter key | ||||||
|  |         press_up_down_enter_and_wait(0, 2, True, 'Quit') | ||||||
|  | 
 | ||||||
|  |         # Set Initrd file(initrd-2.img) | ||||||
|  |         press_up_down_enter_and_wait(0, 2, True, 'Quit') | ||||||
|  |         press_up_down_enter_and_wait(0, 0, True, 'host 0:1') | ||||||
|  |         # Select 'host 0:1' | ||||||
|  |         press_up_down_enter_and_wait(0, 0, True, 'Quit') | ||||||
|  |         # Press down key to select "initrd-1.img" entry followed by the enter key | ||||||
|  |         press_up_down_enter_and_wait(0, 1, True, 'Quit') | ||||||
|  | 
 | ||||||
|  |         # Set optional_data | ||||||
|  |         press_up_down_enter_and_wait(0, 3, True, 'Optional Data:') | ||||||
|  |         # Send Description user input, press ENTER key to complete | ||||||
|  |         send_user_input_and_wait('', None) | ||||||
|  |         for i in ('Description: test 3', 'File: host 0:1/initrddump.efi', | ||||||
|  |                   'Initrd File: host 0:1/initrd-2.img', 'Optional Data:', 'Save', 'Quit'): | ||||||
|  |             u_boot_console.p.expect([i]) | ||||||
|  | 
 | ||||||
|  |         # Save the Boot Option | ||||||
|  |         press_up_down_enter_and_wait(0, 4, True, 'Quit') | ||||||
|  |         press_escape_key(False) | ||||||
|  |         check_current_is_maintenance_menu() | ||||||
|  | 
 | ||||||
|  |         # Check the updated Boot Option is handled correctly | ||||||
|  |         # Return to U-Boot console | ||||||
|  |         press_escape_key(True) | ||||||
|  |         u_boot_console.run_command(cmd = 'bootefi bootmgr') | ||||||
|  |         response = u_boot_console.run_command(cmd = 'load', wait_for_echo=False) | ||||||
|  |         assert 'crc32: 0x811d3515' in response | ||||||
|  |         u_boot_console.run_command(cmd = 'exit', wait_for_echo=False) | ||||||
|  | 
 | ||||||
|  |         # | ||||||
|  |         # Test Case 8: Delete Boot Option(label:test 3) | ||||||
|  |         # | ||||||
|  |         u_boot_console.run_command('eficonfig', wait_for_prompt=False) | ||||||
|  | 
 | ||||||
|  |         # Select 'Delete Boot Option' | ||||||
|  |         press_up_down_enter_and_wait(0, 3, True, None) | ||||||
|  |         # Check the curren BootOrder | ||||||
|  |         for i in ('test 3', 'Quit'): | ||||||
|  |             u_boot_console.p.expect([i]) | ||||||
|  | 
 | ||||||
|  |         # Delete 'test 3' | ||||||
|  |         press_up_down_enter_and_wait(0, 0, True, 'Quit') | ||||||
|  |         press_escape_key(False) | ||||||
|  |         check_current_is_maintenance_menu() | ||||||
|  |         # Return to U-Boot console | ||||||
|  |         press_escape_key(True) | ||||||
|  | 
 | ||||||
|  |         # remove the host device | ||||||
|  |         u_boot_console.run_command(cmd = f'host bind -r 0') | ||||||
|  | 
 | ||||||
|  |         # | ||||||
|  |         # Test Case 9: No block device found | ||||||
|  |         # | ||||||
|  |         u_boot_console.run_command('eficonfig', wait_for_prompt=False) | ||||||
|  | 
 | ||||||
|  |         # Select 'Add Boot Option' | ||||||
|  |         press_up_down_enter_and_wait(0, 0, True, 'Quit') | ||||||
|  | 
 | ||||||
|  |         # Set EFI image | ||||||
|  |         press_up_down_enter_and_wait(0, 1, True, 'Quit') | ||||||
|  |         press_up_down_enter_and_wait(0, 0, True, 'No block device found!') | ||||||
|  |         press_escape_key(False) | ||||||
|  |         check_current_is_maintenance_menu() | ||||||
|  |         # Return to U-Boot console | ||||||
|  |         press_escape_key(True) | ||||||
		Loading…
	
		Reference in New Issue