mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
3.6 KiB
165 lines
3.6 KiB
// SPDX-License-Identifier: GPL-2.0+ |
|
/* |
|
* Copyright (c) 2015 Google, Inc |
|
* |
|
* EFI information obtained here: |
|
* http://wiki.phoenix.com/wiki/index.php/EFI_BOOT_SERVICES |
|
* |
|
* This file implements U-Boot running as an EFI application. |
|
*/ |
|
|
|
#include <common.h> |
|
#include <debug_uart.h> |
|
#include <dm.h> |
|
#include <errno.h> |
|
#include <linux/err.h> |
|
#include <linux/types.h> |
|
#include <efi.h> |
|
#include <efi_api.h> |
|
#include <sysreset.h> |
|
|
|
DECLARE_GLOBAL_DATA_PTR; |
|
|
|
static struct efi_priv *global_priv; |
|
|
|
struct efi_system_table *efi_get_sys_table(void) |
|
{ |
|
return global_priv->sys_table; |
|
} |
|
|
|
unsigned long efi_get_ram_base(void) |
|
{ |
|
return global_priv->ram_base; |
|
} |
|
|
|
static efi_status_t setup_memory(struct efi_priv *priv) |
|
{ |
|
struct efi_boot_services *boot = priv->boot; |
|
efi_physical_addr_t addr; |
|
efi_status_t ret; |
|
int pages; |
|
|
|
/* |
|
* Use global_data_ptr instead of gd since it is an assignment. There |
|
* are very few assignments to global_data in U-Boot and this makes |
|
* it easier to find them. |
|
*/ |
|
global_data_ptr = efi_malloc(priv, sizeof(struct global_data), &ret); |
|
if (!global_data_ptr) |
|
return ret; |
|
memset(gd, '\0', sizeof(*gd)); |
|
|
|
gd->malloc_base = (ulong)efi_malloc(priv, CONFIG_VAL(SYS_MALLOC_F_LEN), |
|
&ret); |
|
if (!gd->malloc_base) |
|
return ret; |
|
pages = CONFIG_EFI_RAM_SIZE >> 12; |
|
|
|
/* |
|
* Don't allocate any memory above 4GB. U-Boot is a 32-bit application |
|
* so we want it to load below 4GB. |
|
*/ |
|
addr = 1ULL << 32; |
|
ret = boot->allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, |
|
priv->image_data_type, pages, &addr); |
|
if (ret) { |
|
printf("(using pool %lx) ", ret); |
|
priv->ram_base = (ulong)efi_malloc(priv, CONFIG_EFI_RAM_SIZE, |
|
&ret); |
|
if (!priv->ram_base) |
|
return ret; |
|
priv->use_pool_for_malloc = true; |
|
} else { |
|
priv->ram_base = addr; |
|
} |
|
gd->ram_size = pages << 12; |
|
|
|
return 0; |
|
} |
|
|
|
static void free_memory(struct efi_priv *priv) |
|
{ |
|
struct efi_boot_services *boot = priv->boot; |
|
|
|
if (priv->use_pool_for_malloc) |
|
efi_free(priv, (void *)priv->ram_base); |
|
else |
|
boot->free_pages(priv->ram_base, gd->ram_size >> 12); |
|
|
|
efi_free(priv, (void *)gd->malloc_base); |
|
efi_free(priv, gd); |
|
global_data_ptr = NULL; |
|
} |
|
|
|
/** |
|
* efi_main() - Start an EFI image |
|
* |
|
* This function is called by our EFI start-up code. It handles running |
|
* U-Boot. If it returns, EFI will continue. Another way to get back to EFI |
|
* is via reset_cpu(). |
|
*/ |
|
efi_status_t EFIAPI efi_main(efi_handle_t image, |
|
struct efi_system_table *sys_table) |
|
{ |
|
struct efi_priv local_priv, *priv = &local_priv; |
|
efi_status_t ret; |
|
|
|
/* Set up access to EFI data structures */ |
|
efi_init(priv, "App", image, sys_table); |
|
|
|
global_priv = priv; |
|
|
|
/* |
|
* Set up the EFI debug UART so that printf() works. This is |
|
* implemented in the EFI serial driver, serial_efi.c. The application |
|
* can use printf() freely. |
|
*/ |
|
debug_uart_init(); |
|
|
|
ret = setup_memory(priv); |
|
if (ret) { |
|
printf("Failed to set up memory: ret=%lx\n", ret); |
|
return ret; |
|
} |
|
|
|
printf("starting\n"); |
|
|
|
board_init_f(GD_FLG_SKIP_RELOC); |
|
board_init_r(NULL, 0); |
|
free_memory(priv); |
|
|
|
return EFI_SUCCESS; |
|
} |
|
|
|
static void efi_exit(void) |
|
{ |
|
struct efi_priv *priv = global_priv; |
|
|
|
free_memory(priv); |
|
printf("U-Boot EFI exiting\n"); |
|
priv->boot->exit(priv->parent_image, EFI_SUCCESS, 0, NULL); |
|
} |
|
|
|
static int efi_sysreset_request(struct udevice *dev, enum sysreset_t type) |
|
{ |
|
efi_exit(); |
|
|
|
return -EINPROGRESS; |
|
} |
|
|
|
static const struct udevice_id efi_sysreset_ids[] = { |
|
{ .compatible = "efi,reset" }, |
|
{ } |
|
}; |
|
|
|
static struct sysreset_ops efi_sysreset_ops = { |
|
.request = efi_sysreset_request, |
|
}; |
|
|
|
U_BOOT_DRIVER(efi_sysreset) = { |
|
.name = "efi-sysreset", |
|
.id = UCLASS_SYSRESET, |
|
.of_match = efi_sysreset_ids, |
|
.ops = &efi_sysreset_ops, |
|
.flags = DM_FLAG_PRE_RELOC, |
|
};
|
|
|