Pull request for UEFI sub-system for efi-2021-04-rc1-2

* Provide a test tool for initial RAM disk provided via load file2 protocol.
 * Make more items configurable to reduce code size:
   * Boot manager
   * EFI_DT_FIXUP_PROTOCOL
   * EFI_DEVICE_PATH_UTILITIES_PROTOCOL
 * Bug fixes
   * avoid EFI runtime symbols in global symbol table
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEbcT5xx8ppvoGt20zxIHbvCwFGsQFAmAIHfIACgkQxIHbvCwF
 GsSz8g/+No9xNYiAK1pY0Fjus6ZSfBhMCY9NGwkEkyzFwXZG+ckmlWwMd+auk8Oz
 noU5vVBkr4JdrdpACdgiCdCeAfsYwxPy7/GulgVMLpptMlrLfbOhA/n7uOzhAilV
 QDt3BouOuvW+sVlxoxD2FNkpw4vFS6CasFgBj1+tWunARoXqIRxD4MbFp1zwApHb
 qC67jomsDS6MvQtrebZ3Erqkp67W0RVtD6X4KGq8+6g+8akVAan5zl7/gPj9Z8h6
 M1AXG/pLqDMrG+3RFGMyqncPOlxPVL85BQAAJVB8/SQcAQ726R4z/ia+3VBFBWWf
 N9rmzNJ9KnbAr3OHZnfqYITe/E2xgiRVqTYl5IL8701E41qhEjRiBWFF+U+QG/8b
 3IByp4FZXVbVxjsjK8dIi5aTmBvznwb0HcrlcbwJRonTvBCBOZCVIoAn2PalZUFW
 4zc4hGaoWVTdwRXaiiQKQuAfA52B3tfPqfWyUsm1E+crf/JYngstQe4A88FDorV6
 ozISWNXb5RzYdNluewJl2c1rfWcUiWHbbnKMt+YbDvE4OTy6lbJC9oY0mNfPE7nK
 7cq/Tk8WNhrMIv95nqzDBCv78naa0iQF5P+tHk6/r3IJ/wFFyD6f4ZvGijvCK+9o
 vgnmK0kz9Qd53m+g4L54xpTsyoCXaU2N9zzD1QgwV3HjW2JyjxY=
 =yVF7
 -----END PGP SIGNATURE-----

Merge tag 'efi-2021-04-rc1-2' of https://gitlab.denx.de/u-boot/custodians/u-boot-efi

Pull request for UEFI sub-system for efi-2021-04-rc1-2

* Provide a test tool for initial RAM disk provided via load file2 protocol.
* Make more items configurable to reduce code size:
  * Boot manager
  * EFI_DT_FIXUP_PROTOCOL
  * EFI_DEVICE_PATH_UTILITIES_PROTOCOL
* Bug fixes
  * avoid EFI runtime symbols in global symbol table
This commit is contained in:
Tom Rini 2021-01-20 10:49:23 -05:00
commit 404bbc809d
19 changed files with 820 additions and 265 deletions

View File

