Commit 3dcdd17b43c5cfd3a216169948dfd08d6741c631

Authored by Ben Stoltz
Committed by Simon Glass
1 parent ed3b4d3736

x86: Add support for U-Boot as an EFI application

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@google.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

Showing 11 changed files with 319 additions and 0 deletions Side-by-side Diff

... ... @@ -11,6 +11,9 @@
11 11 config VENDOR_COREBOOT
12 12 bool "coreboot"
13 13  
  14 +config VENDOR_EFI
  15 + bool "efi"
  16 +
14 17 config VENDOR_EMULATION
15 18 bool "emulation"
16 19  
... ... @@ -2,7 +2,9 @@
2 2 # SPDX-License-Identifier: GPL-2.0+
3 3 #
4 4  
  5 +ifeq ($(CONFIG_EFI_APP),)
5 6 head-y := arch/x86/cpu/start.o
  7 +endif
6 8 ifeq ($(CONFIG_SPL_BUILD),y)
7 9 head-y += arch/x86/cpu/start16.o
8 10 head-y += arch/x86/cpu/resetvec.o
arch/x86/cpu/Makefile
... ... @@ -14,6 +14,7 @@
14 14  
15 15 obj-$(CONFIG_INTEL_BAYTRAIL) += baytrail/
16 16 obj-$(CONFIG_SYS_COREBOOT) += coreboot/
  17 +obj-$(CONFIG_EFI_APP) += efi/
17 18 obj-$(CONFIG_QEMU) += qemu/
18 19 obj-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += ivybridge/
19 20 obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/
arch/x86/cpu/efi/Makefile
  1 +#
  2 +# Copyright (c) 2015 Google, Inc
  3 +#
  4 +# SPDX-License-Identifier: GPL-2.0+
  5 +#
  6 +
  7 +obj-y += efi.o
  8 +obj-y += sdram.o
arch/x86/cpu/efi/efi.c
  1 +/*
  2 + * Copyright (c) 2015 Google, Inc
  3 + *
  4 + * SPDX-License-Identifier: GPL-2.0+
  5 + */
  6 +
  7 +#include <common.h>
  8 +#include <fdtdec.h>
  9 +#include <netdev.h>
  10 +
  11 +int arch_cpu_init(void)
  12 +{
  13 +#ifdef CONFIG_SYS_X86_TSC_TIMER
  14 + timer_set_base(rdtsc());
  15 +#endif
  16 +
  17 + return 0;
  18 +}
  19 +
  20 +int board_early_init_f(void)
  21 +{
  22 + return 0;
  23 +}
  24 +
  25 +int print_cpuinfo(void)
  26 +{
  27 + return default_print_cpuinfo();
  28 +}
  29 +
  30 +void board_final_cleanup(void)
  31 +{
  32 +}
  33 +
  34 +int misc_init_r(void)
  35 +{
  36 + return 0;
  37 +}
  38 +
  39 +int arch_misc_init(void)
  40 +{
  41 + return 0;
  42 +}
