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
  34struct efi_boot_services *efi_get_boot(void)
  35{
  36        return global_priv->boot;
  37}
  38
  39unsigned long efi_get_ram_base(void)
  40{
  41        return global_priv->ram_base;
  42}
  43
  44int efi_info_get(enum efi_entry_t type, void **datap, int *sizep)
  45{
  46        return -ENOSYS;
  47}
  48
  49static efi_status_t setup_memory(struct efi_priv *priv)
  50{
  51        struct efi_boot_services *boot = priv->boot;
  52        efi_physical_addr_t addr;
  53        efi_status_t ret;
  54        int pages;
  55
  56        /*
  57         * Use global_data_ptr instead of gd since it is an assignment. There
  58         * are very few assignments to global_data in U-Boot and this makes
  59         * it easier to find them.
  60         */
  61        global_data_ptr = efi_malloc(priv, sizeof(struct global_data), &ret);
  62        if (!global_data_ptr)
  63                return ret;
  64        memset(gd, '\0', sizeof(*gd));
  65
  66        gd->malloc_base = (ulong)efi_malloc(priv, CONFIG_VAL(SYS_MALLOC_F_LEN),
  67                                            &ret);
  68        if (!gd->malloc_base)
  69                return ret;
  70        pages = CONFIG_EFI_RAM_SIZE >> 12;
  71
  72        /*
  73         * Don't allocate any memory above 4GB. U-Boot is a 32-bit application
  74         * so we want it to load below 4GB.
  75         */
  76        addr = 1ULL << 32;
  77        ret = boot->allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
  78                                   priv->image_data_type, pages, &addr);
  79        if (ret) {
  80                printf("(using pool %lx) ", ret);
  81                priv->ram_base = (ulong)efi_malloc(priv, CONFIG_EFI_RAM_SIZE,
  82                                                   &ret);
  83                if (!priv->ram_base)
  84                        return ret;
  85                priv->use_pool_for_malloc = true;
  86        } else {
  87                priv->ram_base = addr;
  88        }
  89        gd->ram_size = pages << 12;
  90
  91        return 0;
  92}
  93
  94static void free_memory(struct efi_priv *priv)
  95{
  96        struct efi_boot_services *boot = priv->boot;
  97
  98        if (priv->use_pool_for_malloc)
  99                efi_free(priv, (void *)priv->ram_base);
 100        else
 101                boot->free_pages(priv->ram_base, gd->ram_size >> 12);
 102
 103        efi_free(priv, (void *)gd->malloc_base);
 104        efi_free(priv, gd);
 105        global_data_ptr = NULL;
 106}
 107
 108/**
 109 * efi_main() - Start an EFI image
 110 *
 111 * This function is called by our EFI start-up code. It handles running
 112 * U-Boot. If it returns, EFI will continue. Another way to get back to EFI
 113 * is via reset_cpu().
 114 */
 115efi_status_t EFIAPI efi_main(efi_handle_t image,
 116                             struct efi_system_table *sys_table)
 117{
 118        struct efi_priv local_priv, *priv = &local_priv;
 119        efi_status_t ret;
 120
 121        /* Set up access to EFI data structures */
 122        efi_init(priv, "App", image, sys_table);
 123
 124        global_priv = priv;
 125
 126        /*
 127         * Set up the EFI debug UART so that printf() works. This is
 128         * implemented in the EFI serial driver, serial_efi.c. The application
 129         * can use printf() freely.
 130         */
 131        debug_uart_init();
 132
 133        ret = setup_memory(priv);
 134        if (ret) {
 135                printf("Failed to set up memory: ret=%lx\n", ret);
 136                return ret;
 137        }
 138
 139        printf("starting\n");
 140
 141        board_init_f(GD_FLG_SKIP_RELOC);
 142        board_init_r(NULL, 0);
 143        free_memory(priv);
 144
 145        return EFI_SUCCESS;
 146}
 147
 148static void efi_exit(void)
 149{
 150        struct efi_priv *priv = global_priv;
 151
 152        free_memory(priv);
 153        printf("U-Boot EFI exiting\n");
 154        priv->boot->exit(priv->parent_image, EFI_SUCCESS, 0, NULL);
 155}
 156
 157static int efi_sysreset_request(struct udevice *dev, enum sysreset_t type)
 158{
 159        efi_exit();
 160
 161        return -EINPROGRESS;
 162}
 163
 164static const struct udevice_id efi_sysreset_ids[] = {
 165        { .compatible = "efi,reset" },
 166        { }
 167};
 168
 169static struct sysreset_ops efi_sysreset_ops = {
 170        .request = efi_sysreset_request,
 171};
 172
 173U_BOOT_DRIVER(efi_sysreset) = {
 174        .name = "efi-sysreset",
 175        .id = UCLASS_SYSRESET,
 176        .of_match = efi_sysreset_ids,
 177        .ops = &efi_sysreset_ops,
 178};
 179