]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
[sd-stub] add support for embedding devicetree
authorMax Resch <resch.max@gmail.com>
Fri, 15 Oct 2021 12:18:57 +0000 (14:18 +0200)
committerMax Resch <resch.max@gmail.com>
Fri, 15 Oct 2021 19:47:42 +0000 (21:47 +0200)
src/boot/efi/devicetree.c
src/boot/efi/devicetree.h
src/boot/efi/meson.build
src/boot/efi/stub.c

index fd4b9c406c1a7f51507775537a8e2898bb38f776..d8a279e826c1b5bb6150c0a3f02848e1e347f475 100644 (file)
@@ -109,6 +109,31 @@ EFI_STATUS devicetree_install(struct devicetree_state *state,
         return uefi_call_wrapper(BS->InstallConfigurationTable, 2, &EfiDtbTableGuid, PHYSICAL_ADDRESS_TO_POINTER(state->addr));
 }
 
+EFI_STATUS devicetree_install_from_memory(struct devicetree_state *state,
+                const VOID *dtb_buffer, UINTN dtb_length) {
+
+        EFI_STATUS err;
+
+        assert(state);
+        assert(dtb_buffer && dtb_length > 0);
+
+        err = LibGetSystemConfigurationTable(&EfiDtbTableGuid, &state->orig);
+        if (EFI_ERROR(err))
+                return EFI_UNSUPPORTED;
+
+        err = devicetree_allocate(state, dtb_length);
+        if (EFI_ERROR(err))
+                return err;
+
+        CopyMem(PHYSICAL_ADDRESS_TO_POINTER(state->addr), dtb_buffer, dtb_length);
+
+        err = devicetree_fixup(state, dtb_length);
+        if (EFI_ERROR(err))
+                return err;
+
+        return uefi_call_wrapper(BS->InstallConfigurationTable, 2, &EfiDtbTableGuid, PHYSICAL_ADDRESS_TO_POINTER(state->addr));
+}
+
 void devicetree_cleanup(struct devicetree_state *state) {
         EFI_STATUS err;
 
index 2839cb681c192d1c5059c53affa6501368276f38..25f93f97f9e832f5946a9eac36e6c3e2f46a9950 100644 (file)
@@ -8,4 +8,6 @@ struct devicetree_state {
 };
 
 EFI_STATUS devicetree_install(struct devicetree_state *state, EFI_FILE_HANDLE root_dir, CHAR16 *name);
+EFI_STATUS devicetree_install_from_memory(
+                struct devicetree_state *state, const VOID *dtb_buffer, UINTN dtb_length);
 void devicetree_cleanup(struct devicetree_state *state);
index fdcf279f13f657ea1c75f7bdd54eb6955277eff2..e3e13fec0412105aa75fa9e2367dea4784a1306f 100644 (file)
@@ -20,6 +20,7 @@ efi_headers = files('''
 
 common_sources = '''
         assert.c
+        devicetree.c
         disk.c
         graphics.c
         measure.c
@@ -31,7 +32,6 @@ common_sources = '''
 systemd_boot_sources = '''
         boot.c
         console.c
-        devicetree.c
         drivers.c
         random-seed.c
         shim.c
index 4af9704627d5bb10cbccd90f6c2f151b349705f8..01774d1fd53dd7d395bfc5a9ee9e02b4ab23279c 100644 (file)
@@ -4,6 +4,7 @@
 #include <efilib.h>
 
 #include "cpio.h"
+#include "devicetree.h"
 #include "disk.h"
 #include "graphics.h"
 #include "linux.h"
@@ -141,6 +142,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
                 SECTION_LINUX,
                 SECTION_INITRD,
                 SECTION_SPLASH,
+                SECTION_DTB,
                 _SECTION_MAX,
         };
 
@@ -149,12 +151,15 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
                 [SECTION_LINUX]   = (const CHAR8*) ".linux",
                 [SECTION_INITRD]  = (const CHAR8*) ".initrd",
                 [SECTION_SPLASH]  = (const CHAR8*) ".splash",
+                [SECTION_DTB]     = (const CHAR8*) ".dtb",
                 NULL,
         };
 
-        UINTN cmdline_len = 0, linux_size, initrd_size, credential_initrd_size = 0, sysext_initrd_size = 0;
+        UINTN cmdline_len = 0, linux_size, initrd_size, dt_size;
+        UINTN credential_initrd_size = 0, sysext_initrd_size = 0;
         _cleanup_freepool_ VOID *credential_initrd = NULL, *sysext_initrd = NULL;
-        EFI_PHYSICAL_ADDRESS linux_base, initrd_base;
+        EFI_PHYSICAL_ADDRESS linux_base, initrd_base, dt_base;
+        _cleanup_(devicetree_cleanup) struct devicetree_state dt_state = {};
         EFI_LOADED_IMAGE *loaded_image;
         UINTN addrs[_SECTION_MAX] = {};
         UINTN szs[_SECTION_MAX] = {};
@@ -228,6 +233,9 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
         initrd_size = szs[SECTION_INITRD];
         initrd_base = initrd_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[SECTION_INITRD] : 0;
 
+        dt_size = szs[SECTION_DTB];
+        dt_base = dt_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[SECTION_DTB] : 0;
+
         if (credential_initrd || sysext_initrd) {
                 /* If we have generated initrds dynamically, let's combine them with the built-in initrd. */
                 err = combine_initrd(
@@ -250,6 +258,13 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
                 }
         }
 
+        if (dt_size > 0) {
+                err = devicetree_install_from_memory(
+                                &dt_state, PHYSICAL_ADDRESS_TO_POINTER(dt_base), dt_size);
+                if (EFI_ERROR(err))
+                        log_error_stall(L"Error loading embedded devicetree: %r", err);
+        }
+
         err = linux_exec(image, cmdline, cmdline_len,
                          PHYSICAL_ADDRESS_TO_POINTER(linux_base), linux_size,
                          PHYSICAL_ADDRESS_TO_POINTER(initrd_base), initrd_size);