[U-Boot] [PATCH 38/48] efi: Add 64-bit payload support
Bin Meng
bmeng.cn at gmail.com
Fri Jul 24 09:39:49 CEST 2015
Hi Simon,
On Wed, Jul 22, 2015 at 11:49 PM, Simon Glass <sjg at chromium.org> wrote:
> Most EFI implementations use 64-bit. Add a way to build U-Boot as a 64-bit
> EFI payload. The payload unpacks a (32-bit) U-Boot and starts it. This can
> be enabled for x86 boards at present.
>
> Signed-off-by: Simon Glass <sjg at chromium.org>
> ---
>
> Makefile | 2 +-
> arch/x86/config.mk | 11 +++++++++
> arch/x86/include/asm/types.h | 5 +++-
> lib/efi/efi_stub.c | 58 ++++++++++++++++++++++++++++++++++++++++----
> 4 files changed, 69 insertions(+), 7 deletions(-)
>
> diff --git a/Makefile b/Makefile
> index 9f863e1..6e3edb4 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -1109,7 +1109,7 @@ u-boot-payload.lds: $(LDSCRIPT_EFI) FORCE
> u-boot-payload: u-boot-dtb.bin.o u-boot-payload.lds \
> FORCE
> $(LD) $(LDFLAGS_EFI) -o $@ \
> - -T u-boot-payload.lds \
> + -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/,$(EFISTUB))
>
> diff --git a/arch/x86/config.mk b/arch/x86/config.mk
> index bb0b254..5107b43 100644
> --- a/arch/x86/config.mk
> +++ b/arch/x86/config.mk
> @@ -15,7 +15,10 @@ PF_CPPFLAGS_X86 := $(call cc-option, -fno-toplevel-reorder, \
>
> PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_X86)
> PLATFORM_CPPFLAGS += -fno-dwarf2-cfi-asm
> +
> +ifeq ($(CONFIG_X86_64),)
Again I don't see CONFIG_X86_64 is introduced anywhere so far.
> PLATFORM_CPPFLAGS += -march=i386 -m32
> +endif
>
> PLATFORM_RELFLAGS += -ffunction-sections -fvisibility=hidden
>
> @@ -33,11 +36,19 @@ OBJCOPYFLAGS_EFI := -j .text -j .sdata -j .data -j .dynamic -j .dynsym \
> CFLAGS_NON_EFI := -mregparm=3
> CFLAGS_EFI := -fpic -fshort-wchar $(call cc-option, -mno-red-zone)
>
> +ifeq ($(CONFIG_X86_64)$(CONFIG_EFI_STUB_64BIT),)
> EFIARCH=ia32
> +else
> +EFIARCH=x86_64
> +endif
>
> 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_ARCH_EFI),y)
>
> PLATFORM_CPPFLAGS += $(CFLAGS_EFI)
> diff --git a/arch/x86/include/asm/types.h b/arch/x86/include/asm/types.h
> index e272c90..766617f 100644
> --- a/arch/x86/include/asm/types.h
> +++ b/arch/x86/include/asm/types.h
> @@ -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;
> diff --git a/lib/efi/efi_stub.c b/lib/efi/efi_stub.c
> index e3b7cdb..36f14ff 100644
> --- a/lib/efi/efi_stub.c
> +++ b/lib/efi/efi_stub.c
> @@ -6,8 +6,8 @@
> * EFI information obtained here:
> * http://wiki.phoenix.com/wiki/index.php/EFI_BOOT_SERVICES
> *
> - * Loads a payload (U-Boot) within the EFI environment. This is built as a
> - * 32-bit EFI application.
> + * Loads a payload (U-Boot) within the EFI environment. This is built as an
> + * EFI application. It can be built either in 32-bit or 64-bit mode.
> */
>
> #include <common.h>
> @@ -116,12 +116,12 @@ void *memset(void *inptr, int ch, size_t size)
>
> static void jump_to_uboot(ulong cs32, ulong addr, ulong info)
> {
> +#ifdef CONFIG_EFI_STUB_32BIT
> typedef void (*func_t)(int bist, int unused, ulong info);
>
> -#ifdef CONFIG_EFI_STUB_32BIT
> ((func_t)addr)(bist, 0, info);
> #else
> - /* TODO: Implement this */
> + cpu_call32(cs32, CONFIG_SYS_TEXT_BASE, info);
> #endif
> }
>
> @@ -151,7 +151,55 @@ static int get_codeseg32(void)
> {
> int cs32 = 0;
>
> - /* TODO(sjg): Implement this for 64-bit mode */
> +#ifdef CONFIG_EFI_STUB_64BIT
> + struct desctab_info gdt;
> + uint64_t *ptr;
> + int i;
> +
> + get_gdt(&gdt);
> + for (ptr = (uint64_t *)(unsigned long)gdt.addr, i = 0; i < gdt.limit;
> + i += 8, ptr++) {
> + uint64_t desc = *ptr;
> +
> + if ((desc & GDT_PRESENT) && (desc && GDT_NOTSYS) &&
> + !(desc & GDT_LONG) && (desc & GDT_4GB) &&
> + (desc & GDT_32BIT) && (desc & GDT_CODE)) {
I think only checking GDT_4KB is not enough. We should check segment
limit to make sure CONFIG_SYS_TEXT_BASE is within the range.
> + cs32 = i;
> + break;
> + }
> + }
> +
> +#ifdef DEBUG
> + puts("\ngdt: ");
> + printhex8(gdt.limit);
> + puts(", addr: ");
> + printhex8(gdt.addr >> 32);
> + printhex8(gdt.addr);
> + for (i = 0; i < gdt.limit; i += 8) {
> + uint32_t *ptr = (uint32_t *)((unsigned long)gdt.addr + i);
> +
> + puts("\n");
> + printhex2(i);
> + puts(": ");
> + printhex8(ptr[1]);
> + puts(" ");
> + printhex8(ptr[0]);
> + }
> + puts("\n ");
> + puts("32-bit code segment: ");
> + printhex2(cs32);
> + puts("\n ");
> +
> + puts("page_table: ");
> + printhex8(read_cr3());
> + puts("\n ");
> +#endif
> + if (!cs32) {
> + puts("Can't find 32-bit code segment\n");
> + return -ENOENT;
> + }
> +#endif
> +
> return cs32;
> }
>
Regards,
Bin
More information about the U-Boot
mailing list