[U-Boot] [PATCH 44/48] x86: Add helper code for running from EFI

Bin Meng bmeng.cn at gmail.com
Fri Jul 24 11:03:14 CEST 2015


Hi Simon,

On Wed, Jul 22, 2015 at 11:49 PM, Simon Glass <sjg at chromium.org> wrote:
> When U-Boot is running from EFI some of the x86 init is replaced with
> EFI-specific init. For example, since DRAM has already been set up, we only
> need to find it, not init it. Add these functions so that boards can easily
> allow booting from EFI if required.
>
> Signed-off-by: Simon Glass <sjg at chromium.org>
> ---
>
>  arch/x86/lib/Makefile     |   1 +
>  arch/x86/lib/efi/Makefile |   9 +++
>  arch/x86/lib/efi/car.S    |  12 ++++
>  arch/x86/lib/efi/efi.c    | 151 ++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 173 insertions(+)
>  create mode 100644 arch/x86/lib/efi/Makefile
>  create mode 100644 arch/x86/lib/efi/car.S
>  create mode 100644 arch/x86/lib/efi/efi.c
>
> diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
> index fb4a73c..3db373c 100644
> --- a/arch/x86/lib/Makefile
> +++ b/arch/x86/lib/Makefile
> @@ -31,6 +31,7 @@ obj-y += bios_interrupts.o
>  obj-$(CONFIG_CMD_BOOTM) += bootm.o
>  obj-y  += cmd_boot.o
>  obj-$(CONFIG_HAVE_FSP) += cmd_hob.o
> +obj-$(CONFIG_EFI_STUB) += efi/
>  obj-y  += gcc.o
>  obj-y  += init_helpers.o
>  obj-y  += interrupts.o
> diff --git a/arch/x86/lib/efi/Makefile b/arch/x86/lib/efi/Makefile
> new file mode 100644
> index 0000000..a308a0e
> --- /dev/null
> +++ b/arch/x86/lib/efi/Makefile
> @@ -0,0 +1,9 @@
> +#
> +# (C) Copyright 2002-2006
> +# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
> +#
> +# SPDX-License-Identifier:     GPL-2.0+
> +#
> +
> +obj-y += car.o
> +obj-y += efi.o
> diff --git a/arch/x86/lib/efi/car.S b/arch/x86/lib/efi/car.S
> new file mode 100644
> index 0000000..6dda058
> --- /dev/null
> +++ b/arch/x86/lib/efi/car.S
> @@ -0,0 +1,12 @@
> +/*
> + * Copyright (c) 2015 Google, Inc
> + * Written by Simon Glass <sjg at chromium.org>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +.section .text
> +

This is not needed.

> +.globl car_init
> +car_init:
> +       jmp     car_init_ret
> diff --git a/arch/x86/lib/efi/efi.c b/arch/x86/lib/efi/efi.c
> new file mode 100644
> index 0000000..ede5d56
> --- /dev/null
> +++ b/arch/x86/lib/efi/efi.c
> @@ -0,0 +1,151 @@
> +/*
> + * Copyright (c) 2015 Google, Inc
> + * Written by Simon Glass <sjg at chromium.org>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <debug_uart.h>
> +#include <efi.h>
> +#include <errno.h>
> +#include <linux/err.h>
> +#include <linux/types.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/*
> + * This function looks for the highest region of memory lower than 4GB which
> + * has enough space for U-Boot where U-Boot is aligned on a page boundary.
> + * It overrides the default implementation found elsewhere which simply
> + * picks the end of ram, wherever that may be. The location of the stack,
> + * the relocation address, and how far U-Boot is moved by relocation are
> + * set in the global data structure.
> + */
> +ulong board_get_usable_ram_top(ulong total_size)
> +{
> +       struct efi_mem_desc *desc, *end;
> +       struct efi_entry_memmap *map;
> +       int ret, size;
> +       uintptr_t dest_addr = 0;
> +       struct efi_mem_desc *largest = NULL;
> +
> +       /*
> +        * Find largest area of memory below 4GB. We could
> +        * call efi_build_mem_table() for a more accurate picture since it
> +        * merges areas together where possible. But that function uses more
> +        * pre-relocation memory, and it's not critical that we find the
> +        * absolute largest region.
> +        */
> +       ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size);
> +       if (ret) {
> +               /* We should have stopped in dram_init(), something is wrong */
> +               debug("%s: Missing memory map\n", __func__);
> +               goto err;
> +       }
> +
> +       end = (struct efi_mem_desc *)((ulong)map + size);
> +       desc = map->desc;
> +       for (; desc < end; desc = efi_get_next_mem_desc(map, desc)) {
> +               if (desc->type != EFI_CONVENTIONAL_MEMORY ||
> +                   desc->physical_start >= 1ULL << 32)
> +                       continue;
> +               if (!largest || desc->num_pages > largest->num_pages)
> +                       largest = desc;
> +       }
> +
> +       /* If no suitable area was found, return an error. */
> +       assert(largest);
> +       if (!largest || (largest->num_pages << EFI_PAGE_SHIFT) < (2 << 20))
> +               goto err;
> +
> +       dest_addr = largest->physical_start + (largest->num_pages <<
> +                       EFI_PAGE_SHIFT);
> +
> +       return (ulong)dest_addr;
> +err:
> +       panic("No available memory found for relocation");
> +       return 0;
> +}
> +
> +int dram_init(void)
> +{
> +       struct efi_mem_desc *desc, *end;
> +       struct efi_entry_memmap *map;
> +       int size, ret;
> +
> +       ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size);
> +       if (ret) {
> +               printf("Cannot find EFI memory map tables, ret=%d\n", ret);
> +
> +               return -ENODEV;
> +       }
> +
> +       end = (struct efi_mem_desc *)((ulong)map + size);
> +       gd->ram_size = 0;
> +       desc = map->desc;
> +       for (; desc < end; desc = efi_get_next_mem_desc(map, desc)) {
> +               if (desc->type < EFI_MMAP_IO)
> +                       gd->ram_size += desc->num_pages << EFI_PAGE_SHIFT;
> +       }
> +
> +       return 0;
> +}
> +
> +void dram_init_banksize(void)
> +{
> +       struct efi_mem_desc *desc, *end;
> +       struct efi_entry_memmap *map;
> +       int ret, size;
> +       int num_banks;
> +
> +       ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size);
> +       if (ret) {
> +               /* We should have stopped in dram_init(), something is wrong */
> +               debug("%s: Missing memory map\n", __func__);
> +               return;
> +       }
> +       end = (struct efi_mem_desc *)((ulong)map + size);
> +       desc = map->desc;
> +       for (num_banks = 0;
> +            desc < end && num_banks < CONFIG_NR_DRAM_BANKS;
> +            desc = efi_get_next_mem_desc(map, desc)) {
> +               /*
> +                * We only use conventional memory below 4GB, and ignore
> +                * anything less than 1MB.
> +                */
> +               if (desc->type != EFI_CONVENTIONAL_MEMORY ||
> +                   desc->physical_start >= 1ULL << 32 ||
> +                   (desc->num_pages << EFI_PAGE_SHIFT) < 1 << 20)
> +                       continue;
> +               gd->bd->bi_dram[num_banks].start = desc->physical_start;
> +               gd->bd->bi_dram[num_banks].size = desc->num_pages <<
> +                       EFI_PAGE_SHIFT;
> +               num_banks++;
> +       }
> +}
> +
> +int print_cpuinfo(void)
> +{
> +       return default_print_cpuinfo();
> +}
> +
> +/* Find any available tables and copy them to a safe place */
> +int reserve_arch(void)
> +{
> +       struct efi_info_hdr *hdr;
> +
> +       debug("table=%lx\n", gd->arch.table);
> +       if (!gd->arch.table)
> +               return 0;
> +
> +       hdr = (struct efi_info_hdr *)gd->arch.table;
> +
> +       gd->start_addr_sp -= hdr->total_size;
> +       memcpy((void *)gd->start_addr_sp, hdr, hdr->total_size);
> +       debug("Stashing EFI table at %lx to %lx, size %x\n",
> +             gd->arch.table, gd->start_addr_sp, hdr->total_size);
> +       gd->arch.table = gd->start_addr_sp;
> +
> +       return 0;
> +}
> --

Regards,
Bin


More information about the U-Boot mailing list