mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-05-05 12:46:14 +02:00
x86: Support booting a 64-bit kernel from 64-bit U-Boot
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>
This commit is contained in:
parent
1404914ddd
commit
37c9f9cc86
@ -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
|
||||
|
||||
@ -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)
|
||||
);
|
||||
|
||||
@ -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 = ¶ms->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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user