From: Aiden Park <aiden.p...@intel.com>

Signed-off-by: Aiden Park <aiden.p...@intel.com>
---
 arch/x86/cpu/x86_64/Makefile     |  2 +-
 arch/x86/cpu/x86_64/call64.S     | 21 +++++++++++++++++++++
 arch/x86/cpu/x86_64/cpu.c        | 10 ++++++++++
 arch/x86/include/asm/bootparam.h | 10 +++++++++-
 arch/x86/include/asm/zimage.h    |  2 +-
 arch/x86/lib/bootm.c             | 10 +++++++---
 arch/x86/lib/zimage.c            | 24 ++++++++++++++++--------
 7 files changed, 65 insertions(+), 14 deletions(-)
 create mode 100644 arch/x86/cpu/x86_64/call64.S

diff --git a/arch/x86/cpu/x86_64/Makefile b/arch/x86/cpu/x86_64/Makefile
index 400f0ffe39..951e503a1f 100644
--- a/arch/x86/cpu/x86_64/Makefile
+++ b/arch/x86/cpu/x86_64/Makefile
@@ -3,4 +3,4 @@
 # Written by Simon Glass <s...@chromium.org>
 #
 
-obj-y += cpu.o interrupts.o setjmp.o
+obj-y += cpu.o interrupts.o setjmp.o call64.o
diff --git a/arch/x86/cpu/x86_64/call64.S b/arch/x86/cpu/x86_64/call64.S
new file mode 100644
index 0000000000..e2cfe15080
--- /dev/null
+++ b/arch/x86/cpu/x86_64/call64.S
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2020 Intel Corporation <www.intel.com>
+ */
+
+.code64
+.globl cpu_call64
+cpu_call64:
+       /*
+        * cpu_call64(ulong pgtable, ulong setup_base, ulong target)
+        *
+        * rdi - pgtable (unused - already in 64-bit with paging)
+        * rsi - setup_base
+        * rdx - target
+        *
+        */
+       cli
+       mov     %rdx, %rcx
+       mov     %rsi, %rdx
+       call    *%rcx
+       ret
diff --git a/arch/x86/cpu/x86_64/cpu.c b/arch/x86/cpu/x86_64/cpu.c
index 90925e46ea..0730c43f1c 100644
--- a/arch/x86/cpu/x86_64/cpu.c
+++ b/arch/x86/cpu/x86_64/cpu.c
@@ -7,6 +7,7 @@
 #include <common.h>
 #include <cpu_func.h>
 #include <debug_uart.h>
+#include <asm/cpu.h>
 
 /*
  * Global declaration of gd.
@@ -67,3 +68,12 @@ int x86_cpu_reinit_f(void)
 {
        return 0;
 }
+
+int cpu_jump_to_64bit(ulong setup_base, ulong load_address)
+{
+       ulong target = load_address + 0x200;
+
+       cpu_call64(0, setup_base, target);
+
+       return -EFAULT;
+}
diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h
index d961dddc9e..73c94a33ec 100644
--- a/arch/x86/include/asm/bootparam.h
+++ b/arch/x86/include/asm/bootparam.h
@@ -59,7 +59,15 @@ struct setup_header {
        __u32   initrd_addr_max;
        __u32   kernel_alignment;
        __u8    relocatable_kernel;
-       __u8    _pad2[3];
+       __u8    min_alignment;
+       __u16   xloadflags;
+#define XLF_KERNEL_64                  BIT(0)
+#define XLF_CAN_BE_LOADED_ABOVE_4G     BIT(1)
+#define XLF_EFI_HANDOVER_32            BIT(2)
+#define XLF_EFI_HANDOVER_64            BIT(3)
+#define XLF_EFI_KEXEC                  BIT(4)
+#define XLF_5LEVEL                     BIT(5)
+#define XLF_5LEVEL_ENABLED             BIT(6)
        __u32   cmdline_size;
        __u32   hardware_subarch;
        __u64   hardware_subarch_data;
diff --git a/arch/x86/include/asm/zimage.h b/arch/x86/include/asm/zimage.h
index 80e128ccf3..cadeb04168 100644
--- a/arch/x86/include/asm/zimage.h
+++ b/arch/x86/include/asm/zimage.h
@@ -31,7 +31,7 @@
 #define ZIMAGE_LOAD_ADDR   0x10000
 
 struct boot_params *load_zimage(char *image, unsigned long kernel_size,
-                               ulong *load_addressp);
+                               ulong *load_addressp, bool *image_64bit);
 int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
                 unsigned long initrd_addr, unsigned long initrd_size);
 void setup_video(struct screen_info *screen_info);
diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c
index 07d8f1f279..ebed9e4605 100644
--- a/arch/x86/lib/bootm.c
+++ b/arch/x86/lib/bootm.c
@@ -74,6 +74,7 @@ static int boot_prep_linux(bootm_headers_t *images)
        void *data = NULL;
        size_t len;
        int ret;
+       bool image_64bit;
 
 #ifdef CONFIG_OF_LIBFDT
        if (images->ft_len) {
@@ -116,7 +117,8 @@ static int boot_prep_linux(bootm_headers_t *images)
                ulong load_address;
                char *base_ptr;
 
-               base_ptr = (char *)load_zimage(data, len, &load_address);
+               base_ptr = (char *)load_zimage(data, len, &load_address,
+                                              &image_64bit);
                if (!base_ptr) {
                        puts("## Kernel loading failed ...\n");
                        goto error;
@@ -124,6 +126,10 @@ static int boot_prep_linux(bootm_headers_t *images)
                images->os.load = load_address;
                cmd_line_dest = base_ptr + COMMAND_LINE_OFFSET;
                images->ep = (ulong)base_ptr;
+#if CONFIG_IS_ENABLED(X86_64)
+               if (image_64bit)
+                       images->os.arch = IH_ARCH_X86_64;
+#endif
        } else if (images->ep) {
                cmd_line_dest = (void *)images->ep + COMMAND_LINE_OFFSET;
        } else {
@@ -164,9 +170,7 @@ int boot_linux_kernel(ulong setup_base, ulong load_address, 
bool image_64bit)
                 * TODO(s...@chromium.org): Support booting both 32-bit and
                 * 64-bit kernels from 64-bit U-Boot.
                 */
