x86: Support jumping from SPL to U-Boot
authorSimon Glass <sjg@chromium.org>
Mon, 16 Jan 2017 14:04:15 +0000 (07:04 -0700)
committerBin Meng <bmeng.cn@gmail.com>
Mon, 6 Feb 2017 03:38:46 +0000 (11:38 +0800)
Add a rough function to handle jumping from 32-bit SPL to 64-bit U-Boot.
This still needs work to clean it up.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
arch/x86/cpu/call64.S
arch/x86/cpu/i386/cpu.c
arch/x86/include/asm/cpu.h

index 08dc473d6af40e528f574c19f26fae07cb658778..970c4615083ab7cd7b5e37c36f108afce23ab5d8 100644 (file)
@@ -81,6 +81,9 @@ lret_target:
        jmp     *%eax                   /* Jump to the 64-bit target */
 
        .data
+       .align  16
+       .globl  gdt64
+gdt64:
 gdt:
        .word   gdt_end - gdt - 1
        .long   gdt                     /* Fixed up by code above */
index 09a5b919e077d761f431808a57d9120b7934276d..aabdc94bb0e24d32ebf909d8230c73ce1ef23aef 100644 (file)
@@ -503,6 +503,70 @@ int cpu_jump_to_64bit(ulong setup_base, ulong target)
        return -EFAULT;
 }
 
+/*
+ * Jump from SPL to U-Boot
+ *
+ * This function is work-in-progress with many issues to resolve.
+ *
+ * It works by setting up several regions:
+ *   ptr      - a place to put the code that jumps into 64-bit mode
+ *   gdt      - a place to put the global descriptor table
+ *   pgtable  - a place to put the page tables
+ *
+ * The cpu_call64() code is copied from ROM and then manually patched so that
+ * it has the correct GDT address in RAM. U-Boot is copied from ROM into
+ * its pre-relocation address. Then we jump to the cpu_call64() code in RAM,
+ * which changes to 64-bit mode and starts U-Boot.
+ */
+int cpu_jump_to_64bit_uboot(ulong target)
+{
+       typedef void (*func_t)(ulong pgtable, ulong setup_base, ulong target);
+       uint32_t *pgtable;
+       func_t func;
+
+       /* TODO(sjg@chromium.org): Find a better place for this */
+       pgtable = (uint32_t *)0x1000000;
+       if (!pgtable)
+               return -ENOMEM;
+
+       build_pagetable(pgtable);
+
+       /* TODO(sjg@chromium.org): Find a better place for this */
+       char *ptr = (char *)0x3000000;
+       char *gdt = (char *)0x3100000;
+
+       extern char gdt64[];
+
+       memcpy(ptr, cpu_call64, 0x1000);
+       memcpy(gdt, gdt64, 0x100);
+
+       /*
+        * TODO(sjg@chromium.org): This manually inserts the pointers into
+        * the code. Tidy this up to avoid this.
+        */
+       func = (func_t)ptr;
+       ulong ofs = (ulong)cpu_call64 - (ulong)ptr;
+       *(ulong *)(ptr + 7) = (ulong)gdt;
+       *(ulong *)(ptr + 0xc) = (ulong)gdt + 2;
+       *(ulong *)(ptr + 0x13) = (ulong)gdt;
+       *(ulong *)(ptr + 0x117 - 0xd4) -= ofs;
+
+       /*
+        * Copy U-Boot from ROM
+        * TODO(sjg@chromium.org): Figure out a way to get the text base
+        * correctly here, and in the device-tree binman definition.
+        *
+        * Also consider using FIT so we get the correct image length and
+        * parameters.
+        */
+       memcpy((char *)target, (char *)0xfff00000, 0x100000);
+
+       /* Jump to U-Boot */
+       func((ulong)pgtable, 0, (ulong)target);
+
+       return -EFAULT;
+}
+
 #ifdef CONFIG_SMP
 static int enable_smis(struct udevice *cpu, void *unused)
 {
index b408515582c1637a71f8d3ef5dbb5bea69be5fb6..c651f2f594535ab47c315d9b9fa4176cfe844748 100644 (file)
@@ -263,6 +263,15 @@ void cpu_call32(ulong code_seg32, ulong target, ulong table);
  */
 int cpu_jump_to_64bit(ulong setup_base, ulong target);
 
+/**
+ * cpu_jump_to_64bit_uboot() - special function to jump from SPL to U-Boot
+ *
+ * This handles calling from 32-bit SPL to 64-bit U-Boot.
+ *
+ * @target:    Address of U-Boot in RAM
+ */
+int cpu_jump_to_64bit_uboot(ulong target);
+
 /**
  * cpu_get_family_model() - Get the family and model for the CPU
  *