Merge git://git.denx.de/u-boot-x86

This commit is contained in:
Tom Rini 2015-08-05 14:12:37 -04:00
commit 1a2728ae4f
122 changed files with 8325 additions and 235 deletions

1
.gitignore vendored
View File

@ -48,6 +48,7 @@
/LOG
/spl/
/tpl/
/defconfig
#
# Generated include files

View File

@ -179,6 +179,7 @@ config SYS_EXTRA_OPTIONS
config SYS_TEXT_BASE
depends on SPARC || ARC || X86 || ARCH_UNIPHIER || ARCH_ZYNQMP
depends on !EFI_APP
hex "Text Base"
help
TODO: Move CONFIG_SYS_TEXT_BASE for all the architecture

View File

@ -754,6 +754,8 @@ ifneq ($(CONFIG_SPL_TARGET),)
ALL-$(CONFIG_SPL) += $(CONFIG_SPL_TARGET:"%"=%)
endif
ALL-$(CONFIG_REMAKE_ELF) += u-boot.elf
ALL-$(CONFIG_EFI_APP) += u-boot-app.efi
ALL-$(CONFIG_EFI_STUB) += u-boot-payload.efi
ifneq ($(BUILD_ROM),)
ALL-$(CONFIG_X86_RESET_VECTOR) += u-boot.rom
@ -780,8 +782,17 @@ ifneq ($(CONFIG_SYS_TEXT_BASE),)
LDFLAGS_u-boot += -Ttext $(CONFIG_SYS_TEXT_BASE)
endif
# Normally we fill empty space with 0xff
quiet_cmd_objcopy = OBJCOPY $@
cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
cmd_objcopy = $(OBJCOPY) --gap-fill=0xff $(OBJCOPYFLAGS) \
$(OBJCOPYFLAGS_$(@F)) $< $@
# Provide a version which does not do this, for use by EFI
quiet_cmd_zobjcopy = OBJCOPY $@
cmd_zobjcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
quiet_cmd_efipayload = OBJCOPY $@
cmd_efipayload = $(OBJCOPY) -I binary -O $(EFIPAYLOAD_BFDTARGET) -B $(EFIPAYLOAD_BFDARCH) $< $@
quiet_cmd_mkimage = MKIMAGE $@
cmd_mkimage = $(objtree)/tools/mkimage $(MKIMAGEFLAGS_$(@F)) -d $< $@ \
@ -1076,6 +1087,30 @@ u-boot-dtb-tegra.bin: u-boot-nodtb-tegra.bin dts/dt.dtb FORCE
endif
endif
OBJCOPYFLAGS_u-boot-app.efi := $(OBJCOPYFLAGS_EFI)
u-boot-app.efi: u-boot FORCE
$(call if_changed,zobjcopy)
u-boot-dtb.bin.o: u-boot-dtb.bin FORCE
$(call if_changed,efipayload)
u-boot-payload.lds: $(LDSCRIPT_EFI) FORCE
$(call if_changed_dep,cpp_lds)
# Rule to link the EFI payload which contains a stub and a U-Boot binary
quiet_cmd_u-boot_payload ?= LD $@
cmd_u-boot_payload ?= $(LD) $(LDFLAGS_EFI_PAYLOAD) -o $@ \
-T u-boot-payload.lds arch/x86/cpu/call32.o \
lib/efi/efi.o lib/efi/efi_stub.o u-boot-dtb.bin.o \
$(addprefix arch/$(ARCH)/lib/efi/,$(EFISTUB))
u-boot-payload: u-boot-dtb.bin.o u-boot-payload.lds FORCE
$(call if_changed,u-boot_payload)
OBJCOPYFLAGS_u-boot-payload.efi := $(OBJCOPYFLAGS_EFI)
u-boot-payload.efi: u-boot-payload FORCE
$(call if_changed,zobjcopy)
u-boot-img.bin: spl/u-boot-spl.bin u-boot.img FORCE
$(call if_changed,cat)

View File

@ -11,6 +11,9 @@ choice
config VENDOR_COREBOOT
bool "coreboot"
config VENDOR_EFI
bool "efi"
config VENDOR_EMULATION
bool "emulation"
@ -24,6 +27,7 @@ endchoice
# board-specific options below
source "board/coreboot/Kconfig"
source "board/efi/Kconfig"
source "board/emulation/Kconfig"
source "board/google/Kconfig"
source "board/intel/Kconfig"
@ -190,6 +194,7 @@ config X86_RAMTEST
config HAVE_FSP
bool "Add an Firmware Support Package binary"
depends on !EFI
help
Select this option to add an Firmware Support Package binary to
the resulting U-Boot image. It is a binary blob which U-Boot uses
@ -305,6 +310,7 @@ menu "System tables"
config GENERATE_PIRQ_TABLE
bool "Generate a PIRQ table"
depends on !EFI
default n
help
Generate a PIRQ routing table for this board. The PIRQ routing table
@ -315,6 +321,7 @@ config GENERATE_PIRQ_TABLE
config GENERATE_SFI_TABLE
bool "Generate a SFI (Simple Firmware Interface) table"
depends on !EFI
help
The Simple Firmware Interface (SFI) provides a lightweight method
for platform firmware to pass information to the operating system
@ -329,6 +336,7 @@ config GENERATE_SFI_TABLE
config GENERATE_MP_TABLE
bool "Generate an MP (Multi-Processor) table"
depends on !EFI
default n
help
Generate an MP (Multi-Processor) table for this board. The MP table
@ -379,4 +387,6 @@ config PCIE_ECAM_SIZE
so a default 0x10000000 size covers all of the 256 buses which is the
maximum number of PCI buses as defined by the PCI specification.
source "arch/x86/lib/efi/Kconfig"
endmenu

View File

@ -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

View File

@ -8,19 +8,60 @@
CONFIG_STANDALONE_LOAD_ADDR ?= 0x40000
PLATFORM_CPPFLAGS += -fno-strict-aliasing
PLATFORM_CPPFLAGS += -mregparm=3
PLATFORM_CPPFLAGS += -fomit-frame-pointer
PF_CPPFLAGS_X86 := $(call cc-option, -fno-toplevel-reorder, \
$(call cc-option, -fno-unit-at-a-time)) \
$(call cc-option, -mpreferred-stack-boundary=2)
PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_X86)
PLATFORM_CPPFLAGS += -fno-dwarf2-cfi-asm
PLATFORM_CPPFLAGS += -march=i386 -m32
PLATFORM_RELFLAGS += -ffunction-sections -fvisibility=hidden
PLATFORM_LDFLAGS += --emit-relocs -Bsymbolic -Bsymbolic-functions -m elf_i386
PLATFORM_LDFLAGS += -Bsymbolic -Bsymbolic-functions -m elf_i386
LDFLAGS_FINAL += --gc-sections -pie
LDFLAGS_FINAL += --wrap=__divdi3 --wrap=__udivdi3
LDFLAGS_FINAL += --wrap=__moddi3 --wrap=__umoddi3
# This is used in the top-level Makefile which does not include
# PLATFORM_LDFLAGS
LDFLAGS_EFI_PAYLOAD := -Bsymbolic -Bsymbolic-functions -shared --no-undefined
OBJCOPYFLAGS_EFI := -j .text -j .sdata -j .data -j .dynamic -j .dynsym \
-j .rel -j .rela -j .reloc
CFLAGS_NON_EFI := -mregparm=3
CFLAGS_EFI := -fpic -fshort-wchar
ifeq ($(CONFIG_EFI_STUB_64BIT),)
CFLAGS_EFI += $(call cc-option, -mno-red-zone)
EFIARCH = ia32
EFIPAYLOAD_BFDTARGET = elf32-i386
else
EFIARCH = x86_64
EFIPAYLOAD_BFDTARGET = elf64-x86-64
endif
EFIPAYLOAD_BFDARCH = i386
LDSCRIPT_EFI := $(srctree)/$(CPUDIR)/efi/elf_$(EFIARCH)_efi.lds
EFISTUB := crt0-efi-$(EFIARCH).o reloc_$(EFIARCH).o
OBJCOPYFLAGS_EFI += --target=efi-app-$(EFIARCH)
CPPFLAGS_REMOVE_crt0-efi-$(EFIARCH).o += $(CFLAGS_NON_EFI)
CPPFLAGS_crt0-efi-$(EFIARCH).o += $(CFLAGS_EFI)
ifeq ($(CONFIG_EFI_APP),y)
PLATFORM_CPPFLAGS += $(CFLAGS_EFI)
LDFLAGS_FINAL += -znocombreloc -shared
LDSCRIPT := $(LDSCRIPT_EFI)
else
PLATFORM_CPPFLAGS += $(CFLAGS_NON_EFI)
PLATFORM_LDFLAGS += --emit-relocs
LDFLAGS_FINAL += --gc-sections -pie
endif

View File

@ -12,8 +12,15 @@ extra-y = start.o
obj-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o
obj-y += interrupts.o cpu.o cpu_x86.o call64.o
AFLAGS_REMOVE_call32.o := -mregparm=3 \
$(if $(CONFIG_EFI_STUB_64BIT),-march=i386 -m32)
AFLAGS_call32.o := -fpic -fshort-wchar
extra-y += call32.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/

View File

@ -6,4 +6,4 @@
config INTEL_BAYTRAIL
bool
select HAVE_FSP
select HAVE_FSP if !EFI

View File

@ -45,6 +45,8 @@ static void set_max_freq(void)
static int cpu_x86_baytrail_probe(struct udevice *dev)
{
if (!ll_boot_init())
return 0;
debug("Init BayTrail core\n");
/*

View File

@ -7,6 +7,7 @@
#include <common.h>
#include <mmc.h>
#include <pci_ids.h>
#include <asm/irq.h>
#include <asm/post.h>
static struct pci_device_id mmc_supported[] = {
@ -20,6 +21,7 @@ int cpu_mmc_init(bd_t *bis)
ARRAY_SIZE(mmc_supported));
}
#ifndef CONFIG_EFI_APP
int arch_cpu_init(void)
{
int ret;
@ -35,3 +37,11 @@ int arch_cpu_init(void)
return 0;
}
int arch_misc_init(void)
{
pirq_init();
return 0;
}
#endif

64
arch/x86/cpu/call32.S Normal file
View File

@ -0,0 +1,64 @@
/*
* (C) Copyright 2015 Google, Inc
* Written by Simon Glass <sjg@chromium.org>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <asm/global_data.h>
#include <asm/msr-index.h>
#include <asm/processor-flags.h>
/*
* rdi - 32-bit code segment selector
* rsi - target address
* rdx - table address (0 if none)
*/
.code64
.globl cpu_call32
cpu_call32:
cli
/* Save table pointer */
mov %edx, %ebx
/*
* Debugging option, this outputs characters to the console UART
* mov $0x3f8,%edx
* mov $'a',%al
* out %al,(%dx)
*/
pushf
push %rdi /* 32-bit code segment */
lea compat(%rip), %rax
push %rax
.byte 0x48 /* REX prefix to force 64-bit far return */
retf
.code32
compat:
/*
* We are now in compatibility mode with a default operand size of
* 32 bits. First disable paging.
*/
movl %cr0, %eax
andl $~X86_CR0_PG, %eax
movl %eax, %cr0
/* Invalidate TLB */
xorl %eax, %eax
movl %eax, %cr3
/* Disable Long mode in EFER (Extended Feature Enable Register) */
movl $MSR_EFER, %ecx
rdmsr
btr $_EFER_LME, %eax
wrmsr
/* Set up table pointer for _x86boot_start */
mov %ebx, %ecx
/* Jump to the required target */
pushl %edi /* 32-bit code segment */
pushl %esi /* 32-bit target address */
retf

View File

@ -82,8 +82,8 @@ lret_target:
.data
gdt:
.word gdt_end - gdt
.long gdt
.word gdt_end - gdt - 1
.long gdt /* Fixed up by code above */
.word 0
.quad 0x0000000000000000 /* NULL descriptor */
.quad 0x00af9a000000ffff /* __KERNEL_CS */

View File

@ -330,13 +330,15 @@ int x86_cpu_init_f(void)
const u32 em_rst = ~X86_CR0_EM;
const u32 mp_ne_set = X86_CR0_MP | X86_CR0_NE;
/* initialize FPU, reset EM, set MP and NE */
asm ("fninit\n" \
"movl %%cr0, %%eax\n" \
"andl %0, %%eax\n" \
"orl %1, %%eax\n" \
"movl %%eax, %%cr0\n" \
: : "i" (em_rst), "i" (mp_ne_set) : "eax");
if (ll_boot_init()) {
/* initialize FPU, reset EM, set MP and NE */
asm ("fninit\n" \
"movl %%cr0, %%eax\n" \
"andl %0, %%eax\n" \
"orl %1, %%eax\n" \
"movl %%eax, %%cr0\n" \
: : "i" (em_rst), "i" (mp_ne_set) : "eax");
}
/* identify CPU via cpuid and store the decoded info into gd->arch */
if (has_cpuid()) {
@ -456,7 +458,7 @@ void x86_full_reset(void)
int dcache_status(void)
{
return !(read_cr0() & 0x40000000);
return !(read_cr0() & X86_CR0_CD);
}
/* Define these functions to allow ehch-hcd to function */
@ -712,5 +714,8 @@ __weak int x86_init_cpus(void)
int cpu_init_r(void)
{
return x86_init_cpus();
if (ll_boot_init())
return x86_init_cpus();
return 0;
}

View File

@ -0,0 +1,8 @@
#
# Copyright (c) 2015 Google, Inc
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += efi.o
obj-y += sdram.o

42
arch/x86/cpu/efi/efi.c Normal file
View File

@ -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;
}

View File

@ -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) }
}

View File

