[U-Boot] [PATCH v2 28/47] x86: Add support for U-Boot as an EFI application
Bin Meng
bmeng.cn at gmail.com
Tue Aug 4 07:07:54 CEST 2015
Hi Simon,
On Fri, Jul 31, 2015 at 11:31 PM, Simon Glass <sjg at chromium.org> wrote:
> From: Ben Stoltz <stoltz at google.com>
>
> Add the required x86 glue code. This includes the initial start-up,
> relocation and jumping to efi_main(). We also need to avoid fiddling with
> interrupts.
>
> Signed-off-by: Ben Stoltz <stoltz at google.com>
> Signed-off-by: Simon Glass <sjg at chromium.org>
> ---
>
> Changes in v2:
> - Add ALIGN() before .dynamic in the linker script
> - Add a blank line before return in the _relocate() function
> - Add a comment as to why .hash has to be first in the linker script
> - Add a comment as to why interrupt_init() must be skipped for EFI
> - Drop unused DECLARE_GLOBAL_DATA_INIT
> - Drop unused board_eth_init()
> - Drop use of CONFIG_X86_64 since we don't support a 64-bit EFI application yet
> - Fix spacing around operators
> - Move 64-bit crt0 to a later patch
> - Move crt0 and reloc files into arch/x86/lib/efi/
> - Remove KEEP in the EFI linker script since garbage collection is not enabled
> - Rename CONFIG_ARCH_EFI to CONFIG_EFI_APP
> - Rename ImageBase to image_base
> - Use SPDX for the EFI start and relocation code
> - Use u-boot-app.efi instead of u-boot.efi
>
> Makefile | 6 +--
> arch/x86/Kconfig | 3 ++
> arch/x86/Makefile | 2 +
> arch/x86/cpu/Makefile | 1 +
> arch/x86/cpu/efi/Makefile | 8 +++
> arch/x86/cpu/efi/efi.c | 42 ++++++++++++++++
> arch/x86/cpu/efi/elf_ia32_efi.lds | 94 ++++++++++++++++++++++++++++++++++++
> arch/x86/cpu/efi/sdram.c | 29 +++++++++++
> arch/x86/cpu/interrupts.c | 6 +++
> arch/x86/include/asm/arch-efi/gpio.h | 10 ++++
> arch/x86/lib/efi/crt0-efi-ia32.S | 52 ++++++++++++++++++++
> arch/x86/lib/efi/reloc_ia32.c | 72 +++++++++++++++++++++++++++
> 12 files changed, 322 insertions(+), 3 deletions(-)
> create mode 100644 arch/x86/cpu/efi/Makefile
> create mode 100644 arch/x86/cpu/efi/efi.c
> create mode 100644 arch/x86/cpu/efi/elf_ia32_efi.lds
> create mode 100644 arch/x86/cpu/efi/sdram.c
> create mode 100644 arch/x86/include/asm/arch-efi/gpio.h
> create mode 100644 arch/x86/lib/efi/crt0-efi-ia32.S
> create mode 100644 arch/x86/lib/efi/reloc_ia32.c
>
> diff --git a/Makefile b/Makefile
> index 3fb006b..6da9224 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -750,7 +750,7 @@ ifneq ($(CONFIG_SPL_TARGET),)
> ALL-$(CONFIG_SPL) += $(CONFIG_SPL_TARGET:"%"=%)
> endif
> ALL-$(CONFIG_REMAKE_ELF) += u-boot.elf
> -ALL-$(CONFIG_EFI_APP) += u-boot.efi
> +ALL-$(CONFIG_EFI_APP) += u-boot-app.efi
>
Can we move this change to http://patchwork.ozlabs.org/patch/502642/?
> ifneq ($(BUILD_ROM),)
> ALL-$(CONFIG_X86_RESET_VECTOR) += u-boot.rom
> @@ -1079,8 +1079,8 @@ u-boot-dtb-tegra.bin: u-boot-nodtb-tegra.bin dts/dt.dtb FORCE
> endif
> endif
>
> -OBJCOPYFLAGS_u-boot.efi := $(OBJCOPYFLAGS_EFI)
> -u-boot.efi: u-boot FORCE
> +OBJCOPYFLAGS_u-boot-app.efi := $(OBJCOPYFLAGS_EFI)
> +u-boot-app.efi: u-boot FORCE
> $(call if_changed,zobjcopy)
>
Ditto.
> u-boot-img.bin: spl/u-boot-spl.bin u-boot.img FORCE
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index e8968a7..7e6e89c 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -11,6 +11,9 @@ choice
> config VENDOR_COREBOOT
> bool "coreboot"
>
> +config VENDOR_EFI
> + bool "efi"
> +
> config VENDOR_EMULATION
> bool "emulation"
>
> diff --git a/arch/x86/Makefile b/arch/x86/Makefile
> index 36a6018..d104a49 100644
> --- a/arch/x86/Makefile
> +++ b/arch/x86/Makefile
> @@ -2,7 +2,9 @@
> # SPDX-License-Identifier: GPL-2.0+
> #
>
> +ifeq ($(CONFIG_EFI_APP),)
> head-y := arch/x86/cpu/start.o
> +endif
> ifeq ($(CONFIG_SPL_BUILD),y)
> head-y += arch/x86/cpu/start16.o
> head-y += arch/x86/cpu/resetvec.o
> diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile
> index 8a8e63e..5e058c0 100644
> --- a/arch/x86/cpu/Makefile
> +++ b/arch/x86/cpu/Makefile
> @@ -14,6 +14,7 @@ obj-y += interrupts.o cpu.o cpu_x86.o call64.o
>
> obj-$(CONFIG_INTEL_BAYTRAIL) += baytrail/
> obj-$(CONFIG_SYS_COREBOOT) += coreboot/
> +obj-$(CONFIG_EFI_APP) += efi/
> obj-$(CONFIG_QEMU) += qemu/
> obj-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += ivybridge/
> obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/
> diff --git a/arch/x86/cpu/efi/Makefile b/arch/x86/cpu/efi/Makefile
> new file mode 100644
> index 0000000..e091637
> --- /dev/null
> +++ b/arch/x86/cpu/efi/Makefile
> @@ -0,0 +1,8 @@
> +#
> +# Copyright (c) 2015 Google, Inc
> +#
> +# SPDX-License-Identifier: GPL-2.0+
> +#
> +
> +obj-y += efi.o
> +obj-y += sdram.o
> diff --git a/arch/x86/cpu/efi/efi.c b/arch/x86/cpu/efi/efi.c
> new file mode 100644
> index 0000000..75ba0d4
> --- /dev/null
> +++ b/arch/x86/cpu/efi/efi.c
> @@ -0,0 +1,42 @@
> +/*
> + * Copyright (c) 2015 Google, Inc
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <fdtdec.h>
> +#include <netdev.h>
> +
> +int arch_cpu_init(void)
> +{
> +#ifdef CONFIG_SYS_X86_TSC_TIMER
> + timer_set_base(rdtsc());
> +#endif
> +
> + return 0;
> +}
> +
> +int board_early_init_f(void)
> +{
> + return 0;
> +}
> +
> +int print_cpuinfo(void)
> +{
> + return default_print_cpuinfo();
> +}
> +
> +void board_final_cleanup(void)
> +{
> +}
> +
> +int misc_init_r(void)
> +{
> + return 0;
> +}
> +
> +int arch_misc_init(void)
> +{
> + return 0;
> +}
> diff --git a/arch/x86/cpu/efi/elf_ia32_efi.lds b/arch/x86/cpu/efi/elf_ia32_efi.lds
> new file mode 100644
> index 0000000..a83ddd0
> --- /dev/null
> +++ b/arch/x86/cpu/efi/elf_ia32_efi.lds
> @@ -0,0 +1,94 @@
> +/*
> + * U-Boot EFI linker script
> + *
> + * SPDX-License-Identifier: bsd-2-clause
Should be "BSD-2-Clause" (per http://spdx.org/licenses/)
> + *
> + * Modified from usr/lib32/elf_ia32_efi.lds in gnu-efi
> + */
> +
> +#include <config.h>
> +
> +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
> +OUTPUT_ARCH(i386)
> +ENTRY(_start)
> +SECTIONS
> +{
> + image_base = .;
> + .hash : { *(.hash) } /* this MUST come first, EFI expects it */
> + . = ALIGN(4096);
> + .text :
> + {
> + *(.text)
> + *(.text.*)
> + *(.gnu.linkonce.t.*)
> + }
> + . = ALIGN(4096);
> + .sdata :
> + {
> + *(.got.plt)
> + *(.got)
> + *(.srodata)
> + *(.sdata)
> + *(.sbss)
> + *(.scommon)
> + }
> + . = ALIGN(4096);
> + .data :
> + {
> + *(.rodata*)
> + *(.data)
> + *(.data1)
> + *(.data.*)
> + *(.sdata)
> + *(.got.plt)
> + *(.got)
> + /*
> + * the EFI loader doesn't seem to like a .bss section, so we
> + * stick it all into .data:
> + */
> + *(.sbss)
> + *(.scommon)
> + *(.dynbss)
> + *(.bss)
> + *(COMMON)
> +
> + /* U-Boot lists and device tree */
> + . = ALIGN(8);
> + *(SORT(.u_boot_list*));
> + . = ALIGN(8);
> + *(.dtb*);
> + }
> +
> + . = ALIGN(4096);
> + .dynamic : { *(.dynamic) }
> + . = ALIGN(4096);
> + .rel :
> + {
> + *(.rel.data)
> + *(.rel.data.*)
> + *(.rel.got)
> + *(.rel.stab)
> + *(.data.rel.ro.local)
> + *(.data.rel.local)
> + *(.data.rel.ro)
> + *(.data.rel*)
> + *(.rel.u_boot_list*)
> + }
> + . = ALIGN(4096);
> + .reloc : /* This is the PECOFF .reloc section! */
> + {
> + *(.reloc)
> + }
> + . = ALIGN(4096);
> + .dynsym : { *(.dynsym) }
> + . = ALIGN(4096);
> + .dynstr : { *(.dynstr) }
> + . = ALIGN(4096);
> + /DISCARD/ :
> + {
> + *(.rel.reloc)
> + *(.eh_frame)
> + *(.note.GNU-stack)
> + }
> + .comment 0 : { *(.comment) }
> +}
> diff --git a/arch/x86/cpu/efi/sdram.c b/arch/x86/cpu/efi/sdram.c
> new file mode 100644
> index 0000000..5159944
> --- /dev/null
> +++ b/arch/x86/cpu/efi/sdram.c
> @@ -0,0 +1,29 @@
> +/*
> + * Copyright (c) 2015 Google, Inc
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <efi.h>
> +#include <asm/u-boot-x86.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +ulong board_get_usable_ram_top(ulong total_size)
> +{
> + return (ulong)efi_get_ram_base() + gd->ram_size;
> +}
> +
> +int dram_init(void)
> +{
> + /* gd->ram_size is set as part of EFI init */
> +
> + return 0;
> +}
> +
> +void dram_init_banksize(void)
> +{
> + gd->bd->bi_dram[0].start = efi_get_ram_base();
> + gd->bd->bi_dram[0].size = CONFIG_EFI_RAM_SIZE;
> +}
> diff --git a/arch/x86/cpu/interrupts.c b/arch/x86/cpu/interrupts.c
> index 3a9c2d4..a112938 100644
> --- a/arch/x86/cpu/interrupts.c
> +++ b/arch/x86/cpu/interrupts.c
> @@ -242,6 +242,11 @@ int disable_interrupts(void)
>
> int interrupt_init(void)
> {
> + /*
> + * When running as an EFI application we are not in control of
> + * interrupts and should leave them alone.
> + */
> +#ifndef CONFIG_EFI_APP
> /* Just in case... */
> disable_interrupts();
>
> @@ -255,6 +260,7 @@ int interrupt_init(void)
>
> /* It is now safe to enable interrupts */
> enable_interrupts();
> +#endif
>
> return 0;
> }
> diff --git a/arch/x86/include/asm/arch-efi/gpio.h b/arch/x86/include/asm/arch-efi/gpio.h
> new file mode 100644
> index 0000000..f044f07
> --- /dev/null
> +++ b/arch/x86/include/asm/arch-efi/gpio.h
> @@ -0,0 +1,10 @@
> +/*
> + * Copyright (c) 2015 Google, Inc.
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#ifndef _X86_ARCH_GPIO_H_
> +#define _X86_ARCH_GPIO_H_
> +
> +#endif /* _X86_ARCH_GPIO_H_ */
> diff --git a/arch/x86/lib/efi/crt0-efi-ia32.S b/arch/x86/lib/efi/crt0-efi-ia32.S
> new file mode 100644
> index 0000000..30e5eb0
> --- /dev/null
> +++ b/arch/x86/lib/efi/crt0-efi-ia32.S
> @@ -0,0 +1,52 @@
> +/*
> + * crt0-efi-ia32.S - x86 EFI startup code.
> + *
> + * Copyright (C) 1999 Hewlett-Packard Co.
> + * Contributed by David Mosberger <davidm at hpl.hp.com>.
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier: BSD-3-Clause
> + */
> +
> + .text
> + .align 4
> +
> + .globl _start
> +_start:
> + pushl %ebp
> + movl %esp,%ebp
> +
> + pushl 12(%ebp) # copy "image" argument
> + pushl 8(%ebp) # copy "systab" argument
> +
> + call 0f
> +0: popl %eax
> + movl %eax,%ebx
> +
> + addl $image_base-0b,%eax # %eax = ldbase
> + addl $_DYNAMIC-0b,%ebx # %ebx = _DYNAMIC
> +
> + pushl %ebx # pass _DYNAMIC as second argument
> + pushl %eax # pass ldbase as first argument
> + call _relocate
> + popl %ebx
> + popl %ebx
> + testl %eax,%eax
> + jne .exit
> + call efi_main # call app with "image" and "systab" argument
> +
> +.exit: leave
> + ret
> +
> + /*
> + * hand-craft a dummy .reloc section so EFI knows it's a relocatable
> + * executable:
> + */
> + .data
> +dummy: .long 0
> +
> +#define IMAGE_REL_ABSOLUTE 0
> + .section .reloc
> + .long dummy /* Page RVA */
> + .long 10 /* Block Size (2*4+2) */
> + .word (IMAGE_REL_ABSOLUTE << 12) + 0 /* reloc for dummy */
> diff --git a/arch/x86/lib/efi/reloc_ia32.c b/arch/x86/lib/efi/reloc_ia32.c
> new file mode 100644
> index 0000000..4d68255
> --- /dev/null
> +++ b/arch/x86/lib/efi/reloc_ia32.c
> @@ -0,0 +1,72 @@
> +/*
> + * reloc_ia32.c - position independent x86 ELF shared object relocator
> + * Copyright (C) 1999 Hewlett-Packard Co.
> + * Contributed by David Mosberger <davidm at hpl.hp.com>.
> + *
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier: BSD-3-Clause
> + */
> +
> +#include <common.h>
> +#include <efi.h>
> +#include <elf.h>
> +#include <asm/elf.h>
> +
> +efi_status_t _relocate(long ldbase, Elf32_Dyn *dyn, efi_handle_t image,
> + struct efi_system_table *systab)
> +{
> + long relsz = 0, relent = 0;
> + Elf32_Rel *rel = 0;
> + unsigned long *addr;
> + int i;
> +
> + for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
> + switch (dyn[i].d_tag) {
> + case DT_REL:
> + rel = (Elf32_Rel *)((unsigned long)dyn[i].d_un.d_ptr +
> + ldbase);
> + break;
> +
> + case DT_RELSZ:
> + relsz = dyn[i].d_un.d_val;
> + break;
> +
> + case DT_RELENT:
> + relent = dyn[i].d_un.d_val;
> + break;
> +
> + case DT_RELA:
> + break;
> +
> + default:
> + break;
> + }
> + }
> +
> + if (!rel && relent == 0)
> + return EFI_SUCCESS;
> +
> + if (!rel || relent == 0)
> + return EFI_LOAD_ERROR;
> +
> + while (relsz > 0) {
> + /* apply the relocs */
> + switch (ELF32_R_TYPE(rel->r_info)) {
> + case R_386_NONE:
> + break;
> +
> + case R_386_RELATIVE:
> + addr = (unsigned long *)(ldbase + rel->r_offset);
> + *addr += ldbase;
> + break;
> +
> + default:
> + break;
> + }
> + rel = (Elf32_Rel *)((char *)rel + relent);
> + relsz -= relent;
> + }
> +
> + return EFI_SUCCESS;
> +}
> --
Regards,
Bin
More information about the U-Boot
mailing list