arch/x86/cpu/efi/elf_ia32_efi.lds
  1 +/*
  2 + * U-Boot EFI linker script
  3 + *
  4 + * SPDX-License-Identifier: BSD-2-Clause
  5 + *
  6 + * Modified from usr/lib32/elf_ia32_efi.lds in gnu-efi
  7 + */
  8 +
  9 +#include <config.h>
  10 +
  11 +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
  12 +OUTPUT_ARCH(i386)
  13 +ENTRY(_start)
  14 +SECTIONS
  15 +{
  16 + image_base = .;
  17 + .hash : { *(.hash) } /* this MUST come first, EFI expects it */
  18 + . = ALIGN(4096);
  19 + .text :
  20 + {
  21 + *(.text)
  22 + *(.text.*)
  23 + *(.gnu.linkonce.t.*)
  24 + }
  25 + . = ALIGN(4096);
  26 + .sdata :
  27 + {
  28 + *(.got.plt)
  29 + *(.got)
  30 + *(.srodata)
  31 + *(.sdata)
  32 + *(.sbss)
  33 + *(.scommon)
  34 + }
  35 + . = ALIGN(4096);
  36 + .data :
  37 + {
  38 + *(.rodata*)
  39 + *(.data)
  40 + *(.data1)
  41 + *(.data.*)
  42 + *(.sdata)
  43 + *(.got.plt)
  44 + *(.got)
  45 + /*
  46 + * the EFI loader doesn't seem to like a .bss section, so we
  47 + * stick it all into .data:
  48 + */
  49 + *(.sbss)
  50 + *(.scommon)
  51 + *(.dynbss)
  52 + *(.bss)
  53 + *(COMMON)
  54 +
  55 + /* U-Boot lists and device tree */
  56 + . = ALIGN(8);
  57 + *(SORT(.u_boot_list*));
  58 + . = ALIGN(8);
  59 + *(.dtb*);
  60 + }
  61 +
  62 + . = ALIGN(4096);
  63 + .dynamic : { *(.dynamic) }
  64 + . = ALIGN(4096);
  65 + .rel :
  66 + {
  67 + *(.rel.data)
  68 + *(.rel.data.*)
  69 + *(.rel.got)
  70 + *(.rel.stab)
  71 + *(.data.rel.ro.local)
  72 + *(.data.rel.local)
  73 + *(.data.rel.ro)
  74 + *(.data.rel*)
  75 + *(.rel.u_boot_list*)
  76 + }
  77 + . = ALIGN(4096);
  78 + .reloc : /* This is the PECOFF .reloc section! */
  79 + {
  80 + *(.reloc)
  81 + }
  82 + . = ALIGN(4096);
  83 + .dynsym : { *(.dynsym) }
  84 + . = ALIGN(4096);
  85 + .dynstr : { *(.dynstr) }
  86 + . = ALIGN(4096);
  87 + /DISCARD/ :
  88 + {
  89 + *(.rel.reloc)
  90 + *(.eh_frame)
  91 + *(.note.GNU-stack)
  92 + }
  93 + .comment 0 : { *(.comment) }
  94 +}
arch/x86/cpu/efi/sdram.c
  1 +/*
  2 + * Copyright (c) 2015 Google, Inc
  3 + *
  4 + * SPDX-License-Identifier: GPL-2.0+
  5 + */
  6 +
  7 +#include <common.h>
  8 +#include <efi.h>
  9 +#include <asm/u-boot-x86.h>
  10 +
  11 +DECLARE_GLOBAL_DATA_PTR;
  12 +
  13 +ulong board_get_usable_ram_top(ulong total_size)
  14 +{
  15 + return (ulong)efi_get_ram_base() + gd->ram_size;
  16 +}
  17 +
  18 +int dram_init(void)
  19 +{
  20 + /* gd->ram_size is set as part of EFI init */
  21 +
  22 + return 0;
  23 +}
  24 +
  25 +void dram_init_banksize(void)
  26 +{
  27 + gd->bd->bi_dram[0].start = efi_get_ram_base();
  28 + gd->bd->bi_dram[0].size = CONFIG_EFI_RAM_SIZE;
  29 +}
arch/x86/cpu/interrupts.c
... ... @@ -242,6 +242,11 @@
242 242  
243 243 int interrupt_init(void)
244 244 {
  245 + /*
  246 + * When running as an EFI application we are not in control of
  247 + * interrupts and should leave them alone.
  248 + */
  249 +#ifndef CONFIG_EFI_APP
245 250 /* Just in case... */
246 251 disable_interrupts();
247 252  
... ... @@ -255,6 +260,7 @@
255 260  
256 261 /* It is now safe to enable interrupts */
257 262 enable_interrupts();
  263 +#endif
258 264  
259 265 return 0;
260 266 }
arch/x86/include/asm/arch-efi/gpio.h
  1 +/*
  2 + * Copyright (c) 2015 Google, Inc.
  3 + *
  4 + * SPDX-License-Identifier: GPL-2.0+
  5 + */
  6 +
  7 +#ifndef _X86_ARCH_GPIO_H_
  8 +#define _X86_ARCH_GPIO_H_
  9 +
  10 +#endif /* _X86_ARCH_GPIO_H_ */