@ -0,0 +1,83 @@
/*
* U-Boot EFI linker script
*
* SPDX-License-Identifier: BSD-2-Clause
*
* Modified from usr/lib32/elf_x86_64_efi.lds in gnu-efi
*/
#include <config.h>
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(_start)
SECTIONS
{
image_base = .;
.hash : { *(.hash) } /* this MUST come first, EFI expects it */
. = ALIGN(4096);
.eh_frame : {
*(.eh_frame)
}
. = ALIGN(4096);
.text : {
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
}
. = ALIGN(4096);
.reloc : {
*(.reloc)
}
. = ALIGN(4096);
.data : {
*(.rodata*)
*(.got.plt)
*(.got)
*(.data*)
*(.sdata)
/* the EFI loader doesn't seem to like a .bss section, so we stick
* it all into .data: */
*(.sbss)
*(.scommon)
*(.dynbss)
*(.bss)
*(COMMON)
*(.rel.local)
/* U-Boot lists and device tree */
. = ALIGN(8);
*(SORT(.u_boot_list*));
. = ALIGN(8);
*(.dtb*);
}
. = ALIGN(4096);
.dynamic : { *(.dynamic) }
. = ALIGN(4096);
.rela : {
*(.rela.data*)
*(.rela.got)
*(.rela.stab)
}
. = ALIGN(4096);
.dynsym : { *(.dynsym) }
. = ALIGN(4096);
.dynstr : { *(.dynstr) }
. = ALIGN(4096);
.ignored.reloc : {
*(.rela.reloc)
*(.eh_frame)
*(.note.GNU-stack)
}
.comment 0 : { *(.comment) }
}

29
arch/x86/cpu/efi/sdram.c Normal file
View File

@ -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;
}

View File

@ -19,6 +19,7 @@
#include <asm/processor-flags.h>
#include <linux/compiler.h>
#include <asm/msr.h>
#include <asm/processor.h>
#include <asm/u-boot-x86.h>
#include <asm/i8259.h>
@ -46,7 +47,7 @@ static char *exceptions[] = {
"Invalid TSS",
"Segment Not Present",
"Stack Segment Fault",
"Gerneral Protection",
"General Protection",
"Page Fault",
"Reserved",
"x87 FPU Floating-Point Error",
@ -165,7 +166,6 @@ struct idt_entry {
struct desc_ptr {
unsigned short size;
unsigned long address;
unsigned short segment;
} __packed;
struct idt_entry idt[256] __aligned(16);
@ -202,14 +202,13 @@ int cpu_init_interrupts(void)
for (i = 0; i < 256; i++) {
idt[i].access = 0x8e;
idt[i].res = 0;
idt[i].selector = 0x10;
idt[i].selector = X86_GDT_ENTRY_32BIT_CS * X86_GDT_ENTRY_SIZE;
set_vector(i, irq_entry);
irq_entry += irq_entry_size;
}
idt_ptr.size = 256 * 8;
idt_ptr.size = 256 * 8 - 1;
idt_ptr.address = (unsigned long) idt;
idt_ptr.segment = 0x18;
load_idt(&idt_ptr);
@ -243,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();
@ -254,8 +258,15 @@ int interrupt_init(void)
/* Initialize core interrupt and exception functionality of CPU */
cpu_init_interrupts();
/* It is now safe to enable interrupts */
enable_interrupts();
/*
* It is now safe to enable interrupts.
*
* TODO(sjg@chromium.org): But we don't handle these correctly when
* booted from EFI.
*/
if (ll_boot_init())
enable_interrupts();
#endif
return 0;
}

View File

@ -24,6 +24,8 @@
#include <dm/uclass-internal.h>
#include <linux/linkage.h>
DECLARE_GLOBAL_DATA_PTR;
/* Total CPUs include BSP */
static int num_cpus;

View File

@ -4,5 +4,8 @@
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += car.o dram.o qemu.o
ifndef CONFIG_EFI_STUB
obj-y += car.o dram.o
endif
obj-y += qemu.o
obj-$(CONFIG_PCI) += pci.o

View File

@ -25,11 +25,13 @@ int arch_cpu_init(void)
return 0;
}
#ifndef CONFIG_EFI_STUB
int print_cpuinfo(void)
{
post_code(POST_CPU_INFO);
return default_print_cpuinfo();
}
#endif
void reset_cpu(ulong addr)
{

View File

@ -25,11 +25,11 @@
.globl _x86boot_start
_x86boot_start:
/*
* This is the fail safe 32-bit bootstrap entry point. The
* following code is not executed from a cold-reset (actually, a
* lot of it is, but from real-mode after cold reset. It is
* repeated here to put the board into a state as close to cold
* reset as necessary)
* This is the fail-safe 32-bit bootstrap entry point.
*
* This code is used when booting from another boot loader like
* coreboot or EFI. So we repeat some of the same init found in
* start16.
*/
cli
cld
@ -41,19 +41,34 @@ _x86boot_start:
wbinvd
/* Tell 32-bit code it is being entered from an in-RAM copy */
movw $GD_FLG_WARM_BOOT, %bx
movl $GD_FLG_WARM_BOOT, %ebx
/*
* Zero the BIST (Built-In Self Test) value since we don't have it.
* It must be 0 or the previous loader would have reported an error.
*/
movl $0, %ebp
jmp 1f
/* Add a way for tools to discover the _start entry point */
.align 4
.long 0x12345678
_start:
/*
* This is the 32-bit cold-reset entry point. Initialize %bx to 0
* in case we're preceeded by some sort of boot stub.
* This is the 32-bit cold-reset entry point, coming from start16.
* Set %ebx to GD_FLG_COLD_BOOT to indicate this.
*/
movw $GD_FLG_COLD_BOOT, %bx
1:
movl $GD_FLG_COLD_BOOT, %ebx
/* Save BIST */
movl %eax, %ebp
1:
/* Load the segement registes to match the gdt loaded in start16.S */
/* Save table pointer */
movl %ecx, %esi
/* Load the segement registers to match the GDT loaded in start16.S */
movl $(X86_GDT_ENTRY_32BIT_DS * X86_GDT_ENTRY_SIZE), %eax
movw %ax, %fs
movw %ax, %ds
@ -64,7 +79,11 @@ _start:
/* Clear the interrupt vectors */
lidt blank_idt_ptr
/* Early platform init (setup gpio, etc ) */
/*
* Critical early platform init - generally not used, we prefer init
* to happen later when we have a console, in case something goes
* wrong.
*/
jmp early_board_init
.globl early_board_init_ret
early_board_init_ret:
@ -79,7 +98,7 @@ car_init_ret:
* We now have CONFIG_SYS_CAR_SIZE bytes of Cache-As-RAM (or SRAM,
* or fully initialised SDRAM - we really don't care which)
* starting at CONFIG_SYS_CAR_ADDR to be used as a temporary stack
* and early malloc area. The MRC requires some space at the top.
* and early malloc() area. The MRC requires some space at the top.
*
* Stack grows down from top of CAR. We have:
*
@ -97,7 +116,7 @@ car_init_ret:
#endif
#else
/*
* When we get here after car_init, esp points to a temporary stack
* When we get here after car_init(), esp points to a temporary stack
* and esi holds the HOB list address returned by the FSP.
*/
#endif
@ -125,7 +144,13 @@ car_init_ret:
movl %esi, (%edx)
skip_hob:
#else
/* Store table pointer */
movl %esp, %edx
addl $GD_TABLE, %edx
movl %esi, (%edx)
#endif
/* Setup first parameter to setup_gdt, pointer to global_data */
movl %esp, %eax
@ -137,17 +162,18 @@ skip_hob:
movl %esp, %ecx
#if defined(CONFIG_SYS_MALLOC_F_LEN)
/* Set up the pre-relocation malloc pool */
subl $CONFIG_SYS_MALLOC_F_LEN, %esp
movl %eax, %edx
addl $GD_MALLOC_BASE, %edx
movl %esp, (%edx)
#endif
/* Store BIST */
/* Store BIST into global_data */
movl %eax, %edx
addl $GD_BIST, %edx
movl %ebp, (%edx)
/* Set second parameter to setup_gdt */
/* Set second parameter to setup_gdt() */
movl %ecx, %edx
/* Setup global descriptor table so gd->xyz works */
@ -157,7 +183,7 @@ skip_hob:
post_code(POST_START_DONE)
xorl %eax, %eax
/* Enter, U-boot! */
/* Enter, U-Boot! */
call board_init_f
/* indicate (lack of) progress */
@ -184,13 +210,13 @@ board_init_f_r_trampoline:
/* Align global data to 16-byte boundary */
andl $0xfffffff0, %esp
/* Setup first parameter to memcpy (and setup_gdt) */
/* Setup first parameter to memcpy() and setup_gdt() */
movl %esp, %eax
/* Setup second parameter to memcpy */
/* Setup second parameter to memcpy() */
fs movl 0, %edx
/* Set third parameter to memcpy */
/* Set third parameter to memcpy() */
movl $GENERATED_GBL_DATA_SIZE, %ecx
/* Copy global data from CAR to SDRAM stack */
@ -202,7 +228,7 @@ board_init_f_r_trampoline:
/* Align global descriptor table to 16-byte boundary */
andl $0xfffffff0, %esp
/* Set second parameter to setup_gdt */
/* Set second parameter to setup_gdt() */
movl %esp, %edx
/* Setup global descriptor table so gd->xyz works */
@ -216,7 +242,7 @@ board_init_f_r_trampoline:
call car_uninit
1:
/* Re-enter U-Boot by calling board_init_f_r */
/* Re-enter U-Boot by calling board_init_f_r() */
call board_init_f_r
die:
@ -230,9 +256,10 @@ blank_idt_ptr:
.p2align 2 /* force 4-byte alignment */
/* Add a multiboot header so U-Boot can be loaded by GRUB2 */
multiboot_header:
/* magic */
.long 0x1BADB002
.long 0x1badb002
/* flags */
.long (1 << 16)
/* checksum */

View File

@ -1,6 +1,8 @@
dtb-y += chromebook_link.dtb \
dtb-y += bayleybay.dtb \
chromebook_link.dtb \
chromebox_panther.dtb \
crownbay.dtb \
efi.dtb \
galileo.dtb \
minnowmax.dtb \
qemu-x86_i440fx.dtb \

197
arch/x86/dts/bayleybay.dts Normal file
View File

@ -0,0 +1,197 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
/dts-v1/;
#include <dt-bindings/gpio/x86-gpio.h>
#include <dt-bindings/interrupt-router/intel-irq.h>
/include/ "skeleton.dtsi"
/include/ "serial.dtsi"
/include/ "rtc.dtsi"
/ {
model = "Intel Bayley Bay";
compatible = "intel,bayleybay", "intel,baytrail";
aliases {
serial0 = &serial;
spi0 = "/spi";
};
config {
silent_console = <0>;
};
chosen {
stdout-path = "/serial";
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
device_type = "cpu";
compatible = "intel,baytrail-cpu";
reg = <0>;
intel,apic-id = <0>;
};
cpu@1 {
device_type = "cpu";
compatible = "intel,baytrail-cpu";
reg = <1>;
intel,apic-id = <2>;
};
cpu@2 {
device_type = "cpu";
compatible = "intel,baytrail-cpu";
reg = <2>;
intel,apic-id = <4>;
};
cpu@3 {
device_type = "cpu";
compatible = "intel,baytrail-cpu";
reg = <3>;
intel,apic-id = <6>;
};
};
spi {
#address-cells = <1>;
#size-cells = <0>;
compatible = "intel,ich-spi";
spi-flash@0 {
reg = <0>;
compatible = "winbond,w25q64dw", "spi-flash";
memory-map = <0xff800000 0x00800000>;
};
};
gpioa {
compatible = "intel,ich6-gpio";
u-boot,dm-pre-reloc;
reg = <0 0x20>;
bank-name = "A";
};
gpiob {
compatible = "intel,ich6-gpio";
u-boot,dm-pre-reloc;
reg = <0x20 0x20>;
bank-name = "B";
};
gpioc {
compatible = "intel,ich6-gpio";
u-boot,dm-pre-reloc;
reg = <0x40 0x20>;
bank-name = "C";
};
gpiod {
compatible = "intel,ich6-gpio";
u-boot,dm-pre-reloc;
reg = <0x60 0x20>;
bank-name = "D";
};
gpioe {
compatible = "intel,ich6-gpio";
u-boot,dm-pre-reloc;
reg = <0x80 0x20>;
bank-name = "E";
};
gpiof {
compatible = "intel,ich6-gpio";
u-boot,dm-pre-reloc;
reg = <0xA0 0x20>;
bank-name = "F";
};
pci {
compatible = "pci-x86";
#address-cells = <3>;
#size-cells = <2>;
u-boot,dm-pre-reloc;
ranges = <0x02000000 0x0 0x80000000 0x80000000 0 0x40000000
0x42000000 0x0 0xc0000000 0xc0000000 0 0x20000000
0x01000000 0x0 0x2000 0x2000 0 0xe000>;
irq-router@1f,0 {
reg = <0x0000f800 0 0 0 0>;
compatible = "intel,irq-router";
intel,pirq-config = "ibase";
intel,ibase-offset = <0x50>;
intel,pirq-link = <8 8>;
intel,pirq-mask = <0xdee0>;
intel,pirq-routing = <
/* BayTrail PCI devices */
PCI_BDF(0, 2, 0) INTA PIRQA
PCI_BDF(0, 3, 0) INTA PIRQA
PCI_BDF(0, 16, 0) INTA PIRQA
PCI_BDF(0, 17, 0) INTA PIRQA
PCI_BDF(0, 18, 0) INTA PIRQA
PCI_BDF(0, 19, 0) INTA PIRQA
PCI_BDF(0, 20, 0) INTA PIRQA
PCI_BDF(0, 21, 0) INTA PIRQA
PCI_BDF(0, 22, 0) INTA PIRQA
PCI_BDF(0, 23, 0) INTA PIRQA
PCI_BDF(0, 24, 0) INTA PIRQA
PCI_BDF(0, 24, 1) INTC PIRQC
PCI_BDF(0, 24, 2) INTD PIRQD
PCI_BDF(0, 24, 3) INTB PIRQB
PCI_BDF(0, 24, 4) INTA PIRQA
PCI_BDF(0, 24, 5) INTC PIRQC
PCI_BDF(0, 24, 6) INTD PIRQD
PCI_BDF(0, 24, 7) INTB PIRQB
PCI_BDF(0, 26, 0) INTA PIRQA
PCI_BDF(0, 27, 0) INTA PIRQA
PCI_BDF(0, 28, 0) INTA PIRQA
PCI_BDF(0, 28, 1) INTB PIRQB
PCI_BDF(0, 28, 2) INTC PIRQC
PCI_BDF(0, 28, 3) INTD PIRQD
PCI_BDF(0, 29, 0) INTA PIRQA
PCI_BDF(0, 30, 0) INTA PIRQA
PCI_BDF(0, 30, 1) INTD PIRQD
PCI_BDF(0, 30, 2) INTB PIRQB
PCI_BDF(0, 30, 3) INTC PIRQC
PCI_BDF(0, 30, 4) INTD PIRQD
PCI_BDF(0, 30, 5) INTB PIRQB
PCI_BDF(0, 31, 3) INTB PIRQB
/* PCIe root ports downstream interrupts */
PCI_BDF(1, 0, 0) INTA PIRQA
PCI_BDF(1, 0, 0) INTB PIRQB
PCI_BDF(1, 0, 0) INTC PIRQC
PCI_BDF(1, 0, 0) INTD PIRQD
PCI_BDF(2, 0, 0) INTA PIRQB
PCI_BDF(2, 0, 0) INTB PIRQC
PCI_BDF(2, 0, 0) INTC PIRQD
PCI_BDF(2, 0, 0) INTD PIRQA
PCI_BDF(3, 0, 0) INTA PIRQC
PCI_BDF(3, 0, 0) INTB PIRQD
PCI_BDF(3, 0, 0) INTC PIRQA
PCI_BDF(3, 0, 0) INTD PIRQB
PCI_BDF(4, 0, 0) INTA PIRQD
PCI_BDF(4, 0, 0) INTB PIRQA
PCI_BDF(4, 0, 0) INTC PIRQB
PCI_BDF(4, 0, 0) INTD PIRQC
>;
};
};
microcode {
update@0 {
#include "microcode/m0230671117.dtsi"
};
};
};

22
arch/x86/dts/efi.dts Normal file
View File

@ -0,0 +1,22 @@
/*
* Copyright (c) 2015 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
/dts-v1/;
/include/ "skeleton.dtsi"
/ {
model = "EFI";
compatible = "efi,app";
chosen {
stdout-path = &serial;
};
serial: serial {
compatible = "efi,uart";
};
};

File diff suppressed because it is too large Load Diff

View File

@ -34,6 +34,13 @@
reg = <0>;
intel,apic-id = <0>;
};
cpu@1 {
device_type = "cpu";
compatible = "cpu-x86";
reg = <1>;
intel,apic-id = <1>;
};
};
pci {

View File

@ -45,6 +45,13 @@
reg = <0>;
intel,apic-id = <0>;
};
cpu@1 {
device_type = "cpu";
compatible = "cpu-x86";
reg = <1>;
intel,apic-id = <1>;
};
};
pci {

View File

@ -75,7 +75,8 @@ struct __packed upd_region {
uint8_t emmc45_ddr50_enabled; /* Offset 0x0051 */
uint8_t emmc45_hs200_enabled; /* Offset 0x0052 */
uint8_t emmc45_retune_timer_value; /* Offset 0x0053 */
uint8_t unused_upd_space1[156]; /* Offset 0x0054 */
uint8_t enable_igd; /* Offset 0x0054 */
uint8_t unused_upd_space1[155]; /* Offset 0x0055 */
struct memory_down_data memory_params; /* Offset 0x00f0 */
uint16_t terminator; /* Offset 0x0100 */
};

