grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/2] efi: EFI Device Tree Fixup Protocol


From: Heinrich Schuchardt
Subject: [PATCH 1/2] efi: EFI Device Tree Fixup Protocol
Date: Thu, 4 Feb 2021 14:15:57 +0100

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.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 grub-core/loader/efi/fdt.c | 35 ++++++++++++++++++++++++++++++++++-
 include/grub/efi/api.h     | 22 ++++++++++++++++++++++
 2 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/grub-core/loader/efi/fdt.c b/grub-core/loader/efi/fdt.c
index 57ee81686..58e95eb05 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_efi_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,38 @@ static void *fdt;
                              sizeof (FDT_ADDR_CELLS_STRING) + \
                              sizeof (FDT_SIZE_CELLS_STRING))

+static void *grub_fdt_fixup (void)
+{
+  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 loaded_fdt;
+
+  grub_dprintf ("linux", "EFI_DT_FIXUP_PROTOCOL available\n");
+
+  status = efi_call_4 (dt_fixup_prot->fixup, dt_fixup_prot, loaded_fdt, &size,
+                      GRUB_EFI_DT_APPLY_FIXUPS | GRUB_EFI_DT_RESERVE_MEMORY);
+  if (status != GRUB_EFI_BUFFER_TOO_SMALL)
+    return loaded_fdt;
+
+  fixup_fdt = grub_realloc (loaded_fdt, size);
+  if (!fixup_fdt)
+    return loaded_fdt;
+  loaded_fdt = fixup_fdt;
+
+  status = efi_call_4 (dt_fixup_prot->fixup, dt_fixup_prot, loaded_fdt, &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 loaded_fdt;
+}
+
 void *
 grub_fdt_load (grub_size_t additional_size)
 {
@@ -49,7 +82,7 @@ grub_fdt_load (grub_size_t additional_size)
     }

   if (loaded_fdt)
-    raw_fdt = loaded_fdt;
+    raw_fdt = grub_fdt_fixup();
   else
     raw_fdt = grub_efi_get_firmware_fdt();

diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index 34109861a..8101df0df 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -334,6 +334,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 } \
@@ -1641,6 +1646,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;
@@ -1704,6 +1716,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 (*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
 {
   grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size);
--
2.30.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]