arch/x86/lib/efi/crt0-efi-ia32.S
  1 +/*
  2 + * crt0-efi-ia32.S - x86 EFI startup code.
  3 + *
  4 + * Copyright (C) 1999 Hewlett-Packard Co.
  5 + * Contributed by David Mosberger <davidm@hpl.hp.com>.
  6 + * All rights reserved.
  7 + *
  8 + * SPDX-License-Identifier: BSD-3-Clause
  9 + */
  10 +
  11 + .text
  12 + .align 4
  13 +
  14 + .globl _start
  15 +_start:
  16 + pushl %ebp
  17 + movl %esp,%ebp
  18 +
  19 + pushl 12(%ebp) # copy "image" argument
  20 + pushl 8(%ebp) # copy "systab" argument
  21 +
  22 + call 0f
  23 +0: popl %eax
  24 + movl %eax,%ebx
  25 +
  26 + addl $image_base-0b,%eax # %eax = ldbase
  27 + addl $_DYNAMIC-0b,%ebx # %ebx = _DYNAMIC
  28 +
  29 + pushl %ebx # pass _DYNAMIC as second argument
  30 + pushl %eax # pass ldbase as first argument
  31 + call _relocate
  32 + popl %ebx
  33 + popl %ebx
  34 + testl %eax,%eax
  35 + jne .exit
  36 + call efi_main # call app with "image" and "systab" argument
  37 +
  38 +.exit: leave
  39 + ret
  40 +
  41 + /*
  42 + * hand-craft a dummy .reloc section so EFI knows it's a relocatable
  43 + * executable:
  44 + */
  45 + .data
  46 +dummy: .long 0
  47 +
  48 +#define IMAGE_REL_ABSOLUTE 0
  49 + .section .reloc
  50 + .long dummy /* Page RVA */
  51 + .long 10 /* Block Size (2*4+2) */
  52 + .word (IMAGE_REL_ABSOLUTE << 12) + 0 /* reloc for dummy */
arch/x86/lib/efi/reloc_ia32.c
  1 +/*
  2 + * reloc_ia32.c - position independent x86 ELF shared object relocator
  3 + * Copyright (C) 1999 Hewlett-Packard Co.
  4 + * Contributed by David Mosberger <davidm@hpl.hp.com>.
  5 + *
  6 + * All rights reserved.
  7 + *
  8 + * SPDX-License-Identifier: BSD-3-Clause
  9 + */
  10 +
  11 +#include <common.h>
  12 +#include <efi.h>
  13 +#include <elf.h>
  14 +#include <asm/elf.h>
  15 +
  16 +efi_status_t _relocate(long ldbase, Elf32_Dyn *dyn, efi_handle_t image,
  17 + struct efi_system_table *systab)
  18 +{
  19 + long relsz = 0, relent = 0;
  20 + Elf32_Rel *rel = 0;
  21 + unsigned long *addr;
  22 + int i;
  23 +
  24 + for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
  25 + switch (dyn[i].d_tag) {
  26 + case DT_REL:
  27 + rel = (Elf32_Rel *)((unsigned long)dyn[i].d_un.d_ptr +
  28 + ldbase);
  29 + break;
  30 +
  31 + case DT_RELSZ:
  32 + relsz = dyn[i].d_un.d_val;
  33 + break;
  34 +
  35 + case DT_RELENT:
  36 + relent = dyn[i].d_un.d_val;
  37 + break;
  38 +
  39 + case DT_RELA:
  40 + break;
  41 +
  42 + default:
  43 + break;
  44 + }
  45 + }
  46 +
  47 + if (!rel && relent == 0)
  48 + return EFI_SUCCESS;
  49 +
  50 + if (!rel || relent == 0)
  51 + return EFI_LOAD_ERROR;
  52 +
  53 + while (relsz > 0) {
  54 + /* apply the relocs */
  55 + switch (ELF32_R_TYPE(rel->r_info)) {
  56 + case R_386_NONE:
  57 + break;
  58 +
  59 + case R_386_RELATIVE:
  60 + addr = (unsigned long *)(ldbase + rel->r_offset);
  61 + *addr += ldbase;
  62 + break;
  63 +
  64 + default:
  65 + break;
  66 + }
  67 + rel = (Elf32_Rel *)((char *)rel + relent);
  68 + relsz -= relent;
  69 + }
  70 +
  71 + return EFI_SUCCESS;
  72 +}