View File

@ -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_ */

View File

@ -27,6 +27,24 @@ enum {
X86_VENDOR_UNKNOWN = 0xff
};
/* Global descriptor table (GDT) bits */
enum {
GDT_4KB = 1ULL << 55,
GDT_32BIT = 1ULL << 54,
GDT_LONG = 1ULL << 53,
GDT_PRESENT = 1ULL << 47,
GDT_NOTSYS = 1ULL << 44,
GDT_CODE = 1ULL << 43,
GDT_LIMIT_LOW_SHIFT = 0,
GDT_LIMIT_LOW_MASK = 0xffff,
GDT_LIMIT_HIGH_SHIFT = 48,
GDT_LIMIT_HIGH_MASK = 0xf,
GDT_BASE_LOW_SHIFT = 16,
GDT_BASE_LOW_MASK = 0xffff,
GDT_BASE_HIGH_SHIFT = 56,
GDT_BASE_HIGH_MASK = 0xf,
};
struct cpuid_result {
uint32_t eax;
uint32_t ebx;
@ -211,6 +229,15 @@ char *cpu_get_name(char *name);
*/
void cpu_call64(ulong pgtable, ulong setup_base, ulong target);
/**
* cpu_call32() - Jump to a 32-bit entry point
*
* @code_seg32: 32-bit code segment to use (GDT offset, e.g. 0x20)
* @target: Pointer to the start of the 32-bit U-Boot image/entry point
* @table: Pointer to start of info table to pass to U-Boot
*/
void cpu_call32(ulong code_seg32, ulong target, ulong table);
/**
* cpu_jump_to_64bit() - Jump to a 64-bit Linux kernel
*

View File

@ -0,0 +1,46 @@
/*
* Brought in from Linux 4.1, removed things not useful to U-Boot.
* The definitions perhaps came from the GNU Library which is GPL.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _ASM_X86_ELF_H
#define _ASM_X86_ELF_H
/* ELF register definitions */
#define R_386_NONE 0
#define R_386_32 1
#define R_386_PC32 2
#define R_386_GOT32 3
#define R_386_PLT32 4
#define R_386_COPY 5
#define R_386_GLOB_DAT 6
#define R_386_JMP_SLOT 7
#define R_386_RELATIVE 8
#define R_386_GOTOFF 9
#define R_386_GOTPC 10
#define R_386_NUM 11
/* x86-64 relocation types */
#define R_X86_64_NONE 0 /* No reloc */
#define R_X86_64_64 1 /* Direct 64 bit */
#define R_X86_64_PC32 2 /* PC relative 32 bit signed */
#define R_X86_64_GOT32 3 /* 32 bit GOT entry */
#define R_X86_64_PLT32 4 /* 32 bit PLT address */
#define R_X86_64_COPY 5 /* Copy symbol at runtime */
#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */
#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */
#define R_X86_64_RELATIVE 8 /* Adjust by program base */
/* 32 bit signed pc relative offset to GOT */
#define R_X86_64_GOTPCREL 9
#define R_X86_64_32 10 /* Direct 32 bit zero extended */
#define R_X86_64_32S 11 /* Direct 32 bit sign extended */
#define R_X86_64_16 12 /* Direct 16 bit zero extended */
#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */
#define R_X86_64_8 14 /* Direct 8 bit sign extended */
#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */
#define R_X86_64_NUM 16
#endif

View File

@ -8,6 +8,8 @@
#ifndef __FSP_HOB_H__
#define __FSP_HOB_H__
#include <efi.h>
/* Type of HOB Header */
#define HOB_TYPE_MEM_ALLOC 0x0002
#define HOB_TYPE_RES_DESC 0x0003
@ -25,63 +27,6 @@ struct hob_header {
u32 reserved; /* always zero */
};
/* Enumeration of memory types introduced in UEFI */
enum efi_mem_type {
EFI_RESERVED_MEMORY_TYPE,
/*
* The code portions of a loaded application.
* (Note that UEFI OS loaders are UEFI applications.)
*/
EFI_LOADER_CODE,
/*
* The data portions of a loaded application and
* the default data allocation type used by an application
* to allocate pool memory.
*/
EFI_LOADER_DATA,
/* The code portions of a loaded Boot Services Driver */
EFI_BOOT_SERVICES_CODE,
/*
* The data portions of a loaded Boot Serves Driver and
* the default data allocation type used by a Boot Services
* Driver to allocate pool memory.
*/
EFI_BOOT_SERVICES_DATA,
/* The code portions of a loaded Runtime Services Driver */
EFI_RUNTIME_SERVICES_CODE,
/*
* The data portions of a loaded Runtime Services Driver and
* the default data allocation type used by a Runtime Services
* Driver to allocate pool memory.
*/
EFI_RUNTIME_SERVICES_DATA,
/* Free (unallocated) memory */
EFI_CONVENTIONAL_MEMORY,
/* Memory in which errors have been detected */
EFI_UNUSABLE_MEMORY,
/* Memory that holds the ACPI tables */
EFI_ACPI_RECLAIM_MEMORY,
/* Address space reserved for use by the firmware */
EFI_ACPI_MEMORY_NVS,
/*
* Used by system firmware to request that a memory-mapped IO region
* be mapped by the OS to a virtual address so it can be accessed by
* EFI runtime services.
*/
EFI_MMAP_IO,
/*
* System memory-mapped IO region that is used to translate
* memory cycles to IO cycles by the processor.
*/
EFI_MMAP_IO_PORT,
/*
* Address space reserved by the firmware for code that is
* part of the processor.
*/
EFI_PAL_CODE,
EFI_MAX_MEMORY_TYPE
};
/*
* Describes all memory ranges used during the HOB producer phase that
* exist outside the HOB list. This HOB type describes how memory is used,

View File

@ -69,6 +69,7 @@ struct arch_global_data {
char *mrc_output;
unsigned int mrc_output_len;
void *gdt; /* Global descriptor table */
ulong table; /* Table pointer from previous loader */
};
#endif
@ -76,6 +77,12 @@ struct arch_global_data {
#include <asm-generic/global_data.h>
#ifndef __ASSEMBLY__
# ifdef CONFIG_EFI_APP
#define gd global_data_ptr
#define DECLARE_GLOBAL_DATA_PTR extern struct global_data *global_data_ptr
# else
static inline __attribute__((no_instrument_function)) gd_t *get_fs_gd_ptr(void)
{
gd_t *gd_ptr;
@ -87,14 +94,15 @@ static inline __attribute__((no_instrument_function)) gd_t *get_fs_gd_ptr(void)
#define gd get_fs_gd_ptr()
#define DECLARE_GLOBAL_DATA_PTR
# endif
#endif
/*
* Our private Global Data Flags
*/
#define GD_FLG_COLD_BOOT 0x00100 /* Cold Boot */
#define GD_FLG_WARM_BOOT 0x00200 /* Warm Boot */
#define DECLARE_GLOBAL_DATA_PTR
#define GD_FLG_COLD_BOOT 0x10000 /* Cold Boot */
#define GD_FLG_WARM_BOOT 0x20000 /* Warm Boot */
#endif /* __ASM_GBL_DATA_H */

View File

@ -11,7 +11,6 @@
#include <common.h>
int copy_uboot_to_ram(void);
int copy_fdt_to_ram(void);
int clear_bss(void);
int do_elf_reloc_fixups(void);

View File

@ -44,8 +44,11 @@ typedef __INT64_TYPE__ s64;
typedef __UINT64_TYPE__ u64;
#endif
#ifdef CONFIG_EFI_STUB_64BIT
#define BITS_PER_LONG 64
#else
#define BITS_PER_LONG 32
#endif
/* Dma addresses are 32-bits wide. */
typedef u32 dma_addr_t;

View File

@ -11,6 +11,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) += efi/
obj-y += gcc.o
obj-y += init_helpers.o
obj-y += interrupts.o
@ -34,7 +35,7 @@ obj-$(CONFIG_SYS_X86_TSC_TIMER) += tsc_timer.o
obj-$(CONFIG_CMD_ZBOOT) += zimage.o
obj-$(CONFIG_HAVE_FSP) += fsp/
extra-$(CONFIG_USE_PRIVATE_LIBGCC) := lib.a
extra-$(CONFIG_USE_PRIVATE_LIBGCC) += lib.a
NORMAL_LIBGCC = $(shell $(CC) $(PLATFORM_CPPFLAGS) -print-libgcc-file-name)
OBJCOPYFLAGS := --prefix-symbols=__normal_

View File

@ -21,5 +21,6 @@ int main(void)
#ifdef CONFIG_HAVE_FSP
DEFINE(GD_HOB_LIST, offsetof(gd_t, arch.hob_list));
#endif
DEFINE(GD_TABLE, offsetof(gd_t, arch.table));
return 0;
}

View File

@ -22,6 +22,8 @@
#include <asm/arch/timestamp.h>
#endif
DECLARE_GLOBAL_DATA_PTR;
#define COMMAND_LINE_OFFSET 0x9000
/*
@ -162,7 +164,11 @@ int boot_linux_kernel(ulong setup_base, ulong load_address, bool image_64bit)
* the data segments are 0x18, 4GB flat, and read/write.
* U-boot is setting them up that way for itself in
* arch/i386/cpu/cpu.c.
*
* Note that we cannot currently boot a kernel while running as
* an EFI application. Please use the payload option for that.
*/
#ifndef CONFIG_EFI_APP
__asm__ __volatile__ (
"movl $0, %%ebp\n"
"cli\n"
@ -171,6 +177,7 @@ int boot_linux_kernel(ulong setup_base, ulong load_address, bool image_64bit)
[boot_params] "S"(setup_base),
"b"(0), "D"(0)
);
#endif
}
/* We can't get to here */

11
arch/x86/lib/efi/Kconfig Normal file
View File

@ -0,0 +1,11 @@
if EFI
config SYS_CAR_ADDR
hex
default 0x100000
config SYS_CAR_SIZE
hex
default 0x20000
endif

27
arch/x86/lib/efi/Makefile Normal file
View File

@ -0,0 +1,27 @@
#
# (C) Copyright 2002-2006
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-$(CONFIG_EFI_STUB) += car.o
obj-$(CONFIG_EFI_STUB) += efi.o
obj-$(CONFIG_EFI_APP) += crt0-efi-ia32.o reloc_ia32.o
ifneq ($(CONFIG_EFI_STUB),)
CFLAGS_REMOVE_reloc_ia32.o += -mregparm=3
CFLAGS_reloc_ia32.o += -fpic -fshort-wchar
# When building for 64-bit we must remove the i386-specific flags
CFLAGS_REMOVE_reloc_x86_64.o += -mregparm=3 -march=i386 -m32
CFLAGS_reloc_x86_64.o += -fpic -fshort-wchar
AFLAGS_REMOVE_crt0-efi-x86_64.o += -mregparm=3 -march=i386 -m32
AFLAGS_crt0-efi-x86_64.o += -fpic -fshort-wchar
extra-$(CONFIG_EFI_STUB_32BIT) += crt0-efi-ia32.o reloc_ia32.o
extra-$(CONFIG_EFI_STUB_64BIT) += crt0-efi-x86_64.o reloc_x86_64.o
endif

10
arch/x86/lib/efi/car.S Normal file
View File

@ -0,0 +1,10 @@
/*
* Copyright (c) 2015 Google, Inc
* Written by Simon Glass <sjg@chromium.org>
*
* SPDX-License-Identifier: GPL-2.0+
*/
.globl car_init
car_init:
jmp car_init_ret

View File

@ -0,0 +1,52 @@
/*
* crt0-efi-ia32.S - x86 EFI startup code.
*
* Copyright (C) 1999 Hewlett-Packard Co.
* Contributed by David Mosberger <davidm@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 */

View File

@ -0,0 +1,51 @@
/*
* crt0-efi-x86_64.S - x86_64 EFI startup code.
* Copyright (C) 1999 Hewlett-Packard Co.
* Contributed by David Mosberger <davidm@hpl.hp.com>.
* Copyright (C) 2005 Intel Co.
* Contributed by Fenghua Yu <fenghua.yu@intel.com>.
*
* All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
*/
.text
.align 4
.globl _start
_start:
subq $8, %rsp
pushq %rcx
pushq %rdx
0:
lea image_base(%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 */

151
arch/x86/lib/efi/efi.c Normal file
View File

@ -0,0 +1,151 @@
/*
* Copyright (c) 2015 Google, Inc
* Written by Simon Glass <sjg@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;
}

View File

@ -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@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;
}

View File

@ -0,0 +1,66 @@
/*
* reloc_x86_64.c - position independent x86_64 ELF shared object relocator
* Copyright (C) 1999 Hewlett-Packard Co.
* Contributed by David Mosberger <davidm@hpl.hp.com>.
* Copyright (C) 2005 Intel Co.
* Contributed by Fenghua Yu <fenghua.yu@intel.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, Elf64_Dyn *dyn, efi_handle_t image,
struct efi_system_table *systab)
{
long relsz = 0, relent = 0;
Elf64_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_RELA:
rel = (Elf64_Rel *)
((unsigned long)dyn[i].d_un.d_ptr + ldbase);
break;
case DT_RELASZ:
relsz = dyn[i].d_un.d_val;
break;
case DT_RELAENT:
relent = dyn[i].d_un.d_val;
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 (ELF64_R_TYPE(rel->r_info)) {
case R_X86_64_NONE:
break;
case R_X86_64_RELATIVE:
addr = (unsigned long *)(ldbase + rel->r_offset);
*addr += ldbase;
break;
default:
break;
}
rel = (Elf64_Rel *)((char *)rel + relent);
relsz -= relent;
}
return EFI_SUCCESS;
}

View File

@ -11,6 +11,8 @@
#include <asm/processor.h>
#include <asm/fsp/fsp_support.h>
DECLARE_GLOBAL_DATA_PTR;
int print_cpuinfo(void)
{
post_code(POST_CPU_INFO);

View File

@ -9,6 +9,8 @@
#include <dm.h>
#include <dm/root.h>
DECLARE_GLOBAL_DATA_PTR;
static int lpc_uclass_post_bind(struct udevice *bus)
{
/*

View File

@ -9,6 +9,8 @@
#include <dm.h>
#include <dm/root.h>
DECLARE_GLOBAL_DATA_PTR;
static int pch_uclass_post_bind(struct udevice *bus)
{
/*

View File

@ -17,8 +17,6 @@
#include <common.h>
#include <inttypes.h>
#include <libfdt.h>
#include <malloc.h>
#include <asm/u-boot-x86.h>
#include <asm/relocate.h>
#include <asm/sections.h>
@ -30,32 +28,20 @@ int copy_uboot_to_ram(void)
{
size_t len = (size_t)&__data_end - (size_t)&__text_start;
if (gd->flags & GD_FLG_SKIP_RELOC)
return 0;
memcpy((void *)gd->relocaddr, (void *)&__text_start, len);
return 0;
}
int copy_fdt_to_ram(void)
{
if (gd->new_fdt) {
ulong fdt_size;
fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob) + 0x1000, 32);
memcpy(gd->new_fdt, gd->fdt_blob, fdt_size);
debug("Relocated fdt from %p to %p, size %lx\n",
gd->fdt_blob, gd->new_fdt, fdt_size);
gd->fdt_blob = gd->new_fdt;
}
return 0;
}
int clear_bss(void)
{
ulong dst_addr = (ulong)&__bss_start + gd->reloc_off;
size_t len = (size_t)&__bss_end - (size_t)&__bss_start;
if (gd->flags & GD_FLG_SKIP_RELOC)
return 0;
memset((void *)dst_addr, 0x00, len);
return 0;
@ -72,36 +58,43 @@ int do_elf_reloc_fixups(void)
Elf32_Addr *offset_ptr_rom, *last_offset = NULL;
Elf32_Addr *offset_ptr_ram;
unsigned int text_base = 0;
/* The size of the region of u-boot that runs out of RAM. */
uintptr_t size = (uintptr_t)&__bss_end - (uintptr_t)&__text_start;
if (gd->flags & GD_FLG_SKIP_RELOC)
return 0;
if (re_src == re_end)
panic("No relocation data");
#ifdef CONFIG_SYS_TEXT_BASE
text_base = CONFIG_SYS_TEXT_BASE;
#else
panic("No CONFIG_SYS_TEXT_BASE");
#endif
do {
/* Get the location from the relocation entry */
offset_ptr_rom = (Elf32_Addr *)re_src->r_offset;
/* Check that the location of the relocation is in .text */
if (offset_ptr_rom >= (Elf32_Addr *)CONFIG_SYS_TEXT_BASE &&
offset_ptr_rom > last_offset) {
if (offset_ptr_rom >= (Elf32_Addr *)text_base &&
offset_ptr_rom > last_offset) {
/* Switch to the in-RAM version */
offset_ptr_ram = (Elf32_Addr *)((ulong)offset_ptr_rom +
gd->reloc_off);
/* Check that the target points into .text */
if (*offset_ptr_ram >= CONFIG_SYS_TEXT_BASE &&
*offset_ptr_ram <=
(CONFIG_SYS_TEXT_BASE + size)) {
if (*offset_ptr_ram >= text_base &&
*offset_ptr_ram <= text_base + size) {
*offset_ptr_ram += gd->reloc_off;
} else {
debug(" %p: rom reloc %x, ram %p, value %x,"
" limit %" PRIXPTR "\n", re_src,
re_src->r_offset, offset_ptr_ram,
*offset_ptr_ram,
CONFIG_SYS_TEXT_BASE + size);
text_base + size);
}
} else {
debug(" %p: rom reloc %x, last %p\n", re_src,

View File

@ -355,7 +355,15 @@ void __udelay(unsigned long usec)
stop = now + usec * get_tbclk_mhz();
while ((int64_t)(stop - get_ticks()) > 0)
#if defined(CONFIG_QEMU) && defined(CONFIG_SMP)
/*
* Add a 'pause' instruction on qemu target,
* to give other VCPUs a chance to run.
*/
asm volatile("pause");
#else
;
#endif
}
int timer_init(void)

19
board/efi/Kconfig Normal file
View File

@ -0,0 +1,19 @@
if VENDOR_EFI
choice
prompt "Mainboard model"
optional
config TARGET_EFI
bool "efi"
help
This target is used for running U-Boot on top of EFI. In
this case EFI does the early initialisation, and U-Boot
takes over once the RAM, video and CPU are fully running.
U-Boot is loaded as an application from EFI.
endchoice
source "board/efi/efi-x86/Kconfig"
endif

15
board/efi/efi-x86/Kconfig Normal file
View File

@ -0,0 +1,15 @@
if TARGET_EFI
config SYS_BOARD
default "efi-x86"
config SYS_VENDOR
default "efi"
config SYS_SOC
default "efi"
config SYS_CONFIG_NAME
default "efi-x86"
endif

View File

@ -0,0 +1,6 @@
EFI-X86 BOARD
M: Simon Glass <sjg@chromium.org>
S: Maintained
F: board/efi/efi-x86/
F: include/configs/efi-x86.h
F: configs/efi-x86_defconfig

View File

@ -0,0 +1,7 @@
#
# Copyright (c) 2015 Google, Inc
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += efi.o

18
board/efi/efi-x86/efi.c Normal file
View File

@ -0,0 +1,18 @@
/*
* Copyright (C) 2015 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/gpio.h>
int arch_early_init_r(void)
{
return 0;
}
void setup_pch_gpios(u16 gpiobase, const struct pch_gpio_map *gpio)
{
return;
}

View File

@ -13,11 +13,12 @@ config SYS_CONFIG_NAME
default "qemu-x86"
config SYS_TEXT_BASE
default 0xfff00000
default 0xfff00000 if !EFI_STUB
default 0x01110000 if EFI_STUB
config BOARD_SPECIFIC_OPTIONS # dummy
def_bool y
select X86_RESET_VECTOR
select X86_RESET_VECTOR if !EFI_STUB
select QEMU
select BOARD_ROMSIZE_KB_1024

View File

@ -10,6 +10,14 @@ choice
prompt "Mainboard model"
optional
config TARGET_BAYLEYBAY
bool "Bayley Bay"
help
This is the Intel Bayley Bay Customer Reference Board. It contains an
Intel quad-core Atom Processor E3800 with dual-channel DDR3L SODIMM
4GB memory, HDMI/DP/VGA display, HD audio, SATA, USB2, USB3, SD, eMMC,
PCIe and some other sensor interfaces.
config TARGET_CROWNBAY
bool "Crown Bay"
help
@ -45,6 +53,7 @@ config TARGET_MINNOWMAX
endchoice
source "board/intel/bayleybay/Kconfig"
source "board/intel/crownbay/Kconfig"
source "board/intel/galileo/Kconfig"
source "board/intel/minnowmax/Kconfig"

View File

@ -0,0 +1,27 @@
if TARGET_BAYLEYBAY
config SYS_BOARD
default "bayleybay"
config SYS_VENDOR
default "intel"
config SYS_SOC
default "baytrail"
config SYS_CONFIG_NAME
default "bayleybay"
config SYS_TEXT_BASE
default 0xfff00000
config BOARD_SPECIFIC_OPTIONS # dummy
def_bool y
select X86_RESET_VECTOR
select INTEL_BAYTRAIL
select BOARD_ROMSIZE_KB_8192
config PCIE_ECAM_BASE
default 0xe0000000
endif

View File

@ -0,0 +1,6 @@
Intel Bayley Bay
M: Bin Meng <bmeng.cn@gmail.com>
S: Maintained
F: board/intel/bayleybay
F: include/configs/bayleybay.h
F: configs/bayleybay_defconfig

View File

@ -0,0 +1,7 @@
#
# Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += bayleybay.o start.o

View File

@ -0,0 +1,19 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/gpio.h>
#include <netdev.h>
void setup_pch_gpios(u16 gpiobase, const struct pch_gpio_map *gpio)
{
return;
}
int board_eth_init(bd_t *bis)
{
return pci_eth_init(bis);
}

View File

@ -0,0 +1,9 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
.globl early_board_init
early_board_init:
jmp early_board_init_ret

View File

@ -13,11 +13,12 @@ config SYS_CONFIG_NAME
default "minnowmax"
config SYS_TEXT_BASE
default 0xfff00000
default 0xfff00000 if !EFI_STUB
default 0x01110000 if EFI_STUB
config BOARD_SPECIFIC_OPTIONS # dummy
def_bool y
select X86_RESET_VECTOR
select X86_RESET_VECTOR if !EFI_STUB
select INTEL_BAYTRAIL
select BOARD_ROMSIZE_KB_8192

View File

@ -6,12 +6,7 @@
#include <common.h>
#include <asm/gpio.h>
#include <asm/ibmpc.h>
#include <asm/pnp_def.h>
#include <netdev.h>
#include <smsc_lpc47m.h>
#define SERIAL_DEV PNP_DEV(0x2e, 4)
int arch_early_init_r(void)
{
@ -21,13 +16,6 @@ int arch_early_init_r(void)
return 0;
}
int board_early_init_f(void)
{
lpc47m_enable_serial(SERIAL_DEV, UART0_BASE, UART0_IRQ);
return 0;
}
void setup_pch_gpios(u16 gpiobase, const struct pch_gpio_map *gpio)
{
return;

View File

@ -90,6 +90,7 @@ obj-$(CONFIG_CMD_DTT) += cmd_dtt.o
obj-$(CONFIG_CMD_ECHO) += cmd_echo.o
obj-$(CONFIG_ENV_IS_IN_EEPROM) += cmd_eeprom.o
obj-$(CONFIG_CMD_EEPROM) += cmd_eeprom.o
obj-$(CONFIG_EFI_STUB) += cmd_efi.o
obj-$(CONFIG_CMD_ELF) += cmd_elf.o
obj-$(CONFIG_SYS_HUSH_PARSER) += cmd_exit.o
obj-$(CONFIG_CMD_EXT4) += cmd_ext4.o

View File

@ -144,7 +144,7 @@ static int init_baud_rate(void)
static int display_text_info(void)
{
#ifndef CONFIG_SANDBOX
#if !defined(CONFIG_SANDBOX) && !defined(CONFIG_EFI_APP)
ulong bss_start, bss_end, text_base;
bss_start = (ulong)&__bss_start;
@ -267,7 +267,7 @@ static int setup_mon_len(void)
{
#if defined(__ARM__) || defined(__MICROBLAZE__)
gd->mon_len = (ulong)&__bss_end - (ulong)_start;
#elif defined(CONFIG_SANDBOX)
#elif defined(CONFIG_SANDBOX) || defined(CONFIG_EFI_APP)
gd->mon_len = (ulong)&_end - (ulong)_init;
#elif defined(CONFIG_BLACKFIN) || defined(CONFIG_NIOS2)
gd->mon_len = CONFIG_SYS_MONITOR_LEN;
@ -654,6 +654,8 @@ static int setup_dram_config(void)
static int reloc_fdt(void)
{
if (gd->flags & GD_FLG_SKIP_RELOC)
return 0;
if (gd->new_fdt) {
memcpy(gd->new_fdt, gd->fdt_blob, gd->fdt_size);
gd->fdt_blob = gd->new_fdt;
@ -664,6 +666,11 @@ static int reloc_fdt(void)
static int setup_reloc(void)
{
if (gd->flags & GD_FLG_SKIP_RELOC) {
debug("Skipping relocation due to flag\n");
return 0;
}
#ifdef CONFIG_SYS_TEXT_BASE
gd->reloc_off = gd->relocaddr - CONFIG_SYS_TEXT_BASE;
#ifdef CONFIG_M68K
@ -689,6 +696,8 @@ static int setup_reloc(void)
static int jump_to_copy(void)
{
if (gd->flags & GD_FLG_SKIP_RELOC)
return 0;
/*
* x86 is special, but in a nice way. It uses a trampoline which
* enables the dcache if possible.
@ -968,7 +977,8 @@ void board_init_f(ulong boot_flags)
if (initcall_run_list(init_sequence_f))
hang();
#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX)
#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && \
!defined(CONFIG_EFI_APP)
/* NOTREACHED - jump_to_copy() does not return */
hang();
#endif

View File

@ -8,7 +8,6 @@
int __weak checkboard(void)
{
printf("Board: Unknown\n");
return 0;
}

257
common/cmd_efi.c Normal file
View File

@ -0,0 +1,257 @@
/*
* (C) Copyright 2015 Google, Inc
* Written by Simon Glass <sjg@chromium.org>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <command.h>
#include <efi.h>
#include <errno.h>
#include <malloc.h>
static const char *const type_name[] = {
"reserved",
"loader_code",
"loader_data",
"bs_code",
"bs_data",
"rt_code",
"rt_data",
"conv",
"unusable",
"acpi_reclaim",
"acpi_nvs",
"io",
"io_port",
"pal_code",
};
static struct attr_info {
int shift;
const char *name;
} mem_attr[] = {
{ EFI_MEMORY_UC_SHIFT, "uncached" },
{ EFI_MEMORY_WC_SHIFT, "write-coalescing" },
{ EFI_MEMORY_WT_SHIFT, "write-through" },
{ EFI_MEMORY_WB_SHIFT, "write-back" },
{ EFI_MEMORY_UCE_SHIFT, "uncached & exported" },
{ EFI_MEMORY_WP_SHIFT, "write-protect" },
{ EFI_MEMORY_RP_SHIFT, "read-protect" },
{ EFI_MEMORY_XP_SHIFT, "execute-protect" },
{ EFI_MEMORY_RUNTIME_SHIFT, "needs runtime mapping" }
};
/* Maximum different attribute values we can track */
#define ATTR_SEEN_MAX 30
static inline bool is_boot_services(int type)
{
return type == EFI_LOADER_CODE || type == EFI_LOADER_DATA ||
type == EFI_BOOT_SERVICES_CODE ||
type == EFI_BOOT_SERVICES_DATA;
}
static int h_cmp_entry(const void *v1, const void *v2)
{
const struct efi_mem_desc *desc1 = v1;
const struct efi_mem_desc *desc2 = v2;
int64_t diff = desc1->physical_start - desc2->physical_start;
/*
* Manually calculate the difference to avoid sign loss in the 64-bit
* to 32-bit conversion
*/
return diff < 0 ? -1 : diff > 0 ? 1 : 0;
}
void *efi_build_mem_table(struct efi_entry_memmap *map, int size, bool skip_bs)
{
struct efi_mem_desc *desc, *end, *base, *dest, *prev;
int count;
u64 addr;
base = malloc(size + sizeof(*desc));
if (!base) {
debug("%s: Cannot allocate %#x bytes\n", __func__, size);
return NULL;
}
end = (struct efi_mem_desc *)((ulong)map + size);
count = ((ulong)end - (ulong)map->desc) / map->desc_size;
memcpy(base, map->desc, (ulong)end - (ulong)map->desc);
qsort(base, count, map->desc_size, h_cmp_entry);
prev = NULL;
addr = 0;
dest = base;
end = base + count;
for (desc = base; desc < end; desc = efi_get_next_mem_desc(map, desc)) {
bool merge = true;
int type = desc->type;
if (skip_bs && is_boot_services(desc->type))
type = EFI_CONVENTIONAL_MEMORY;
memcpy(dest, desc, map->desc_size);
dest->type = type;
if (!skip_bs || !prev)
merge = false;
else if (desc->physical_start != addr)
merge = false;
else if (type != EFI_CONVENTIONAL_MEMORY)
merge = false;
else if (prev->type != EFI_CONVENTIONAL_MEMORY)
merge = false;
if (merge) {
prev->num_pages += desc->num_pages;
} else {
prev = dest;
dest = efi_get_next_mem_desc(map, dest);
}
addr = desc->physical_start + (desc->num_pages <<
EFI_PAGE_SHIFT);
}
/* Mark the end */
dest->type = EFI_TABLE_END;
return base;
}
static void efi_print_mem_table(struct efi_entry_memmap *map,
struct efi_mem_desc *desc, bool skip_bs)
{
u64 attr_seen[ATTR_SEEN_MAX];
int attr_seen_count;
int upto, i;
u64 addr;
printf(" # %-14s %10s %10s %10s %s\n", "Type", "Physical",
"Virtual", "Size", "Attributes");
/* Keep track of all the different attributes we have seen */
attr_seen_count = 0;
addr = 0;
for (upto = 0; desc->type != EFI_TABLE_END;
upto++, desc = efi_get_next_mem_desc(map, desc)) {
const char *name;
u64 size;
if (skip_bs && is_boot_services(desc->type))
continue;
if (desc->physical_start != addr) {
printf(" %-14s %010llx %10s %010llx\n", "<gap>",
addr, "", desc->physical_start - addr);
}
size = desc->num_pages << EFI_PAGE_SHIFT;
name = desc->type < ARRAY_SIZE(type_name) ?
type_name[desc->type] : "<invalid>";
printf("%2d %x:%-12s %010llx %010llx %010llx ", upto,
desc->type, name, desc->physical_start,
desc->virtual_start, size);
if (desc->attribute & EFI_MEMORY_RUNTIME)
putc('r');
printf("%llx", desc->attribute & ~EFI_MEMORY_RUNTIME);
putc('\n');
for (i = 0; i < attr_seen_count; i++) {
if (attr_seen[i] == desc->attribute)
break;
}
if (i == attr_seen_count && i < ATTR_SEEN_MAX)
attr_seen[attr_seen_count++] = desc->attribute;
addr = desc->physical_start + size;
}
printf("\nAttributes key:\n");
for (i = 0; i < attr_seen_count; i++) {
u64 attr = attr_seen[i];
bool first;
int j;
printf("%c%llx: ", attr & EFI_MEMORY_RUNTIME ? 'r' : ' ',
attr & ~EFI_MEMORY_RUNTIME);
for (j = 0, first = true; j < ARRAY_SIZE(mem_attr); j++) {
if (attr & (1ULL << mem_attr[j].shift)) {
if (first)
first = false;
else
printf(", ");
printf("%s", mem_attr[j].name);
}
}
putc('\n');
}
if (skip_bs)
printf("*Some areas are merged (use 'all' to see)\n");
}
static int do_efi_mem(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
struct efi_mem_desc *desc;
struct efi_entry_memmap *map;
int size, ret;
bool skip_bs;
skip_bs = !argc || *argv[0] != 'a';
ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size);
switch (ret) {
case -ENOENT:
printf("No EFI table available\n");
goto done;
case -EPROTONOSUPPORT:
printf("Incorrect EFI table version\n");
goto done;
}
printf("EFI table at %lx, memory map %p, size %x, version %x, descr. size %#x\n",
gd->arch.table, map, size, map->version, map->desc_size);
if (map->version != EFI_MEM_DESC_VERSION) {
printf("Incorrect memory map version\n");
ret = -EPROTONOSUPPORT;
goto done;
}
desc = efi_build_mem_table(map, size, skip_bs);
if (!desc) {
ret = -ENOMEM;
goto done;
}
efi_print_mem_table(map, desc, skip_bs);
free(desc);
done:
if (ret)
printf("Error: %d\n", ret);
return ret ? CMD_RET_FAILURE : 0;
}
static cmd_tbl_t efi_commands[] = {
U_BOOT_CMD_MKENT(mem, 1, 1, do_efi_mem, "", ""),
};
static int do_efi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
cmd_tbl_t *efi_cmd;
int ret;
if (argc < 2)
return CMD_RET_USAGE;
efi_cmd = find_cmd_tbl(argv[1], efi_commands, ARRAY_SIZE(efi_commands));
argc -= 2;
argv += 2;
if (!efi_cmd || argc > efi_cmd->maxargs)
return CMD_RET_USAGE;
ret = efi_cmd->cmd(efi_cmd, flag, argc, argv);
return cmd_process_error(efi_cmd, ret);
}
U_BOOT_CMD(
efi, 3, 1, do_efi,
"EFI access",
"mem [all] Dump memory information [include boot services]"
);

View File

@ -492,7 +492,7 @@ static int cmd_call(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
result = (cmdtp->cmd)(cmdtp, flag, argc, argv);
if (result)
debug("Command failed, result=%d", result);
debug("Command failed, result=%d\n", result);
return result;
}

View File

@ -73,8 +73,6 @@ endif
RELFLAGS := $(PLATFORM_RELFLAGS)
OBJCOPYFLAGS += --gap-fill=0xff
PLATFORM_CPPFLAGS += $(RELFLAGS)
PLATFORM_CPPFLAGS += -pipe

View File

@ -0,0 +1,27 @@
CONFIG_X86=y
CONFIG_VENDOR_INTEL=y
CONFIG_DEFAULT_DEVICE_TREE="bayleybay"
CONFIG_TARGET_BAYLEYBAY=y
CONFIG_HAVE_INTEL_ME=y
CONFIG_SMP=y
CONFIG_HAVE_VGA_BIOS=y
CONFIG_GENERATE_PIRQ_TABLE=y
CONFIG_GENERATE_MP_TABLE=y
CONFIG_CMD_CPU=y
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_FLASH is not set
# CONFIG_CMD_SETEXPR is not set
# CONFIG_CMD_NFS is not set
CONFIG_BOOTSTAGE=y
CONFIG_BOOTSTAGE_REPORT=y
CONFIG_CMD_BOOTSTAGE=y
CONFIG_OF_CONTROL=y
CONFIG_CPU=y
CONFIG_DM_PCI=y
CONFIG_SPI_FLASH=y
CONFIG_VIDEO_VESA=y
CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
CONFIG_FRAMEBUFFER_VESA_MODE_11A=y
CONFIG_DM_RTC=y
CONFIG_USE_PRIVATE_LIBGCC=y
CONFIG_SYS_VSNPRINTF=y

View File

@ -14,6 +14,9 @@ CONFIG_CMD_BOOTSTAGE=y
CONFIG_OF_CONTROL=y
CONFIG_DM_PCI=y
CONFIG_SPI_FLASH=y
CONFIG_CMD_CROS_EC=y
CONFIG_CROS_EC=y
CONFIG_CROS_EC_LPC=y
CONFIG_VIDEO_VESA=y
CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
CONFIG_FRAMEBUFFER_VESA_MODE_11A=y

View File

@ -14,6 +14,9 @@ CONFIG_CMD_BOOTSTAGE=y
CONFIG_OF_CONTROL=y
CONFIG_DM_PCI=y
CONFIG_SPI_FLASH=y
CONFIG_CMD_CROS_EC=y
CONFIG_CROS_EC=y
CONFIG_CROS_EC_LPC=y
CONFIG_VIDEO_VESA=y
CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
CONFIG_FRAMEBUFFER_VESA_MODE_11A=y

16
configs/efi-x86_defconfig Normal file
View File

@ -0,0 +1,16 @@
CONFIG_X86=y
CONFIG_VENDOR_EFI=y
CONFIG_TARGET_EFI=y
CONFIG_TSC_CALIBRATION_BYPASS=y
CONFIG_OF_CONTROL=y
CONFIG_OF_EMBED=y
CONFIG_DM_PCI=y
CONFIG_DEFAULT_DEVICE_TREE="efi"
CONFIG_EFI=y
CONFIG_EFI_APP=y
CONFIG_DEBUG_UART=y
CONFIG_DEBUG_EFI_CONSOLE=y
CONFIG_DEBUG_UART_BASE=0
CONFIG_DEBUG_UART_CLOCK=0
# CONFIG_CMD_NET is not set
# CONFIG_CMD_BOOTM is not set

View File

@ -1,5 +1,7 @@
CONFIG_X86=y
CONFIG_DEFAULT_DEVICE_TREE="qemu-x86_i440fx"
CONFIG_SMP=y
CONFIG_MAX_CPUS=2
CONFIG_GENERATE_PIRQ_TABLE=y
CONFIG_GENERATE_MP_TABLE=y
CONFIG_CMD_CPU=y

237
doc/README.efi Normal file
View File

@ -0,0 +1,237 @@
#
# Copyright (C) 2015 Google, Inc
#
# SPDX-License-Identifier: GPL-2.0+
#
U-Boot on EFI
=============
This document provides information about U-Boot running on top of EFI, either
as an application or just as a means of getting U-Boot onto a new platform.
In God's Name, Why?
-------------------
This is useful in several situations:
- You have EFI running on a board but U-Boot does not natively support it
fully yet. You can boot into U-Boot from EFI and use that until U-Boot is
fully ported
- You need to use an EFI implementation (e.g. UEFI) because your vendor
requires it in order to provide support
- You plan to use coreboot to boot into U-Boot but coreboot support does
not currently exist for your platform. In the meantime you can use U-Boot
on EFI and then move to U-Boot on coreboot when ready
- You use EFI but want to experiment with a simpler alternative like U-Boot
Status
------
Only x86 is supported at present. If you are using EFI on another architecture
you may want to reconsider. However, much of the code is generic so could be
ported.
U-Boot supports running as an EFI application for 32-bit EFI only. This is
not very useful since only a serial port is provided. You can look around at
memory and type 'help' but that is about it.
More usefully, U-Boot supports building itself as a payload for either 32-bit
or 64-bit EFI. U-Boot is packaged up and loaded in its entirety by EFI. Once
started, U-Boot changes to 32-bit mode (currently) and takes over the
machine. You can use devices, boot a kernel, etc.
Build Instructions
------------------
First choose a board that has EFI support and obtain an EFI implementation
for that board. It will be either 32-bit or 64-bit.
To build U-Boot as an EFI application (32-bit EFI required), enable
CONFIG_EFI and CONFIG_EFI_APP. The efi-x86 config is set up for this.
To build U-Boot as an EFI payload (32-bit or 64-bit EFI can be used), adjust
an existing config to enable CONFIG_EFI, CONFIG_EFI_STUB and either
CONFIG_EFI_STUB_32BIT or CONFIG_EFI_STUB_64BIT.
Then build U-Boot as normal, e.g.
make qemu-x86_defconfig
make menuconfig (or make xconfig if you prefer)
# change the settings as above
make
You will end up with one of these files:
u-boot-app.efi - U-Boot EFI application
u-boot-payload.efi - U-Boot EFI payload application
Trying it out
-------------
Qemu is an emulator and it can emulate an x86 machine. You can run the
payload with something like this:
mkdir /tmp/efi
cp /path/to/u-boot*.efi /tmp/efi
qemu-system-x86_64 -bios bios.bin -hda fat:/tmp/efi/
Add -nographic if you want to use the terminal for output. Once it starts
type 'fs0:u-boot-payload.efi' to run the payload or 'fs0:u-boot-app.efi' to
run the application. 'bios.bin' is the EFI 'BIOS'.
To try it on real hardware, put u-boot-app.efi on a suitable boot medium,
such as a USB stick. Then you can type something like this to start it:
fs0:u-boot-payload.efi
(or fs0:u-boot-app.efi for the application)
This will start the payload, copy U-Boot into RAM and start U-Boot. Note
that EFI does not support booting a 64-bit application from a 32-bit
EFI (or vice versa). Also it will often fail to print an error message if
you get this wrong.
Inner workings
==============
Here follow a few implementation notes for those who want to fiddle with
this and perhaps contribute patches.
The application and payload approaches sound similar but are in fact
implemented completely differently.
EFI Application
---------------
For the application the whole of U-Boot is built as a shared library. The
efi_main() function is in lib/efi/efi_app.c. It sets up some basic EFI
functions with efi_init(), sets up U-Boot global_data, allocates memory for
U-Boot's malloc(), etc. and enters the normal init sequence (board_init_f()
and board_init_r()).
Since U-Boot limits its memory access to the allocated regions very little
special code is needed. The CONFIG_EFI_APP option controls a few things
that need to change so 'git grep CONFIG_EFI_APP' may be instructive.
The CONFIG_EFI option controls more general EFI adjustments.
The only available driver is the serial driver. This calls back into EFI
'boot services' to send and receive characters. Although it is implemented
as a serial driver the console device is not necessarilly serial. If you
boot EFI with video output then the 'serial' device will operate on your
target devices's display instead and the device's USB keyboard will also
work if connected. If you have both serial and video output, then both
consoles will be active. Even though U-Boot does the same thing normally,
These are features of EFI, not U-Boot.
Very little code is involved in implementing the EFI application feature.
U-Boot is highly portable. Most of the difficulty is in modifying the
Makefile settings to pass the right build flags. In particular there is very
little x86-specific code involved - you can find most of it in
arch/x86/cpu. Porting to ARM (which can also use EFI if you are brave
enough) should be straightforward.
Use the 'reset' command to get back to EFI.
EFI Payload
-----------
The payload approach is a different kettle of fish. It works by building
U-Boot exactly as normal for your target board, then adding the entire
image (including device tree) into a small EFI stub application responsible
for booting it. The stub application is built as a normal EFI application
except that it has a lot of data attached to it.
The stub application is implemented in lib/efi/efi_stub.c. The efi_main()
function is called by EFI. It is responsible for copying U-Boot from its
original location into memory, disabling EFI boot services and starting
U-Boot. U-Boot then starts as normal, relocates, starts all drivers, etc.
The stub application is architecture-dependent. At present it has some
x86-specific code and a comment at the top of efi_stub.c describes this.
While the stub application does allocate some memory from EFI this is not
used by U-Boot (the payload). In fact when U-Boot starts it has all of the
memory available to it and can operate as it pleases (but see the next
section).
Tables
------
The payload can pass information to U-Boot in the form of EFI tables. At
present this feature is used to pass the EFI memory map, an inordinately
large list of memory regions. You can use the 'efi mem all' command to
display this list. U-Boot uses the list to work out where to relocate
itself.
Although U-Boot can use any memory it likes, EFI marks some memory as used
by 'run-time services', code that hangs around while U-Boot is running and
is even present when Linux is running. This is common on x86 and provides
a way for Linux to call back into the firmware to control things like CPU
fan speed. U-Boot uses only 'conventional' memory, in EFI terminology. It
will relocate itself to the top of the largest block of memory it can find
below 4GB.
Interrupts
----------
U-Boot drivers typically don't use interrupts. Since EFI enables interrupts
it is possible that an interrupt will fire that U-Boot cannot handle. This
seems to cause problems. For this reason the U-Boot payload runs with
interrupts disabled at present.
32/64-bit
---------
While the EFI application can in principle be built as either 32- or 64-bit,
only 32-bit is currently supported. This means that the application can only
be used with 32-bit EFI.
The payload stub can be build as either 32- or 64-bits. Only a small amount
of code is built this way (see the extra- line in lib/efi/Makefile).
Everything else is built as a normal U-Boot, so is always 32-bit on x86 at
present.
Future work
-----------
This work could be extended in a number of ways:
- Add a generic x86 EFI payload configuration. At present you need to modify
an existing one, but mostly the low-level x86 code is disabled when booting
on EFI anyway, so a generic 'EFI' board could be created with a suitable set
of drivers enabled.
- Add ARM support
- Add 64-bit application support
- Figure out how to solve the interrupt problem
- Add more drivers to the application side (e.g. video, block devices, USB,
environment access). This would mostly be an academic exercise as a strong
use case is not readily apparent, but it might be fun.
- Avoid turning off boot services in the stub. Instead allow U-Boot to make
use of boot services in case it wants to. It is unclear what it might want
though.
Where is the code?
------------------
lib/efi
payload stub, application, support code. Mostly arch-neutral
arch/x86/lib/efi
helper functions for the fake DRAM init, etc. These can be used by
any board that runs as a payload.
arch/x86/cpu/efi
x86 support code for running as an EFI application
board/efi/efi-x86/efi.c
x86 board code for running as an EFI application
common/cmd_efi.c
the 'efi' command
--
Ben Stoltz, Simon Glass
Google, Inc
July 2015

View File

@ -281,6 +281,11 @@ QEMU emulates a graphic card which U-Boot supports. Removing '-nographic' will
show QEMU's VGA console window. Note this will disable QEMU's serial output.
If you want to check both consoles, use '-serial stdio'.
Multicore is also supported by QEMU via '-smp n' where n is the number of cores
to instantiate. Currently the default U-Boot built for QEMU supports 2 cores.
In order to support more cores, you need add additional cpu nodes in the device
tree and change CONFIG_MAX_CPUS accordingly.
CPU Microcode
-------------
Modern CPUs usually require a special bit stream called microcode [8] to be
@ -325,6 +330,281 @@ mtrr - List and set the Memory Type Range Registers (MTRR). These are used to
mode to use. U-Boot sets up some reasonable values but you can
adjust then with this command.
Booting Ubuntu
--------------
As an example of how to set up your boot flow with U-Boot, here are
instructions for starting Ubuntu from U-Boot. These instructions have been
tested on Minnowboard MAX with a SATA driver but are equally applicable on
other platforms and other media. There are really only four steps and its a
very simple script, but a more detailed explanation is provided here for
completeness.
Note: It is possible to set up U-Boot to boot automatically using syslinux.
It could also use the grub.cfg file (/efi/ubuntu/grub.cfg) to obtain the
GUID. If you figure these out, please post patches to this README.
Firstly, you will need Ubunutu installed on an available disk. It should be
possible to make U-Boot start a USB start-up disk but for now let's assume
that you used another boot loader to install Ubuntu.
Use the U-Boot command line to find the UUID of the partition you want to
boot. For example our disk is SCSI device 0:
=> part list scsi 0
Partition Map for SCSI device 0 -- Partition Type: EFI
Part Start LBA End LBA Name
Attributes
Type GUID
Partition GUID
1 0x00000800 0x001007ff ""
attrs: 0x0000000000000000
type: c12a7328-f81f-11d2-ba4b-00a0c93ec93b
guid: 9d02e8e4-4d59-408f-a9b0-fd497bc9291c
2 0x00100800 0x037d8fff ""
attrs: 0x0000000000000000
type: 0fc63daf-8483-4772-8e79-3d69d8477de4
guid: 965c59ee-1822-4326-90d2-b02446050059
3 0x037d9000 0x03ba27ff ""
attrs: 0x0000000000000000
type: 0657fd6d-a4ab-43c4-84e5-0933c84b4f4f
guid: 2c4282bd-1e82-4bcf-a5ff-51dedbf39f17
=>
This shows that your SCSI disk has three partitions. The really long hex
strings are called Globally Unique Identifiers (GUIDs). You can look up the
'type' ones here [11]. On this disk the first partition is for EFI and is in
VFAT format (DOS/Windows):
=> fatls scsi 0:1
efi/
0 file(s), 1 dir(s)
Partition 2 is 'Linux filesystem data' so that will be our root disk. It is
in ext2 format:
=> ext2ls scsi 0:2
<DIR> 4096 .
<DIR> 4096 ..
<DIR> 16384 lost+found
<DIR> 4096 boot
<DIR> 12288 etc
<DIR> 4096 media
<DIR> 4096 bin
<DIR> 4096 dev
<DIR> 4096 home
<DIR> 4096 lib
<DIR> 4096 lib64
<DIR> 4096 mnt
<DIR> 4096 opt
<DIR> 4096 proc
<DIR> 4096 root
<DIR> 4096 run
<DIR> 12288 sbin
<DIR> 4096 srv
<DIR> 4096 sys
<DIR> 4096 tmp
<DIR> 4096 usr
<DIR> 4096 var
<SYM> 33 initrd.img
<SYM> 30 vmlinuz
<DIR> 4096 cdrom
<SYM> 33 initrd.img.old
=>
and if you look in the /boot directory you will see the kernel:
=> ext2ls scsi 0:2 /boot
<DIR> 4096 .
<DIR> 4096 ..
<DIR> 4096 efi
<DIR> 4096 grub
3381262 System.map-3.13.0-32-generic
1162712 abi-3.13.0-32-generic
165611 config-3.13.0-32-generic
176500 memtest86+.bin
178176 memtest86+.elf
178680 memtest86+_multiboot.bin
5798112 vmlinuz-3.13.0-32-generic
165762 config-3.13.0-58-generic
1165129 abi-3.13.0-58-generic
5823136 vmlinuz-3.13.0-58-generic
19215259 initrd.img-3.13.0-58-generic
3391763 System.map-3.13.0-58-generic
5825048 vmlinuz-3.13.0-58-generic.efi.signed
28304443 initrd.img-3.13.0-32-generic
=>
The 'vmlinuz' files contain a packaged Linux kernel. The format is a kind of
self-extracting compressed file mixed with some 'setup' configuration data.
Despite its size (uncompressed it is >10MB) this only includes a basic set of
device drivers, enough to boot on most hardware types.
The 'initrd' files contain a RAM disk. This is something that can be loaded
into RAM and will appear to Linux like a disk. Ubuntu uses this to hold lots
of drivers for whatever hardware you might have. It is loaded before the
real root disk is accessed.
The numbers after the end of each file are the version. Here it is Linux
version 3.13. You can find the source code for this in the Linux tree with
the tag v3.13. The '.0' allows for additional Linux releases to fix problems,
but normally this is not needed. The '-58' is used by Ubuntu. Each time they
release a new kernel they increment this number. New Ubuntu versions might
include kernel patches to fix reported bugs. Stable kernels can exist for
some years so this number can get quite high.
The '.efi.signed' kernel is signed for EFI's secure boot. U-Boot has its own
secure boot mechanism - see [12] [13] and cannot read .efi files at present.
To boot Ubuntu from U-Boot the steps are as follows:
1. Set up the boot arguments. Use the GUID for the partition you want to
boot:
=> setenv bootargs root=/dev/disk/by-partuuid/965c59ee-1822-4326-90d2-b02446050059 ro
Here root= tells Linux the location of its root disk. The disk is specified
by its GUID, using '/dev/disk/by-partuuid/', a Linux path to a 'directory'
containing all the GUIDs Linux has found. When it starts up, there will be a
file in that directory with this name in it. It is also possible to use a
device name here, see later.
2. Load the kernel. Since it is an ext2/4 filesystem we can do:
=> ext2load scsi 0:2 03000000 /boot/vmlinuz-3.13.0-58-generic
The address 30000000 is arbitrary, but there seem to be problems with using
small addresses (sometimes Linux cannot find the ramdisk). This is 48MB into
the start of RAM (which is at 0 on x86).
3. Load the ramdisk (to 64MB):
=> ext2load scsi 0:2 04000000 /boot/initrd.img-3.13.0-58-generic
4. Start up the kernel. We need to know the size of the ramdisk, but can use
a variable for that. U-Boot sets 'filesize' to the size of the last file it
loaded.
=> zboot 03000000 0 04000000 ${filesize}
Type 'help zboot' if you want to see what the arguments are. U-Boot on x86 is
quite verbose when it boots a kernel. You should see these messages from
U-Boot:
Valid Boot Flag
Setup Size = 0x00004400
Magic signature found
Using boot protocol version 2.0c
Linux kernel version 3.13.0-58-generic (buildd@allspice) #97-Ubuntu SMP Wed Jul 8 02:56:15 UTC 2015
Building boot_params at 0x00090000
Loading bzImage at address 100000 (5805728 bytes)
Magic signature found
Initial RAM disk at linear address 0x04000000, size 19215259 bytes
Kernel command line: "console=ttyS0,115200 root=/dev/disk/by-partuuid/965c59ee-1822-4326-90d2-b02446050059 ro"
Starting kernel ...
U-Boot prints out some bootstage timing. This is more useful if you put the
above commands into a script since then it will be faster.
Timer summary in microseconds:
Mark Elapsed Stage
0 0 reset
241,535 241,535 board_init_r
2,421,611 2,180,076 id=64
2,421,790 179 id=65
2,428,215 6,425 main_loop
48,860,584 46,432,369 start_kernel
Accumulated time:
240,329 ahci
1,422,704 vesa display
Now the kernel actually starts:
[ 0.000000] Initializing cgroup subsys cpuset
[ 0.000000] Initializing cgroup subsys cpu
[ 0.000000] Initializing cgroup subsys cpuacct
[ 0.000000] Linux version 3.13.0-58-generic (buildd@allspice) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) ) #97-Ubuntu SMP Wed Jul 8 02:56:15 UTC 2015 (Ubuntu 3.13.0-58.97-generic 3.13.11-ckt22)
[ 0.000000] Command line: console=ttyS0,115200 root=/dev/disk/by-partuuid/965c59ee-1822-4326-90d2-b02446050059 ro
It continues for a long time. Along the way you will see it pick up your
ramdisk:
[ 0.000000] RAMDISK: [mem 0x04000000-0x05253fff]
...
[ 0.788540] Trying to unpack rootfs image as initramfs...
[ 1.540111] Freeing initrd memory: 18768K (ffff880004000000 - ffff880005254000)
...
Later it actually starts using it:
Begin: Running /scripts/local-premount ... done.
You should also see your boot disk turn up:
[ 4.357243] scsi 1:0:0:0: Direct-Access ATA ADATA SP310 5.2 PQ: 0 ANSI: 5
[ 4.366860] sd 1:0:0:0: [sda] 62533296 512-byte logical blocks: (32.0 GB/29.8 GiB)
[ 4.375677] sd 1:0:0:0: Attached scsi generic sg0 type 0
[ 4.381859] sd 1:0:0:0: [sda] Write Protect is off
[ 4.387452] sd 1:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[ 4.399535] sda: sda1 sda2 sda3
Linux has found the three partitions (sda1-3). Mercifully it doesn't print out
the GUIDs. In step 1 above we could have used:
setenv bootargs root=/dev/sda2 ro
instead of the GUID. However if you add another drive to your board the
numbering may change whereas the GUIDs will not. So if your boot partition
becomes sdb2, it will still boot. For embedded systems where you just want to
boot the first disk, you have that option.
The last thing you will see on the console is mention of plymouth (which
displays the Ubuntu start-up screen) and a lot of 'Starting' messages:
* Starting Mount filesystems on boot [ OK ]
After a pause you should see a login screen on your display and you are done.
If you want to put this in a script you can use something like this:
setenv bootargs root=UUID=b2aaf743-0418-4d90-94cc-3e6108d7d968 ro
setenv boot zboot 03000000 0 04000000 \${filesize}
setenv bootcmd "ext2load scsi 0:2 03000000 /boot/vmlinuz-3.13.0-58-generic; ext2load scsi 0:2 04000000 /boot/initrd.img-3.13.0-58-generic; run boot"
saveenv
The \ is to tell the shell not to evaluate ${filesize} as part of the setenv
command.
You will also need to add this to your board configuration file, e.g.
include/configs/minnowmax.h:
#define CONFIG_BOOTDELAY 2
Now when you reset your board it wait a few seconds (in case you want to
interrupt) and then should boot straight into Ubuntu.
You can also bake this behaviour into your build by hard-coding the
environment variables if you add this to minnowmax.h:
#undef CONFIG_BOOTARGS
#undef CONFIG_BOOTCOMMAND
#define CONFIG_BOOTARGS \
"root=/dev/sda2 ro"
#define CONFIG_BOOTCOMMAND \
"ext2load scsi 0:2 03000000 /boot/vmlinuz-3.13.0-58-generic; " \
"ext2load scsi 0:2 04000000 /boot/initrd.img-3.13.0-58-generic; " \
"run boot"
#undef CONFIG_EXTRA_ENV_SETTINGS
#define CONFIG_EXTRA_ENV_SETTINGS "boot=zboot 03000000 0 04000000 ${filesize}"
Development Flow
----------------
These notes are for those who want to port U-Boot to a new x86 platform.
@ -388,6 +668,46 @@ boot progress. This can be good for debugging.
If not, you can try to get serial working as early as possible. The early
debug serial port may be useful here. See setup_early_uart() for an example.
During the U-Boot porting, one of the important steps is to write correct PIRQ
routing information in the board device tree. Without it, device drivers in the
Linux kernel won't function correctly due to interrupt is not working. Please
refer to U-Boot doc [14] for the device tree bindings of Intel interrupt router.
Here we have more details on the intel,pirq-routing property below.
intel,pirq-routing = <
PCI_BDF(0, 2, 0) INTA PIRQA
...
>;
As you see each entry has 3 cells. For the first one, we need describe all pci
devices mounted on the board. For SoC devices, normally there is a chapter on
the chipset datasheet which lists all the available PCI devices. For example on
Bay Trail, this is chapter 4.3 (PCI configuration space). For the second one, we
can get the interrupt pin either from datasheet or hardware via U-Boot shell.
The reliable source is the hardware as sometimes chipset datasheet is not 100%
up-to-date. Type 'pci header' plus the device's pci bus/device/function number
from U-Boot shell below.
=> pci header 0.1e.1
vendor ID = 0x8086
device ID = 0x0f08
...
interrupt line = 0x09
interrupt pin = 0x04
...
It shows this PCI device is using INTD pin as it reports 4 in the interrupt pin
register. Repeat this until you get interrupt pins for all the devices. The last
cell is the PIRQ line which a particular interrupt pin is mapped to. On Intel
chipset, the power-up default mapping is INTA/B/C/D maps to PIRQA/B/C/D. This
can be changed by registers in LPC bridge. So far Intel FSP does not touch those
registers so we can write down the PIRQ according to the default mapping rule.
Once we get the PIRQ routing information in the device tree, the interrupt
allocation and assignment will be done by U-Boot automatically. Now you can
enable CONFIG_GENERATE_PIRQ_TABLE for testing Linux kernel using i8259 PIC and
CONFIG_GENERATE_MP_TABLE for testing Linux kernel using local APIC and I/O APIC.
TODO List
---------
- Audio
@ -406,3 +726,7 @@ References
[8] http://en.wikipedia.org/wiki/Microcode
[9] http://simplefirmware.org
[10] http://www.intel.com/design/archives/processors/pro/docs/242016.htm
[11] https://en.wikipedia.org/wiki/GUID_Partition_Table
[12] http://events.linuxfoundation.org/sites/events/files/slides/chromeos_and_diy_vboot_0.pdf
[13] http://events.linuxfoundation.org/sites/events/files/slides/elce-2014.pdf
[14] doc/device-tree-bindings/misc/intel,irq-router.txt

