boot: efi: Use an event to relocate the OS
Rather than a weak function, use the recently added event to adjust the OS load-address. Tidy up the code a little while here. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
14
boot/bootm.c
14
boot/bootm.c
@@ -50,10 +50,6 @@ __weak void board_quiesce_devices(void)
|
||||
{
|
||||
}
|
||||
|
||||
__weak void board_fixup_os(struct image_info *os)
|
||||
{
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)
|
||||
/**
|
||||
* image_get_kernel - verify legacy format kernel image
|
||||
@@ -1077,7 +1073,15 @@ int bootm_run_states(struct bootm_info *bmi, int states)
|
||||
/* Load the OS */
|
||||
if (!ret && (states & BOOTM_STATE_LOADOS)) {
|
||||
iflag = bootm_disable_interrupts();
|
||||
board_fixup_os(&images->os);
|
||||
if (IS_ENABLED(CONFIG_EVENT)) {
|
||||
struct event_os_load data;
|
||||
|
||||
data.addr = images->os.load;
|
||||
ret = event_notify(EVT_BOOT_OS_ADDR, &data,
|
||||
sizeof(data));
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
ret = bootm_load_os(bmi, 0);
|
||||
if (ret && ret != BOOTM_ERR_OVERLAP)
|
||||
goto err;
|
||||
|
||||
@@ -263,12 +263,6 @@ void arch_preboot_os(void);
|
||||
*/
|
||||
void board_quiesce_devices(void);
|
||||
|
||||
/*
|
||||
* boards should define this if they need to fix up the kernel before boot
|
||||
* (eg, by modifying the desired load address).
|
||||
*/
|
||||
void board_fixup_os(struct image_info *os);
|
||||
|
||||
/**
|
||||
* switch_to_non_secure_mode() - switch to non-secure mode
|
||||
*/
|
||||
|
||||
@@ -20,6 +20,7 @@ config EFI_APP
|
||||
bool "Support running as an EFI application"
|
||||
depends on X86 || ARM
|
||||
select CHARSET
|
||||
select EVENT
|
||||
help
|
||||
Build U-Boot as an application which can be started from EFI. This
|
||||
is useful for examining a platform in the early stages of porting
|
||||
|
||||
@@ -241,8 +241,7 @@ static int efi_sysreset_request(struct udevice *dev, enum sysreset_t type)
|
||||
/*
|
||||
* Attempt to relocate the kernel to somewhere the firmware isn't using
|
||||
*/
|
||||
#define PAGE_SIZE_BITS 12
|
||||
void board_fixup_os(struct image_info *os)
|
||||
int board_fixup_os(void *ctx, struct event *evt)
|
||||
{
|
||||
int pages;
|
||||
ulong load_addr;
|
||||
@@ -250,28 +249,32 @@ void board_fixup_os(struct image_info *os)
|
||||
efi_status_t status;
|
||||
struct efi_priv *priv = efi_get_priv();
|
||||
struct efi_boot_services *boot = priv->boot;
|
||||
struct event_os_load *os_load = &evt->data.os_load;
|
||||
|
||||
pages = (os->image_len + ((1 << PAGE_SIZE_BITS) - 1)) >> PAGE_SIZE_BITS;
|
||||
pages = DIV_ROUND_UP(os_load->size, EFI_PAGE_SIZE);
|
||||
|
||||
addr = os->load;
|
||||
addr = os_load->addr;
|
||||
|
||||
/* Try to allocate at the preferred address */
|
||||
status = boot->allocate_pages(EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA,
|
||||
pages, &addr);
|
||||
if (status == EFI_SUCCESS)
|
||||
return;
|
||||
if (!status)
|
||||
return 0;
|
||||
|
||||
/* That failed, so try allocating anywhere there's enough room */
|
||||
status = boot->allocate_pages(EFI_ALLOCATE_ANY_PAGES, EFI_LOADER_DATA, pages, &addr);
|
||||
if (status == EFI_SUCCESS) {
|
||||
/* Make sure bootm knows where we loaded the image */
|
||||
os->load = addr;
|
||||
return;
|
||||
if (status) {
|
||||
printf("Failed to alloc %lx bytes at %lx: %lx\n", os_load->size,
|
||||
load_addr, status);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
printf("Failed to alloc %lx bytes at %lx: %lx\n", os->image_len, load_addr,
|
||||
status);
|
||||
/* Make sure bootm knows where we loaded the image */
|
||||
os_load->addr = addr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EVENT_SPY_FULL(EVT_BOOT_OS_ADDR, board_fixup_os);
|
||||
|
||||
static const struct udevice_id efi_sysreset_ids[] = {
|
||||
{ .compatible = "efi,reset" },
|
||||
|
||||
Reference in New Issue
Block a user