When loading a device tree using the "mach dtb" command, give firmware
authorkettenis <kettenis@openbsd.org>
Fri, 14 Jun 2024 19:49:17 +0000 (19:49 +0000)
committerkettenis <kettenis@openbsd.org>
Fri, 14 Jun 2024 19:49:17 +0000 (19:49 +0000)
a chance to make modifications (such as applying memory reservations)
by using the EFI devicetree fixup protocol.

ok patrick@, jca@

sys/arch/arm64/stand/efiboot/conf.c
sys/arch/arm64/stand/efiboot/efiboot.c
sys/arch/arm64/stand/efiboot/efidt.h [new file with mode: 0644]

index 770bf2e..a1174dc 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: conf.c,v 1.47 2023/10/26 14:13:37 jsg Exp $   */
+/*     $OpenBSD: conf.c,v 1.48 2024/06/14 19:49:17 kettenis Exp $      */
 
 /*
  * Copyright (c) 1996 Michael Shalayeff
@@ -47,7 +47,7 @@
 #include "efipxe.h"
 #include "softraid_arm64.h"
 
-const char version[] = "1.18";
+const char version[] = "1.19";
 int    debug = 0;
 
 struct fs_ops file_system[] = {
index 7d1c1b7..0bae140 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: efiboot.c,v 1.50 2024/02/23 21:52:12 kettenis Exp $   */
+/*     $OpenBSD: efiboot.c,v 1.51 2024/06/14 19:49:17 kettenis Exp $   */
 
 /*
  * Copyright (c) 2015 YASUOKA Masahiko <yasuoka@yasuoka.net>
@@ -41,6 +41,7 @@
 
 #include "efidev.h"
 #include "efiboot.h"
+#include "efidt.h"
 #include "fdt.h"
 
 EFI_SYSTEM_TABLE       *ST;
@@ -67,6 +68,7 @@ static EFI_GUID                gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
 static EFI_GUID                 fdt_guid = FDT_TABLE_GUID;
 static EFI_GUID                 smbios_guid = SMBIOS_TABLE_GUID;
 static EFI_GUID                 smbios3_guid = SMBIOS3_TABLE_GUID;
+static EFI_GUID                 dt_fixup_guid = EFI_DT_FIXUP_PROTOCOL_GUID;
 
 #define efi_guidcmp(_a, _b)    memcmp((_a), (_b), sizeof(EFI_GUID))
 
@@ -1134,12 +1136,18 @@ efi_fdt(void)
        return fdt_override ? fdt_override : fdt_sys;
 }
 
+#define EXTRA_DT_SPACE (32 * 1024)
+
 int
 fdt_load_override(char *file)
 {
+       EFI_DT_FIXUP_PROTOCOL *dt_fixup;
        EFI_PHYSICAL_ADDRESS addr;
        char path[MAXPATHLEN];
+       EFI_STATUS status;
        struct stat sb;
+       size_t dt_size;
+       UINTN sz;
        int fd;
 
        if (file == NULL && fdt_override) {
@@ -1157,7 +1165,8 @@ fdt_load_override(char *file)
                printf("cannot open %s\n", path);
                return 0;
        }
-       if (efi_memprobe_find(EFI_SIZE_TO_PAGES(sb.st_size),
+       dt_size = sb.st_size + EXTRA_DT_SPACE;
+       if (efi_memprobe_find(EFI_SIZE_TO_PAGES(dt_size),
            PAGE_SIZE, EfiLoaderData, &addr) != EFI_SUCCESS) {
                printf("cannot allocate memory for %s\n", path);
                return 0;
@@ -1167,9 +1176,18 @@ fdt_load_override(char *file)
                return 0;
        }
 
+       status = BS->LocateProtocol(&dt_fixup_guid, NULL, (void **)&dt_fixup);
+       if (status == EFI_SUCCESS) {
+               sz = dt_size;
+               status = dt_fixup->Fixup(dt_fixup, (void *)addr, &sz,
+                   EFI_DT_APPLY_FIXUPS | EFI_DT_RESERVE_MEMORY);
+               if (status != EFI_SUCCESS)
+                       panic("DT fixup failed: 0x%lx", status);
+       }
+
        if (!fdt_init((void *)addr)) {
                printf("invalid device tree\n");
-               BS->FreePages(addr, EFI_SIZE_TO_PAGES(sb.st_size));
+               BS->FreePages(addr, EFI_SIZE_TO_PAGES(dt_size));
                return 0;
        }
 
@@ -1180,7 +1198,7 @@ fdt_load_override(char *file)
        }
 
        fdt_override = (void *)addr;
-       fdt_override_size = sb.st_size;
+       fdt_override_size = dt_size;
        return 0;
 }
 
diff --git a/sys/arch/arm64/stand/efiboot/efidt.h b/sys/arch/arm64/stand/efiboot/efidt.h
new file mode 100644 (file)
index 0000000..537c08c
--- /dev/null
@@ -0,0 +1,44 @@
+/*     $OpenBSD: efidt.h,v 1.1 2024/06/14 19:49:17 kettenis Exp $      */
+
+/*
+ * Copyright (c) 2024 Mark Kettenis <kettenis@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+
+#include <efi.h>
+#include <efiapi.h>
+
+#define EFI_DT_FIXUP_PROTOCOL_GUID             \
+  { 0xe617d64c, 0xfe08, 0x46da, \
+    { 0xf4, 0xdc, 0xbb, 0xd5, 0x87, 0x0c, 0x73, 0x00 } }
+
+INTERFACE_DECL(_EFI_DT_FIXUP_PROTOCOL);
+
+typedef EFI_STATUS
+(EFIAPI *EFI_DT_FIXUP) (
+    IN struct _EFI_DT_FIXUP_PROTOCOL   *This,
+    IN VOID                            *Fdt,
+    IN OUT UINTN                       *BufferSize,
+    IN UINT32                          Flags
+    );
+
+#define EFI_DT_APPLY_FIXUPS    0x00000001
+#define EFI_DT_RESERVE_MEMORY  0x00000002
+
+typedef struct _EFI_DT_FIXUP_PROTOCOL {
+       UINT64                  Revision;
+       EFI_DT_FIXUP            Fixup;
+} EFI_DT_FIXUP_PROTOCOL;