View File

@ -17,8 +17,8 @@ Required properties :
- intel,pirq-link : Specifies the PIRQ link information with two cells. The
first cell is the register offset that controls the first PIRQ link routing.
The second cell is the total number of PIRQ links the router supports.
- intel,pirq-mask : Specifies the IRQ mask reprenting the 16 IRQs in 8259 PIC.
Bit N is 1 means IRQ N is available to be routed.
- intel,pirq-mask : Specifies the IRQ mask representing the 16 IRQs in the
8259 PIC. Bit N is 1 means IRQ N is available to be routed.
- intel,pirq-routing : Specifies all PCI devices' IRQ routing information,
encoded as 3 cells a group for a device. The first cell is the device's PCI
bus number, device number and function number encoding with PCI_BDF() macro.

View File

@ -6,7 +6,7 @@ How busses are scanned
Any config read will end up at pci_read_config(). This uses
uclass_get_device_by_seq() to get the PCI bus for a particular bus number.
Bus number 0 will need to be requested first, and the alias in the device
Bus number 0 will need to be requested first, and the alias in the device
tree file will point to the correct device:
@ -23,7 +23,7 @@ tree file will point to the correct device:
If there is no alias the devices will be numbered sequentially in the device
tree.
The call to uclass_get_device by seq() will cause the PCI bus to be probed.
The call to uclass_get_device() will cause the PCI bus to be probed.
This does a scan of the bus to locate available devices. These devices are
bound to their appropriate driver if available. If there is no driver, then
they are bound to a generic PCI driver which does nothing.
@ -32,7 +32,7 @@ After probing a bus, the available devices will appear in the device tree
under that bus.
Note that this is all done on a lazy basis, as needed, so until something is
touched on PCI it will not be probed.
touched on PCI (eg: a call to pci_find_devices()) it will not be probed.
PCI devices can appear in the device tree. If they do this serves to specify
the driver to use for the device. In this case they will be bound at

View File

@ -153,6 +153,8 @@ int uclass_find_device(enum uclass_id id, int index, struct udevice **devp)
ret = uclass_get(id, &uc);
if (ret)
return ret;
if (list_empty(&uc->dev_head))
return -ENODEV;
list_for_each_entry(dev, &uc->dev_head, uclass_node) {
if (!index--) {

View File

@ -35,6 +35,8 @@
#include <asm/io.h>
#include <asm/pci.h>
DECLARE_GLOBAL_DATA_PTR;
#define GPIO_PER_BANK 32
struct ich6_bank_priv {

View File

@ -641,10 +641,6 @@ static int pci_uclass_post_probe(struct udevice *bus)
{
int ret;
/* Don't scan buses before relocation */
if (!(gd->flags & GD_FLG_RELOC))
return 0;
debug("%s: probing bus %d\n", __func__, bus->seq);
ret = pci_bind_bus_devices(bus);
if (ret)

View File

@ -269,7 +269,8 @@ int pci_hose_config_device(struct pci_controller *hose,
/* Disable interrupt line, if device says it wants to use interrupts */
pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_PIN, &pin);
if (pin != 0) {
pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, 0xff);
pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE,
PCI_INTERRUPT_LINE_DISABLE);
}
pci_hose_read_config_dword(hose, dev, PCI_COMMAND, &old_command);

View File

@ -14,12 +14,6 @@
#include <errno.h>
#include <pci.h>
#ifdef DEBUG
#define DEBUGF(x...) printf(x)
#else
#define DEBUGF(x...)
#endif /* DEBUG */
/* the user can define CONFIG_SYS_PCI_CACHE_LINE_SIZE to avoid problems */
#ifndef CONFIG_SYS_PCI_CACHE_LINE_SIZE
#define CONFIG_SYS_PCI_CACHE_LINE_SIZE 8
@ -50,20 +44,21 @@ int pciauto_region_allocate(struct pci_region *res, pci_size_t size,
pci_addr_t addr;
if (!res) {
DEBUGF("No resource");
debug("No resource");
goto error;
}
addr = ((res->bus_lower - 1) | (size - 1)) + 1;
if (addr - res->bus_start + size > res->size) {
DEBUGF("No room in resource");
debug("No room in resource");
goto error;
}
res->bus_lower = addr + size;
DEBUGF("address=0x%llx bus_lower=0x%llx", (u64)addr, (u64)res->bus_lower);
debug("address=0x%llx bus_lower=0x%llx", (unsigned long long)addr,
(unsigned long long)res->bus_lower);
*bar = addr;
return 0;
@ -87,9 +82,9 @@ void pciauto_setup_device(struct pci_controller *hose,
pci_size_t bar_size;
u16 cmdstat = 0;
int bar, bar_nr = 0;
#ifndef CONFIG_PCI_ENUM_ONLY
u8 header_type;
int rom_addr;
#ifndef CONFIG_PCI_ENUM_ONLY
pci_addr_t bar_value;
struct pci_region *bar_res;
int found_mem64 = 0;
@ -122,7 +117,8 @@ void pciauto_setup_device(struct pci_controller *hose,
bar_res = io;
#endif
DEBUGF("PCI Autoconfig: BAR %d, I/O, size=0x%llx, ", bar_nr, (u64)bar_size);
debug("PCI Autoconfig: BAR %d, I/O, size=0x%llx, ",
bar_nr, (unsigned long long)bar_size);
} else {
if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
PCI_BASE_ADDRESS_MEM_TYPE_64) {
@ -152,7 +148,9 @@ void pciauto_setup_device(struct pci_controller *hose,
bar_res = mem;
#endif
DEBUGF("PCI Autoconfig: BAR %d, Mem, size=0x%llx, ", bar_nr, (u64)bar_size);
debug("PCI Autoconfig: BAR %d, %s, size=0x%llx, ",
bar_nr, bar_res == prefetch ? "Prf" : "Mem",
(unsigned long long)bar_size);
}
#ifndef CONFIG_PCI_ENUM_ONLY
@ -179,11 +177,12 @@ void pciauto_setup_device(struct pci_controller *hose,
cmdstat |= (bar_response & PCI_BASE_ADDRESS_SPACE) ?
PCI_COMMAND_IO : PCI_COMMAND_MEMORY;
DEBUGF("\n");
debug("\n");
bar_nr++;
}
#ifndef CONFIG_PCI_ENUM_ONLY
/* Configure the expansion ROM address */
pci_hose_read_config_byte(hose, dev, PCI_HEADER_TYPE, &header_type);
if (header_type != PCI_HEADER_TYPE_CARDBUS) {
@ -193,16 +192,18 @@ void pciauto_setup_device(struct pci_controller *hose,
pci_hose_read_config_dword(hose, dev, rom_addr, &bar_response);
if (bar_response) {
bar_size = -(bar_response & ~1);
DEBUGF("PCI Autoconfig: ROM, size=%#x, ", bar_size);
debug("PCI Autoconfig: ROM, size=%#x, ",
(unsigned int)bar_size);
if (pciauto_region_allocate(mem, bar_size,
&bar_value) == 0) {
pci_hose_write_config_dword(hose, dev, rom_addr,
bar_value);
}
cmdstat |= PCI_COMMAND_MEMORY;
DEBUGF("\n");
debug("\n");
}
}
#endif
pci_hose_write_config_word(hose, dev, PCI_COMMAND, cmdstat);
pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE,
@ -411,7 +412,7 @@ void pciauto_config_init(struct pci_controller *hose)
if (hose->pci_mem) {
pciauto_region_init(hose->pci_mem);
DEBUGF("PCI Autoconfig: Bus Memory region: [0x%llx-0x%llx],\n"
debug("PCI Autoconfig: Bus Memory region: [0x%llx-0x%llx],\n"
"\t\tPhysical Memory [%llx-%llxx]\n",
(u64)hose->pci_mem->bus_start,
(u64)(hose->pci_mem->bus_start + hose->pci_mem->size - 1),
@ -422,7 +423,7 @@ void pciauto_config_init(struct pci_controller *hose)
if (hose->pci_prefetch) {
pciauto_region_init(hose->pci_prefetch);
DEBUGF("PCI Autoconfig: Bus Prefetchable Mem: [0x%llx-0x%llx],\n"
debug("PCI Autoconfig: Bus Prefetchable Mem: [0x%llx-0x%llx],\n"
"\t\tPhysical Memory [%llx-%llx]\n",
(u64)hose->pci_prefetch->bus_start,
(u64)(hose->pci_prefetch->bus_start +
@ -435,7 +436,7 @@ void pciauto_config_init(struct pci_controller *hose)
if (hose->pci_io) {
pciauto_region_init(hose->pci_io);
DEBUGF("PCI Autoconfig: Bus I/O region: [0x%llx-0x%llx],\n"
debug("PCI Autoconfig: Bus I/O region: [0x%llx-0x%llx],\n"
"\t\tPhysical Memory: [%llx-%llx]\n",
(u64)hose->pci_io->bus_start,
(u64)(hose->pci_io->bus_start + hose->pci_io->size - 1),
@ -475,8 +476,8 @@ int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev)
switch (class) {
case PCI_CLASS_BRIDGE_PCI:
DEBUGF("PCI Autoconfig: Found P2P bridge, device %d\n",
PCI_DEV(dev));
debug("PCI Autoconfig: Found P2P bridge, device %d\n",
PCI_DEV(dev));
pciauto_setup_device(hose, dev, 2, pci_mem,
pci_prefetch, pci_io);
@ -512,8 +513,8 @@ int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev)
pciauto_setup_device(hose, dev, 0, pci_mem,
pci_prefetch, pci_io);
DEBUGF("PCI Autoconfig: Found P2CardBus bridge, device %d\n",
PCI_DEV(dev));
debug("PCI Autoconfig: Found P2CardBus bridge, device %d\n",
PCI_DEV(dev));
#ifndef CONFIG_DM_PCI
hose->current_busno++;
@ -522,8 +523,8 @@ int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev)
#if defined(CONFIG_PCIAUTO_SKIP_HOST_BRIDGE)
case PCI_CLASS_BRIDGE_OTHER:
DEBUGF("PCI Autoconfig: Skipping bridge device %d\n",
PCI_DEV(dev));
debug("PCI Autoconfig: Skipping bridge device %d\n",
PCI_DEV(dev));
break;
#endif
#if defined(CONFIG_MPC834x) && !defined(CONFIG_VME8349)
@ -534,14 +535,14 @@ int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev)
* device claiming resources io/mem/irq.. we only allow for
* the PIMMR window to be allocated (BAR0 - 1MB size)
*/
DEBUGF("PCI Autoconfig: Broken bridge found, only minimal config\n");
debug("PCI Autoconfig: Broken bridge found, only minimal config\n");
pciauto_setup_device(hose, dev, 0, hose->pci_mem,
hose->pci_prefetch, hose->pci_io);
break;
#endif
case PCI_CLASS_PROCESSOR_POWERPC: /* an agent or end-point */
DEBUGF("PCI AutoConfig: Found PowerPC device\n");
debug("PCI AutoConfig: Found PowerPC device\n");
default:
pciauto_setup_device(hose, dev, 6, pci_mem,

View File

@ -5,7 +5,6 @@
*
* SPDX-License-Identifier: GPL-2.0+
*/
#define DEBUG
#include <common.h>
#include <dm.h>
#include <errno.h>

View File

@ -235,6 +235,10 @@ void setup_video(struct screen_info *screen_info)
#ifdef CONFIG_FRAMEBUFFER_SET_VESA_MODE
struct vesa_mode_info *vesa = &mode_info.vesa;
/* Sanity test on VESA parameters */
if (!vesa->x_resolution || !vesa->y_resolution)
return;
screen_info->orig_video_isVGA = VIDEO_TYPE_VLFB;
screen_info->lfb_width = vesa->x_resolution;

View File

@ -44,6 +44,15 @@ config DEBUG_UART_NS16550
will need to provide parameters to make this work. The driver will
be available until the real driver model serial is running.
config DEBUG_EFI_CONSOLE
bool "EFI"
depends on EFI_APP
help
Select this to enable a debug console which calls back to EFI to
output to the console. This can be useful for early debugging of
U-Boot when running on top of EFI (Extensive Firmware Interface).
This is a type of BIOS used by PCs.
endchoice
config DEBUG_UART_BASE
@ -102,3 +111,13 @@ config UNIPHIER_SERIAL
help
If you have a UniPhier based board and want to use the on-chip
serial ports, say Y to this option. If unsure, say N.
config X86_SERIAL
bool "Support for 16550 serial port on x86 machines"
depends on X86
default y
help
Most x86 machines have a ns16550 UART or compatible. This can be
enabled in the device tree with the correct input clock frequency
provided (default 1843200). Enable this to obtain serial console
output.

View File

@ -21,6 +21,7 @@ obj-$(CONFIG_ALTERA_JTAG_UART) += altera_jtag_uart.o
obj-$(CONFIG_ARM_DCC) += arm_dcc.o
obj-$(CONFIG_ATMEL_USART) += atmel_usart.o
obj-$(CONFIG_DW_SERIAL) += serial_dw.o
obj-$(CONFIG_EFI_APP) += serial_efi.o
obj-$(CONFIG_LPC32XX_HSUART) += lpc32xx_hsuart.o
obj-$(CONFIG_MCFUART) += mcfuart.o
obj-$(CONFIG_OPENCORES_YANU) += opencores_yanu.o

View File

@ -71,7 +71,7 @@ static void serial_find_console_or_panic(void)
#endif
if (!uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &dev) ||
!uclass_get_device(UCLASS_SERIAL, INDEX, &dev) ||
(!uclass_first_device(UCLASS_SERIAL, &dev) || dev)) {
(!uclass_first_device(UCLASS_SERIAL, &dev) && dev)) {
gd->cur_serial_dev = dev;
return;
}

157
drivers/serial/serial_efi.c Normal file
View File

@ -0,0 +1,157 @@
/*
* Copyright (c) 2015 Google, Inc
* Written by Simon Glass <sjg@chromium.org>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <debug_uart.h>
#include <dm.h>
#include <efi.h>
#include <efi_api.h>
#include <errno.h>
#include <fdtdec.h>
#include <linux/compiler.h>
#include <asm/io.h>
#include <serial.h>
/* Information about the efi console */
struct serial_efi_priv {
struct efi_simple_input_interface *con_in;
struct efi_simple_text_output_protocol *con_out;
struct efi_input_key key;
bool have_key;
};
int serial_efi_setbrg(struct udevice *dev, int baudrate)
{
return 0;
}
static int serial_efi_get_key(struct serial_efi_priv *priv)
{
int ret;
if (priv->have_key)
return 0;
ret = priv->con_in->read_key_stroke(priv->con_in, &priv->key);
if (ret == EFI_NOT_READY)
return -EAGAIN;
else if (ret != EFI_SUCCESS)
return -EIO;
priv->have_key = true;
return 0;
}
static int serial_efi_getc(struct udevice *dev)
{
struct serial_efi_priv *priv = dev_get_priv(dev);
int ret, ch;
ret = serial_efi_get_key(priv);
if (ret)
return ret;
priv->have_key = false;
ch = priv->key.unicode_char;
/*
* Unicode char 8 (for backspace) is never returned. Instead we get a
* key scan code of 8. Handle this so that backspace works correctly
* in the U-Boot command line.
*/
if (!ch && priv->key.scan_code == 8)
ch = 8;
debug(" [%x %x %x] ", ch, priv->key.unicode_char, priv->key.scan_code);
return ch;
}
static int serial_efi_putc(struct udevice *dev, const char ch)
{
struct serial_efi_priv *priv = dev_get_priv(dev);
uint16_t ucode[2];
int ret;
ucode[0] = ch;
ucode[1] = '\0';
ret = priv->con_out->output_string(priv->con_out, ucode);
if (ret)
return -EIO;
return 0;
}
static int serial_efi_pending(struct udevice *dev, bool input)
{
struct serial_efi_priv *priv = dev_get_priv(dev);
int ret;
/* We assume that EFI will stall if its output buffer fills up */
if (!input)
return 0;
ret = serial_efi_get_key(priv);
if (ret == -EAGAIN)
return 0;
else if (ret)
return ret;
return 1;
}
/*
* There is nothing to init here since the EFI console is already running by
* the time we enter U-Boot.
*/
void debug_uart_init(void)
{
}
static inline void _debug_uart_putc(int ch)
{
struct efi_system_table *sys_table = efi_get_sys_table();
uint16_t ucode[2];
ucode[0] = ch;
ucode[1] = '\0';
sys_table->con_out->output_string(sys_table->con_out, ucode);
}
DEBUG_UART_FUNCS
static int serial_efi_probe(struct udevice *dev)
{
struct efi_system_table *table = efi_get_sys_table();
struct serial_efi_priv *priv = dev_get_priv(dev);
priv->con_in = table->con_in;
priv->con_out = table->con_out;
return 0;
}
static const struct dm_serial_ops serial_efi_ops = {
.putc = serial_efi_putc,
.getc = serial_efi_getc,
.pending = serial_efi_pending,
.setbrg = serial_efi_setbrg,
};
static const struct udevice_id serial_efi_ids[] = {
{ .compatible = "efi,uart" },
{ }
};
U_BOOT_DRIVER(serial_efi) = {
.name = "serial_efi",
.id = UCLASS_SERIAL,
.of_match = serial_efi_ids,
.priv_auto_alloc_size = sizeof(struct serial_efi_priv),
.probe = serial_efi_probe,
.ops = &serial_efi_ops,
.flags = DM_FLAG_PRE_RELOC,
};

View File

@ -24,6 +24,14 @@ void *video_hw_init(void)
int ret;
printf("Video: ");
if (!ll_boot_init()) {
/*
* If we are running from EFI or coreboot, this driver can't
* work.
*/
printf("Not available (previous bootloader prevents it)\n");
return NULL;
}
if (vbe_get_video_info(gdev)) {
dev = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, 0);
if (dev == -1) {

View File

@ -104,7 +104,7 @@ typedef struct global_data {
#endif
/*
* Global Data Flags
* Global Data Flags - the top 16 bits are reserved for arch-specific flags
*/
#define GD_FLG_RELOC 0x00001 /* Code was relocated to RAM */
#define GD_FLG_DEVINIT 0x00002 /* Devices have been initialized */
@ -117,5 +117,6 @@ typedef struct global_data {
#define GD_FLG_SERIAL_READY 0x00100 /* Pre-reloc serial console ready */
#define GD_FLG_FULL_MALLOC_INIT 0x00200 /* Full malloc() is ready */
#define GD_FLG_SPL_INIT 0x00400 /* spl_init() has been called */
#define GD_FLG_SKIP_RELOC 0x00800 /* Don't relocate */
#endif /* __ASM_GENERIC_GBL_DATA_H */

View File

@ -1021,6 +1021,13 @@ int cpu_release(int nr, int argc, char * const argv[]);
offsetof(struct structure, member) == offset, \
"`struct " #structure "` offset for `" #member "` is not " #offset)
/* Avoid using CONFIG_EFI_STUB directly as we may boot from other loaders */
#ifdef CONFIG_EFI_STUB
#define ll_boot_init() false
#else
#define ll_boot_init() true
#endif
/* Pull in stuff for the build system */
#ifdef DO_DEPS_ONLY
# include <environment.h>

View File

@ -0,0 +1,44 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
/*
* board/config.h - configuration options, board specific
*/
#ifndef __CONFIG_H
#define __CONFIG_H
#include <configs/x86-common.h>
#define CONFIG_SYS_MONITOR_LEN (1 << 20)
#define CONFIG_ARCH_MISC_INIT
#define CONFIG_PCI_CONFIG_HOST_BRIDGE
#define CONFIG_SYS_EARLY_PCI_INIT
#define CONFIG_PCI_PNP
#define CONFIG_E1000
#define CONFIG_STD_DEVICES_SETTINGS "stdin=serial,vga,usbkbd\0" \
"stdout=serial,vga\0" \
"stderr=serial,vga\0"
#define CONFIG_SCSI_DEV_LIST \
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VALLEYVIEW_SATA}
#define CONFIG_MMC
#define CONFIG_SDHCI
#define CONFIG_GENERIC_MMC
#define CONFIG_MMC_SDMA
#define CONFIG_CMD_MMC
/* BayTrail IGD support */
#define CONFIG_VGA_AS_SINGLE_DEVICE
/* Environment configuration */
#define CONFIG_ENV_SECT_SIZE 0x1000
#define CONFIG_ENV_OFFSET 0x006ff000
#endif /* __CONFIG_H */

View File

@ -17,7 +17,6 @@
#define CONFIG_BOARD_EARLY_INIT_F
#define CONFIG_ARCH_MISC_INIT
#define CONFIG_X86_SERIAL
#define CONFIG_SMSC_LPC47M
#define CONFIG_PCI_MEM_BUS 0x40000000

34
include/configs/efi-x86.h Normal file
View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2015 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __CONFIG_H
#define __CONFIG_H
#include <configs/x86-common.h>
#undef CONFIG_CMD_SF_TEST
#undef CONFIG_TPM
#undef CONFIG_TPM_TIS_LPC
#undef CONFIG_TPM_TIS_BASE_ADDRESS
#undef CONFIG_CMD_IMLS
#undef CONFIG_SYS_NS16550
#undef CONFIG_X86_SERIAL
#undef CONFIG_ENV_IS_IN_SPI_FLASH
#define CONFIG_ENV_IS_NOWHERE
#undef CONFIG_VIDEO
#undef CONFIG_CFB_CONSOLE
#undef CONFIG_SCSI_AHCI
#undef CONFIG_CMD_SCSI
#undef CONFIG_INTEL_ICH6_GPIO
#define CONFIG_STD_DEVICES_SETTINGS "stdin=usbkbd,vga,serial\0" \
"stdout=vga,serial\0" \
"stderr=vga,serial\0"
#endif

View File

@ -17,8 +17,6 @@
#define CONFIG_BOARD_EARLY_INIT_F
#define CONFIG_ARCH_MISC_INIT
#define CONFIG_X86_SERIAL
/* ns16550 UART is memory-mapped in Quark SoC */
#undef CONFIG_SYS_NS16550_PORT_MAPPED

Some files were not shown because too many files have changed in this diff Show More