@ -631,10 +631,12 @@ static int do_bootefi(struct cmd_tbl *cmdtp, int flag, int argc,
else if (ret != EFI_SUCCESS)
return CMD_RET_FAILURE;
if (!strcmp(argv[1], "bootmgr"))
return do_efibootmgr();
if (IS_ENABLED(CONFIG_CMD_BOOTEFI_BOOTMGR)) {
if (!strcmp(argv[1], "bootmgr"))
return do_efibootmgr();
}
#ifdef CONFIG_CMD_BOOTEFI_SELFTEST
else if (!strcmp(argv[1], "selftest"))
if (!strcmp(argv[1], "selftest"))
return do_efi_selftest();
#endif
@ -657,11 +659,14 @@ static char bootefi_help_text[] =
" Use environment variable efi_selftest to select a single test.\n"
" Use 'setenv efi_selftest list' to enumerate all tests.\n"
#endif
#ifdef CONFIG_CMD_BOOTEFI_BOOTMGR
"bootefi bootmgr [fdt address]\n"
" - load and boot EFI payload based on BootOrder/BootXXXX variables.\n"
"\n"
" If specified, the device tree located at <fdt address> gets\n"
" exposed as EFI configuration table.\n";
" exposed as EFI configuration table.\n"
#endif
;
#endif
U_BOOT_CMD(

View File

@ -1367,8 +1367,8 @@ static int do_efi_boot_opt(struct cmd_tbl *cmdtp, int flag,
*
* efidebug test bootmgr
*/
static int do_efi_test_bootmgr(struct cmd_tbl *cmdtp, int flag,
int argc, char * const argv[])
static __maybe_unused int do_efi_test_bootmgr(struct cmd_tbl *cmdtp, int flag,
int argc, char * const argv[])
{
efi_handle_t image;
efi_uintn_t exit_data_size = 0;
@ -1392,8 +1392,10 @@ static int do_efi_test_bootmgr(struct cmd_tbl *cmdtp, int flag,
}
static struct cmd_tbl cmd_efidebug_test_sub[] = {
#ifdef CONFIG_CMD_BOOTEFI_BOOTMGR
U_BOOT_CMD_MKENT(bootmgr, CONFIG_SYS_MAXARGS, 1, do_efi_test_bootmgr,
"", ""),
#endif
};
/**
@ -1581,8 +1583,10 @@ static char efidebug_help_text[] =
" - show UEFI memory map\n"
"efidebug tables\n"
" - show UEFI configuration tables\n"
#ifdef CONFIG_CMD_BOOTEFI_BOOTMGR
"efidebug test bootmgr\n"
" - run simple bootmgr for test\n"
#endif
"efidebug query [-nv][-bs][-rt][-at]\n"
" - show size of UEFI variables store\n";
#endif

View File

@ -123,14 +123,20 @@
#endif
#endif
#define BOOTENV_SHARED_EFI \
#ifdef CONFIG_CMD_BOOTEFI_BOOTMGR
#define BOOTENV_EFI_BOOTMGR \
"boot_efi_bootmgr=" \
"if fdt addr ${fdt_addr_r}; then " \
"bootefi bootmgr ${fdt_addr_r};" \
"else " \
"bootefi bootmgr;" \
"fi\0" \
"fi\0"
#else
#define BOOTENV_EFI_BOOTMGR
#endif
#define BOOTENV_SHARED_EFI \
BOOTENV_EFI_BOOTMGR \
\
"boot_efi_binary=" \
"load ${devtype} ${devnum}:${distro_bootpart} " \

View File

@ -1693,10 +1693,6 @@ struct efi_driver_binding_protocol {
efi_handle_t driver_binding_handle;
};
/* Deprecated version of the Unicode collation protocol */
#define EFI_UNICODE_COLLATION_PROTOCOL_GUID \
EFI_GUID(0x1d85cd7f, 0xf43d, 0x11d2, \
0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
/* Current version of the Unicode collation protocol */
#define EFI_UNICODE_COLLATION_PROTOCOL2_GUID \
EFI_GUID(0xa4c751fc, 0x23ae, 0x4c3e, \

View File

@ -147,9 +147,6 @@ extern const struct efi_device_path_to_text_protocol efi_device_path_to_text;
/* implementation of the EFI_DEVICE_PATH_UTILITIES_PROTOCOL */
extern const struct efi_device_path_utilities_protocol
efi_device_path_utilities;
/* deprecated version of the EFI_UNICODE_COLLATION_PROTOCOL */
extern const struct efi_unicode_collation_protocol
efi_unicode_collation_protocol;
/* current version of the EFI_UNICODE_COLLATION_PROTOCOL */
extern const struct efi_unicode_collation_protocol
efi_unicode_collation_protocol2;
@ -564,7 +561,7 @@ struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp);
* @size: size in bytes
* Return: size in pages
*/
#define efi_size_in_pages(size) ((size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT)
#define efi_size_in_pages(size) (((size) + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT)
/* Generic EFI memory allocator, call this to get memory */
void *efi_alloc(uint64_t len, int memory_type);
/* More specific EFI memory allocator, called by EFI payloads */

View File

@ -306,4 +306,15 @@ efi_status_t __efi_runtime EFIAPI
efi_get_next_variable_name_runtime(efi_uintn_t *variable_name_size,
u16 *variable_name, efi_guid_t *guid);
/**
* efi_var_buf_update() - udpate memory buffer for variables
*
* @var_buf: source buffer
*
* This function copies to the memory buffer for UEFI variables. Call this
* function in ExitBootServices() if memory backed variables are only used
* at runtime to fill the buffer.
*/
void efi_var_buf_update(struct efi_var_file *var_buf);
#endif

View File

@ -27,6 +27,14 @@ config EFI_LOADER
if EFI_LOADER
config CMD_BOOTEFI_BOOTMGR
bool "UEFI Boot Manager"
default y
help
Select this option if you want to select the UEFI binary to be booted
via UEFI variables Boot####, BootOrder, and BootNext. This enables the
'bootefi bootmgr' command.
config EFI_SETUP_EARLY
bool
default n
@ -200,6 +208,21 @@ config EFI_DEVICE_PATH_TO_TEXT
The device path to text protocol converts device nodes and paths to
human readable strings.
config EFI_DEVICE_PATH_UTIL
bool "Device path utilities protocol"
default y
help
The device path utilities protocol creates and manipulates device
paths and device nodes. It is required to run the EFI Shell.
config EFI_DT_FIXUP
bool "Device tree fixup protocol"
depends on !GENERATE_ACPI_TABLE
default y
help
The EFI device-tree fix-up protocol provides a function to let the
firmware apply fix-ups. This may be used by boot loaders.
config EFI_LOADER_HII
bool "HII protocols"
default y
@ -229,17 +252,6 @@ config EFI_UNICODE_CAPITALIZATION
set, only the the correct handling of the letters of the codepage
used by the FAT file system is ensured.
config EFI_UNICODE_COLLATION_PROTOCOL
bool "Deprecated version of the Unicode collation protocol"
default n
help
In EFI 1.10 a version of the Unicode collation protocol using ISO
639-2 language codes existed. This protocol is not part of the UEFI
specification any longer. Unfortunately it is required to run the
UEFI Self Certification Test (SCT) II, version 2.6, 2017.
Choose this option for testing only. It is bound to be removed.
endif
config EFI_LOADER_BOUNCE_BUFFER

View File

@ -21,20 +21,21 @@ targets += helloworld.o
endif
obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o
obj-y += efi_bootmgr.o
obj-$(CONFIG_CMD_BOOTEFI_BOOTMGR) += efi_bootmgr.o
obj-y += efi_boottime.o
obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o
obj-$(CONFIG_EFI_CAPSULE_FIRMWARE) += efi_firmware.o
obj-y += efi_console.o
obj-y += efi_device_path.o
obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_device_path_to_text.o
obj-y += efi_device_path_utilities.o
obj-$(CONFIG_EFI_DEVICE_PATH_UTIL) += efi_device_path_utilities.o
ifeq ($(CONFIG_GENERATE_ACPI_TABLE),)
obj-y += efi_dt_fixup.o
endif
obj-y += efi_file.o
obj-$(CONFIG_EFI_LOADER_HII) += efi_hii.o
obj-y += efi_image_loader.o
obj-y += efi_load_options.o
obj-y += efi_memory.o
obj-y += efi_root_node.o
obj-y += efi_runtime.o

View File

@ -30,141 +30,6 @@ static const struct efi_runtime_services *rs;
* should do normal or recovery boot.
*/
/**
* efi_set_load_options() - set the load options of a loaded image
*
* @handle: the image handle
* @load_options_size: size of load options
* @load_options: pointer to load options
* Return: status code
*/
efi_status_t efi_set_load_options(efi_handle_t handle,
efi_uintn_t load_options_size,
void *load_options)
{
struct efi_loaded_image *loaded_image_info;
efi_status_t ret;
ret = EFI_CALL(systab.boottime->open_protocol(
handle,
&efi_guid_loaded_image,
(void **)&loaded_image_info,
efi_root, NULL,
EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL));
if (ret != EFI_SUCCESS)
return EFI_INVALID_PARAMETER;
loaded_image_info->load_options = load_options;
loaded_image_info->load_options_size = load_options_size;
return EFI_CALL(systab.boottime->close_protocol(handle,
&efi_guid_loaded_image,
efi_root, NULL));
}
/**
* efi_deserialize_load_option() - parse serialized data
*
* Parse serialized data describing a load option and transform it to the
* efi_load_option structure.
*
* @lo: pointer to target
* @data: serialized data
* @size: size of the load option, on return size of the optional data
* Return: status code
*/
efi_status_t efi_deserialize_load_option(struct efi_load_option *lo, u8 *data,
efi_uintn_t *size)
{
efi_uintn_t len;
len = sizeof(u32);
if (*size < len + 2 * sizeof(u16))
return EFI_INVALID_PARAMETER;
lo->attributes = get_unaligned_le32(data);
data += len;
*size -= len;
len = sizeof(u16);
lo->file_path_length = get_unaligned_le16(data);
data += len;
*size -= len;
lo->label = (u16 *)data;
len = u16_strnlen(lo->label, *size / sizeof(u16) - 1);
if (lo->label[len])
return EFI_INVALID_PARAMETER;
len = (len + 1) * sizeof(u16);
if (*size < len)
return EFI_INVALID_PARAMETER;
data += len;
*size -= len;
len = lo->file_path_length;
if (*size < len)
return EFI_INVALID_PARAMETER;
lo->file_path = (struct efi_device_path *)data;
if (efi_dp_check_length(lo->file_path, len) < 0)
return EFI_INVALID_PARAMETER;
data += len;
*size -= len;
lo->optional_data = data;
return EFI_SUCCESS;
}
/**
* efi_serialize_load_option() - serialize load option
*
* Serialize efi_load_option structure into byte stream for BootXXXX.
*
* @data: buffer for serialized data
* @lo: load option
* Return: size of allocated buffer
*/
unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data)
{
unsigned long label_len;
unsigned long size;
u8 *p;
label_len = (u16_strlen(lo->label) + 1) * sizeof(u16);
/* total size */
size = sizeof(lo->attributes);
size += sizeof(lo->file_path_length);
size += label_len;
size += lo->file_path_length;
if (lo->optional_data)
size += (utf8_utf16_strlen((const char *)lo->optional_data)
+ 1) * sizeof(u16);
p = malloc(size);
if (!p)
return 0;
/* copy data */
*data = p;
memcpy(p, &lo->attributes, sizeof(lo->attributes));
p += sizeof(lo->attributes);
memcpy(p, &lo->file_path_length, sizeof(lo->file_path_length));
p += sizeof(lo->file_path_length);
memcpy(p, lo->label, label_len);
p += label_len;
memcpy(p, lo->file_path, lo->file_path_length);
p += lo->file_path_length;
if (lo->optional_data) {
utf8_utf16_strcpy((u16 **)&p, (const char *)lo->optional_data);
p += sizeof(u16); /* size of trailing \0 */
}
return size;
}
/**
* get_var() - get UEFI variable
*

View File

@ -10,16 +10,6 @@
#include <efi_loader.h>
#include <mapmem.h>
static efi_status_t EFIAPI efi_dt_fixup(struct efi_dt_fixup_protocol *this,
void *dtb,
efi_uintn_t *buffer_size,
u32 flags);
struct efi_dt_fixup_protocol efi_dt_fixup_prot = {
.revision = EFI_DT_FIXUP_PROTOCOL_REVISION,
.fixup = efi_dt_fixup
};
const efi_guid_t efi_guid_dt_fixup_protocol = EFI_DT_FIXUP_PROTOCOL_GUID;
/**
@ -102,10 +92,21 @@ void efi_carve_out_dt_rsv(void *fdt)
}
}
static efi_status_t EFIAPI efi_dt_fixup(struct efi_dt_fixup_protocol *this,
void *dtb,
efi_uintn_t *buffer_size,
u32 flags)
/**
* efi_dt_fixup() - fix up device tree
*
* This function implements the Fixup() service of the
* EFI Device Tree Fixup Protocol.
*
* @this: instance of the protocol
* @dtb: device tree provided by caller
* @buffer_size: size of buffer for the device tree including free space
* @flags: bit field designating action to be performed
* Return: status code
*/
static efi_status_t __maybe_unused EFIAPI
efi_dt_fixup(struct efi_dt_fixup_protocol *this, void *dtb,
efi_uintn_t *buffer_size, u32 flags)
{
efi_status_t ret;
size_t required_size;
@ -158,3 +159,8 @@ static efi_status_t EFIAPI efi_dt_fixup(struct efi_dt_fixup_protocol *this,
out:
return EFI_EXIT(ret);
}
struct efi_dt_fixup_protocol efi_dt_fixup_prot = {
.revision = EFI_DT_FIXUP_PROTOCOL_REVISION,
.fixup = efi_dt_fixup
};

View File

@ -0,0 +1,149 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* EFI boot manager
*
* Copyright (c) 2018 AKASHI Takahiro, et.al.
*/
#define LOG_CATEGORY LOGC_EFI
#include <common.h>
#include <charset.h>
#include <log.h>
#include <malloc.h>
#include <efi_loader.h>
#include <asm/unaligned.h>
/**
* efi_set_load_options() - set the load options of a loaded image
*
* @handle: the image handle
* @load_options_size: size of load options
* @load_options: pointer to load options
* Return: status code
*/
efi_status_t efi_set_load_options(efi_handle_t handle,
efi_uintn_t load_options_size,
void *load_options)
{
struct efi_loaded_image *loaded_image_info;
efi_status_t ret;
ret = EFI_CALL(systab.boottime->open_protocol(
handle,
&efi_guid_loaded_image,
(void **)&loaded_image_info,
efi_root, NULL,
EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL));
if (ret != EFI_SUCCESS)
return EFI_INVALID_PARAMETER;
loaded_image_info->load_options = load_options;
loaded_image_info->load_options_size = load_options_size;
return EFI_CALL(systab.boottime->close_protocol(handle,
&efi_guid_loaded_image,
efi_root, NULL));
}
/**
* efi_deserialize_load_option() - parse serialized data
*
* Parse serialized data describing a load option and transform it to the
* efi_load_option structure.
*
* @lo: pointer to target
* @data: serialized data
* @size: size of the load option, on return size of the optional data
* Return: status code
*/
efi_status_t efi_deserialize_load_option(struct efi_load_option *lo, u8 *data,
efi_uintn_t *size)
{
efi_uintn_t len;
len = sizeof(u32);
if (*size < len + 2 * sizeof(u16))
return EFI_INVALID_PARAMETER;
lo->attributes = get_unaligned_le32(data);
data += len;
*size -= len;
len = sizeof(u16);
lo->file_path_length = get_unaligned_le16(data);
data += len;
*size -= len;
lo->label = (u16 *)data;
len = u16_strnlen(lo->label, *size / sizeof(u16) - 1);
if (lo->label[len])
return EFI_INVALID_PARAMETER;
len = (len + 1) * sizeof(u16);
if (*size < len)
return EFI_INVALID_PARAMETER;
data += len;
*size -= len;
len = lo->file_path_length;
if (*size < len)
return EFI_INVALID_PARAMETER;
lo->file_path = (struct efi_device_path *)data;
if (efi_dp_check_length(lo->file_path, len) < 0)
return EFI_INVALID_PARAMETER;
data += len;
*size -= len;
lo->optional_data = data;
return EFI_SUCCESS;
}
/**
* efi_serialize_load_option() - serialize load option
*
* Serialize efi_load_option structure into byte stream for BootXXXX.
*
* @data: buffer for serialized data
* @lo: load option
* Return: size of allocated buffer
*/
unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data)
{
unsigned long label_len;
unsigned long size;
u8 *p;
label_len = (u16_strlen(lo->label) + 1) * sizeof(u16);
/* total size */
size = sizeof(lo->attributes);
size += sizeof(lo->file_path_length);
size += label_len;
size += lo->file_path_length;
if (lo->optional_data)
size += (utf8_utf16_strlen((const char *)lo->optional_data)
+ 1) * sizeof(u16);
p = malloc(size);
if (!p)
return 0;
/* copy data */
*data = p;
memcpy(p, &lo->attributes, sizeof(lo->attributes));
p += sizeof(lo->attributes);
memcpy(p, &lo->file_path_length, sizeof(lo->file_path_length));
p += sizeof(lo->file_path_length);
memcpy(p, lo->label, label_len);
p += label_len;
memcpy(p, lo->file_path, lo->file_path_length);
p += lo->file_path_length;
if (lo->optional_data) {
utf8_utf16_strcpy((u16 **)&p, (const char *)lo->optional_data);
p += sizeof(u16); /* size of trailing \0 */
}
return size;
}

View File

@ -58,21 +58,17 @@ efi_status_t efi_root_node_register(void)
&efi_guid_device_path_to_text_protocol,
(void *)&efi_device_path_to_text,
#endif
#ifdef CONFIG_EFI_DEVICE_PATH_UTIL
/* Device path utilities protocol */
&efi_guid_device_path_utilities_protocol,
(void *)&efi_device_path_utilities,
#if !CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE)
#endif
#ifdef CONFIG_EFI_DT_FIXUP
/* Device-tree fix-up protocol */
&efi_guid_dt_fixup_protocol,
(void *)&efi_dt_fixup_prot,
#endif
#if CONFIG_IS_ENABLED(EFI_UNICODE_COLLATION_PROTOCOL2)
#if CONFIG_IS_ENABLED(EFI_UNICODE_COLLATION_PROTOCOL)
/* Deprecated Unicode collation protocol */
&efi_guid_unicode_collation_protocol,
(void *)&efi_unicode_collation_protocol,
#endif
/* Current Unicode collation protocol */
&efi_guid_unicode_collation_protocol2,
(void *)&efi_unicode_collation_protocol2,
#endif

View File

@ -38,7 +38,7 @@ const efi_guid_t efi_guid_unicode_collation_protocol2 =
* @s2: second string
*
* This function implements the StriColl() service of the
* EFI_UNICODE_COLLATION_PROTOCOL.
* EFI_UNICODE_COLLATION_PROTOCOL2.
*
* See the Unified Extensible Firmware Interface (UEFI) specification for
* details.
@ -179,7 +179,7 @@ static bool metai_match(const u16 *string, const u16 *pattern)
* - [<char1>-<char2>] matches any character in the range
*
* This function implements the MetaMatch() service of the
* EFI_UNICODE_COLLATION_PROTOCOL.
* EFI_UNICODE_COLLATION_PROTOCOL2.
*
* Return: true if the string is matched.
*/
@ -204,7 +204,7 @@ static bool EFIAPI efi_metai_match(struct efi_unicode_collation_protocol *this,
* same number of words this does not pose a problem.
*
* This function implements the StrLwr() service of the
* EFI_UNICODE_COLLATION_PROTOCOL.
* EFI_UNICODE_COLLATION_PROTOCOL2.
*/
static void EFIAPI efi_str_lwr(struct efi_unicode_collation_protocol *this,
u16 *string)
@ -225,7 +225,7 @@ static void EFIAPI efi_str_lwr(struct efi_unicode_collation_protocol *this,
* same number of words this does not pose a problem.
*
* This function implements the StrUpr() service of the
* EFI_UNICODE_COLLATION_PROTOCOL.
* EFI_UNICODE_COLLATION_PROTOCOL2.
*/
static void EFIAPI efi_str_upr(struct efi_unicode_collation_protocol *this,
u16 *string)
@ -245,7 +245,7 @@ static void EFIAPI efi_str_upr(struct efi_unicode_collation_protocol *this,
* @string: converted string
*
* This function implements the FatToStr() service of the
* EFI_UNICODE_COLLATION_PROTOCOL.
* EFI_UNICODE_COLLATION_PROTOCOL2.
*/
static void EFIAPI efi_fat_to_str(struct efi_unicode_collation_protocol *this,
efi_uintn_t fat_size, char *fat, u16 *string)
@ -276,7 +276,7 @@ static void EFIAPI efi_fat_to_str(struct efi_unicode_collation_protocol *this,
* @fat: converted string
*
* This function implements the StrToFat() service of the
* EFI_UNICODE_COLLATION_PROTOCOL.
* EFI_UNICODE_COLLATION_PROTOCOL2.
*
* Return: true if an illegal character was substituted by '_'.
*/
@ -337,30 +337,3 @@ const struct efi_unicode_collation_protocol efi_unicode_collation_protocol2 = {
.str_to_fat = efi_str_to_fat,
.supported_languages = "en",
};
/*
* In EFI 1.10 a version of the Unicode collation protocol using ISO 639-2
* language codes existed. This protocol is not part of the UEFI specification
* any longer. Unfortunately it is required to run the UEFI Self Certification
* Test (SCT) II, version 2.6, 2017. So we implement it here for the sole
* purpose of running the SCT. It can be removed when a compliant SCT is
* available.
*/
#if CONFIG_IS_ENABLED(EFI_UNICODE_COLLATION_PROTOCOL)
/* GUID of the EFI_UNICODE_COLLATION_PROTOCOL */
const efi_guid_t efi_guid_unicode_collation_protocol =
EFI_UNICODE_COLLATION_PROTOCOL_GUID;
const struct efi_unicode_collation_protocol efi_unicode_collation_protocol = {
.stri_coll = efi_stri_coll,
.metai_match = efi_metai_match,
.str_lwr = efi_str_lwr,
.str_upr = efi_str_upr,
.fat_to_str = efi_fat_to_str,
.str_to_fat = efi_str_to_fat,
/* ISO 639-2 language code */
.supported_languages = "eng",
};
#endif

View File

@ -10,7 +10,13 @@
#include <efi_variable.h>
#include <u-boot/crc.h>
struct efi_var_file __efi_runtime_data *efi_var_buf;
/*
* The variables efi_var_file and efi_var_entry must be static to avoid
* referencing them via the global offset table (section .got). The GOT
* is neither mapped as EfiRuntimeServicesData nor do we support its
* relocation during SetVirtualAddressMap().
*/
static struct efi_var_file __efi_runtime_data *efi_var_buf;
static struct efi_var_entry __efi_runtime_data *efi_current_var;
/**
@ -339,3 +345,8 @@ efi_get_next_variable_name_mem(efi_uintn_t *variable_name_size,
return EFI_SUCCESS;
}
void efi_var_buf_update(struct efi_var_file *var_buf)
{
memcpy(efi_var_buf, var_buf, EFI_VAR_BUF_SIZE);
}

View File

@ -702,7 +702,7 @@ void efi_variables_boot_exit_notify(void)
if (ret != EFI_SUCCESS)
log_err("Can't populate EFI variables. No runtime variables will be available\n");
else
memcpy(efi_var_buf, var_buf, len);
efi_var_buf_update(var_buf);
free(var_buf);
/* Update runtime service table */

View File

@ -14,6 +14,8 @@ CFLAGS_efi_selftest_miniapp_exit.o := $(CFLAGS_EFI) -Os -ffreestanding
CFLAGS_REMOVE_efi_selftest_miniapp_exit.o := $(CFLAGS_NON_EFI)
CFLAGS_efi_selftest_miniapp_return.o := $(CFLAGS_EFI) -Os -ffreestanding
CFLAGS_REMOVE_efi_selftest_miniapp_return.o := $(CFLAGS_NON_EFI)
CFLAGS_initrddump_exit.o := $(CFLAGS_EFI) -Os -ffreestanding
CFLAGS_REMOVE_initrddump.o := $(CFLAGS_NON_EFI)
obj-y += \
efi_selftest.o \
@ -78,8 +80,13 @@ efi_selftest_miniapp_exception.efi \
efi_selftest_miniapp_exit.efi \
efi_selftest_miniapp_return.efi
always += \
dtbdump.efi
ifeq ($(CONFIG_GENERATE_ACPI_TABLE),)
always += dtbdump.efi
endif
ifdef CONFIG_EFI_LOAD_FILE2_INITRD
always += initrddump.efi
endif
$(obj)/efi_miniapp_file_image_exception.h: $(obj)/efi_selftest_miniapp_exception.efi
$(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_exception.efi > \

View File

@ -28,6 +28,16 @@ static struct efi_system_table *systable;
static const efi_guid_t efi_dt_fixup_protocol_guid = EFI_DT_FIXUP_PROTOCOL_GUID;
static const efi_guid_t efi_file_info_guid = EFI_FILE_INFO_GUID;
/**
* print() - print string
*
* @string: text
*/
static void print(u16 *string)
{
cout->output_string(cout, string);
}
/**
* error() - print error string
*
@ -36,12 +46,56 @@ static const efi_guid_t efi_file_info_guid = EFI_FILE_INFO_GUID;
static void error(u16 *string)
{
cout->set_attribute(cout, EFI_LIGHTRED | EFI_BACKGROUND_BLACK);
cout->output_string(cout, string);
print(string);
cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK);
}
/**
* input() - read string from console
* efi_input_yn() - get answer to yes/no question
*
* Return:
* y or Y
* EFI_SUCCESS
* n or N
* EFI_ACCESS_DENIED
* ESC
* EFI_ABORTED
*/
static efi_status_t efi_input_yn(void)
{
struct efi_input_key key = {0};
efi_uintn_t index;
efi_status_t ret;
/* Drain the console input */
ret = cin->reset(cin, true);
for (;;) {
ret = bs->wait_for_event(1, &cin->wait_for_key, &index);
if (ret != EFI_SUCCESS)
continue;
ret = cin->read_key_stroke(cin, &key);
if (ret != EFI_SUCCESS)
continue;
switch (key.scan_code) {
case 0x17: /* Escape */
return EFI_ABORTED;
default:
break;
}
/* Convert to lower case */
switch (key.unicode_char | 0x20) {
case 'y':
return EFI_SUCCESS;
case 'n':
return EFI_ACCESS_DENIED;
default:
break;
}
}
}
/**
* efi_input() - read string from console
*
* @buffer: input buffer
* @buffer_size: buffer size
@ -67,7 +121,7 @@ static efi_status_t efi_input(u16 *buffer, efi_uintn_t buffer_size)
continue;
switch (key.scan_code) {
case 0x17: /* Escape */
cout->output_string(cout, L"\nAborted\n");
print(L"\r\nAborted\r\n");
return EFI_ABORTED;
default:
break;
@ -76,12 +130,12 @@ static efi_status_t efi_input(u16 *buffer, efi_uintn_t buffer_size)
case 0x08: /* Backspace */
if (pos) {
buffer[pos--] = 0;
cout->output_string(cout, L"\b \b");
print(L"\b \b");
}
break;
case 0x0a: /* Linefeed */
case 0x0d: /* Carriage return */
cout->output_string(cout, L"\n");
print(L"\r\n");
return EFI_SUCCESS;
default:
break;
@ -94,7 +148,7 @@ static efi_status_t efi_input(u16 *buffer, efi_uintn_t buffer_size)
*outbuf = key.unicode_char;
buffer[pos++] = key.unicode_char;
buffer[pos] = 0;
cout->output_string(cout, outbuf);
print(outbuf);
}
}
}
@ -171,9 +225,9 @@ bool starts_with(u16 *string, u16 *keyword)
*/
void do_help(void)
{
error(L"load <dtb> - load device-tree from file\n");
error(L"save <dtb> - save device-tree to file\n");
error(L"exit - exit the shell\n");
error(L"load <dtb> - load device-tree from file\r\n");
error(L"save <dtb> - save device-tree to file\r\n");
error(L"exit - exit the shell\r\n");
}
/**
@ -198,7 +252,7 @@ efi_status_t do_load(u16 *filename)
ret = bs->locate_protocol(&efi_dt_fixup_protocol_guid, NULL,
(void **)&dt_fixup_prot);
if (ret != EFI_SUCCESS) {
error(L"Device-tree fix-up protocol not found\n");
error(L"Device-tree fix-up protocol not found\r\n");
return ret;
}
@ -208,7 +262,7 @@ efi_status_t do_load(u16 *filename)
(void **)&loaded_image, NULL, NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (ret != EFI_SUCCESS) {
error(L"Loaded image protocol not found\n");
error(L"Loaded image protocol not found\r\n");
return ret;
}
/* Open the simple file system protocol */
@ -217,57 +271,57 @@ efi_status_t do_load(u16 *filename)
(void **)&file_system, NULL, NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (ret != EFI_SUCCESS) {
error(L"Failed to open simple file system protocol\n");
error(L"Failed to open simple file system protocol\r\n");
goto out;
}
/* Open volume */
ret = file_system->open_volume(file_system, &root);
if (ret != EFI_SUCCESS) {
error(L"Failed to open volume\n");
error(L"Failed to open volume\r\n");
goto out;
}
/* Open file */
ret = root->open(root, &file, filename, EFI_FILE_MODE_READ, 0);
if (ret != EFI_SUCCESS) {
error(L"File not found\n");
error(L"File not found\r\n");
goto out;
}
/* Get file size */
buffer_size = 0;
ret = file->getinfo(file, &efi_file_info_guid, &buffer_size, NULL);
if (ret != EFI_BUFFER_TOO_SMALL) {
error(L"Can't get file info size\n");
error(L"Can't get file info size\r\n");
goto out;
}
ret = bs->allocate_pool(EFI_LOADER_DATA, buffer_size, (void **)&info);
if (ret != EFI_SUCCESS) {
error(L"Out of memory\n");
error(L"Out of memory\r\n");
goto out;
}
ret = file->getinfo(file, &efi_file_info_guid, &buffer_size, info);
if (ret != EFI_SUCCESS) {
error(L"Can't get file info\n");
error(L"Can't get file info\r\n");
goto out;
}
buffer_size = info->file_size;
pages = efi_size_in_pages(buffer_size);
ret = bs->free_pool(info);
if (ret != EFI_SUCCESS)
error(L"Can't free memory pool\n");
error(L"Can't free memory pool\r\n");
/* Read file */
ret = bs->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
EFI_ACPI_RECLAIM_MEMORY,
pages, &addr);
if (ret != EFI_SUCCESS) {
error(L"Out of memory\n");
error(L"Out of memory\r\n");
goto out;
}
dtb = (struct fdt_header *)(uintptr_t)addr;
ret = file->read(file, &buffer_size, dtb);
if (ret != EFI_SUCCESS) {
error(L"Can't read file\n");
error(L"Can't read file\r\n");
goto out;
}
/* Fixup file, expecting EFI_BUFFER_TOO_SMALL */
@ -278,24 +332,24 @@ efi_status_t do_load(u16 *filename)
/* Read file into larger buffer */
ret = bs->free_pages(addr, pages);
if (ret != EFI_SUCCESS)
error(L"Can't free memory pages\n");
error(L"Can't free memory pages\r\n");
pages = efi_size_in_pages(buffer_size);
ret = bs->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
EFI_ACPI_RECLAIM_MEMORY,
pages, &addr);
if (ret != EFI_SUCCESS) {
error(L"Out of memory\n");
error(L"Out of memory\r\n");
goto out;
}
dtb = (struct fdt_header *)(uintptr_t)addr;
ret = file->setpos(file, 0);
if (ret != EFI_SUCCESS) {
error(L"Can't position file\n");
error(L"Can't position file\r\n");
goto out;
}
ret = file->read(file, &buffer_size, dtb);
if (ret != EFI_SUCCESS) {
error(L"Can't read file\n");
error(L"Can't read file\r\n");
goto out;
}
buffer_size = pages << EFI_PAGE_SHIFT;
@ -305,24 +359,24 @@ efi_status_t do_load(u16 *filename)
EFI_DT_INSTALL_TABLE);
}
if (ret == EFI_SUCCESS)
cout->output_string(cout, L"device-tree installed\n");
print(L"device-tree installed\r\n");
else
error(L"Device-tree fix-up failed\n");
error(L"Device-tree fix-up failed\r\n");
out:
if (addr) {
ret2 = bs->free_pages(addr, pages);
if (ret2 != EFI_SUCCESS)
error(L"Can't free memory pages\n");
error(L"Can't free memory pages\r\n");
}
if (file) {
ret2 = file->close(file);
if (ret2 != EFI_SUCCESS)
error(L"Can't close file\n");
error(L"Can't close file\r\n");
}
if (root) {
ret2 = root->close(root);
if (ret2 != EFI_SUCCESS)
error(L"Can't close volume\n");
error(L"Can't close volume\r\n");
}
return ret;
}
@ -344,11 +398,11 @@ efi_status_t do_save(u16 *filename)
dtb = get_dtb(systable);
if (!dtb) {
error(L"DTB not found\n");
error(L"DTB not found\r\n");
return EFI_NOT_FOUND;
}
if (f2h(dtb->magic) != FDT_MAGIC) {
error(L"Wrong device tree magic\n");
error(L"Wrong device tree magic\r\n");
return EFI_NOT_FOUND;
}
dtb_size = f2h(dtb->totalsize);
@ -359,7 +413,7 @@ efi_status_t do_save(u16 *filename)
(void **)&loaded_image, NULL, NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (ret != EFI_SUCCESS) {
error(L"Loaded image protocol not found\n");
error(L"Loaded image protocol not found\r\n");
return ret;
}
@ -369,16 +423,30 @@ efi_status_t do_save(u16 *filename)
(void **)&file_system, NULL, NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (ret != EFI_SUCCESS) {
error(L"Failed to open simple file system protocol\n");
error(L"Failed to open simple file system protocol\r\n");
return ret;
}
/* Open volume */
ret = file_system->open_volume(file_system, &root);
if (ret != EFI_SUCCESS) {
error(L"Failed to open volume\n");
error(L"Failed to open volume\r\n");
return ret;
}
/* Check if file already exists */
ret = root->open(root, &file, filename, EFI_FILE_MODE_READ, 0);
if (ret == EFI_SUCCESS) {
file->close(file);
print(L"Overwrite existing file (y/n)? ");
ret = efi_input_yn();
print(L"\r\n");
if (ret != EFI_SUCCESS) {
root->close(root);
error(L"Aborted by user\r\n");
return ret;
}
}
/* Create file */
ret = root->open(root, &file, filename,
EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE |
@ -387,16 +455,16 @@ efi_status_t do_save(u16 *filename)
/* Write file */
ret = file->write(file, &dtb_size, dtb);
if (ret != EFI_SUCCESS)
error(L"Failed to write file\n");
error(L"Failed to write file\r\n");
file->close(file);
} else {
error(L"Failed to open file\n");
error(L"Failed to open file\r\n");
}
root->close(root);
if (ret == EFI_SUCCESS) {
cout->output_string(cout, filename);
cout->output_string(cout, L" written\n");
print(filename);
print(L" written\r\n");
}
return ret;
@ -422,7 +490,7 @@ efi_status_t EFIAPI efi_main(efi_handle_t image_handle,
cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK);
cout->clear_screen(cout);
cout->set_attribute(cout, EFI_WHITE | EFI_BACKGROUND_BLACK);
cout->output_string(cout, L"DTB Dump\n========\n\n");
print(L"DTB Dump\r\n========\r\n\r\n");
cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK);
for (;;) {
@ -430,7 +498,7 @@ efi_status_t EFIAPI efi_main(efi_handle_t image_handle,
u16 *pos;
efi_uintn_t ret;
cout->output_string(cout, L"=> ");
print(L"=> ");
ret = efi_input(command, sizeof(command));
if (ret == EFI_ABORTED)
break;

View File

@ -46,11 +46,10 @@ static void mac(void *pointer, u16 **buf)
/*
* printx() - print hexadecimal number to an u16 string
*
* @pointer: pointer
* @p: value to print
* @prec: minimum number of digits to print
* @buf: pointer to buffer address,
* on return position of terminating zero word
* @size: size of value to be printed in bytes
*/
static void printx(u64 p, int prec, u16 **buf)
{

View File

@ -0,0 +1,449 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2020, Heinrich Schuchardt <xypron.glpk@gmx.de>
*
* initrddump.efi saves the initial RAM disk provided via the
* EFI_LOAD_FILE2_PROTOCOL.
*/
#include <common.h>
#include <efi_api.h>
#include <efi_load_initrd.h>
#define BUFFER_SIZE 64
#define ESC 0x17
#define efi_size_in_pages(size) (((size) + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT)
static struct efi_system_table *systable;
static struct efi_boot_services *bs;
static struct efi_simple_text_output_protocol *cerr;
static struct efi_simple_text_output_protocol *cout;
static struct efi_simple_text_input_protocol *cin;
static const efi_guid_t loaded_image_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
static const efi_guid_t guid_simple_file_system_protocol =
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
static const efi_guid_t load_file2_guid = EFI_LOAD_FILE2_PROTOCOL_GUID;
static efi_handle_t handle;
/*
* Device path defined by Linux to identify the handle providing the
* EFI_LOAD_FILE2_PROTOCOL used for loading the initial ramdisk.
*/
static const struct efi_initrd_dp initrd_dp = {
.vendor = {
{
DEVICE_PATH_TYPE_MEDIA_DEVICE,
DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
sizeof(initrd_dp.vendor),
},
EFI_INITRD_MEDIA_GUID,
},
.end = {
DEVICE_PATH_TYPE_END,
DEVICE_PATH_SUB_TYPE_END,
sizeof(initrd_dp.end),
}
};
/**
* print() - print string
*
* @string: text
*/
static void print(u16 *string)
{
cout->output_string(cout, string);
}
/**
* error() - print error string
*
* @string: error text
*/
static void error(u16 *string)
{
cout->set_attribute(cout, EFI_LIGHTRED | EFI_BACKGROUND_BLACK);
print(string);
cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK);
}
/*
* printx() - print hexadecimal number
*
* @val: value to print;
* @prec: minimum number of digits to print
*/
static void printx(u64 val, u32 prec)
{
int i;
u16 c;
u16 buf[16];
u16 *pos = buf;
for (i = 2 * sizeof(val) - 1; i >= 0; --i) {
c = (val >> (4 * i)) & 0x0f;
if (c || pos != buf || !i || i < prec) {
c += '0';
if (c > '9')
c += 'a' - '9' - 1;
*pos++ = c;
}
}
*pos = 0;
print(buf);
}
/**
* efi_input_yn() - get answer to yes/no question
*
* Return:
* y or Y
* EFI_SUCCESS
* n or N
* EFI_ACCESS_DENIED
* ESC
* EFI_ABORTED
*/
static efi_status_t efi_input_yn(void)
{
struct efi_input_key key = {0};
efi_uintn_t index;
efi_status_t ret;
/* Drain the console input */
ret = cin->reset(cin, true);
for (;;) {
ret = bs->wait_for_event(1, &cin->wait_for_key, &index);
if (ret != EFI_SUCCESS)
continue;
ret = cin->read_key_stroke(cin, &key);
if (ret != EFI_SUCCESS)
continue;
switch (key.scan_code) {
case 0x17: /* Escape */
return EFI_ABORTED;
default:
break;
}
/* Convert to lower case */
switch (key.unicode_char | 0x20) {
case 'y':
return EFI_SUCCESS;
case 'n':
return EFI_ACCESS_DENIED;
default:
break;
}
}
}
/**
* efi_input() - read string from console
*
* @buffer: input buffer
* @buffer_size: buffer size
* Return: status code
*/
static efi_status_t efi_input(u16 *buffer, efi_uintn_t buffer_size)
{
struct efi_input_key key = {0};
efi_uintn_t index;
efi_uintn_t pos = 0;
u16 outbuf[2] = L" ";
efi_status_t ret;
/* Drain the console input */
ret = cin->reset(cin, true);
*buffer = 0;
for (;;) {
ret = bs->wait_for_event(1, &cin->wait_for_key, &index);
if (ret != EFI_SUCCESS)
continue;
ret = cin->read_key_stroke(cin, &key);
if (ret != EFI_SUCCESS)
continue;
switch (key.scan_code) {
case 0x17: /* Escape */
print(L"\r\nAborted\r\n");
return EFI_ABORTED;
default:
break;
}
switch (key.unicode_char) {
case 0x08: /* Backspace */
if (pos) {
buffer[pos--] = 0;
print(L"\b \b");
}
break;
case 0x0a: /* Linefeed */
case 0x0d: /* Carriage return */
print(L"\r\n");
return EFI_SUCCESS;
default:
break;
}
/* Ignore surrogate codes */
if (key.unicode_char >= 0xD800 && key.unicode_char <= 0xDBFF)
continue;
if (key.unicode_char >= 0x20 &&
pos < buffer_size - 1) {
*outbuf = key.unicode_char;
buffer[pos++] = key.unicode_char;
buffer[pos] = 0;
print(outbuf);
}
}
}
/**
* skip_whitespace() - skip over leading whitespace
*
* @pos: UTF-16 string
* Return: pointer to first non-whitespace
*/
static u16 *skip_whitespace(u16 *pos)
{
for (; *pos && *pos <= 0x20; ++pos)
;
return pos;
}
/**
* starts_with() - check if @string starts with @keyword
*
* @string: string to search for keyword
* @keyword: keyword to be searched
* Return: true fi @string starts with the keyword
*/
static bool starts_with(u16 *string, u16 *keyword)
{
for (; *keyword; ++string, ++keyword) {
if (*string != *keyword)
return false;
}
return true;
}
/**
* do_help() - print help
*/
static void do_help(void)
{
error(L"load - show length and CRC32 of initial RAM disk\r\n");
error(L"save <initrd> - save initial RAM disk to file\r\n");
error(L"exit - exit the shell\r\n");
}
/**
* get_initrd() - read initial RAM disk via EFI_LOAD_FILE2_PROTOCOL
*
* @initrd: on return buffer with initial RAM disk
* @initrd_size: size of initial RAM disk
* Return: status code
*/
static efi_status_t get_initrd(void **initrd, efi_uintn_t *initrd_size)
{
struct efi_device_path *dp = (struct efi_device_path *)&initrd_dp;
struct efi_load_file_protocol *load_file2_prot;
u64 buffer;
efi_handle_t handle;
efi_status_t ret;
*initrd = NULL;
*initrd_size = 0;
ret = bs->locate_device_path(&load_file2_guid, &dp, &handle);
if (ret != EFI_SUCCESS) {
error(L"Load File2 protocol not found\r\n");
return ret;
}
ret = bs->handle_protocol(handle, &load_file2_guid,
(void **)&load_file2_prot);
ret = load_file2_prot->load_file(load_file2_prot, dp, false,
initrd_size, NULL);
if (ret != EFI_BUFFER_TOO_SMALL) {
error(L"Load File2 protocol does not provide file length\r\n");
return EFI_LOAD_ERROR;
}
ret = bs->allocate_pages(EFI_ALLOCATE_ANY_PAGES, EFI_LOADER_DATA,
efi_size_in_pages(*initrd_size), &buffer);
if (ret != EFI_SUCCESS) {
error(L"Out of memory\r\n");
return ret;
}
*initrd = (void *)buffer;
ret = load_file2_prot->load_file(load_file2_prot, dp, false,
initrd_size, *initrd);
if (ret != EFI_SUCCESS) {
error(L"Load File2 protocol failed to provide file\r\n");
bs->free_pages(buffer, efi_size_in_pages(*initrd_size));
return EFI_LOAD_ERROR;
}
return ret;
}
/**
* do_load() - load initial RAM disk and display CRC32 and length
*
* @filename: file name
* Return: status code
*/
static efi_status_t do_load(void)
{
void *initrd;
efi_uintn_t initrd_size;
u32 crc32;
efi_uintn_t ret;
ret = get_initrd(&initrd, &initrd_size);
if (ret != EFI_SUCCESS)
return ret;
print(L"length: 0x");
printx(initrd_size, 1);
print(L"\r\n");
ret = bs->calculate_crc32(initrd, initrd_size, &crc32);
if (ret != EFI_SUCCESS) {
error(L"Calculating CRC32 failed\r\n");
return EFI_LOAD_ERROR;
}
print(L"crc32: 0x");
printx(crc32, 8);
print(L"\r\n");
return EFI_SUCCESS;
}
/**
* do_save() - save initial RAM disk
*
* @filename: file name
* Return: status code
*/
static efi_status_t do_save(u16 *filename)
{
struct efi_loaded_image *loaded_image;
struct efi_simple_file_system_protocol *file_system;
struct efi_file_handle *root, *file;
void *initrd;
efi_uintn_t initrd_size;
efi_uintn_t ret;
ret = get_initrd(&initrd, &initrd_size);
if (ret != EFI_SUCCESS)
return ret;
filename = skip_whitespace(filename);
ret = bs->open_protocol(handle, &loaded_image_guid,
(void **)&loaded_image, NULL, NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (ret != EFI_SUCCESS) {
error(L"Loaded image protocol not found\r\n");
goto out;
}
/* Open the simple file system protocol */
ret = bs->open_protocol(loaded_image->device_handle,
&guid_simple_file_system_protocol,
(void **)&file_system, NULL, NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (ret != EFI_SUCCESS) {
error(L"Failed to open simple file system protocol\r\n");
goto out;
}
/* Open volume */
ret = file_system->open_volume(file_system, &root);
if (ret != EFI_SUCCESS) {
error(L"Failed to open volume\r\n");
goto out;
}
/* Check if file already exists */
ret = root->open(root, &file, filename, EFI_FILE_MODE_READ, 0);
if (ret == EFI_SUCCESS) {
file->close(file);
print(L"Overwrite existing file (y/n)? ");
ret = efi_input_yn();
print(L"\r\n");
if (ret != EFI_SUCCESS) {
root->close(root);
error(L"Aborted by user\r\n");
goto out;
}
}
/* Create file */
ret = root->open(root, &file, filename,
EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE |
EFI_FILE_MODE_CREATE, EFI_FILE_ARCHIVE);
if (ret == EFI_SUCCESS) {
/* Write file */
ret = file->write(file, &initrd_size, initrd);
if (ret != EFI_SUCCESS) {
error(L"Failed to write file\r\n");
} else {
print(filename);
print(L" written\r\n");
}
file->close(file);
} else {
error(L"Failed to open file\r\n");
}
root->close(root);
out:
if (initrd)
bs->free_pages((uintptr_t)initrd,
efi_size_in_pages(initrd_size));
return ret;
}
/**
* efi_main() - entry point of the EFI application.
*
* @handle: handle of the loaded image
* @systab: system table
* @return: status code
*/
efi_status_t EFIAPI efi_main(efi_handle_t image_handle,
struct efi_system_table *systab)
{
handle = image_handle;
systable = systab;
cerr = systable->std_err;
cout = systable->con_out;
cin = systable->con_in;
bs = systable->boottime;
cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK);
cout->clear_screen(cout);
cout->set_attribute(cout, EFI_WHITE | EFI_BACKGROUND_BLACK);
print(L"INITRD Dump\r\n========\r\n\r\n");
cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK);
for (;;) {
u16 command[BUFFER_SIZE];
u16 *pos;
efi_uintn_t ret;
print(L"=> ");
ret = efi_input(command, sizeof(command));
if (ret == EFI_ABORTED)
break;
pos = skip_whitespace(command);
if (starts_with(pos, L"exit"))
break;
else if (starts_with(pos, L"load"))
do_load();
else if (starts_with(pos, L"save "))
do_save(pos + 5);
else
do_help();
}
cout->set_attribute(cout, EFI_LIGHTGRAY | EFI_BACKGROUND_BLACK);
cout->clear_screen(cout);
return EFI_SUCCESS;
}