[U-Boot] [PATCH v3 08/28] x86: Add support for U-Boot as an EFI application
Simon Glass
sjg at chromium.org
Wed Aug 5 20:02:51 CEST 2015
On 5 August 2015 at 01:42, Bin Meng <bmeng.cn at gmail.com> wrote:
> On Wed, Aug 5, 2015 at 2:33 AM, 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 v3:
>> - Move u-boot-app.efi Makefile change to the earlier patch
>> - Use "BSD-2-Clause" for the SPDX license
>>
>> 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
>>
>> 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 +++++++++++++++++++++++++++
>> 11 files changed, 319 insertions(+)
>> 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/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..cd3b0a9
>> --- /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
>> + *
>> + * 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;
>> +}
>> --
>
> Reviewed-by: Bin Meng <bmeng.cn at gmail.com>
Applied to u-boot-x86.
More information about the U-Boot
mailing list