x86: Support jumping from SPL to U-Boot
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>
This commit is contained in:
parent
c2bf0dfaa3
commit
fa5fcb3bc6
|
@ -81,6 +81,9 @@ lret_target:
|
||||||
jmp *%eax /* Jump to the 64-bit target */
|
jmp *%eax /* Jump to the 64-bit target */
|
||||||
|
|
||||||
.data
|
.data
|
||||||
|
.align 16
|
||||||
|
.globl gdt64
|
||||||
|
gdt64:
|
||||||
gdt:
|
gdt:
|
||||||
.word gdt_end - gdt - 1
|
.word gdt_end - gdt - 1
|
||||||
.long gdt /* Fixed up by code above */
|
.long gdt /* Fixed up by code above */
|
||||||
|
|
|
@ -503,6 +503,70 @@ int cpu_jump_to_64bit(ulong setup_base, ulong target)
|
||||||
return -EFAULT;
|
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
|
#ifdef CONFIG_SMP
|
||||||
static int enable_smis(struct udevice *cpu, void *unused)
|
static int enable_smis(struct udevice *cpu, void *unused)
|
||||||
{
|
{
|
||||||
|
|
|
@ -263,6 +263,15 @@ void cpu_call32(ulong code_seg32, ulong target, ulong table);
|
||||||
*/
|
*/
|
||||||
int cpu_jump_to_64bit(ulong setup_base, ulong target);
|
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
|
* cpu_get_family_model() - Get the family and model for the CPU
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue