]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
boot/stub: allocate pages for combined initrds below 4GiB only on x86 (#35149)
authorandre4ik3 <little.ice3735@fastmail.com>
Thu, 14 Nov 2024 04:20:09 +0000 (08:20 +0400)
committerGitHub <noreply@github.com>
Thu, 14 Nov 2024 04:20:09 +0000 (13:20 +0900)
Outside of x86, some machines (e.g. Apple silicon, AMD Opteron A1100)
have physical memory mapped above 4GiB, meaning this allocation will
fail, causing the entire boot process to fail on these machines.

This commit makes it so that the below-4GB address space allocation
requirement is only set on x86 platforms, and not on other platforms
(that don't have the specific Linux x86 boot protocol), thereby fixing
boot on those that have no memory mapped below 4GiB in their address
space.

Tested on an Apple silicon M1 laptop and an AMD x86_64 desktop tower.

Fixes: #35026
src/boot/boot.c
src/boot/stub.c
src/boot/util.h

index 87b0232860f02093702ee25a499967273e315a9a..129d6f8f5d3eb7e0cd46daaf450220794254a50a 100644 (file)
@@ -2469,11 +2469,7 @@ static EFI_STATUS initrd_prepare(
                         return EFI_OUT_OF_RESOURCES;
         }
 
-        _cleanup_pages_ Pages pages = xmalloc_pages(
-                AllocateMaxAddress,
-                EfiLoaderData,
-                EFI_SIZE_TO_PAGES(size),
-                UINT32_MAX /* Below 4G boundary. */);
+        _cleanup_pages_ Pages pages = xmalloc_initrd_pages(size);
         uint8_t *p = PHYSICAL_ADDRESS_TO_POINTER(pages.addr);
 
         STRV_FOREACH(i, entry->initrd) {
index 7261e942d339ea5b76856a45cfe91fd450d145dc..c92df686c8a96912570bab84bfa7266245832532 100644 (file)
@@ -114,12 +114,9 @@ static EFI_STATUS combine_initrds(
                 n += initrd_size;
         }
 
-        _cleanup_pages_ Pages pages = xmalloc_pages(
-                        AllocateMaxAddress,
-                        EfiLoaderData,
-                        EFI_SIZE_TO_PAGES(n),
-                        UINT32_MAX /* Below 4G boundary. */);
+        _cleanup_pages_ Pages pages = xmalloc_initrd_pages(n);
         uint8_t *p = PHYSICAL_ADDRESS_TO_POINTER(pages.addr);
+
         FOREACH_ARRAY(i, initrds, n_initrds) {
                 size_t pad;
 
index c7634576cf48d70d92e8fb7063ad8444b58504e5..3164d520bd294a65efb5052a3f093c1dc744bc0b 100644 (file)
@@ -99,6 +99,22 @@ static inline Pages xmalloc_pages(
         };
 }
 
+static inline Pages xmalloc_initrd_pages(size_t n_pages) {
+#if defined(__i386__) || defined(__x86_64__)
+        return xmalloc_pages(
+                        AllocateMaxAddress,
+                        EfiLoaderData,
+                        EFI_SIZE_TO_PAGES(n_pages),
+                        UINT32_MAX /* Below 4G boundary. */);
+#else
+        return xmalloc_pages(
+                        AllocateAnyPages,
+                        EfiLoaderData,
+                        EFI_SIZE_TO_PAGES(n_pages),
+                        0 /* Ignored. */);
+#endif
+}
+
 void convert_efi_path(char16_t *path);
 char16_t *xstr8_to_path(const char *stra);
 char16_t *mangle_stub_cmdline(char16_t *cmdline);