]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
x86: Support booting a 64-bit kernel from 64-bit U-Boot
authorSimon Glass <sjg@chromium.org>
Sun, 19 Mar 2023 19:30:08 +0000 (08:30 +1300)
committerHeinrich Schuchardt <heinrich.schuchardt@canonical.com>
Sat, 25 Mar 2023 10:07:21 +0000 (11:07 +0100)
Add the missing code to handle this. For a 64-bit kernel the entry
address is 0x200 bytes after the normal entry.

Rename the parameter to boot_linux_kernel() accordingly. Update the
comments to indicate that these are addresses, not pointers.

Signed-off-by: Simon Glass <sjg@chromium.org>
arch/x86/include/asm/bootm.h
arch/x86/lib/bootm.c
arch/x86/lib/zimage.c

index 109f686f7403b98c0ced432cdb64a525678bea32..3b641783b9cd789ad02729766b1a80511b2a00d4 100644 (file)
@@ -14,14 +14,14 @@ void bootm_announce_and_cleanup(void);
  * This boots a kernel image, either 32-bit or 64-bit. It will also work with
  * a self-extracting kernel, if you set @image_64bit to false.
  *
- * @setup_base:                Pointer to the setup.bin information for the kernel
- * @load_address:      Pointer to the start of the kernel image
- * @image_64bit:       true if the image is a raw 64-bit kernel, false if it
- *                     is raw 32-bit or any type of self-extracting kernel
- *                     such as a bzImage.
+ * @setup_base:                Address of the setup.bin information for the kernel
+ * @entry:             Address of the kernel entry point
+ * @image_64bit:       true if the image is a raw 64-bit kernel, or a kernel
+ * which supports booting in 64-bit mode; false if it is raw 32-bit or any type
+ * of self-extracting kernel such as a bzImage.
  * Return: -ve error code. This function does not return if the kernel was
  * booted successfully.
  */
-int boot_linux_kernel(ulong setup_base, ulong load_address, bool image_64bit);
+int boot_linux_kernel(ulong setup_base, ulong entry, bool image_64bit);
 
 #endif
index 873e2bc176f3b9ceeec40291e424f3f4bade68f9..9beb376bb9c292abcdeba189617e7e2665b913c9 100644 (file)
@@ -149,7 +149,7 @@ error:
        return 1;
 }
 
-int boot_linux_kernel(ulong setup_base, ulong load_address, bool image_64bit)
+int boot_linux_kernel(ulong setup_base, ulong entry, bool image_64bit)
 {
        bootm_announce_and_cleanup();
 
@@ -161,14 +161,23 @@ int boot_linux_kernel(ulong setup_base, ulong load_address, bool image_64bit)
                        puts("Cannot boot 64-bit kernel on 32-bit machine\n");
                        return -EFAULT;
                }
-               /* At present 64-bit U-Boot does not support booting a
+               /*
+                * At present 64-bit U-Boot only supports booting a 64-bit
                 * kernel.
-                * TODO(sjg@chromium.org): Support booting both 32-bit and
-                * 64-bit kernels from 64-bit U-Boot.
+                *
+                * TODO(sjg@chromium.org): Support booting 32-bit kernels from
+                * 64-bit U-Boot
                 */
-#if !CONFIG_IS_ENABLED(X86_64)
-               return cpu_jump_to_64bit(setup_base, load_address);
-#endif
+               if (CONFIG_IS_ENABLED(X86_64)) {
+                       typedef void (*h_func)(ulong zero, ulong setup);
+                       h_func func;
+
+                       /* jump to Linux with rdi=0, rsi=setup_base */
+                       func = (h_func)entry;
+                       func(0, setup_base);
+               } else {
+                       return cpu_jump_to_64bit(setup_base, entry);
+               }
        } else {
                /*
                * Set %ebx, %ebp, and %edi to 0, %esi to point to the
@@ -190,7 +199,7 @@ int boot_linux_kernel(ulong setup_base, ulong load_address, bool image_64bit)
                "movl $0, %%ebp\n"
                "cli\n"
                "jmp *%[kernel_entry]\n"
-               :: [kernel_entry]"a"(load_address),
+               :: [kernel_entry]"a"(entry),
                [boot_params] "S"(setup_base),
                "b"(0), "D"(0)
                );
index a6d9151c32408bdbd031696e5714a70c6a9b0145..e5ea5129c1e948528ab8842bb952bc11845b4279 100644 (file)
@@ -504,13 +504,24 @@ static int do_zboot_info(struct cmd_tbl *cmdtp, int flag, int argc,
 static int do_zboot_go(struct cmd_tbl *cmdtp, int flag, int argc,
                       char *const argv[])
 {
+       struct boot_params *params = state.base_ptr;
+       struct setup_header *hdr = &params->hdr;
+       bool image_64bit;
+       ulong entry;
        int ret;
 
        disable_interrupts();
 
+       entry = state.load_address;
+       image_64bit = false;
+       if (IS_ENABLED(CONFIG_X86_RUN_64BIT) &&
+           (hdr->xloadflags & XLF_KERNEL_64)) {
+               entry += 0x200;
+               image_64bit = true;
+       }
+
        /* we assume that the kernel is in place */
-       ret = boot_linux_kernel((ulong)state.base_ptr, state.load_address,
-                               false);
+       ret = boot_linux_kernel((ulong)state.base_ptr, entry, image_64bit);
        printf("Kernel returned! (err=%d)\n", ret);
 
        return CMD_RET_FAILURE;