[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