diff options
Diffstat (limited to 'arch/x86/cpu/i386/cpu.c')
-rw-r--r-- | arch/x86/cpu/i386/cpu.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/arch/x86/cpu/i386/cpu.c b/arch/x86/cpu/i386/cpu.c index 09a5b919e07..aabdc94bb0e 100644 --- a/arch/x86/cpu/i386/cpu.c +++ b/arch/x86/cpu/i386/cpu.c @@ -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) { |