-#if !CONFIG_IS_ENABLED(X86_64)
                return cpu_jump_to_64bit(setup_base, load_address);
-#endif
        } else {
                /*
                * Set %ebx, %ebp, and %edi to 0, %esi to point to the
diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c
index ffc09630b7..c84e2d39b2 100644
--- a/arch/x86/lib/zimage.c
+++ b/arch/x86/lib/zimage.c
@@ -129,7 +129,7 @@ static int setup_device_tree(struct setup_header *hdr, 
const void *fdt_blob)
 }
 
 struct boot_params *load_zimage(char *image, unsigned long kernel_size,
-                               ulong *load_addressp)
+                               ulong *load_addressp, bool *image_64bit)
 {
        struct boot_params *setup_base;
        int setup_size;
@@ -179,6 +179,9 @@ struct boot_params *load_zimage(char *image, unsigned long 
kernel_size,
        big_image = (bootproto >= 0x0200) &&
                    (hdr->loadflags & BIG_KERNEL_FLAG);
 
+       /* Determine 64-bit kernel */
+       *image_64bit = (hdr->xloadflags & XLF_KERNEL_64) ? true : false;
+
        /* Determine load address */
        if (big_image)
                *load_addressp = BZIMAGE_LOAD_ADDR;
@@ -313,12 +316,13 @@ void __setup_pcat_compatibility(void)
 int do_zboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
 {
        struct boot_params *base_ptr;
-       void *bzImage_addr = NULL;
+       void *bzimage_addr = NULL;
        ulong load_address;
        char *s;
-       ulong bzImage_size = 0;
+       ulong bzimage_size = 0;
        ulong initrd_addr = 0;
        ulong initrd_size = 0;
+       bool image_64bit;
 
        disable_interrupts();
 
@@ -333,11 +337,11 @@ int do_zboot(cmd_tbl_t *cmdtp, int flag, int argc, char 
*const argv[])
        }
 
        if (s)
-               bzImage_addr = (void *)simple_strtoul(s, NULL, 16);
+               bzimage_addr = (void *)simple_strtoul(s, NULL, 16);
 
        if (argc >= 3) {
                /* argv[2] holds the size of the bzImage */
-               bzImage_size = simple_strtoul(argv[2], NULL, 16);
+               bzimage_size = simple_strtoul(argv[2], NULL, 16);
        }
 
        if (argc >= 4)
@@ -346,8 +350,13 @@ int do_zboot(cmd_tbl_t *cmdtp, int flag, int argc, char 
*const argv[])
                initrd_size = simple_strtoul(argv[4], NULL, 16);
 
        /* Lets look for */
-       base_ptr = load_zimage(bzImage_addr, bzImage_size, &load_address);
+       base_ptr = load_zimage(bzimage_addr, bzimage_size, &load_address,
+                              &image_64bit);
+#if !CONFIG_IS_ENABLED(X86_64)
+       image_64bit = false;
+#endif
 
+       /* we assume that the kernel is in place */
        if (!base_ptr) {
                puts("## Kernel loading failed ...\n");
                return -1;
@@ -358,8 +367,7 @@ int do_zboot(cmd_tbl_t *cmdtp, int flag, int argc, char 
*const argv[])
                return -1;
        }
 
-       /* we assume that the kernel is in place */
-       return boot_linux_kernel((ulong)base_ptr, load_address, false);
+       return boot_linux_kernel((ulong)base_ptr, load_address, image_64bit);
 }
 
 U_BOOT_CMD(
-- 
2.20.1

Reply via email to