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