uboot/lib/efi/efi_app.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 2015 Google, Inc
   4 *
   5 * EFI information obtained here:
   6 * http://wiki.phoenix.com/wiki/index.php/EFI_BOOT_SERVICES
   7 *
   8 * This file implements U-Boot running as an EFI application.
   9 */
  10
  11#include <common.h>
  12#include <cpu_func.h>
  13#include <debug_uart.h>
  14#include <dm.h>
  15#include <errno.h>
  16#include <init.h>
  17#include <malloc.h>
  18#include <asm/global_data.h>
  19#include <linux/err.h>
  20#include <linux/types.h>
  21#include <efi.h>
  22#include <efi_api.h>
  23#include <sysreset.h>
  24
  25DECLARE_GLOBAL_DATA_PTR;
  26
  27static struct efi_priv *global_priv;
  28
  29struct efi_system_table *efi_get_sys_table(void)
  30{
  31        return global_priv->sys_table;
  32}
  33
  34unsigned long efi_get_ram_base(void)
  35{
  36        return global_priv->ram_base;
  37}
  38
  39static efi_status_t setup_memory(struct efi_priv *priv)
  40{
  41        struct efi_boot_services *boot = priv->boot;
  42        efi_physical_addr_t addr;
  43        efi_status_t ret;
  44        int pages;
  45
  46        /*
  47         * Use global_data_ptr instead of gd since it is an assignment. There
  48         * are very few assignments to global_data in U-Boot and this makes
  49         * it easier to find them.
  50         */
  51        global_data_ptr = efi_malloc(priv, sizeof(struct global_data), &ret);
  52        if (!global_data_ptr)
  53                return ret;
  54        memset(gd, '\0', sizeof(*gd));
  55
  56        gd->malloc_base = (ulong)efi_malloc(priv, CONFIG_VAL(SYS_MALLOC_F_LEN),
  57                                            &ret);
  58        if (!gd->malloc_base)
  59                return ret;
  60        pages = CONFIG_EFI_RAM_SIZE >> 12;
  61
  62        /*
  63         * Don't allocate any memory above 4GB. U-Boot is a 32-bit application
  64         * so we want it to load below 4GB.
  65         */
  66        addr = 1ULL << 32;
  67        ret = boot->allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
  68                                   priv->image_data_type, pages, &addr);
  69        if (ret) {
  70                printf("(using pool %lx) ", ret);
  71                priv->ram_base = (ulong)efi_malloc(priv, CONFIG_EFI_RAM_SIZE,
  72                                                   &ret);
  73                if (!priv->ram_base)
  74                        return ret;
  75                priv->use_pool_for_malloc = true;
  76        } else {
  77                priv->ram_base = addr;
  78        }
  79        gd->ram_size = pages << 12;
  80
  81        return 0;
  82}
  83
  84static void free_memory(struct efi_priv *priv)
  85{
  86        struct efi_boot_services *boot = priv->boot;
  87
  88        if (priv->use_pool_for_malloc)
  89                efi_free(priv, (void *)priv->ram_base);
  90        else
  91                boot->free_pages(priv->ram_base, gd->ram_size >> 12);
  92
  93        efi_free(priv, (void *)gd->malloc_base);
  94        efi_free(priv, gd);
  95        global_data_ptr = NULL;
  96}
  97
  98/**
  99 * efi_main() - Start an EFI image
 100 *
 101 * This function is called by our EFI start-up code. It handles running
 102 * U-Boot. If it returns, EFI will continue. Another way to get back to EFI
 103 * is via reset_cpu().
 104 */
 105efi_status_t EFIAPI efi_main(efi_handle_t image,
 106                             struct efi_system_table *sys_table)
 107{
 108        struct efi_priv local_priv, *priv = &local_priv;
 109        efi_status_t ret;
 110
 111        /* Set up access to EFI data structures */
 112        efi_init(priv, "App", image, sys_table);
 113
 114        global_priv = priv;
 115
 116        /*
 117         * Set up the EFI debug UART so that printf() works. This is
 118         * implemented in the EFI serial driver, serial_efi.c. The application
 119         * can use printf() freely.
 120         */
 121        debug_uart_init();
 122
 123        ret = setup_memory(priv);
 124        if (ret) {
 125                printf("Failed to set up memory: ret=%lx\n", ret);
 126                return ret;
 127        }
 128
 129        printf("starting\n");
 130
 131        board_init_f(GD_FLG_SKIP_RELOC);
 132        board_init_r(NULL, 0);
 133        free_memory(priv);
 134
 135        return EFI_SUCCESS;
 136}
 137
 138static void efi_exit(void)
 139{
 140        struct efi_priv *priv = global_priv;
 141
 142        free_memory(priv);
 143        printf("U-Boot EFI exiting\n");
 144        priv->boot->exit(priv->parent_image, EFI_SUCCESS, 0, NULL);
 145}
 146
 147static int efi_sysreset_request(struct udevice *dev, enum sysreset_t type)
 148{
 149        efi_exit();
 150
 151        return -EINPROGRESS;
 152}
 153
 154static const struct udevice_id efi_sysreset_ids[] = {
 155        { .compatible = "efi,reset" },
 156        { }
 157};
 158
 159static struct sysreset_ops efi_sysreset_ops = {
 160        .request = efi_sysreset_request,
 161};
 162
 163U_BOOT_DRIVER(efi_sysreset) = {
 164        .name = "efi-sysreset",
 165        .id = UCLASS_SYSRESET,
 166        .of_match = efi_sysreset_ids,
 167        .ops = &efi_sysreset_ops,
 168};
 169