[PATCH v2 4/6] efi_loader: add EFI_RAM_DISK_PROTOCOL implementation
Masahisa Kojima
masahisa.kojima at linaro.org
Fri Jul 14 07:44:04 CEST 2023
This commit adds the EFI_RAM_DISK_PROTOCOL implementation.
User can mount the distro installer by registering the
memory mapped ISO image through EFI_RAM_DISK_PROTOCOL.
Note that the installation process may not proceed
after the distro installer calls ExitBootServices()
since there is no hand-off process for the block device of
memory mapped ISO image.
Signed-off-by: Masahisa Kojima <masahisa.kojima at linaro.org>
---
Changes in v2:
- implement EFI_RAM_DISK_PROTOCOL based on the
ramdisk uclass
include/efi_api.h | 13 ++++
include/efi_loader.h | 4 +
lib/efi_loader/Kconfig | 7 ++
lib/efi_loader/Makefile | 1 +
lib/efi_loader/efi_ram_disk.c | 142 ++++++++++++++++++++++++++++++++++
lib/efi_loader/efi_setup.c | 6 ++
lib/uuid.c | 4 +
7 files changed, 177 insertions(+)
create mode 100644 lib/efi_loader/efi_ram_disk.c
diff --git a/include/efi_api.h b/include/efi_api.h
index 4ee4a1b5e9..3982ab89bc 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -764,6 +764,19 @@ struct efi_block_io {
efi_status_t (EFIAPI *flush_blocks)(struct efi_block_io *this);
};
+#define EFI_RAM_DISK_PROTOCOL_GUID \
+ EFI_GUID(0xab38a0df, 0x6873, 0x44a9, \
+ 0x87, 0xe6, 0xd4, 0xeb, 0x56, 0x14, 0x84, 0x49)
+
+struct efi_ram_disk_protocol {
+ /* "register" is a reserved keyword in C, use "disk_register" instead */
+ efi_status_t(EFIAPI *disk_register)(
+ u64 ram_disk_base, u64 ram_disk_size, efi_guid_t *ram_disk_type,
+ struct efi_device_path *parent_device_path,
+ struct efi_device_path **device_path);
+ efi_status_t (EFIAPI *unregister)(struct efi_device_path *device_path);
+};
+
struct simple_text_output_mode {
s32 max_mode;
s32 mode;
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 604fd765f7..70c8c83099 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -333,6 +333,8 @@ extern const efi_guid_t smbios_guid;
/*GUID of console */
extern const efi_guid_t efi_guid_text_input_protocol;
extern const efi_guid_t efi_guid_text_output_protocol;
+/* GUID of Ram Disk protocol */
+extern const efi_guid_t efi_guid_ram_disk_protocol;
extern char __efi_runtime_start[], __efi_runtime_stop[];
extern char __efi_runtime_rel_start[], __efi_runtime_rel_stop[];
@@ -1159,4 +1161,6 @@ efi_status_t efi_disk_get_device_name(const efi_handle_t handle, char *buf, int
*/
void efi_add_known_memory(void);
+efi_status_t efi_ram_disk_register(void);
+
#endif /* _EFI_LOADER_H */
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index c5835e6ef6..ff0559e8c4 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -433,4 +433,11 @@ config EFI_RISCV_BOOT_PROTOCOL
replace the transfer via the device-tree. The latter is not
possible on systems using ACPI.
+config EFI_RAM_DISK_PROTOCOL
+ bool "EFI_RAM_DISK_PROTOCOL support"
+ depends on PARTITIONS
+ depends on RAM_DISK
+ help
+ Provide a EFI_RAM_DISK_PROTOCOL implementation to register the
+ RAM disk and create the block device.
endif
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index 1a8c8d7cab..4197f594a2 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -86,6 +86,7 @@ obj-$(CONFIG_EFI_RISCV_BOOT_PROTOCOL) += efi_riscv.o
obj-$(CONFIG_EFI_LOAD_FILE2_INITRD) += efi_load_initrd.o
obj-$(CONFIG_EFI_SIGNATURE_SUPPORT) += efi_signature.o
obj-$(CONFIG_EFI_ECPT) += efi_conformance.o
+obj-$(CONFIG_EFI_RAM_DISK_PROTOCOL) += efi_ram_disk.o
EFI_VAR_SEED_FILE := $(subst $\",,$(CONFIG_EFI_VAR_SEED_FILE))
$(obj)/efi_var_seed.o: $(srctree)/$(EFI_VAR_SEED_FILE)
diff --git a/lib/efi_loader/efi_ram_disk.c b/lib/efi_loader/efi_ram_disk.c
new file mode 100644
index 0000000000..a261d93963
--- /dev/null
+++ b/lib/efi_loader/efi_ram_disk.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * RAM Disk Protocol
+ *
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+#include <dm.h>
+#include <efi_loader.h>
+#include <malloc.h>
+#include <ramdisk.h>
+
+const efi_guid_t efi_guid_ram_disk_protocol = EFI_RAM_DISK_PROTOCOL_GUID;
+
+/*
+ * ram_disk_register - Register service of the RAM disk protocol
+ *
+ * @ram_disk_base: The base address of registered RAM disk
+ * @ram_disk_size: The size of registered RAM disk
+ * @ram_disk_type: The type of registered RAM disk
+ * @parent_device_path: Pointer to the parent device path
+ * @device_path: Pointer to the device path
+ * Return: status code
+ */
+static efi_status_t EFIAPI
+ram_disk_register(u64 ram_disk_base, u64 ram_disk_size,
+ efi_guid_t *ram_disk_type,
+ struct efi_device_path *parent_device_path,
+ struct efi_device_path **device_path)
+{
+ efi_status_t ret;
+ struct udevice *bdev;
+ efi_handle_t disk_handle;
+ struct efi_handler *handler;
+ struct efi_device_path *dp;
+
+ EFI_ENTRY("%llu %llu %pUs %p, %p", ram_disk_base, ram_disk_size,
+ ram_disk_type, parent_device_path, device_path);
+
+ if (!ram_disk_size || !ram_disk_type || !device_path) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ *device_path = NULL;
+
+ /* TODO: Add parent_device_path */
+ bdev = ramdisk_mount(ram_disk_base, ram_disk_size, ram_disk_type);
+ if (!bdev) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ if (dev_tag_get_ptr(bdev, DM_TAG_EFI, (void **)&disk_handle)) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ ret = efi_search_protocol(disk_handle, &efi_guid_device_path, &handler);
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ ret = efi_protocol_open(handler, (void **)&dp, NULL, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ log_debug("EFI_RAM_DISK_PROTOCOL register %pD\n", dp);
+
+ *device_path = efi_dp_dup(dp);
+ if (!(*device_path))
+ ret = EFI_OUT_OF_RESOURCES;
+
+out:
+ return EFI_EXIT(ret);
+}
+
+/*
+ * ram_disk_unregister - Unregister service of the RAM disk protocol
+ *
+ * @device_path: Pointer to the device path
+ * Return: status code
+ */
+static efi_status_t EFIAPI
+ram_disk_unregister(struct efi_device_path *device_path)
+{
+ int ret;
+ efi_status_t status = EFI_SUCCESS;
+ enum uclass_id id;
+ efi_handle_t disk_handle;
+
+ EFI_ENTRY("%pD", device_path);
+
+ if (!device_path) {
+ status = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ disk_handle = efi_dp_find_obj(device_path, &efi_block_io_guid, NULL);
+ if (!disk_handle) {
+ status = EFI_NOT_FOUND;
+ goto out;
+ }
+
+ id = device_get_uclass_id(disk_handle->dev);
+ if (id != UCLASS_BLK) {
+ status = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ ret = ramdisk_unmount(disk_handle->dev);
+ if (ret) {
+ log_err("EFI_RAM_DISK_PROTOCOL unregister failed(%d)\n", ret);
+ status = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+out:
+ return EFI_EXIT(status);
+}
+
+static const struct efi_ram_disk_protocol efi_ram_disk_protocol = {
+ .disk_register = ram_disk_register,
+ .unregister = ram_disk_unregister,
+};
+
+/**
+ * efi_ram_disk_register() - register EFI_RAM_DISK_PROTOCOL
+ *
+ * Return: status code
+ */
+efi_status_t efi_ram_disk_register(void)
+{
+ efi_status_t ret;
+
+ ret = efi_add_protocol(efi_root, &efi_guid_ram_disk_protocol,
+ (void *)&efi_ram_disk_protocol);
+ if (ret != EFI_SUCCESS)
+ log_err("Cannot install EFI_RAM_DISK_PROTOCOL\n");
+
+ return ret;
+}
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index 877f3878d6..8c430d4a9c 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -344,6 +344,12 @@ efi_status_t efi_init_obj_list(void)
if (ret != EFI_SUCCESS)
goto out;
+ if (IS_ENABLED(CONFIG_EFI_RAM_DISK_PROTOCOL)) {
+ ret = efi_ram_disk_register();
+ if (ret != EFI_SUCCESS)
+ goto out;
+ }
+
/* Initialize EFI runtime services */
ret = efi_reset_system_init();
if (ret != EFI_SUCCESS)
diff --git a/lib/uuid.c b/lib/uuid.c
index 96e1af3c8b..9827588186 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -195,6 +195,10 @@ static const struct {
"Firmware Management",
EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID
},
+ {
+ "Ram Disk",
+ EFI_RAM_DISK_PROTOCOL_GUID
+ },
/* Configuration table GUIDs */
{
"ACPI table",
--
2.34.1
More information about the U-Boot
mailing list