[U-Boot] [PATCH 25/48] x86: Add support for U-Boot as an EFI application
Bin Meng
bmeng.cn at gmail.com
Thu Jul 23 11:43:35 CEST 2015
Hi Simon,
On Wed, Jul 22, 2015 at 11:49 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>
> ---
>
> 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 | 49 ++++++++++++++++++
> arch/x86/cpu/efi/elf_ia32_efi.lds | 92 ++++++++++++++++++++++++++++++++++
> arch/x86/cpu/efi/sdram.c | 29 +++++++++++
> arch/x86/cpu/interrupts.c | 2 +
> arch/x86/include/asm/arch-efi/gpio.h | 10 ++++
> arch/x86/lib/Makefile | 6 +++
> arch/x86/lib/crt0-efi-ia32.S | 77 +++++++++++++++++++++++++++++
> arch/x86/lib/crt0-efi-x86_64.S | 77 +++++++++++++++++++++++++++++
> arch/x86/lib/reloc_ia32.c | 96 ++++++++++++++++++++++++++++++++++++
> 13 files changed, 452 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/crt0-efi-ia32.S
> create mode 100644 arch/x86/lib/crt0-efi-x86_64.S
> create mode 100644 arch/x86/lib/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..e842015 100644
> --- a/arch/x86/Makefile
> +++ b/arch/x86/Makefile
> @@ -2,7 +2,9 @@
> # SPDX-License-Identifier: GPL-2.0+
> #
>
> +ifeq ($(CONFIG_ARCH_EFI),)
> 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..9678976 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_ARCH_EFI) += 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..0b1c54e
> --- /dev/null
> +++ b/arch/x86/cpu/efi/efi.c
> @@ -0,0 +1,49 @@
> +/*
> + * Copyright (c) 2015 Google, Inc
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <fdtdec.h>
> +#include <netdev.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
This is not needed.
> +
> +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();
> +}
> +
> +int board_eth_init(bd_t *bis)
> +{
> + return pci_eth_init(bis);
I don't think this works. Remove?
> +}
> +
> +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..fca008b
> --- /dev/null
> +++ b/arch/x86/cpu/efi/elf_ia32_efi.lds
> @@ -0,0 +1,92 @@
> +/*
> + * U-Boot EFI link script
Nits: 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
> +{
> + ImageBase = .;
CamelCase
> + .hash : { *(.hash) } /* this MUST come first! */
Why? Please add a comment on this.
> + . = 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);
> + KEEP(*(SORT(.u_boot_list*)));
I doubt KEEP is needed as this is in the .data section anyway.
> + . = ALIGN(8);
> + KEEP(*(.dtb*));
> + }
The original gnuefi codes have a ". = ALIGN(4096)" here. Is it
intended to drop this?
> + .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..a86c673 100644
> --- a/arch/x86/cpu/interrupts.c
> +++ b/arch/x86/cpu/interrupts.c
> @@ -242,6 +242,7 @@ int disable_interrupts(void)
>
> int interrupt_init(void)
> {
> +#ifndef CONFIG_ARCH_EFI
Can we add a comment block above to explain why EFI APP cannot call
interrupt_init()?
> /* Just in case... */
> disable_interrupts();
>
> @@ -255,6 +256,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/Makefile b/arch/x86/lib/Makefile
> index 43489fd..77bba16 100644
> --- a/arch/x86/lib/Makefile
> +++ b/arch/x86/lib/Makefile
> @@ -5,6 +5,12 @@
> # SPDX-License-Identifier: GPL-2.0+
> #
>
> +ifeq ($(CONFIG_X86_64),)
Where is CONFIG_X86_64 introduced?
> +obj-$(CONFIG_ARCH_EFI) += crt0-efi-ia32.o reloc_ia32.o
> +else
> +obj-$(CONFIG_ARCH_EFI) += crt0-efi-ia64.o reloc_ia64.o
> +endif
> +
> obj-y += bios.o
> obj-y += bios_asm.o
> obj-y += bios_interrupts.o
> diff --git a/arch/x86/lib/crt0-efi-ia32.S b/arch/x86/lib/crt0-efi-ia32.S
Can we put this file to arch/x86/lib/efi instead given it is only used for efi?
> new file mode 100644
> index 0000000..a5aebda
> --- /dev/null
> +++ b/arch/x86/lib/crt0-efi-ia32.S
> @@ -0,0 +1,77 @@
> +/* 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.
> +
> + Redistribution and use in source and binary forms, with or without
> + modification, are permitted provided that the following conditions
> + are met:
> +
> + * Redistributions of source code must retain the above copyright
> + notice, this list of conditions and the following disclaimer.
> + * Redistributions in binary form must reproduce the above
> + copyright notice, this list of conditions and the following
> + disclaimer in the documentation and/or other materials
> + provided with the distribution.
> + * Neither the name of Hewlett-Packard Co. nor the names of its
> + contributors may be used to endorse or promote products derived
> + from this software without specific prior written permission.
> +
> + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
> + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
> + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
> + BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
> + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
> + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
> + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + SUCH DAMAGE.
Can we replace the above license with simplified SPDX version?
> +*/
> +
> + .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 $ImageBase-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 */
Nits: space around <<
> diff --git a/arch/x86/lib/crt0-efi-x86_64.S b/arch/x86/lib/crt0-efi-x86_64.S
I believe this file needs to be introduced in later patches, as we
only handle 32-bit so far.
> new file mode 100644
> index 0000000..65a2795
> --- /dev/null
> +++ b/arch/x86/lib/crt0-efi-x86_64.S
> @@ -0,0 +1,77 @@
> +/* crt0-efi-x86_64.S - x86_64 EFI startup code.
> + Copyright (C) 1999 Hewlett-Packard Co.
> + Contributed by David Mosberger <davidm at hpl.hp.com>.
> + Copyright (C) 2005 Intel Co.
> + Contributed by Fenghua Yu <fenghua.yu at intel.com>.
> +
> + All rights reserved.
> +
> + Redistribution and use in source and binary forms, with or without
> + modification, are permitted provided that the following conditions
> + are met:
> +
> + * Redistributions of source code must retain the above copyright
> + notice, this list of conditions and the following disclaimer.
> + * Redistributions in binary form must reproduce the above
> + copyright notice, this list of conditions and the following
> + disclaimer in the documentation and/or other materials
> + provided with the distribution.
> + * Neither the name of Hewlett-Packard Co. nor the names of its
> + contributors may be used to endorse or promote products derived
> + from this software without specific prior written permission.
> +
> + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
> + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
> + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
> + BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
> + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
> + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
> + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + SUCH DAMAGE.
Can we replace the above license with simplified SPDX version?
> +*/
> + .text
> + .align 4
> +
> + .globl _start
> +_start:
> + subq $8, %rsp
> + pushq %rcx
> + pushq %rdx
> +
> +0:
> + lea ImageBase(%rip), %rdi
> + lea _DYNAMIC(%rip), %rsi
> +
> + popq %rcx
> + popq %rdx
> + pushq %rcx
> + pushq %rdx
> + call _relocate
> +
> + popq %rdi
> + popq %rsi
> +
> + call efi_main
> + addq $8, %rsp
> +
> +.exit:
> + 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, "a"
> +label1:
> + .long dummy-label1 /* Page RVA */
> + .long 10 /* Block Size (2*4+2) */
> + .word (IMAGE_REL_ABSOLUTE<<12) + 0 /* reloc for dummy */
Nits: space around <<
> diff --git a/arch/x86/lib/reloc_ia32.c b/arch/x86/lib/reloc_ia32.c
> new file mode 100644
> index 0000000..45c6654
> --- /dev/null
> +++ b/arch/x86/lib/reloc_ia32.c
> @@ -0,0 +1,96 @@
> +/* 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.
> +
> + Redistribution and use in source and binary forms, with or without
> + modification, are permitted provided that the following conditions
> + are met:
> +
> + * Redistributions of source code must retain the above copyright
> + notice, this list of conditions and the following disclaimer.
> + * Redistributions in binary form must reproduce the above
> + copyright notice, this list of conditions and the following
> + disclaimer in the documentation and/or other materials
> + provided with the distribution.
> + * Neither the name of Hewlett-Packard Co. nor the names of its
> + contributors may be used to endorse or promote products derived
> + from this software without specific prior written permission.
> +
> + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
> + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
> + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
> + BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
> + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
> + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
> + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + SUCH DAMAGE.
Can we replace the above license with simplified SPDX version?
> +*/
> +
> +#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;
> + }
Nits: need a blank line
> + return EFI_SUCCESS;
> +}
> --
Regards,
Bin
More information about the U-Boot
mailing list