]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
boot: fallback to unrestricted allocation if initrd allocation doesn't fit below...
authorLennart Poettering <lennart@poettering.net>
Wed, 12 Mar 2025 19:14:40 +0000 (20:14 +0100)
committerGitHub <noreply@github.com>
Wed, 12 Mar 2025 19:14:40 +0000 (04:14 +0900)
Fixes: #36706
src/boot/util.h

index 2b5cc7213e93dae7179dd60f4370e3613b367982..e1d65770d6cf1a89031757a22615206a753e02af 100644 (file)
@@ -103,26 +103,32 @@ static inline Pages xmalloc_pages(
 }
 
 static inline Pages xmalloc_initrd_pages(size_t n_pages) {
-        /* The original native x86 boot protocol of the Linux kernel was not 64bit safe, hence we allocate
-         * memory for the initrds below the 4G boundary on x86, since we don't know early enough which
-         * protocol we'll use to ultimately boot the kernel. This restriction is somewhat obsolete, since
-         * these days we generally prefer the kernel's newer EFI entrypoint instead, which has no such
-         * limitations. On other architectures we do not bother with any restriction on this, in particular
-         * as some of them don't even have RAM mapped to such low addresses. */
+        /* The original native x86 boot protocol of the Linux kernel was not 64bit safe, hence we try to
+         * allocate memory for the initrds below the 4G boundary on x86, since we don't know early enough
+         * which protocol we'll use to ultimately boot the kernel. This restriction is somewhat obsolete,
+         * since these days we generally prefer the kernel's newer EFI entrypoint instead, which has no such
+         * limitations. There's a good chance that for large allocations we won't be successful, hence
+         * immediately fallback to an unrestricted allocation. On other architectures we do not bother with
+         * any restriction on this, in particular as some of them don't even have RAM mapped to such low
+         * addresses. */
 
 #if defined(__i386__) || defined(__x86_64__)
-        return xmalloc_pages(
+        EFI_PHYSICAL_ADDRESS addr = UINT32_MAX; /* Below 4G boundary. */
+        if (BS->AllocatePages(
                         AllocateMaxAddress,
                         EfiLoaderData,
                         EFI_SIZE_TO_PAGES(n_pages),
-                        UINT32_MAX /* Below 4G boundary. */);
-#else
+                        &addr) == EFI_SUCCESS)
+                return (Pages) {
+                        .addr = addr,
+                        .n_pages = n_pages,
+                };
+#endif
         return xmalloc_pages(
                         AllocateAnyPages,
                         EfiLoaderData,
                         EFI_SIZE_TO_PAGES(n_pages),
                         0 /* Ignored. */);
-#endif
 }
 
 void convert_efi_path(char16_t *path);