This protocol doesn't do much in barebox, but enough to be able to execute the UEFI shell.
Signed-off-by: Ahmad Fatoum <[email protected]> --- efi/loader/protocols/Kconfig | 7 + efi/loader/protocols/Makefile | 1 + efi/loader/protocols/device_path_utilities.c | 210 +++++++++++++++++++ include/efi/protocol/devicepath.h | 31 +++ 4 files changed, 249 insertions(+) create mode 100644 efi/loader/protocols/device_path_utilities.c create mode 100644 include/efi/protocol/devicepath.h diff --git a/efi/loader/protocols/Kconfig b/efi/loader/protocols/Kconfig index 7d5e203d121a..3405de1acdfb 100644 --- a/efi/loader/protocols/Kconfig +++ b/efi/loader/protocols/Kconfig @@ -39,4 +39,11 @@ config EFI_LOADER_RNG Provide a EFI_RNG_PROTOCOL implementation using the hardware random number generator of the platform. +config EFI_LOADER_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. + endmenu diff --git a/efi/loader/protocols/Makefile b/efi/loader/protocols/Makefile index ecc0fc392856..b5ec5cf5dd46 100644 --- a/efi/loader/protocols/Makefile +++ b/efi/loader/protocols/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_CONSOLE_FULL) += console.o obj-$(CONFIG_EFI_LOADER_HII) += hii.o hii_config.o obj-$(CONFIG_EFI_LOADER_UNICODE_COLLATION_PROTOCOL2) += unicode_collation.o obj-$(CONFIG_EFI_LOADER_RNG) += rng.o +obj-$(CONFIG_EFI_LOADER_DEVICE_PATH_UTIL) += device_path_utilities.o diff --git a/efi/loader/protocols/device_path_utilities.c b/efi/loader/protocols/device_path_utilities.c new file mode 100644 index 000000000000..ef88e2d647fb --- /dev/null +++ b/efi/loader/protocols/device_path_utilities.c @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * EFI device path interface + * + * Copyright (c) 2017 Leif Lindholm + */ + +#include <efi/loader.h> +#include <efi/devicepath.h> +#include <efi/loader/devicepath.h> +#include <efi/protocol/devicepath.h> +#include <efi/loader/trace.h> +#include <efi/loader/object.h> +#include <efi/guid.h> +#include <init.h> + +/* + * Get size of a device path. + * + * This function implements the GetDevicePathSize service of the device path + * utilities protocol. The device path length includes the end of path tag + * which may be an instance end. + * + * See the Unified Extensible Firmware Interface (UEFI) specification + * for details. + * + * @device_path device path + * Return: size in bytes + */ +static efi_uintn_t EFIAPI get_device_path_size( + const struct efi_device_path *device_path) +{ + efi_uintn_t sz = 0; + + EFI_ENTRY("%pD", device_path); + /* size includes the END node: */ + if (device_path) + sz = efi_dp_size(device_path) + sizeof(struct efi_device_path); + return EFI_EXIT(sz); +} + +/* + * Duplicate a device path. + * + * This function implements the DuplicateDevicePath service of the device path + * utilities protocol. + * + * The UEFI spec does not indicate what happens to the end tag. We follow the + * EDK2 logic: In case the device path ends with an end of instance tag, the + * copy will also end with an end of instance tag. + * + * See the Unified Extensible Firmware Interface (UEFI) specification + * for details. + * + * @device_path device path + * Return: copy of the device path + */ +static struct efi_device_path * EFIAPI duplicate_device_path( + const struct efi_device_path *device_path) +{ + EFI_ENTRY("%pD", device_path); + return EFI_EXIT(efi_dp_dup(device_path)); +} + +/* + * Append device path. + * + * This function implements the AppendDevicePath service of the device path + * utilities protocol. + * + * See the Unified Extensible Firmware Interface (UEFI) specification + * for details. + * + * @src1 1st device path + * @src2 2nd device path + * Return: concatenated device path + */ +static struct efi_device_path * EFIAPI append_device_path( + const struct efi_device_path *src1, + const struct efi_device_path *src2) +{ + EFI_ENTRY("%pD, %pD", src1, src2); + return EFI_EXIT(efi_dp_concat(src1, src2, 0)); +} + +/* + * Append device path node. + * + * This function implements the AppendDeviceNode service of the device path + * utilities protocol. + * + * See the Unified Extensible Firmware Interface (UEFI) specification + * for details. + * + * @device_path device path + * @device_node device node + * Return: concatenated device path + */ +static struct efi_device_path * EFIAPI append_device_node( + const struct efi_device_path *device_path, + const struct efi_device_path *device_node) +{ + EFI_ENTRY("%pD, %p", device_path, device_node); + return EFI_EXIT(efi_dp_append_node(device_path, device_node)); +} + +/* + * Append device path instance. + * + * This function implements the AppendDevicePathInstance service of the device + * path utilities protocol. + * + * See the Unified Extensible Firmware Interface (UEFI) specification + * for details. + * + * @device_path 1st device path + * @device_path_instance 2nd device path + * Return: concatenated device path + */ +static struct efi_device_path * EFIAPI append_device_path_instance( + const struct efi_device_path *device_path, + const struct efi_device_path *device_path_instance) +{ + EFI_ENTRY("%pD, %pD", device_path, device_path_instance); + return EFI_EXIT(efi_dp_append_instance(device_path, + device_path_instance)); +} + +/* + * Get next device path instance. + * + * This function implements the GetNextDevicePathInstance service of the device + * path utilities protocol. + * + * See the Unified Extensible Firmware Interface (UEFI) specification + * for details. + * + * @device_path_instance next device path instance + * @device_path_instance_size size of the device path instance + * Return: concatenated device path + */ +static struct efi_device_path * EFIAPI get_next_device_path_instance( + struct efi_device_path **device_path_instance, + efi_uintn_t *device_path_instance_size) +{ + EFI_ENTRY("%pD, %p", device_path_instance, device_path_instance_size); + return EFI_EXIT(efi_dp_get_next_instance(device_path_instance, + device_path_instance_size)); +} + +/* + * Check if a device path contains more than one instance. + * + * This function implements the AppendDeviceNode service of the device path + * utilities protocol. + * + * See the Unified Extensible Firmware Interface (UEFI) specification + * for details. + * + * @device_path device path + * @device_node device node + * Return: concatenated device path + */ +static bool EFIAPI is_device_path_multi_instance( + const struct efi_device_path *device_path) +{ + EFI_ENTRY("%pD", device_path); + return EFI_EXIT(efi_dp_is_multi_instance(device_path)); +} + +/* + * Create device node. + * + * This function implements the CreateDeviceNode service of the device path + * utilities protocol. + * + * See the Unified Extensible Firmware Interface (UEFI) specification + * for details. + * + * @node_type node type + * @node_sub_type node sub type + * @node_length node length + * Return: device path node + */ +static struct efi_device_path * EFIAPI create_device_node( + uint8_t node_type, uint8_t node_sub_type, uint16_t node_length) +{ + EFI_ENTRY("%u, %u, %u", node_type, node_sub_type, node_length); + return EFI_EXIT(efi_dp_create_device_node(node_type, node_sub_type, + node_length)); +} + +static const struct efi_device_path_utilities_protocol efi_device_path_utilities = { + .get_device_path_size = get_device_path_size, + .duplicate_device_path = duplicate_device_path, + .append_device_path = append_device_path, + .append_device_node = append_device_node, + .append_device_path_instance = append_device_path_instance, + .get_next_device_path_instance = get_next_device_path_instance, + .is_device_path_multi_instance = is_device_path_multi_instance, + .create_device_node = create_device_node, +}; + +static int efi_device_path_utilities_init(void) +{ + efi_add_root_node_protocol_deferred(&efi_device_path_utilities_protocol_guid, + &efi_device_path_utilities); + return 0; +} +postcore_initcall(efi_device_path_utilities_init); diff --git a/include/efi/protocol/devicepath.h b/include/efi/protocol/devicepath.h new file mode 100644 index 000000000000..19a35888f9cc --- /dev/null +++ b/include/efi/protocol/devicepath.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __EFI_PROTOCOL_DEVICE_PATH_H +#define __EFI_PROTOCOL_DEVICE_PATH_H + +#include <efi/types.h> + +struct efi_device_path_utilities_protocol { + size_t (EFIAPI *get_device_path_size)( + const struct efi_device_path *device_path); + struct efi_device_path *(EFIAPI *duplicate_device_path)( + const struct efi_device_path *device_path); + struct efi_device_path *(EFIAPI *append_device_path)( + const struct efi_device_path *src1, + const struct efi_device_path *src2); + struct efi_device_path *(EFIAPI *append_device_node)( + const struct efi_device_path *device_path, + const struct efi_device_path *device_node); + struct efi_device_path *(EFIAPI *append_device_path_instance)( + const struct efi_device_path *device_path, + const struct efi_device_path *device_path_instance); + struct efi_device_path *(EFIAPI *get_next_device_path_instance)( + struct efi_device_path **device_path_instance, + size_t *device_path_instance_size); + bool (EFIAPI *is_device_path_multi_instance)( + const struct efi_device_path *device_path); + struct efi_device_path *(EFIAPI *create_device_node)( + uint8_t node_type, + uint8_t node_sub_type, + uint16_t node_length); +}; +#endif -- 2.47.3
