141 lines
4.2 KiB
Diff
141 lines
4.2 KiB
Diff
From: Heinrich Schuchardt <xypron.glpk@gmx.de>
|
|
Date: Fri, 29 Jan 2021 07:36:42 +0100
|
|
Subject: [PATCH] efi: EFI Device Tree Fixup Protocol
|
|
|
|
Device-trees are used to convey information about hardware to the operating
|
|
system. Some of the properties are only known at boot time. (One example of
|
|
such a property is the number of the boot hart on RISC-V systems.) Therefore
|
|
the firmware applies fix-ups to the original device-tree. Some nodes and
|
|
properties are added or altered.
|
|
|
|
When using GRUB's device-tree command the same fix-ups have to be applied.
|
|
The EFI Device Tree Fixup Protocol allows to pass the loaded device tree
|
|
to the firmware for this purpose.
|
|
|
|
The protocol can
|
|
|
|
* add nodes and update properties
|
|
* reserve memory according to the /reserved-memory node and the memory
|
|
reservation block
|
|
* install the device-tree as configuration table
|
|
|
|
With the patch GRUB checks if the protocol is installed and invokes it if
|
|
available. (LP: #1965796)
|
|
|
|
Link: https://lists.gnu.org/archive/html/grub-devel/2021-02/msg00013.html
|
|
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
|
|
Signed-off-by: Julian Andres Klode <julian.klode@canonical.com>
|
|
---
|
|
grub-core/loader/efi/fdt.c | 37 +++++++++++++++++++++++++++++++++++++
|
|
include/grub/efi/api.h | 22 ++++++++++++++++++++++
|
|
2 files changed, 59 insertions(+)
|
|
|
|
diff --git a/grub-core/loader/efi/fdt.c b/grub-core/loader/efi/fdt.c
|
|
index 510958d..9fc5a4d 100644
|
|
--- a/grub-core/loader/efi/fdt.c
|
|
+++ b/grub-core/loader/efi/fdt.c
|
|
@@ -29,6 +29,7 @@
|
|
|
|
static void *loaded_fdt;
|
|
static void *fdt;
|
|
+static grub_guid_t dt_fixup_guid = GRUB_EFI_DT_FIXUP_PROTOCOL_GUID;
|
|
|
|
#define FDT_ADDR_CELLS_STRING "#address-cells"
|
|
#define FDT_SIZE_CELLS_STRING "#size-cells"
|
|
@@ -36,6 +37,41 @@ static void *fdt;
|
|
sizeof (FDT_ADDR_CELLS_STRING) + \
|
|
sizeof (FDT_SIZE_CELLS_STRING))
|
|
|
|
+static void *
|
|
+grub_fdt_fixup (void *blob)
|
|
+{
|
|
+ grub_efi_dt_fixup_t *dt_fixup_prot;
|
|
+ grub_efi_uintn_t size = 0;
|
|
+ grub_efi_status_t status;
|
|
+ void *fixup_fdt;
|
|
+
|
|
+ dt_fixup_prot = grub_efi_locate_protocol (&dt_fixup_guid, 0);
|
|
+ if (!dt_fixup_prot)
|
|
+ return blob;
|
|
+
|
|
+ grub_dprintf ("linux", "EFI_DT_FIXUP_PROTOCOL available\n");
|
|
+
|
|
+ status = dt_fixup_prot->fixup (dt_fixup_prot, blob, &size,
|
|
+ GRUB_EFI_DT_APPLY_FIXUPS
|
|
+ | GRUB_EFI_DT_RESERVE_MEMORY);
|
|
+ if (status != GRUB_EFI_BUFFER_TOO_SMALL)
|
|
+ return blob;
|
|
+
|
|
+ fixup_fdt = grub_realloc (blob, size);
|
|
+ if (!fixup_fdt)
|
|
+ return blob;
|
|
+ blob = fixup_fdt;
|
|
+
|
|
+ status = dt_fixup_prot->fixup (dt_fixup_prot, blob, &size,
|
|
+ GRUB_EFI_DT_APPLY_FIXUPS
|
|
+ | GRUB_EFI_DT_RESERVE_MEMORY);
|
|
+
|
|
+ if (status == GRUB_EFI_SUCCESS)
|
|
+ grub_dprintf ("linux", "Device tree fixed up via EFI_DT_FIXUP_PROTOCOL\n");
|
|
+
|
|
+ return blob;
|
|
+}
|
|
+
|
|
void *
|
|
grub_fdt_load (grub_size_t additional_size)
|
|
{
|
|
@@ -160,6 +196,7 @@ out:
|
|
if (blob)
|
|
{
|
|
grub_dprintf ("fdt", "Device-tree %s loaded\n", argv[0]);
|
|
+ blob = grub_fdt_fixup (blob);
|
|
if (grub_errno == GRUB_ERR_NONE)
|
|
loaded_fdt = blob;
|
|
else
|
|
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
|
|
index ae02e6d..a89bf3d 100644
|
|
--- a/include/grub/efi/api.h
|
|
+++ b/include/grub/efi/api.h
|
|
@@ -354,6 +354,11 @@
|
|
{ 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0 } \
|
|
}
|
|
|
|
+#define GRUB_EFI_DT_FIXUP_PROTOCOL_GUID \
|
|
+ { 0xe617d64c, 0xfe08, 0x46da, \
|
|
+ { 0xf4, 0xdc, 0xbb, 0xd5, 0x87, 0x0c, 0x73, 0x00 } \
|
|
+ }
|
|
+
|
|
#define GRUB_EFI_VENDOR_APPLE_GUID \
|
|
{ 0x2B0585EB, 0xD8B8, 0x49A9, \
|
|
{ 0x8B, 0x8C, 0xE2, 0x1B, 0x01, 0xAE, 0xF2, 0xB7 } \
|
|
@@ -1914,6 +1919,13 @@ enum
|
|
GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST = 0x10,
|
|
};
|
|
|
|
+enum
|
|
+ {
|
|
+ GRUB_EFI_DT_APPLY_FIXUPS = 0x01,
|
|
+ GRUB_EFI_DT_RESERVE_MEMORY = 0x02,
|
|
+ GRUB_EFI_EFI_DT_INSTALL_TABLE = 0x04,
|
|
+ };
|
|
+
|
|
struct grub_efi_simple_network
|
|
{
|
|
grub_uint64_t revision;
|
|
@@ -1996,6 +2008,16 @@ struct grub_efi_block_io
|
|
};
|
|
typedef struct grub_efi_block_io grub_efi_block_io_t;
|
|
|
|
+struct grub_efi_dt_fixup
|
|
+{
|
|
+ grub_efi_uint64_t revision;
|
|
+ grub_efi_status_t (__grub_efi_api *fixup) (struct grub_efi_dt_fixup *this,
|
|
+ void *fdt,
|
|
+ grub_efi_uintn_t *buffer_size,
|
|
+ grub_uint32_t flags);
|
|
+};
|
|
+typedef struct grub_efi_dt_fixup grub_efi_dt_fixup_t;
|
|
+
|
|
struct grub_efi_shim_lock_protocol
|
|
{
|
|
/*
|