mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-11 07:34:31 +00:00
Pull request for UEFI sub-system for efi-2020-04-rc4 (2)
In Linux next-20200228 patches have been merged to load an initial ramdisk using an EFI_LOAD_FILE2_PROTOCOL provided by the firmware. See commit ec93fc371f01 ("efi/libstub: Add support for loading the initrd from a device path"). The idea behind it is that the firmware should be responsible for validating the initrd in a secure boot setup. This pull-request comprises a patch series which let's U-Boot provide an initial implementation of the EFI_LOAD_FILE2_PROTOCOL providing the initrd. -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEbcT5xx8ppvoGt20zxIHbvCwFGsQFAl5ZYAYACgkQxIHbvCwF GsQWeg/+KzBLKSeu8TDBr/dSXGx/pLJK+riqRZsBYYkzVseIJEa6JBNgXUjg4qGD 7+2zt+K1gCUXBo3UDM+aMcjEII7TeQ3179dm8WysdhW2LxUjb8gidfYpyM57iCRV BHGUgRYF+23JOUcJIB3O7rZbwT1G7RRL3uqi0N5JJmu88yxDJ1WEZE9blLJlcX3Q IwP7RkhYigWHPCtdLL2KQ+DTZmoynNemi6RIuTKRKa4K0mqRnbJqk1IpMzsgiQP/ q+ykyRMYUx3iODiPTnF+Inn9Yr1OE5AVz7NN9jWyfNz1CAs7uRzN0XqTPobtOs8C aXaERjhp0U0SNhxUhKqmt7rZyHgwYmYUVfgnixZ3WZdGLXUgAWnkF1kRQRiR3ZcO XuteG20lirfapZhfkchhFXNLaWk/4FSRFGn5WDI5xCDv0/ie+fDw0c6BR5AdgHss ZF2EeaUln+bwyIBdWDrJEsSlTwTz2t0pFZft3hZ24KcdkRVFc9x/K890gTBfffIF qN4a0zwPRIq1tAHJSJvnyX7ViUGZkb8+q8dLTqNNY+yH0nXtAtayz4TslcxFK2lf Iw4URIWngBx1C/OVX5OEv4GNn4o3fL3ARc1BuH4/8tp2IhKq27ATFEm1AT1gJjXo 4VTSuPc9d07SbapsfqwHsEMmRP1GFIO6hQnPErfzliRLYmr00C4= =yydK -----END PGP SIGNATURE----- Merge tag 'efi-2020-04-rc4-2' of https://gitlab.denx.de/u-boot/custodians/u-boot-efi Pull request for UEFI sub-system for efi-2020-04-rc4 (2) In Linux next-20200228 patches have been merged to load an initial ramdisk using an EFI_LOAD_FILE2_PROTOCOL provided by the firmware. See commit ec93fc371f01 ("efi/libstub: Add support for loading the initrd from a device path"). The idea behind it is that the firmware should be responsible for validating the initrd in a secure boot setup. This pull-request comprises a patch series which let's U-Boot provide an initial implementation of the EFI_LOAD_FILE2_PROTOCOL providing the initrd.
This commit is contained in:
commit
5045289820
12 changed files with 508 additions and 0 deletions
|
@ -243,6 +243,10 @@ static const struct {
|
|||
"HII Config Routing",
|
||||
EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID,
|
||||
},
|
||||
{
|
||||
"Load File2",
|
||||
EFI_LOAD_FILE2_PROTOCOL_GUID,
|
||||
},
|
||||
{
|
||||
"Simple Network",
|
||||
EFI_SIMPLE_NETWORK_PROTOCOL_GUID,
|
||||
|
|
|
@ -125,6 +125,15 @@ Graphical output protocol
|
|||
.. kernel-doc:: lib/efi_loader/efi_gop.c
|
||||
:internal:
|
||||
|
||||
Load file 2 protocol
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The load file 2 protocol can be used by the Linux kernel to load the initial
|
||||
RAM disk. U-Boot can be configured to provide an implementation.
|
||||
|
||||
.. kernel-doc:: lib/efi_loader/efi_load_initrd.c
|
||||
:internal:
|
||||
|
||||
Network protocols
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -356,6 +356,18 @@ This driver is only available if U-Boot is configured with::
|
|||
CONFIG_BLK=y
|
||||
CONFIG_PARTITIONS=y
|
||||
|
||||
Miscellaneous
|
||||
-------------
|
||||
|
||||
Load file 2 protocol
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The load file 2 protocol can be used by the Linux kernel to load the initial
|
||||
RAM disk. U-Boot can be configured to provide an implementation with::
|
||||
|
||||
EFI_LOAD_FILE2_INITRD=y
|
||||
EFI_INITRD_FILESPEC=interface dev:part path_to_initrd
|
||||
|
||||
Links
|
||||
-----
|
||||
|
||||
|
|
|
@ -331,6 +331,14 @@ struct efi_runtime_services {
|
|||
EFI_GUID(0xeb9d2d31, 0x2d88, 0x11d3, \
|
||||
0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
|
||||
|
||||
#define EFI_LOAD_FILE_PROTOCOL_GUID \
|
||||
EFI_GUID(0x56ec3091, 0x954c, 0x11d2, \
|
||||
0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
|
||||
|
||||
#define EFI_LOAD_FILE2_PROTOCOL_GUID \
|
||||
EFI_GUID(0x4006c0c1, 0xfcb3, 0x403e, \
|
||||
0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d)
|
||||
|
||||
struct efi_configuration_table {
|
||||
efi_guid_t guid;
|
||||
void *table;
|
||||
|
@ -486,6 +494,7 @@ struct efi_device_path_nvme {
|
|||
#define DEVICE_PATH_TYPE_MEDIA_DEVICE 0x04
|
||||
# define DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH 0x01
|
||||
# define DEVICE_PATH_SUB_TYPE_CDROM_PATH 0x02
|
||||
# define DEVICE_PATH_SUB_TYPE_VENDOR_PATH 0x03
|
||||
# define DEVICE_PATH_SUB_TYPE_FILE_PATH 0x04
|
||||
|
||||
struct efi_device_path_hard_drive_path {
|
||||
|
@ -1619,6 +1628,14 @@ struct efi_unicode_collation_protocol {
|
|||
char *supported_languages;
|
||||
};
|
||||
|
||||
struct efi_load_file_protocol {
|
||||
efi_status_t (EFIAPI *load_file)(struct efi_load_file_protocol *this,
|
||||
struct efi_device_path *file_path,
|
||||
bool boot_policy,
|
||||
efi_uintn_t *buffer_size,
|
||||
void *buffer);
|
||||
};
|
||||
|
||||
/* Boot manager load options */
|
||||
#define LOAD_OPTION_ACTIVE 0x00000001
|
||||
#define LOAD_OPTION_FORCE_RECONNECT 0x00000002
|
||||
|
|
25
include/efi_load_initrd.h
Normal file
25
include/efi_load_initrd.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (c) 2020, Linaro Limited
|
||||
*/
|
||||
|
||||
#if !defined _EFI_LOAD_INITRD_H_
|
||||
#define _EFI_LOAD_INITRD_H_
|
||||
|
||||
#include <efi.h>
|
||||
#include <efi_api.h>
|
||||
|
||||
/*
|
||||
* Vendor GUID used by Linux to identify the handle with the
|
||||
* EFI_LOAD_FILE2_PROTOCOL and load an initial ramdisk.
|
||||
*/
|
||||
#define EFI_INITRD_MEDIA_GUID \
|
||||
EFI_GUID(0x5568e427, 0x68fc, 0x4f3d, \
|
||||
0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68)
|
||||
|
||||
struct efi_initrd_dp {
|
||||
struct efi_device_path_vendor vendor;
|
||||
struct efi_device_path end;
|
||||
} __packed;
|
||||
|
||||
#endif
|
|
@ -378,6 +378,7 @@ efi_status_t efi_gop_register(void);
|
|||
efi_status_t efi_net_register(void);
|
||||
/* Called by bootefi to make the watchdog available */
|
||||
efi_status_t efi_watchdog_register(void);
|
||||
efi_status_t efi_initrd_register(void);
|
||||
/* Called by bootefi to make SMBIOS tables available */
|
||||
/**
|
||||
* efi_acpi_register() - write out ACPI tables
|
||||
|
|
|
@ -130,4 +130,19 @@ config EFI_RNG_PROTOCOL
|
|||
Provide a EFI_RNG_PROTOCOL implementation using the hardware random
|
||||
number generator of the platform.
|
||||
|
||||
config EFI_LOAD_FILE2_INITRD
|
||||
bool "EFI_FILE_LOAD2_PROTOCOL for Linux initial ramdisk"
|
||||
default n
|
||||
help
|
||||
Expose a EFI_FILE_LOAD2_PROTOCOL that the Linux UEFI stub can
|
||||
use to load the initial ramdisk. Once this is enabled using
|
||||
initrd=<ramdisk> will stop working.
|
||||
|
||||
config EFI_INITRD_FILESPEC
|
||||
string "initramfs path"
|
||||
default "host 0:1 initrd"
|
||||
depends on EFI_LOAD_FILE2_INITRD
|
||||
help
|
||||
Full path of the initramfs file, e.g. mmc 0:2 initramfs.cpio.gz.
|
||||
|
||||
endif
|
||||
|
|
|
@ -43,3 +43,4 @@ obj-$(CONFIG_NET) += efi_net.o
|
|||
obj-$(CONFIG_GENERATE_ACPI_TABLE) += efi_acpi.o
|
||||
obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += efi_smbios.o
|
||||
obj-$(CONFIG_EFI_RNG_PROTOCOL) += efi_rng.o
|
||||
obj-$(CONFIG_EFI_LOAD_FILE2_INITRD) += efi_load_initrd.o
|
||||
|
|
198
lib/efi_loader/efi_load_initrd.c
Normal file
198
lib/efi_loader/efi_load_initrd.c
Normal file
|
@ -0,0 +1,198 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (c) 2020, Linaro Limited
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <env.h>
|
||||
#include <malloc.h>
|
||||
#include <mapmem.h>
|
||||
#include <dm.h>
|
||||
#include <fs.h>
|
||||
#include <efi_loader.h>
|
||||
#include <efi_load_initrd.h>
|
||||
|
||||
static const efi_guid_t efi_guid_load_file2_protocol =
|
||||
EFI_LOAD_FILE2_PROTOCOL_GUID;
|
||||
|
||||
static efi_status_t EFIAPI
|
||||
efi_load_file2_initrd(struct efi_load_file_protocol *this,
|
||||
struct efi_device_path *file_path, bool boot_policy,
|
||||
efi_uintn_t *buffer_size, void *buffer);
|
||||
|
||||
static const struct efi_load_file_protocol efi_lf2_protocol = {
|
||||
.load_file = efi_load_file2_initrd,
|
||||
};
|
||||
|
||||
/*
|
||||
* 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 dp = {
|
||||
.vendor = {
|
||||
{
|
||||
DEVICE_PATH_TYPE_MEDIA_DEVICE,
|
||||
DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
|
||||
sizeof(dp.vendor),
|
||||
},
|
||||
EFI_INITRD_MEDIA_GUID,
|
||||
},
|
||||
.end = {
|
||||
DEVICE_PATH_TYPE_END,
|
||||
DEVICE_PATH_SUB_TYPE_END,
|
||||
sizeof(dp.end),
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* get_file_size() - retrieve the size of initramfs, set efi status on error
|
||||
*
|
||||
* @dev: device to read from. i.e "mmc"
|
||||
* @part: device partition. i.e "0:1"
|
||||
* @file: name fo file
|
||||
* @status: EFI exit code in case of failure
|
||||
*
|
||||
* Return: size of file
|
||||
*/
|
||||
static loff_t get_file_size(const char *dev, const char *part, const char *file,
|
||||
efi_status_t *status)
|
||||
{
|
||||
loff_t sz = 0;
|
||||
int ret;
|
||||
|
||||
ret = fs_set_blk_dev(dev, part, FS_TYPE_ANY);
|
||||
if (ret) {
|
||||
*status = EFI_NO_MEDIA;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = fs_size(file, &sz);
|
||||
if (ret) {
|
||||
sz = 0;
|
||||
*status = EFI_NOT_FOUND;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
return sz;
|
||||
}
|
||||
|
||||
/**
|
||||
* load_file2() - get information about random number generation
|
||||
*
|
||||
* This function implement the LoadFile2() service in order to load an initram
|
||||
* disk requested by the Linux kernel stub.
|
||||
* See the UEFI spec for details.
|
||||
*
|
||||
* @this: loadfile2 protocol instance
|
||||
* @file_path: relative path of the file. "" in this case
|
||||
* @boot_policy: must be false for Loadfile2
|
||||
* @buffer_size: size of allocated buffer
|
||||
* @buffer: buffer to load the file
|
||||
*
|
||||
* Return: status code
|
||||
*/
|
||||
static efi_status_t EFIAPI
|
||||
efi_load_file2_initrd(struct efi_load_file_protocol *this,
|
||||
struct efi_device_path *file_path, bool boot_policy,
|
||||
efi_uintn_t *buffer_size, void *buffer)
|
||||
{
|
||||
const char *filespec = CONFIG_EFI_INITRD_FILESPEC;
|
||||
efi_status_t status = EFI_NOT_FOUND;
|
||||
loff_t file_sz = 0, read_sz = 0;
|
||||
char *dev, *part, *file;
|
||||
char *s;
|
||||
int ret;
|
||||
|
||||
EFI_ENTRY("%p, %p, %d, %p, %p", this, file_path, boot_policy,
|
||||
buffer_size, buffer);
|
||||
|
||||
s = strdup(filespec);
|
||||
if (!s)
|
||||
goto out;
|
||||
|
||||
if (!this || this != &efi_lf2_protocol ||
|
||||
!buffer_size) {
|
||||
status = EFI_INVALID_PARAMETER;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (file_path->type != dp.end.type ||
|
||||
file_path->sub_type != dp.end.sub_type) {
|
||||
status = EFI_INVALID_PARAMETER;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (boot_policy) {
|
||||
status = EFI_UNSUPPORTED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* expect something like 'mmc 0:1 initrd.cpio.gz' */
|
||||
dev = strsep(&s, " ");
|
||||
if (!dev)
|
||||
goto out;
|
||||
part = strsep(&s, " ");
|
||||
if (!part)
|
||||
goto out;
|
||||
file = strsep(&s, " ");
|
||||
if (!file)
|
||||
goto out;
|
||||
|
||||
file_sz = get_file_size(dev, part, file, &status);
|
||||
if (!file_sz)
|
||||
goto out;
|
||||
|
||||
if (!buffer || *buffer_size < file_sz) {
|
||||
status = EFI_BUFFER_TOO_SMALL;
|
||||
*buffer_size = file_sz;
|
||||
} else {
|
||||
ret = fs_set_blk_dev(dev, part, FS_TYPE_ANY);
|
||||
if (ret) {
|
||||
status = EFI_NO_MEDIA;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = fs_read(file, map_to_sysmem(buffer), 0, *buffer_size,
|
||||
&read_sz);
|
||||
if (ret || read_sz != file_sz)
|
||||
goto out;
|
||||
*buffer_size = read_sz;
|
||||
|
||||
status = EFI_SUCCESS;
|
||||
}
|
||||
|
||||
out:
|
||||
free(s);
|
||||
return EFI_EXIT(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_initrd_register() - Register a handle and loadfile2 protocol
|
||||
*
|
||||
* This function creates a new handle and installs a linux specific GUID
|
||||
* to handle initram disk loading during boot.
|
||||
* See the UEFI spec for details.
|
||||
*
|
||||
* Return: status code
|
||||
*/
|
||||
efi_status_t efi_initrd_register(void)
|
||||
{
|
||||
efi_handle_t efi_initrd_handle = NULL;
|
||||
efi_status_t ret;
|
||||
|
||||
/*
|
||||
* Set up the handle with the EFI_LOAD_FILE2_PROTOCOL which Linux may
|
||||
* use to load the initial ramdisk.
|
||||
*/
|
||||
ret = EFI_CALL(efi_install_multiple_protocol_interfaces
|
||||
(&efi_initrd_handle,
|
||||
/* initramfs */
|
||||
&efi_guid_device_path, &dp,
|
||||
/* LOAD_FILE2 */
|
||||
&efi_guid_load_file2_protocol,
|
||||
(void *)&efi_lf2_protocol,
|
||||
NULL));
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -155,6 +155,11 @@ efi_status_t efi_init_obj_list(void)
|
|||
if (ret != EFI_SUCCESS)
|
||||
goto out;
|
||||
#endif
|
||||
#ifdef CONFIG_EFI_LOAD_FILE2_INITRD
|
||||
ret = efi_initrd_register();
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto out;
|
||||
#endif
|
||||
#ifdef CONFIG_NET
|
||||
ret = efi_net_register();
|
||||
if (ret != EFI_SUCCESS)
|
||||
|
|
|
@ -49,6 +49,7 @@ obj-$(CONFIG_CPU_V7) += efi_selftest_unaligned.o
|
|||
obj-$(CONFIG_EFI_LOADER_HII) += efi_selftest_hii.o
|
||||
obj-$(CONFIG_EFI_RNG_PROTOCOL) += efi_selftest_rng.o
|
||||
obj-$(CONFIG_EFI_GET_TIME) += efi_selftest_rtc.o
|
||||
obj-$(CONFIG_EFI_LOAD_FILE2_INITRD) += efi_selftest_load_initrd.o
|
||||
|
||||
ifeq ($(CONFIG_GENERATE_ACPI_TABLE),)
|
||||
obj-y += efi_selftest_fdt.o
|
||||
|
|
220
lib/efi_selftest/efi_selftest_load_initrd.c
Normal file
220
lib/efi_selftest/efi_selftest_load_initrd.c
Normal file
|
@ -0,0 +1,220 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* efi_selftest_load_initrd
|
||||
*
|
||||
* Copyright (c) 2020 Ilias Apalodimas <ilias.apalodimas@linaro.org>
|
||||
*
|
||||
* This test checks the FileLoad2 protocol.
|
||||
* A known file is read from the file system and verified.
|
||||
*
|
||||
* An example usage - given a file image with a file system in partition 1
|
||||
* holding file initrd - is:
|
||||
*
|
||||
* * Configure the sandbox with
|
||||
*
|
||||
* CONFIG_EFI_SELFTEST=y
|
||||
* CONFIG_EFI_LOAD_FILE2_INITRD=y
|
||||
* CONFIG_EFI_INITRD_FILESPEC="host 0:1 initrd"
|
||||
*
|
||||
* * Run ./u-boot and execute
|
||||
*
|
||||
* host bind 0 image
|
||||
* setenv efi_selftest load initrd
|
||||
* bootefi selftest
|
||||
*
|
||||
* This would provide a test output like:
|
||||
*
|
||||
* Testing EFI API implementation
|
||||
*
|
||||
* Selected test: 'load initrd'
|
||||
*
|
||||
* Setting up 'load initrd'
|
||||
* Setting up 'load initrd' succeeded
|
||||
*
|
||||
* Executing 'load initrd'
|
||||
* Loaded 12378613 bytes
|
||||
* CRC32 2997478465
|
||||
*
|
||||
* Now the size and CRC32 can be compared to the provided file.
|
||||
*/
|
||||
|
||||
#include <efi_selftest.h>
|
||||
#include <efi_loader.h>
|
||||
#include <efi_load_initrd.h>
|
||||
|
||||
static struct efi_boot_services *boottime;
|
||||
|
||||
static struct efi_initrd_dp dp = {
|
||||
.vendor = {
|
||||
{
|
||||
DEVICE_PATH_TYPE_MEDIA_DEVICE,
|
||||
DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
|
||||
sizeof(dp.vendor),
|
||||
},
|
||||
EFI_INITRD_MEDIA_GUID,
|
||||
},
|
||||
.end = {
|
||||
DEVICE_PATH_TYPE_END,
|
||||
DEVICE_PATH_SUB_TYPE_END,
|
||||
sizeof(dp.end),
|
||||
}
|
||||
};
|
||||
|
||||
static struct efi_initrd_dp dp_invalid = {
|
||||
.vendor = {
|
||||
{
|
||||
DEVICE_PATH_TYPE_MEDIA_DEVICE,
|
||||
DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
|
||||
sizeof(dp.vendor),
|
||||
},
|
||||
EFI_INITRD_MEDIA_GUID,
|
||||
},
|
||||
.end = {
|
||||
0x8f, /* invalid */
|
||||
0xfe, /* invalid */
|
||||
sizeof(dp.end),
|
||||
}
|
||||
};
|
||||
|
||||
static int setup(const efi_handle_t handle,
|
||||
const struct efi_system_table *systable)
|
||||
{
|
||||
boottime = systable->boottime;
|
||||
|
||||
return EFI_ST_SUCCESS;
|
||||
}
|
||||
|
||||
static int execute(void)
|
||||
{
|
||||
efi_guid_t lf2_proto_guid = EFI_LOAD_FILE2_PROTOCOL_GUID;
|
||||
struct efi_load_file_protocol *lf2;
|
||||
struct efi_device_path *dp2, *dp2_invalid;
|
||||
efi_status_t status;
|
||||
efi_handle_t handle;
|
||||
char buffer[64];
|
||||
efi_uintn_t buffer_size;
|
||||
void *buf;
|
||||
u32 crc32;
|
||||
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
dp2 = (struct efi_device_path *)&dp;
|
||||
status = boottime->locate_device_path(&lf2_proto_guid, &dp2, &handle);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_st_error("Unable to locate device path\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
status = boottime->handle_protocol(handle, &lf2_proto_guid,
|
||||
(void **)&lf2);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_st_error("Unable to locate protocol\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
/* Case 1:
|
||||
* buffer_size can't be NULL
|
||||
* protocol can't be NULL
|
||||
*/
|
||||
status = lf2->load_file(lf2, dp2, false, NULL, &buffer);
|
||||
if (status != EFI_INVALID_PARAMETER) {
|
||||
efi_st_error("Buffer size can't be NULL\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
buffer_size = sizeof(buffer);
|
||||
status = lf2->load_file(NULL, dp2, false, &buffer_size, &buffer);
|
||||
if (status != EFI_INVALID_PARAMETER) {
|
||||
efi_st_error("Protocol can't be NULL\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Case 2: Match end node type/sub-type on device path
|
||||
*/
|
||||
dp2_invalid = (struct efi_device_path *)&dp_invalid;
|
||||
buffer_size = sizeof(buffer);
|
||||
status = lf2->load_file(lf2, dp2_invalid, false, &buffer_size, &buffer);
|
||||
if (status != EFI_INVALID_PARAMETER) {
|
||||
efi_st_error("Invalid device path type must return EFI_INVALID_PARAMETER\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
status = lf2->load_file(lf2, dp2_invalid, false, &buffer_size, &buffer);
|
||||
if (status != EFI_INVALID_PARAMETER) {
|
||||
efi_st_error("Invalid device path sub-type must return EFI_INVALID_PARAMETER\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Case 3:
|
||||
* BootPolicy 'true' must return EFI_UNSUPPORTED
|
||||
*/
|
||||
buffer_size = sizeof(buffer);
|
||||
status = lf2->load_file(lf2, dp2, true, &buffer_size, &buffer);
|
||||
if (status != EFI_UNSUPPORTED) {
|
||||
efi_st_error("BootPolicy true must return EFI_UNSUPPORTED\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Case: Pass buffer size as zero, firmware must return
|
||||
* EFI_BUFFER_TOO_SMALL and an appropriate size
|
||||
*/
|
||||
buffer_size = 0;
|
||||
status = lf2->load_file(lf2, dp2, false, &buffer_size, NULL);
|
||||
if (status != EFI_BUFFER_TOO_SMALL || !buffer_size) {
|
||||
efi_st_printf("buffer_size: %u\n", (unsigned int)buffer_size);
|
||||
efi_st_printf("status: %x\n", (unsigned int)status);
|
||||
efi_st_error("Buffer size not updated\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Case: Pass buffer size as smaller than the file_size,
|
||||
* firmware must return * EFI_BUFFER_TOO_SMALL and an appropriate size
|
||||
*/
|
||||
buffer_size = 1;
|
||||
status = lf2->load_file(lf2, dp2, false, &buffer_size, &buffer);
|
||||
if (status != EFI_BUFFER_TOO_SMALL || buffer_size <= 1) {
|
||||
efi_st_error("Buffer size not updated\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
status = boottime->allocate_pool(EFI_BOOT_SERVICES_DATA, buffer_size,
|
||||
&buf);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_st_error("Cannot allocate buffer\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
/* Case: Pass correct buffer, load the file and verify checksum*/
|
||||
status = lf2->load_file(lf2, dp2, false, &buffer_size, buf);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_st_error("Loading initrd failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
efi_st_printf("Loaded %u bytes\n", (unsigned int)buffer_size);
|
||||
status = boottime->calculate_crc32(buf, buffer_size, &crc32);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_st_error("Could not determine CRC32\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
efi_st_printf("CRC32 %u\n", (unsigned int)crc32);
|
||||
|
||||
status = boottime->free_pool(buf);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_st_error("Cannot free buffer\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
return EFI_ST_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_UNIT_TEST(load_initrd) = {
|
||||
.name = "load initrd",
|
||||
.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
|
||||
.setup = setup,
|
||||
.execute = execute,
|
||||
.on_request = true,
|
||||
};
|
Loading…
Reference in a new issue