Pārlūkot izejas kodu

Merge tag 'signed-efi-next' of git://github.com/agraf/u-boot

Patch queue for efi - 2018-07-25

Highlights this time:

  - Many small fixes to improve spec compatibility (found by SCT)
  - Almost enough to run with sandbox target
  - GetTime() improvements
  - Enable EFI_LOADER and HYP entry on ARMv7 with NONSEC=y
Tom Rini 5 gadi atpakaļ
vecāks
revīzija
406fd7e207
70 mainītis faili ar 1172 papildinājumiem un 402 dzēšanām
  1. 1 0
      MAINTAINERS
  2. 2 2
      arch/arm/config.mk
  3. 1 1
      arch/arm/cpu/armv7/Kconfig
  4. 2 0
      arch/arm/cpu/armv7/nonsec_virt.S
  5. 15 9
      arch/arm/cpu/armv8/u-boot.lds
  6. 21 15
      arch/arm/cpu/u-boot.lds
  7. 21 15
      arch/arm/mach-zynq/u-boot.lds
  8. 16 10
      arch/riscv/cpu/ax25/u-boot.lds
  9. 3 0
      arch/sandbox/config.mk
  10. 5 4
      arch/sandbox/cpu/u-boot.lds
  11. 2 0
      arch/x86/config.mk
  12. 1 1
      arch/x86/cpu/start.S
  13. 1 1
      arch/x86/cpu/start64.S
  14. 36 1
      arch/x86/cpu/u-boot-64.lds
  15. 19 15
      arch/x86/cpu/u-boot.lds
  16. 0 45
      arch/x86/include/asm/elf.h
  17. 0 1
      arch/x86/lib/reloc_ia32_efi.c
  18. 0 1
      arch/x86/lib/reloc_x86_64_efi.c
  19. 15 2
      board/qualcomm/dragonboard410c/u-boot.lds
  20. 15 9
      board/qualcomm/dragonboard820c/u-boot.lds
  21. 21 15
      board/ti/am335x/u-boot.lds
  22. 70 20
      cmd/bootefi.c
  23. 0 2
      doc/README.uefi
  24. 0 4
      drivers/rtc/at91sam9_rtt.c
  25. 0 2
      drivers/rtc/davinci.c
  26. 0 4
      drivers/rtc/ds1302.c
  27. 0 4
      drivers/rtc/ds1306.c
  28. 0 4
      drivers/rtc/ds1307.c
  29. 0 4
      drivers/rtc/ds1337.c
  30. 0 3
      drivers/rtc/ds1374.c
  31. 0 4
      drivers/rtc/ds164x.c
  32. 0 4
      drivers/rtc/ds174x.c
  33. 0 4
      drivers/rtc/ds3231.c
  34. 0 4
      drivers/rtc/imxdi.c
  35. 0 3
      drivers/rtc/m41t11.c
  36. 0 3
      drivers/rtc/m41t60.c
  37. 0 4
      drivers/rtc/m41t62.c
  38. 0 4
      drivers/rtc/m48t35ax.c
  39. 0 4
      drivers/rtc/max6900.c
  40. 0 3
      drivers/rtc/mc146818.c
  41. 0 4
      drivers/rtc/mcfrtc.c
  42. 0 4
      drivers/rtc/mk48t59.c
  43. 0 4
      drivers/rtc/pcf8563.c
  44. 0 3
      drivers/rtc/rs5c372.c
  45. 0 4
      drivers/rtc/rx8025.c
  46. 0 4
      drivers/rtc/s3c24x0_rtc.c
  47. 0 4
      drivers/rtc/x1205.c
  48. 15 1
      fs/fat/fat_write.c
  49. 8 0
      include/efi.h
  50. 11 5
      include/efi_api.h
  51. 10 3
      include/efi_loader.h
  52. 35 0
      include/elf.h
  53. 2 0
      lib/efi_driver/efi_block_device.c
  54. 0 2
      lib/efi_loader/Kconfig
  55. 3 0
      lib/efi_loader/Makefile
  56. 116 53
      lib/efi_loader/efi_boottime.c
  57. 8 1
      lib/efi_loader/efi_console.c
  58. 6 6
      lib/efi_loader/efi_image_loader.c
  59. 45 20
      lib/efi_loader/efi_memory.c
  60. 54 29
      lib/efi_loader/efi_runtime.c
  61. 9 2
      lib/efi_loader/efi_smbios.c
  62. 3 1
      lib/efi_selftest/.gitignore
  63. 4 1
      lib/efi_selftest/Makefile
  64. 6 8
      lib/efi_selftest/efi_selftest.c
  65. 70 0
      lib/efi_selftest/efi_selftest_block_device.c
  66. 266 0
      lib/efi_selftest/efi_selftest_config_table.c
  67. 22 11
      lib/efi_selftest/efi_selftest_console.c
  68. 141 0
      lib/efi_selftest/efi_selftest_crc32.c
  69. 67 0
      lib/efi_selftest/efi_selftest_rtc.c
  70. 4 1
      lib/vsprintf.c

+ 1 - 0
MAINTAINERS

@@ -368,6 +368,7 @@ F:	doc/README.iscsi
 F:	include/efi*
 F:	include/pe.h
 F:	include/asm-generic/pe.h
+F:	lib/charset.c
 F:	lib/efi*/
 F:	test/py/tests/test_efi*
 F:	cmd/bootefi.c

+ 2 - 2
arch/arm/config.mk

@@ -134,11 +134,11 @@ endif
 ifdef CONFIG_ARM64
 OBJCOPYFLAGS += -j .text -j .secure_text -j .secure_data -j .rodata -j .data \
 		-j .u_boot_list -j .rela.dyn -j .got -j .got.plt \
-		-j .binman_sym_table
+		-j .binman_sym_table -j .text_rest
 else
 OBJCOPYFLAGS += -j .text -j .secure_text -j .secure_data -j .rodata -j .hash \
 		-j .data -j .got -j .got.plt -j .u_boot_list -j .rel.dyn \
-		-j .binman_sym_table
+		-j .binman_sym_table -j .text_rest
 endif
 
 # if a dtb section exists we always have to include it

+ 1 - 1
arch/arm/cpu/armv7/Kconfig

@@ -53,7 +53,7 @@ config ARMV7_PSCI_NR_CPUS
 config ARMV7_LPAE
 	bool "Use LPAE page table format" if EXPERT
 	depends on CPU_V7A
-	default n
+	default y if ARMV7_VIRT
 	---help---
 	Say Y here to use the long descriptor page table format. This is
 	required if U-Boot runs in HYP mode.

+ 2 - 0
arch/arm/cpu/armv7/nonsec_virt.S

@@ -80,6 +80,8 @@ _secure_monitor:
 #ifdef CONFIG_ARMV7_VIRT
 	orreq	r5, r5, #0x100			@ allow HVC instruction
 	moveq	r6, #HYP_MODE			@ Enter the kernel as HYP
+	mrseq	r3, sp_svc
+	msreq	sp_hyp, r3			@ migrate SP
 #endif
 
 	mcr	p15, 0, r5, c1, c1, 0		@ write SCR (with NS bit set)

+ 15 - 9
arch/arm/cpu/armv8/u-boot.lds

@@ -25,6 +25,19 @@ SECTIONS
 	{
 		*(.__image_copy_start)
 		CPUDIR/start.o (.text*)
+	}
+
+	/* This needs to come before *(.text*) */
+	.efi_runtime : {
+                __efi_runtime_start = .;
+		*(.text.efi_runtime*)
+		*(.rodata.efi_runtime*)
+		*(.data.efi_runtime*)
+                __efi_runtime_stop = .;
+	}
+
+	.text_rest :
+	{
 		*(.text*)
 	}
 
@@ -98,17 +111,10 @@ SECTIONS
 
 	. = ALIGN(8);
 
-	.efi_runtime : {
-                __efi_runtime_start = .;
-		*(efi_runtime_text)
-		*(efi_runtime_data)
-                __efi_runtime_stop = .;
-	}
-
 	.efi_runtime_rel : {
                 __efi_runtime_rel_start = .;
-		*(.relaefi_runtime_text)
-		*(.relaefi_runtime_data)
+		*(.rel*.efi_runtime)
+		*(.rel*.efi_runtime.*)
                 __efi_runtime_rel_stop = .;
 	}
 

+ 21 - 15
arch/arm/cpu/u-boot.lds

@@ -43,6 +43,25 @@ SECTIONS
 		*(.__image_copy_start)
 		*(.vectors)
 		CPUDIR/start.o (.text*)
+	}
+
+	/* This needs to come before *(.text*) */
+	.__efi_runtime_start : {
+		*(.__efi_runtime_start)
+	}
+
+	.efi_runtime : {
+		*(.text.efi_runtime*)
+		*(.rodata.efi_runtime*)
+		*(.data.efi_runtime*)
+	}
+
+	.__efi_runtime_stop : {
+		*(.__efi_runtime_stop)
+	}
+
+	.text_rest :
+	{
 		*(.text*)
 	}
 
@@ -136,27 +155,14 @@ SECTIONS
 
 	. = ALIGN(4);
 
-	.__efi_runtime_start : {
-		*(.__efi_runtime_start)
-	}
-
-	.efi_runtime : {
-		*(efi_runtime_text)
-		*(efi_runtime_data)
-	}
-
-	.__efi_runtime_stop : {
-		*(.__efi_runtime_stop)
-	}
-
 	.efi_runtime_rel_start :
 	{
 		*(.__efi_runtime_rel_start)
 	}
 
 	.efi_runtime_rel : {
-		*(.relefi_runtime_text)
-		*(.relefi_runtime_data)
+		*(.rel*.efi_runtime)
+		*(.rel*.efi_runtime.*)
 	}
 
 	.efi_runtime_rel_stop :

+ 21 - 15
arch/arm/mach-zynq/u-boot.lds

@@ -19,6 +19,25 @@ SECTIONS
 		*(.__image_copy_start)
 		*(.vectors)
 		CPUDIR/start.o (.text*)
+	}
+
+	/* This needs to come before *(.text*) */
+	.__efi_runtime_start : {
+		*(.__efi_runtime_start)
+	}
+
+	.efi_runtime : {
+		*(.text.efi_runtime*)
+		*(.rodata.efi_runtime*)
+		*(.data.efi_runtime*)
+	}
+
+	.__efi_runtime_stop : {
+		*(.__efi_runtime_stop)
+	}
+
+	.text_rest :
+	{
 		*(.text*)
 	}
 
@@ -41,27 +60,14 @@ SECTIONS
 
 	. = ALIGN(4);
 
-	.__efi_runtime_start : {
-		*(.__efi_runtime_start)
-	}
-
-	.efi_runtime : {
-		*(efi_runtime_text)
-		*(efi_runtime_data)
-	}
-
-	.__efi_runtime_stop : {
-		*(.__efi_runtime_stop)
-	}
-
 	.efi_runtime_rel_start :
 	{
 		*(.__efi_runtime_rel_start)
 	}
 
 	.efi_runtime_rel : {
-		*(.relefi_runtime_text)
-		*(.relefi_runtime_data)
+		*(.rel*.efi_runtime)
+		*(.rel*.efi_runtime.*)
 	}
 
 	.efi_runtime_rel_stop :

+ 16 - 10
arch/riscv/cpu/ax25/u-boot.lds

@@ -12,7 +12,20 @@ SECTIONS
 	.text :
 	{
 		arch/riscv/cpu/ax25/start.o	(.text)
-		*(.text)
+	}
+
+	/* This needs to come before *(.text*) */
+	.efi_runtime : {
+                __efi_runtime_start = .;
+		*(.text.efi_runtime*)
+		*(.rodata.efi_runtime*)
+		*(.data.efi_runtime*)
+                __efi_runtime_stop = .;
+	}
+
+	.text_rest :
+	{
+		*(.text*)
 	}
 
 	. = ALIGN(4);
@@ -39,17 +52,10 @@ SECTIONS
 
     . = ALIGN(4);
 
-	.efi_runtime : {
-                __efi_runtime_start = .;
-		*(efi_runtime_text)
-		*(efi_runtime_data)
-                __efi_runtime_stop = .;
-	}
-
 	.efi_runtime_rel : {
                 __efi_runtime_rel_start = .;
-		*(.relaefi_runtime_text)
-		*(.relaefi_runtime_data)
+		*(.rel*.efi_runtime)
+		*(.rel*.efi_runtime.*)
                 __efi_runtime_rel_stop = .;
 	}
 

+ 3 - 0
arch/sandbox/config.mk

@@ -5,6 +5,9 @@ PLATFORM_CPPFLAGS += -D__SANDBOX__ -U_FORTIFY_SOURCE
 PLATFORM_CPPFLAGS += -DCONFIG_ARCH_MAP_SYSMEM
 PLATFORM_LIBS += -lrt
 
+LDFLAGS_FINAL += --gc-sections
+PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections
+
 # Define this to avoid linking with SDL, which requires SDL libraries
 # This can solve 'sdl-config: Command not found' errors
 ifneq ($(NO_SDL),)

+ 5 - 4
arch/sandbox/cpu/u-boot.lds

@@ -24,8 +24,9 @@ SECTIONS
 	}
 
 	.efi_runtime : {
-		*(efi_runtime_text)
-		*(efi_runtime_data)
+		*(.text.efi_runtime*)
+		*(.rodata.efi_runtime*)
+		*(.data.efi_runtime*)
 	}
 
 	.__efi_runtime_stop : {
@@ -38,8 +39,8 @@ SECTIONS
 	}
 
 	.efi_runtime_rel : {
-		*(.relefi_runtime_text)
-		*(.relefi_runtime_data)
+		*(.rel*.efi_runtime)
+		*(.rel*.efi_runtime.*)
 	}
 
 	.efi_runtime_rel_stop :

+ 2 - 0
arch/x86/config.mk

@@ -23,6 +23,8 @@ endif
 
 ifeq ($(IS_32BIT),y)
 PLATFORM_CPPFLAGS += -march=i386 -m32
+# TODO: These break on x86_64; need to debug further
+PLATFORM_RELFLAGS += -fdata-sections
 else
 PLATFORM_CPPFLAGS += $(if $(CONFIG_SPL_BUILD),,-fpic) -fno-common -m64
 endif

+ 1 - 1
arch/x86/cpu/start.S

@@ -17,7 +17,7 @@
 #include <generated/generic-asm-offsets.h>
 #include <generated/asm-offsets.h>
 
-.section .text
+.section .text.start
 .code32
 .globl _start
 .type _start, @function

+ 1 - 1
arch/x86/cpu/start64.S

@@ -8,7 +8,7 @@
 
 #include <config.h>
 
-.section .text
+.section .text.start
 .code64
 .globl _start
 .type _start, @function

+ 36 - 1
arch/x86/cpu/u-boot-64.lds

@@ -17,6 +17,23 @@ SECTIONS
 
 	. = CONFIG_SYS_TEXT_BASE;	/* Location of bootcode in flash */
 	__text_start = .;
+
+	.text.start : { *(.text.start); }
+
+	.__efi_runtime_start : {
+		*(.__efi_runtime_start)
+	}
+
+	.efi_runtime : {
+		*(.text.efi_runtime*)
+		*(.rodata.efi_runtime*)
+		*(.data.efi_runtime*)
+	}
+
+	.__efi_runtime_stop : {
+		*(.__efi_runtime_stop)
+	}
+
 	.text  : { *(.text*); }
 
 	. = ALIGN(4);
@@ -27,7 +44,10 @@ SECTIONS
 	}
 
 	. = ALIGN(4);
-	.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+	.rodata : {
+		*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+		KEEP(*(.rodata.efi.init));
+	}
 
 	. = ALIGN(4);
 	.data : { *(.data*) }
@@ -38,6 +58,21 @@ SECTIONS
 	. = ALIGN(4);
 	.got : { *(.got*) }
 
+	.efi_runtime_rel_start :
+	{
+		*(.__efi_runtime_rel_start)
+	}
+
+	.efi_runtime_rel : {
+		*(.rel*.efi_runtime)
+		*(.rel*.efi_runtime.*)
+	}
+
+	.efi_runtime_rel_stop :
+	{
+		*(.__efi_runtime_rel_stop)
+	}
+
 	. = ALIGN(4);
 	__data_end = .;
 	__init_end = .;

+ 19 - 15
arch/x86/cpu/u-boot.lds

@@ -17,6 +17,23 @@ SECTIONS
 
 	. = CONFIG_SYS_TEXT_BASE;	/* Location of bootcode in flash */
 	__text_start = .;
+
+	.text.start : { *(.text.start); }
+
+	.__efi_runtime_start : {
+		*(.__efi_runtime_start)
+	}
+
+	.efi_runtime : {
+		*(.text.efi_runtime*)
+		*(.rodata.efi_runtime*)
+		*(.data.efi_runtime*)
+	}
+
+	.__efi_runtime_stop : {
+		*(.__efi_runtime_stop)
+	}
+
 	.text  : { *(.text*); }
 
 	. = ALIGN(4);
@@ -43,27 +60,14 @@ SECTIONS
 
 	. = ALIGN(4);
 
-	.__efi_runtime_start : {
-		*(.__efi_runtime_start)
-	}
-
-	.efi_runtime : {
-		*(efi_runtime_text)
-		*(efi_runtime_data)
-	}
-
-	.__efi_runtime_stop : {
-		*(.__efi_runtime_stop)
-	}
-
 	.efi_runtime_rel_start :
 	{
 		*(.__efi_runtime_rel_start)
 	}
 
 	.efi_runtime_rel : {
-		*(.relefi_runtime_text)
-		*(.relefi_runtime_data)
+		*(.rel*.efi_runtime)
+		*(.rel*.efi_runtime.*)
 	}
 
 	.efi_runtime_rel_stop :

+ 0 - 45
arch/x86/include/asm/elf.h

@@ -1,45 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Brought in from Linux 4.1, removed things not useful to U-Boot.
- * The definitions perhaps came from the GNU Library which is GPL.
- */
-
-#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

+ 0 - 1
arch/x86/lib/reloc_ia32_efi.c

@@ -10,7 +10,6 @@
 #include <common.h>
 #include <efi.h>
 #include <elf.h>
-#include <asm/elf.h>
 
 efi_status_t EFIAPI _relocate(long ldbase, Elf32_Dyn *dyn)
 {

+ 0 - 1
arch/x86/lib/reloc_x86_64_efi.c

@@ -12,7 +12,6 @@
 #include <common.h>
 #include <efi.h>
 #include <elf.h>
-#include <asm/elf.h>
 
 efi_status_t EFIAPI _relocate(long ldbase, Elf64_Dyn *dyn)
 {

+ 15 - 2
board/qualcomm/dragonboard410c/u-boot.lds

@@ -20,6 +20,19 @@ SECTIONS
 		*(.__image_copy_start)
 		board/qualcomm/dragonboard410c/head.o (.text*)
 		CPUDIR/start.o (.text*)
+	}
+
+	/* This needs to come before *(.text*) */
+	.efi_runtime : {
+                __efi_runtime_start = .;
+		*(.text.efi_runtime*)
+		*(.rodata.efi_runtime*)
+		*(.data.efi_runtime*)
+                __efi_runtime_stop = .;
+	}
+
+	.text_rest :
+	{
 		*(.text*)
 	}
 
@@ -51,8 +64,8 @@ SECTIONS
 
 	.efi_runtime_rel : {
                 __efi_runtime_rel_start = .;
-		*(.relaefi_runtime_text)
-		*(.relaefi_runtime_data)
+		*(.rel*.efi_runtime)
+		*(.rel*.efi_runtime.*)
                 __efi_runtime_rel_stop = .;
 	}
 

+ 15 - 9
board/qualcomm/dragonboard820c/u-boot.lds

@@ -20,6 +20,19 @@ SECTIONS
 		*(.__image_copy_start)
 		board/qualcomm/dragonboard820c/head.o (.text*)
 		CPUDIR/start.o (.text*)
+	}
+
+	/* This needs to come before *(.text*) */
+	.efi_runtime : {
+                __efi_runtime_start = .;
+		*(.text.efi_runtime*)
+		*(.rodata.efi_runtime*)
+		*(.data.efi_runtime*)
+                __efi_runtime_stop = .;
+	}
+
+	.text_rest :
+	{
 		*(.text*)
 	}
 
@@ -42,17 +55,10 @@ SECTIONS
 
 	. = ALIGN(8);
 
-	.efi_runtime : {
-                __efi_runtime_start = .;
-		*(efi_runtime_text)
-		*(efi_runtime_data)
-                __efi_runtime_stop = .;
-	}
-
 	.efi_runtime_rel : {
                 __efi_runtime_rel_start = .;
-		*(.relaefi_runtime_text)
-		*(.relaefi_runtime_data)
+		*(.rel*.efi_runtime)
+		*(.rel*.efi_runtime.*)
                 __efi_runtime_rel_stop = .;
 	}
 

+ 21 - 15
board/ti/am335x/u-boot.lds

@@ -37,6 +37,25 @@ SECTIONS
 		*(.vectors)
 		CPUDIR/start.o (.text*)
 		board/ti/am335x/built-in.o (.text*)
+	}
+
+	/* This needs to come before *(.text*) */
+	.__efi_runtime_start : {
+		*(.__efi_runtime_start)
+	}
+
+	.efi_runtime : {
+		*(.text.efi_runtime*)
+		*(.rodata.efi_runtime*)
+		*(.data.efi_runtime*)
+	}
+
+	.__efi_runtime_stop : {
+		*(.__efi_runtime_stop)
+	}
+
+	.text_rest :
+	{
 		*(.text*)
 	}
 
@@ -59,27 +78,14 @@ SECTIONS
 
 	. = ALIGN(4);
 
-	.__efi_runtime_start : {
-		*(.__efi_runtime_start)
-	}
-
-	.efi_runtime : {
-		*(efi_runtime_text)
-		*(efi_runtime_data)
-	}
-
-	.__efi_runtime_stop : {
-		*(.__efi_runtime_stop)
-	}
-
 	.efi_runtime_rel_start :
 	{
 		*(.__efi_runtime_rel_start)
 	}
 
 	.efi_runtime_rel : {
-		*(.relefi_runtime_text)
-		*(.relefi_runtime_data)
+		*(.rel*.efi_runtime)
+		*(.rel*.efi_runtime.*)
 	}
 
 	.efi_runtime_rel_stop :

+ 70 - 20
cmd/bootefi.c

@@ -14,12 +14,18 @@
 #include <errno.h>
 #include <linux/libfdt.h>
 #include <linux/libfdt_env.h>
+#include <mapmem.h>
 #include <memalign.h>
 #include <asm/global_data.h>
 #include <asm-generic/sections.h>
 #include <asm-generic/unaligned.h>
 #include <linux/linkage.h>
 
+#ifdef CONFIG_ARMV7_NONSEC
+#include <asm/armv7.h>
+#include <asm/secure.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 #define OBJ_LIST_NOT_INITIALIZED 1
@@ -38,6 +44,11 @@ efi_status_t efi_init_obj_list(void)
 	if (efi_obj_list_initialized != OBJ_LIST_NOT_INITIALIZED)
 		return efi_obj_list_initialized;
 
+	/* Initialize system table */
+	ret = efi_initialize_system_table();
+	if (ret != EFI_SUCCESS)
+		goto out;
+
 	/* Initialize EFI driver uclass */
 	ret = efi_driver_init();
 	if (ret != EFI_SUCCESS)
@@ -79,9 +90,6 @@ efi_status_t efi_init_obj_list(void)
 	ret = efi_reset_system_init();
 	if (ret != EFI_SUCCESS)
 		goto out;
-	ret = efi_get_time_init();
-	if (ret != EFI_SUCCESS)
-		goto out;
 
 out:
 	efi_obj_list_initialized = ret;
@@ -142,8 +150,12 @@ static void *copy_fdt(void *fdt)
 			fdt_ram_start = ram_start;
 	}
 
-	/* Give us at least 4kb breathing room */
-	fdt_size = ALIGN(fdt_size + 4096, EFI_PAGE_SIZE);
+	/*
+	 * Give us at least 4KB of breathing room in case the device tree needs
+	 * to be expanded later. Round up to the nearest EFI page boundary.
+	 */
+	fdt_size += 4096;
+	fdt_size = ALIGN(fdt_size + EFI_PAGE_SIZE - 1, EFI_PAGE_SIZE);
 	fdt_pages = fdt_size >> EFI_PAGE_SHIFT;
 
 	/* Safe fdt location is at 128MB */
@@ -194,8 +206,32 @@ static efi_status_t efi_run_in_el2(EFIAPI efi_status_t (*entry)(
 }
 #endif
 
-/* Carve out DT reserved memory ranges */
-static efi_status_t efi_carve_out_dt_rsv(void *fdt)
+#ifdef CONFIG_ARMV7_NONSEC
+static bool is_nonsec;
+
+static efi_status_t efi_run_in_hyp(EFIAPI efi_status_t (*entry)(
+			efi_handle_t image_handle, struct efi_system_table *st),
+			efi_handle_t image_handle, struct efi_system_table *st)
+{
+	/* Enable caches again */
+	dcache_enable();
+
+	is_nonsec = true;
+
+	return efi_do_enter(image_handle, st, entry);
+}
+#endif
+
+/*
+ * efi_carve_out_dt_rsv() - Carve out DT reserved memory ranges
+ *
+ * The mem_rsv entries of the FDT are added to the memory map. Any failures are
+ * ignored because this is not critical and we would rather continue to try to
+ * boot.
+ *
+ * @fdt: Pointer to device tree
+ */
+static void efi_carve_out_dt_rsv(void *fdt)
 {
 	int nr_rsv, i;
 	uint64_t addr, size, pages;
@@ -208,11 +244,10 @@ static efi_status_t efi_carve_out_dt_rsv(void *fdt)
 			continue;
 
 		pages = ALIGN(size, EFI_PAGE_SIZE) >> EFI_PAGE_SHIFT;
-		efi_add_memory_map(addr, pages, EFI_RESERVED_MEMORY_TYPE,
-				   false);
+		if (!efi_add_memory_map(addr, pages, EFI_RESERVED_MEMORY_TYPE,
+					false))
+			printf("FDT memrsv map %d: Failed to add to map\n", i);
 	}
-
-	return EFI_SUCCESS;
 }
 
 static efi_status_t efi_install_fdt(void *fdt)
@@ -236,10 +271,7 @@ static efi_status_t efi_install_fdt(void *fdt)
 		return EFI_LOAD_ERROR;
 	}
 
-	if (efi_carve_out_dt_rsv(fdt) != EFI_SUCCESS) {
-		printf("ERROR: failed to carve out memory\n");
-		return EFI_LOAD_ERROR;
-	}
+	efi_carve_out_dt_rsv(fdt);
 
 	/* Link to it in the efi tables */
 	ret = efi_install_configuration_table(&efi_guid_fdt, fdt);
@@ -350,6 +382,22 @@ static efi_status_t do_bootefi_exec(void *efi,
 	}
 #endif
 
+#ifdef CONFIG_ARMV7_NONSEC
+	if (armv7_boot_nonsec() && !is_nonsec) {
+		dcache_disable();	/* flush cache before switch to HYP */
+
+		armv7_init_nonsec();
+		secure_ram_addr(_do_nonsec_entry)(
+					efi_run_in_hyp,
+					(uintptr_t)entry,
+					(uintptr_t)loaded_image_info_obj.handle,
+					(uintptr_t)&systab);
+
+		/* Should never reach here, efi exits with longjmp */
+		while (1) { }
+	}
+#endif
+
 	ret = efi_do_enter(loaded_image_info_obj.handle, &systab, entry);
 
 exit:
@@ -394,7 +442,8 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	unsigned long addr;
 	char *saddr;
 	efi_status_t r;
-	void *fdt_addr;
+	unsigned long fdt_addr;
+	void *fdt;
 
 	/* Allow unaligned memory access */
 	allow_unaligned();
@@ -411,11 +460,12 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 		return CMD_RET_USAGE;
 
 	if (argc > 2) {
-		fdt_addr = (void *)simple_strtoul(argv[2], NULL, 16);
+		fdt_addr = simple_strtoul(argv[2], NULL, 16);
 		if (!fdt_addr && *argv[2] != '0')
 			return CMD_RET_USAGE;
 		/* Install device tree */
-		r = efi_install_fdt(fdt_addr);
+		fdt = map_sysmem(fdt_addr, 0);
+		r = efi_install_fdt(fdt);
 		if (r != EFI_SUCCESS) {
 			printf("ERROR: failed to install device tree\n");
 			return CMD_RET_FAILURE;
@@ -434,7 +484,7 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 			addr = simple_strtoul(saddr, NULL, 16);
 		else
 			addr = CONFIG_SYS_LOAD_ADDR;
-		memcpy((char *)addr, __efi_helloworld_begin, size);
+		memcpy(map_sysmem(addr, size), __efi_helloworld_begin, size);
 	} else
 #endif
 #ifdef CONFIG_CMD_BOOTEFI_SELFTEST
@@ -480,7 +530,7 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	}
 
 	printf("## Starting EFI application at %08lx ...\n", addr);
-	r = do_bootefi_exec((void *)addr, bootefi_device_path,
+	r = do_bootefi_exec(map_sysmem(addr, 0), bootefi_device_path,
 			    bootefi_image_path);
 	printf("## Application terminated, r = %lu\n",
 	       r & ~EFI_ERROR_MASK);

+ 0 - 2
doc/README.uefi

@@ -329,8 +329,6 @@ This driver is only available if U-Boot is configured with
   * persistence
   * runtime support
 
-* support bootefi booting ARMv7 in non-secure mode (CONFIG_ARMV7_NONSEC=y)
-
 ## Links
 
 * [1](http://uefi.org/specifications)

+ 0 - 4
drivers/rtc/at91sam9_rtt.c

@@ -27,8 +27,6 @@
 #include <asm/arch/at91_rtt.h>
 #include <asm/arch/at91_gpbr.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 int rtc_get (struct rtc_time *tmp)
 {
 	at91_rtt_t *rtt = (at91_rtt_t *) ATMEL_BASE_RTT;
@@ -78,5 +76,3 @@ void rtc_reset (void)
 	while (readl(&rtt->vr) != 0)
 		;
 }
-
-#endif

+ 0 - 2
drivers/rtc/davinci.c

@@ -9,7 +9,6 @@
 #include <asm/io.h>
 #include <asm/davinci_rtc.h>
 
-#if defined(CONFIG_CMD_DATE)
 int rtc_get(struct rtc_time *tmp)
 {
 	struct davinci_rtc *rtc = (struct davinci_rtc *)DAVINCI_RTC_BASE;
@@ -79,4 +78,3 @@ void rtc_reset(void)
 	/* run RTC counter */
 	writel(0x01, &rtc->ctrl);
 }
-#endif

+ 0 - 4
drivers/rtc/ds1302.c

@@ -9,8 +9,6 @@
 #include <command.h>
 #include <rtc.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 /* GPP Pins */
 #define DATA		0x200
 #define SCLK		0x400
@@ -328,5 +326,3 @@ int rtc_set(struct rtc_time *tmp)
 
 	return 0;
 }
-
-#endif

+ 0 - 4
drivers/rtc/ds1306.c

@@ -19,8 +19,6 @@
 #include <rtc.h>
 #include <spi.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 #define	RTC_SECONDS		0x00
 #define	RTC_MINUTES		0x01
 #define	RTC_HOURS		0x02
@@ -437,5 +435,3 @@ static void rtc_write (unsigned char reg, unsigned char val)
 }
 
 #endif /* end of code exclusion (see #ifdef CONFIG_SXNI855T above) */
-
-#endif

+ 0 - 4
drivers/rtc/ds1307.c

@@ -51,8 +51,6 @@ enum ds_type {
 
 #ifndef CONFIG_DM_RTC
 
-#if defined(CONFIG_CMD_DATE)
-
 /*---------------------------------------------------------------------*/
 #undef DEBUG_RTC
 
@@ -204,8 +202,6 @@ static void rtc_write (uchar reg, uchar val)
 	i2c_reg_write (CONFIG_SYS_I2C_RTC_ADDR, reg, val);
 }
 
-#endif /* CONFIG_CMD_DATE*/
-
 #endif /* !CONFIG_DM_RTC */
 
 #ifdef CONFIG_DM_RTC

+ 0 - 4
drivers/rtc/ds1337.c

@@ -15,8 +15,6 @@
 #include <rtc.h>
 #include <i2c.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 /*
  * RTC register addresses
  */
@@ -190,5 +188,3 @@ static void rtc_write (uchar reg, uchar val)
 {
 	i2c_reg_write (CONFIG_SYS_I2C_RTC_ADDR, reg, val);
 }
-
-#endif

+ 0 - 3
drivers/rtc/ds1374.c

@@ -18,8 +18,6 @@
 #include <rtc.h>
 #include <i2c.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 /*---------------------------------------------------------------------*/
 #undef DEBUG_RTC
 #define DEBUG_RTC
@@ -214,4 +212,3 @@ static void rtc_write_raw (uchar reg, uchar val)
 {
 		i2c_reg_write (CONFIG_SYS_I2C_RTC_ADDR, reg, val);
 }
-#endif

+ 0 - 4
drivers/rtc/ds164x.c

@@ -20,8 +20,6 @@
 #include <rtc.h>
 
 
-#if defined(CONFIG_CMD_DATE)
-
 static uchar    rtc_read(unsigned int addr );
 static void     rtc_write(unsigned int addr, uchar val);
 
@@ -171,5 +169,3 @@ static void rtc_write( unsigned int addr, uchar val )
 #endif
 	*(volatile unsigned char*)(addr) = val;
 }
-
-#endif

+ 0 - 4
drivers/rtc/ds174x.c

@@ -16,8 +16,6 @@
 #include <command.h>
 #include <rtc.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 static uchar rtc_read( unsigned int addr );
 static void  rtc_write( unsigned int addr, uchar val);
 
@@ -172,5 +170,3 @@ static void rtc_write( unsigned int addr, uchar val )
 #endif
 	out8( addr, val );
 }
-
-#endif

+ 0 - 4
drivers/rtc/ds3231.c

@@ -16,8 +16,6 @@
 #include <rtc.h>
 #include <i2c.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 /*
  * RTC register addresses
  */
@@ -166,5 +164,3 @@ static void rtc_write (uchar reg, uchar val)
 {
 	i2c_reg_write (CONFIG_SYS_I2C_RTC_ADDR, reg, val);
 }
-
-#endif

+ 0 - 4
drivers/rtc/imxdi.c

@@ -17,8 +17,6 @@
 #include <linux/compat.h>
 #include <rtc.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 #include <asm/io.h>
 #include <asm/arch/imx-regs.h>
 
@@ -222,5 +220,3 @@ void rtc_reset(void)
 {
 	di_init();
 }
-
-#endif

+ 0 - 3
drivers/rtc/m41t11.c

@@ -29,8 +29,6 @@
 #endif
 */
 
-#if defined(CONFIG_SYS_I2C_RTC_ADDR) && defined(CONFIG_CMD_DATE)
-
 /* ------------------------------------------------------------------------- */
 /*
   these are simple defines for the chip local to here so they aren't too
@@ -167,4 +165,3 @@ void rtc_reset (void)
 	val = val & 0x3F;/*turn off freq test keep calibration*/
 	i2c_write(CONFIG_SYS_I2C_RTC_ADDR, RTC_CONTROL_ADDR, 1, &val, 1);
 }
-#endif

+ 0 - 3
drivers/rtc/m41t60.c

@@ -20,8 +20,6 @@
 #include <rtc.h>
 #include <i2c.h>
 
-#if defined(CONFIG_SYS_I2C_RTC_ADDR) && defined(CONFIG_CMD_DATE)
-
 /*
  * Convert between century and "century bits" (CB1 and CB0).  These routines
  * assume years are in the range 1900 - 2299.
@@ -237,4 +235,3 @@ void rtc_reset(void)
 	}
 	rtc_dump("end reset");
 }
-#endif /* CONFIG_RTC_M41T60 && CONFIG_SYS_I2C_RTC_ADDR && CONFIG_CMD_DATE */

+ 0 - 4
drivers/rtc/m41t62.c

@@ -18,8 +18,6 @@
 #include <rtc.h>
 #include <i2c.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 #define M41T62_REG_SSEC	0
 #define M41T62_REG_SEC	1
 #define M41T62_REG_MIN	2
@@ -130,5 +128,3 @@ void rtc_reset(void)
 	val &= ~M41T80_ALHOUR_HT;
 	i2c_write(CONFIG_SYS_I2C_RTC_ADDR, M41T62_REG_ALARM_HOUR, 1, &val, 1);
 }
-
-#endif

+ 0 - 4
drivers/rtc/m48t35ax.c

@@ -16,8 +16,6 @@
 #include <rtc.h>
 #include <config.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 static uchar rtc_read  (uchar reg);
 static void  rtc_write (uchar reg, uchar val);
 
@@ -135,5 +133,3 @@ static void rtc_write (uchar reg, uchar val)
 	*(unsigned char *)
 		((CONFIG_SYS_NVRAM_BASE_ADDR + CONFIG_SYS_NVRAM_SIZE - 8) + reg) = val;
 }
-
-#endif

+ 0 - 4
drivers/rtc/max6900.c

@@ -15,8 +15,6 @@
 #include <rtc.h>
 #include <i2c.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 #ifndef	CONFIG_SYS_I2C_RTC_ADDR
 #define	CONFIG_SYS_I2C_RTC_ADDR	0x50
 #endif
@@ -104,5 +102,3 @@ int rtc_set (struct rtc_time *tmp)
 void rtc_reset (void)
 {
 }
-
-#endif

+ 0 - 3
drivers/rtc/mc146818.c

@@ -19,8 +19,6 @@
 #define out8(p, v) outb(v, p)
 #endif
 
-#if defined(CONFIG_CMD_DATE)
-
 /* Set this to 1 to clear the CMOS RAM */
 #define CLEAR_CMOS		0
 
@@ -196,7 +194,6 @@ static void mc146818_init(void)
 	/* Clear any pending interrupts */
 	mc146818_read8(RTC_CONFIG_C);
 }
-#endif /* CONFIG_CMD_DATE */
 
 #ifdef CONFIG_DM_RTC
 

+ 0 - 4
drivers/rtc/mcfrtc.c

@@ -6,8 +6,6 @@
 
 #include <common.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 #include <command.h>
 #include <rtc.h>
 #include <asm/immap.h>
@@ -104,5 +102,3 @@ void rtc_reset(void)
 
 	rtc->cr |= RTC_CR_SWR;
 }
-
-#endif				/* CONFIG_MCFRTC && CONFIG_CMD_DATE */

+ 0 - 4
drivers/rtc/mk48t59.c

@@ -70,8 +70,6 @@ void nvram_write(short dest, const void *src, size_t count)
 		rtc_write(d++, *s++);
 }
 
-#if defined(CONFIG_CMD_DATE)
-
 /* ------------------------------------------------------------------------- */
 
 int rtc_get (struct rtc_time *tmp)
@@ -175,5 +173,3 @@ void rtc_set_watchdog(short multi, short res)
 	wd_value = RTC_WDS | ((multi & 0x1F) << 2) | (res & 0x3);
 	rtc_write(RTC_WATCHDOG, wd_value);
 }
-
-#endif

+ 0 - 4
drivers/rtc/pcf8563.c

@@ -15,8 +15,6 @@
 #include <rtc.h>
 #include <i2c.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 static uchar rtc_read  (uchar reg);
 static void  rtc_write (uchar reg, uchar val);
 
@@ -117,5 +115,3 @@ static void rtc_write (uchar reg, uchar val)
 {
 	i2c_reg_write (CONFIG_SYS_I2C_RTC_ADDR, reg, val);
 }
-
-#endif

+ 0 - 3
drivers/rtc/rs5c372.c

@@ -24,7 +24,6 @@
 #include <rtc.h>
 #include <i2c.h>
 
-#if defined(CONFIG_CMD_DATE)
 /*
  * Reads are always done starting with register 15, which requires some
  * jumping-through-hoops to access the data correctly.
@@ -255,5 +254,3 @@ rtc_reset (void)
 	if (!setup_done)
 		rs5c372_enable();
 }
-
-#endif

+ 0 - 4
drivers/rtc/rx8025.c

@@ -13,8 +13,6 @@
 #include <rtc.h>
 #include <i2c.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 /*---------------------------------------------------------------------*/
 #undef DEBUG_RTC
 
@@ -190,5 +188,3 @@ static void rtc_write (uchar reg, uchar val)
 		printf("Error writing to RTC\n");
 
 }
-
-#endif /* CONFIG_RTC_RX8025 && CONFIG_CMD_DATE */

+ 0 - 4
drivers/rtc/s3c24x0_rtc.c

@@ -11,8 +11,6 @@
 #include <common.h>
 #include <command.h>
 
-#if (defined(CONFIG_CMD_DATE))
-
 #include <asm/arch/s3c24x0_cpu.h>
 
 #include <rtc.h>
@@ -149,5 +147,3 @@ void rtc_reset(void)
 	writeb((readb(&rtc->rtccon) & ~0x06) | 0x08, &rtc->rtccon);
 	writeb(readb(&rtc->rtccon) & ~(0x08 | 0x01), &rtc->rtccon);
 }
-
-#endif

+ 0 - 4
drivers/rtc/x1205.c

@@ -22,8 +22,6 @@
 #include <rtc.h>
 #include <i2c.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 #define CCR_SEC			0
 #define CCR_MIN			1
 #define CCR_HOUR		2
@@ -160,5 +158,3 @@ void rtc_reset(void)
 	 * Nothing to do
 	 */
 }
-
-#endif

+ 15 - 1
fs/fat/fat_write.c

@@ -909,9 +909,11 @@ static int do_fat_write(const char *filename, void *buffer, loff_t size,
 	volume_info volinfo;
 	fsdata datablock;
 	fsdata *mydata = &datablock;
-	int cursect;
+	int cursect, i;
 	int ret = -1, name_len;
 	char l_filename[VFAT_MAXLEN_BYTES];
+	char bad[2] = " ";
+	const char illegal[] = "<>:\"/\\|?*";
 
 	*actwrite = size;
 	dir_curclust = 0;
@@ -971,6 +973,18 @@ static int do_fat_write(const char *filename, void *buffer, loff_t size,
 	}
 	dentptr = (dir_entry *) do_fat_read_at_block;
 
+	/* Strip leading (back-)slashes */
+	while ISDIRDELIM(*filename)
+		++filename;
+	/* Check that the filename is valid */
+	for (i = 0; i < strlen(illegal); ++i) {
+		*bad = illegal[i];
+		if (strstr(filename, bad)) {
+			printf("FAT: illegal filename (%s)\n", filename);
+			return -1;
+		}
+	}
+
 	name_len = strlen(filename);
 	if (name_len >= VFAT_MAXLEN_BYTES)
 		name_len = VFAT_MAXLEN_BYTES - 1;

+ 8 - 0
include/efi.h

@@ -29,8 +29,16 @@
  */
 #ifdef __x86_64__
 #define EFIAPI __attribute__((ms_abi))
+#define efi_va_list __builtin_ms_va_list
+#define efi_va_start __builtin_ms_va_start
+#define efi_va_arg __builtin_va_arg
+#define efi_va_end __builtin_ms_va_end
 #else
 #define EFIAPI asmlinkage
+#define efi_va_list va_list
+#define efi_va_start va_start
+#define efi_va_arg va_arg
+#define efi_va_end va_end
 #endif /* __x86_64__ */
 
 struct efi_device_path;

+ 11 - 5
include/efi_api.h

@@ -21,6 +21,9 @@
 #include <asm/setjmp.h>
 #endif
 
+/* UEFI spec version 2.7 */
+#define EFI_SPECIFICATION_VERSION (2 << 16 | 70)
+
 /* Types and defines for EFI CreateEvent */
 enum efi_timer_delay {
 	EFI_TIMER_STOP = 0,
@@ -46,6 +49,7 @@ typedef uint16_t *efi_string_t;
 struct efi_event;
 
 /* EFI Boot Services table */
+#define EFI_BOOT_SERVICES_SIGNATURE 0x56524553544f4f42
 struct efi_boot_services {
 	struct efi_table_hdr hdr;
 	efi_status_t (EFIAPI *raise_tpl)(efi_uintn_t new_tpl);
@@ -161,8 +165,9 @@ struct efi_boot_services {
 			void **handle, ...);
 	efi_status_t (EFIAPI *uninstall_multiple_protocol_interfaces)(
 			void *handle, ...);
-	efi_status_t (EFIAPI *calculate_crc32)(void *data,
-			unsigned long data_size, uint32_t *crc32);
+	efi_status_t (EFIAPI *calculate_crc32)(const void *data,
+					       efi_uintn_t data_size,
+					       u32 *crc32);
 	void (EFIAPI *copy_mem)(void *destination, const void *source,
 			size_t length);
 	void (EFIAPI *set_mem)(void *buffer, size_t size, uint8_t value);
@@ -185,8 +190,7 @@ enum efi_reset_type {
 };
 
 /* EFI Runtime Services table */
-#define EFI_RUNTIME_SERVICES_SIGNATURE	0x5652453544e5552ULL
-#define EFI_RUNTIME_SERVICES_REVISION	0x00010000
+#define EFI_RUNTIME_SERVICES_SIGNATURE	0x56524553544e5552ULL
 
 #define CAPSULE_FLAGS_PERSIST_ACROSS_RESET	0x00010000
 #define CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE	0x00020000
@@ -300,7 +304,7 @@ struct efi_configuration_table
 
 struct efi_system_table {
 	struct efi_table_hdr hdr;
-	unsigned long fw_vendor;   /* physical addr of wchar_t vendor string */
+	u16 *fw_vendor;   /* physical addr of wchar_t vendor string */
 	u32 fw_revision;
 	efi_handle_t con_in_handle;
 	struct efi_simple_input_interface *con_in;
@@ -318,6 +322,8 @@ struct efi_system_table {
 	EFI_GUID(0x5b1b31a1, 0x9562, 0x11d2, \
 		 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
 
+#define EFI_LOADED_IMAGE_PROTOCOL_REVISION 0x1000
+
 struct efi_loaded_image {
 	u32 revision;
 	void *parent_handle;

+ 10 - 3
include/efi_loader.h

@@ -17,6 +17,9 @@
 
 #include <linux/list.h>
 
+/* Maximum number of configuration tables */
+#define EFI_MAX_CONFIGURATION_TABLES 16
+
 int __efi_entry_check(void);
 int __efi_exit_check(void);
 const char *__efi_nesting(void);
@@ -82,6 +85,9 @@ const char *__efi_nesting_dec(void);
 #define EFI_CACHELINE_SIZE 128
 #endif
 
+/* Key identifying current memory map */
+extern efi_uintn_t efi_memory_map_key;
+
 extern struct efi_runtime_services efi_runtime_services;
 extern struct efi_system_table systab;
 
@@ -199,6 +205,8 @@ extern struct list_head efi_obj_list;
 /* List of all events */
 extern struct list_head efi_events;
 
+/* Called by bootefi to initialize runtime */
+efi_status_t efi_initialize_system_table(void);
 /* Called by bootefi to make console interface available */
 int efi_console_register(void);
 /* Called by bootefi to make all disk storage accessible as EFI objects */
@@ -406,8 +414,8 @@ static inline int guidcmp(const efi_guid_t *g1, const efi_guid_t *g2)
  * Use these to indicate that your code / data should go into the EFI runtime
  * section and thus still be available when the OS is running
  */
-#define __efi_runtime_data __attribute__ ((section ("efi_runtime_data")))
-#define __efi_runtime __attribute__ ((section ("efi_runtime_text")))
+#define __efi_runtime_data __attribute__ ((section (".data.efi_runtime")))
+#define __efi_runtime __attribute__ ((section (".text.efi_runtime")))
 
 /* Call this with mmio_ptr as the _pointer_ to a pointer to an MMIO region
  * to make it available at runtime */
@@ -426,7 +434,6 @@ efi_status_t efi_reset_system_init(void);
 efi_status_t __efi_runtime EFIAPI efi_get_time(
 			struct efi_time *time,
 			struct efi_time_cap *capabilities);
-efi_status_t efi_get_time_init(void);
 
 #ifdef CONFIG_CMD_BOOTEFI_SELFTEST
 /*

+ 35 - 0
include/elf.h

@@ -550,6 +550,41 @@ unsigned long elf_hash(const unsigned char *name);
 
 #endif /* __ASSEMBLER */
 
+/* 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
+
 /*
  * XXX - PowerPC defines really don't belong in here,
  * but we'll put them in for simplicity.

+ 2 - 0
lib/efi_driver/efi_block_device.c

@@ -161,6 +161,8 @@ static int efi_bl_bind(efi_handle_t handle, void *interface)
 		return ret;
 	if (!bdev)
 		return -ENOENT;
+	/* Set the DM_FLAG_NAME_ALLOCED flag to avoid a memory leak */
+	device_set_name_alloced(bdev);
 	/* Allocate priv */
 	ret = device_probe(bdev);
 	if (ret)

+ 0 - 2
lib/efi_loader/Kconfig

@@ -1,8 +1,6 @@
 config EFI_LOADER
 	bool "Support running EFI Applications in U-Boot"
 	depends on (ARM || X86 || RISCV) && OF_LIBFDT
-	# We do not support bootefi booting ARMv7 in non-secure mode
-	depends on !ARMV7_NONSEC
 	# We need EFI_STUB_64BIT to be set on x86_64 with EFI_STUB
 	depends on !EFI_STUB || !X86_64 || EFI_STUB_64BIT
 	# We need EFI_STUB_32BIT to be set on x86_32 with EFI_STUB

+ 3 - 0
lib/efi_loader/Makefile

@@ -6,6 +6,9 @@
 # This file only gets included with CONFIG_EFI_LOADER set, so all
 # object inclusion implicitly depends on it
 
+CFLAGS_efi_boottime.o += \
+  -DFW_VERSION="0x$(VERSION)" \
+  -DFW_PATCHLEVEL="0x$(PATCHLEVEL)"
 CFLAGS_helloworld.o := $(CFLAGS_EFI) -Os -ffreestanding
 CFLAGS_REMOVE_helloworld.o := $(CFLAGS_NON_EFI) -Os
 

+ 116 - 53
lib/efi_loader/efi_boottime.c

@@ -35,16 +35,6 @@ LIST_HEAD(efi_events);
  */
 static bool efi_is_direct_boot = true;
 
-/*
- * EFI can pass arbitrary additional "tables" containing vendor specific
- * information to the payload. One such table is the FDT table which contains
- * a pointer to a flattened device tree blob.
- *
- * In most cases we want to pass an FDT to the payload, so reserve one slot of
- * config table space for it. The pointer gets populated by do_bootefi_exec().
- */
-static struct efi_configuration_table __efi_runtime_data efi_conf_table[16];
-
 #ifdef CONFIG_ARM
 /*
  * The "gd" pointer lives in a register on ARM and AArch64 that we declare
@@ -163,6 +153,18 @@ const char *__efi_nesting_dec(void)
 	return indent_string(--nesting_level);
 }
 
+/**
+ * efi_update_table_header_crc32() - Update CRC32 in table header
+ *
+ * @table:	EFI table
+ */
+static void efi_update_table_header_crc32(struct efi_table_hdr *table)
+{
+	table->crc32 = 0;
+	table->crc32 = crc32(0, (const unsigned char *)table,
+			     table->headersize);
+}
+
 /**
  * efi_queue_event() - queue an EFI event
  * @event:     event to signal
@@ -190,6 +192,25 @@ static void efi_queue_event(struct efi_event *event, bool check_tpl)
 	event->is_queued = false;
 }
 
+/**
+ * is_valid_tpl() - check if the task priority level is valid
+ *
+ * @tpl:		TPL level to check
+ * ReturnValue:		status code
+ */
+efi_status_t is_valid_tpl(efi_uintn_t tpl)
+{
+	switch (tpl) {
+	case TPL_APPLICATION:
+	case TPL_CALLBACK:
+	case TPL_NOTIFY:
+	case TPL_HIGH_LEVEL:
+		return EFI_SUCCESS;
+	default:
+		return EFI_INVALID_PARAMETER;
+	}
+}
+
 /**
  * efi_signal_event() - signal an EFI event
  * @event:     event to signal
@@ -592,11 +613,21 @@ efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl,
 	if (event == NULL)
 		return EFI_INVALID_PARAMETER;
 
-	if ((type & EVT_NOTIFY_SIGNAL) && (type & EVT_NOTIFY_WAIT))
+	switch (type) {
+	case 0:
+	case EVT_TIMER:
+	case EVT_NOTIFY_SIGNAL:
+	case EVT_TIMER | EVT_NOTIFY_SIGNAL:
+	case EVT_NOTIFY_WAIT:
+	case EVT_TIMER | EVT_NOTIFY_WAIT:
+	case EVT_SIGNAL_EXIT_BOOT_SERVICES:
+	case EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE:
+		break;
+	default:
 		return EFI_INVALID_PARAMETER;
+	}
 
-	if ((type & (EVT_NOTIFY_SIGNAL | EVT_NOTIFY_WAIT)) &&
-	    notify_function == NULL)
+	if (is_valid_tpl(notify_tpl) != EFI_SUCCESS)
 		return EFI_INVALID_PARAMETER;
 
 	evt = calloc(1, sizeof(struct efi_event));
@@ -1361,9 +1392,9 @@ static efi_status_t EFIAPI efi_locate_handle_ext(
  */
 static void efi_remove_configuration_table(int i)
 {
-	struct efi_configuration_table *this = &efi_conf_table[i];
-	struct efi_configuration_table *next = &efi_conf_table[i + 1];
-	struct efi_configuration_table *end = &efi_conf_table[systab.nr_tables];
+	struct efi_configuration_table *this = &systab.tables[i];
+	struct efi_configuration_table *next = &systab.tables[i + 1];
+	struct efi_configuration_table *end = &systab.tables[systab.nr_tables];
 
 	memmove(this, next, (ulong)end - (ulong)next);
 	systab.nr_tables--;
@@ -1391,9 +1422,9 @@ efi_status_t efi_install_configuration_table(const efi_guid_t *guid,
 
 	/* Check for guid override */
 	for (i = 0; i < systab.nr_tables; i++) {
-		if (!guidcmp(guid, &efi_conf_table[i].guid)) {
+		if (!guidcmp(guid, &systab.tables[i].guid)) {
 			if (table)
-				efi_conf_table[i].table = table;
+				systab.tables[i].table = table;
 			else
 				efi_remove_configuration_table(i);
 			goto out;
@@ -1404,15 +1435,18 @@ efi_status_t efi_install_configuration_table(const efi_guid_t *guid,
 		return EFI_NOT_FOUND;
 
 	/* No override, check for overflow */
-	if (i >= ARRAY_SIZE(efi_conf_table))
+	if (i >= EFI_MAX_CONFIGURATION_TABLES)
 		return EFI_OUT_OF_RESOURCES;
 
 	/* Add a new entry */
-	memcpy(&efi_conf_table[i].guid, guid, sizeof(*guid));
-	efi_conf_table[i].table = table;
+	memcpy(&systab.tables[i].guid, guid, sizeof(*guid));
+	systab.tables[i].table = table;
 	systab.nr_tables = i + 1;
 
 out:
+	/* systab.nr_tables may have changed. So we need to update the crc32 */
+	efi_update_table_header_crc32(&systab.hdr);
+
 	/* Notify that the configuration table was changed */
 	list_for_each_entry(evt, &efi_events, link) {
 		if (evt->group && !guidcmp(evt->group, guid)) {
@@ -1468,6 +1502,7 @@ efi_status_t efi_setup_loaded_image(
 	/* efi_exit() assumes that the handle points to the info */
 	obj->handle = info;
 
+	info->revision =  EFI_LOADED_IMAGE_PROTOCOL_REVISION;
 	info->file_path = file_path;
 
 	if (device_path) {
@@ -1825,6 +1860,10 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
 
 	EFI_ENTRY("%p, %ld", image_handle, map_key);
 
+	/* Check that the caller has read the current memory map */
+	if (map_key != efi_memory_map_key)
+		return EFI_INVALID_PARAMETER;
+
 	/* Make sure that notification functions are not called anymore */
 	efi_tpl = TPL_HIGH_LEVEL;
 
@@ -1867,9 +1906,7 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
 	systab.boottime = NULL;
 
 	/* Recalculate CRC32 */
-	systab.hdr.crc32 = 0;
-	systab.hdr.crc32 = crc32(0, (const unsigned char *)&systab,
-				 sizeof(struct efi_system_table));
+	efi_update_table_header_crc32(&systab.hdr);
 
 	/* Give the payload some time to boot */
 	efi_set_watchdog(0);
@@ -2302,7 +2339,7 @@ static efi_status_t EFIAPI efi_install_multiple_protocol_interfaces(
 {
 	EFI_ENTRY("%p", handle);
 
-	va_list argptr;
+	efi_va_list argptr;
 	const efi_guid_t *protocol;
 	void *protocol_interface;
 	efi_status_t r = EFI_SUCCESS;
@@ -2311,12 +2348,12 @@ static efi_status_t EFIAPI efi_install_multiple_protocol_interfaces(
 	if (!handle)
 		return EFI_EXIT(EFI_INVALID_PARAMETER);
 
-	va_start(argptr, handle);
+	efi_va_start(argptr, handle);
 	for (;;) {
-		protocol = va_arg(argptr, efi_guid_t*);
+		protocol = efi_va_arg(argptr, efi_guid_t*);
 		if (!protocol)
 			break;
-		protocol_interface = va_arg(argptr, void*);
+		protocol_interface = efi_va_arg(argptr, void*);
 		r = EFI_CALL(efi_install_protocol_interface(
 						handle, protocol,
 						EFI_NATIVE_INTERFACE,
@@ -2325,19 +2362,19 @@ static efi_status_t EFIAPI efi_install_multiple_protocol_interfaces(
 			break;
 		i++;
 	}
-	va_end(argptr);
+	efi_va_end(argptr);
 	if (r == EFI_SUCCESS)
 		return EFI_EXIT(r);
 
 	/* If an error occurred undo all changes. */
-	va_start(argptr, handle);
+	efi_va_start(argptr, handle);
 	for (; i; --i) {
-		protocol = va_arg(argptr, efi_guid_t*);
-		protocol_interface = va_arg(argptr, void*);
+		protocol = efi_va_arg(argptr, efi_guid_t*);
+		protocol_interface = efi_va_arg(argptr, void*);
 		EFI_CALL(efi_uninstall_protocol_interface(handle, protocol,
 							  protocol_interface));
 	}
-	va_end(argptr);
+	efi_va_end(argptr);
 
 	return EFI_EXIT(r);
 }
@@ -2361,7 +2398,7 @@ static efi_status_t EFIAPI efi_uninstall_multiple_protocol_interfaces(
 {
 	EFI_ENTRY("%p", handle);
 
-	va_list argptr;
+	efi_va_list argptr;
 	const efi_guid_t *protocol;
 	void *protocol_interface;
 	efi_status_t r = EFI_SUCCESS;
@@ -2370,12 +2407,12 @@ static efi_status_t EFIAPI efi_uninstall_multiple_protocol_interfaces(
 	if (!handle)
 		return EFI_EXIT(EFI_INVALID_PARAMETER);
 
-	va_start(argptr, handle);
+	efi_va_start(argptr, handle);
 	for (;;) {
-		protocol = va_arg(argptr, efi_guid_t*);
+		protocol = efi_va_arg(argptr, efi_guid_t*);
 		if (!protocol)
 			break;
-		protocol_interface = va_arg(argptr, void*);
+		protocol_interface = efi_va_arg(argptr, void*);
 		r = EFI_CALL(efi_uninstall_protocol_interface(
 						handle, protocol,
 						protocol_interface));
@@ -2383,20 +2420,20 @@ static efi_status_t EFIAPI efi_uninstall_multiple_protocol_interfaces(
 			break;
 		i++;
 	}
-	va_end(argptr);
+	efi_va_end(argptr);
 	if (r == EFI_SUCCESS)
 		return EFI_EXIT(r);
 
 	/* If an error occurred undo all changes. */
-	va_start(argptr, handle);
+	efi_va_start(argptr, handle);
 	for (; i; --i) {
-		protocol = va_arg(argptr, efi_guid_t*);
-		protocol_interface = va_arg(argptr, void*);
+		protocol = efi_va_arg(argptr, efi_guid_t*);
+		protocol_interface = efi_va_arg(argptr, void*);
 		EFI_CALL(efi_install_protocol_interface(&handle, protocol,
 							EFI_NATIVE_INTERFACE,
 							protocol_interface));
 	}
-	va_end(argptr);
+	efi_va_end(argptr);
 
 	return EFI_EXIT(r);
 }
@@ -2414,11 +2451,11 @@ static efi_status_t EFIAPI efi_uninstall_multiple_protocol_interfaces(
  *
  * Return: status code
  */
-static efi_status_t EFIAPI efi_calculate_crc32(void *data,
-					       unsigned long data_size,
-					       uint32_t *crc32_p)
+static efi_status_t EFIAPI efi_calculate_crc32(const void *data,
+					       efi_uintn_t data_size,
+					       u32 *crc32_p)
 {
-	EFI_ENTRY("%p, %ld", data, data_size);
+	EFI_ENTRY("%p, %zu", data, data_size);
 	*crc32_p = crc32(0, data, data_size);
 	return EFI_EXIT(EFI_SUCCESS);
 }
@@ -3022,9 +3059,11 @@ out:
 	return EFI_EXIT(r);
 }
 
-static const struct efi_boot_services efi_boot_services = {
+static struct efi_boot_services efi_boot_services = {
 	.hdr = {
-		.headersize = sizeof(struct efi_table_hdr),
+		.signature = EFI_BOOT_SERVICES_SIGNATURE,
+		.revision = EFI_SPECIFICATION_VERSION,
+		.headersize = sizeof(struct efi_boot_services),
 	},
 	.raise_tpl = efi_raise_tpl,
 	.restore_tpl = efi_restore_tpl,
@@ -3074,20 +3113,44 @@ static const struct efi_boot_services efi_boot_services = {
 	.create_event_ex = efi_create_event_ex,
 };
 
-static uint16_t __efi_runtime_data firmware_vendor[] = L"Das U-Boot";
+static u16 __efi_runtime_data firmware_vendor[] = L"Das U-Boot";
 
 struct efi_system_table __efi_runtime_data systab = {
 	.hdr = {
 		.signature = EFI_SYSTEM_TABLE_SIGNATURE,
-		.revision = 2 << 16 | 70, /* 2.7 */
-		.headersize = sizeof(struct efi_table_hdr),
+		.revision = EFI_SPECIFICATION_VERSION,
+		.headersize = sizeof(struct efi_system_table),
 	},
-	.fw_vendor = (long)firmware_vendor,
+	.fw_vendor = firmware_vendor,
+	.fw_revision = FW_VERSION << 16 | FW_PATCHLEVEL << 8,
 	.con_in = (void *)&efi_con_in,
 	.con_out = (void *)&efi_con_out,
 	.std_err = (void *)&efi_con_out,
 	.runtime = (void *)&efi_runtime_services,
 	.boottime = (void *)&efi_boot_services,
 	.nr_tables = 0,
-	.tables = (void *)efi_conf_table,
+	.tables = NULL,
 };
+
+/**
+ * efi_initialize_system_table() - Initialize system table
+ *
+ * Return Value:        status code
+ */
+efi_status_t efi_initialize_system_table(void)
+{
+	efi_status_t ret;
+
+	/* Allocate configuration table array */
+	ret = efi_allocate_pool(EFI_RUNTIME_SERVICES_DATA,
+				EFI_MAX_CONFIGURATION_TABLES *
+				sizeof(struct efi_configuration_table),
+				(void **)&systab.tables);
+
+	/* Set crc32 field in table headers */
+	efi_update_table_header_crc32(&systab.hdr);
+	efi_update_table_header_crc32(&efi_runtime_services.hdr);
+	efi_update_table_header_crc32(&efi_boot_services.hdr);
+
+	return ret;
+}

+ 8 - 1
lib/efi_loader/efi_console.c

@@ -335,6 +335,8 @@ static efi_status_t EFIAPI efi_cout_clear_screen(
 	EFI_ENTRY("%p", this);
 
 	printf(ESC"[2J");
+	efi_con_mode.cursor_column = 0;
+	efi_con_mode.cursor_row = 0;
 
 	return EFI_EXIT(EFI_SUCCESS);
 }
@@ -381,7 +383,12 @@ static efi_status_t EFIAPI efi_cin_reset(
 			bool extended_verification)
 {
 	EFI_ENTRY("%p, %d", this, extended_verification);
-	return EFI_EXIT(EFI_UNSUPPORTED);
+
+	/* Empty input buffer */
+	while (tstc())
+		getc();
+
+	return EFI_EXIT(EFI_SUCCESS);
 }
 
 /*

+ 6 - 6
lib/efi_loader/efi_image_loader.c

@@ -19,25 +19,25 @@ const efi_guid_t efi_simple_file_system_protocol_guid =
 const efi_guid_t efi_file_info_guid = EFI_FILE_INFO_GUID;
 
 static int machines[] = {
-#if defined(CONFIG_ARM64)
+#if defined(__aarch64__)
 	IMAGE_FILE_MACHINE_ARM64,
-#elif defined(CONFIG_ARM)
+#elif defined(__arm__)
 	IMAGE_FILE_MACHINE_ARM,
 	IMAGE_FILE_MACHINE_THUMB,
 	IMAGE_FILE_MACHINE_ARMNT,
 #endif
 
-#if defined(CONFIG_X86_64)
+#if defined(__x86_64__)
 	IMAGE_FILE_MACHINE_AMD64,
-#elif defined(CONFIG_X86)
+#elif defined(__i386__)
 	IMAGE_FILE_MACHINE_I386,
 #endif
 
-#if defined(CONFIG_CPU_RISCV_32)
+#if defined(__riscv) && (__riscv_xlen == 32)
 	IMAGE_FILE_MACHINE_RISCV32,
 #endif
 
-#if defined(CONFIG_CPU_RISCV_64)
+#if defined(__riscv) && (__riscv_xlen == 64)
 	IMAGE_FILE_MACHINE_RISCV64,
 #endif
 	0 };

+ 45 - 20
lib/efi_loader/efi_memory.c

@@ -9,11 +9,14 @@
 #include <efi_loader.h>
 #include <inttypes.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <watchdog.h>
 #include <linux/list_sort.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+efi_uintn_t efi_memory_map_key;
+
 struct efi_mem_list {
 	struct list_head link;
 	struct efi_mem_desc desc;
@@ -159,9 +162,13 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type,
 	debug("%s: 0x%" PRIx64 " 0x%" PRIx64 " %d %s\n", __func__,
 	      start, pages, memory_type, overlap_only_ram ? "yes" : "no");
 
+	if (memory_type >= EFI_MAX_MEMORY_TYPE)
+		return EFI_INVALID_PARAMETER;
+
 	if (!pages)
 		return start;
 
+	++efi_memory_map_key;
 	newlist = calloc(1, sizeof(*newlist));
 	newlist->desc.type = memory_type;
 	newlist->desc.physical_start = start;
@@ -292,10 +299,13 @@ efi_status_t efi_allocate_pages(int type, int memory_type,
 	efi_status_t r = EFI_SUCCESS;
 	uint64_t addr;
 
+	if (!memory)
+		return EFI_INVALID_PARAMETER;
+
 	switch (type) {
 	case EFI_ALLOCATE_ANY_PAGES:
 		/* Any page */
-		addr = efi_find_free_memory(len, gd->start_addr_sp);
+		addr = efi_find_free_memory(len, -1ULL);
 		if (!addr) {
 			r = EFI_NOT_FOUND;
 			break;
@@ -325,7 +335,7 @@ efi_status_t efi_allocate_pages(int type, int memory_type,
 		/* Reserve that map in our memory maps */
 		ret = efi_add_memory_map(addr, pages, memory_type, true);
 		if (ret == addr) {
-			*memory = addr;
+			*memory = (uintptr_t)map_sysmem(addr, len);
 		} else {
 			/* Map would overlap, bail out */
 			r = EFI_OUT_OF_RESOURCES;
@@ -359,11 +369,12 @@ void *efi_alloc(uint64_t len, int memory_type)
 efi_status_t efi_free_pages(uint64_t memory, efi_uintn_t pages)
 {
 	uint64_t r = 0;
+	uint64_t addr = map_to_sysmem((void *)(uintptr_t)memory);
 
-	r = efi_add_memory_map(memory, pages, EFI_CONVENTIONAL_MEMORY, false);
+	r = efi_add_memory_map(addr, pages, EFI_CONVENTIONAL_MEMORY, false);
 	/* Merging of adjacent free regions is missing */
 
-	if (r == memory)
+	if (r == addr)
 		return EFI_SUCCESS;
 
 	return EFI_NOT_FOUND;
@@ -380,20 +391,22 @@ efi_status_t efi_free_pages(uint64_t memory, efi_uintn_t pages)
 efi_status_t efi_allocate_pool(int pool_type, efi_uintn_t size, void **buffer)
 {
 	efi_status_t r;
-	efi_physical_addr_t t;
+	struct efi_pool_allocation *alloc;
 	u64 num_pages = (size + sizeof(struct efi_pool_allocation) +
 			 EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
 
+	if (!buffer)
+		return EFI_INVALID_PARAMETER;
+
 	if (size == 0) {
 		*buffer = NULL;
 		return EFI_SUCCESS;
 	}
 
 	r = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, pool_type, num_pages,
-			       &t);
+			       (uint64_t *)&alloc);
 
 	if (r == EFI_SUCCESS) {
-		struct efi_pool_allocation *alloc = (void *)(uintptr_t)t;
 		alloc->num_pages = num_pages;
 		*buffer = alloc->data;
 	}
@@ -446,6 +459,9 @@ efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size,
 	struct list_head *lhandle;
 	efi_uintn_t provided_map_size = *memory_map_size;
 
+	if (!memory_map_size)
+		return EFI_INVALID_PARAMETER;
+
 	list_for_each(lhandle, &efi_mem)
 		map_entries++;
 
@@ -456,6 +472,9 @@ efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size,
 	if (provided_map_size < map_size)
 		return EFI_BUFFER_TOO_SMALL;
 
+	if (!memory_map)
+		return EFI_INVALID_PARAMETER;
+
 	if (descriptor_size)
 		*descriptor_size = sizeof(struct efi_mem_desc);
 
@@ -463,19 +482,18 @@ efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size,
 		*descriptor_version = EFI_MEMORY_DESCRIPTOR_VERSION;
 
 	/* Copy list into array */
-	if (memory_map) {
-		/* Return the list in ascending order */
-		memory_map = &memory_map[map_entries - 1];
-		list_for_each(lhandle, &efi_mem) {
-			struct efi_mem_list *lmem;
+	/* Return the list in ascending order */
+	memory_map = &memory_map[map_entries - 1];
+	list_for_each(lhandle, &efi_mem) {
+		struct efi_mem_list *lmem;
 
-			lmem = list_entry(lhandle, struct efi_mem_list, link);
-			*memory_map = lmem->desc;
-			memory_map--;
-		}
+		lmem = list_entry(lhandle, struct efi_mem_list, link);
+		*memory_map = lmem->desc;
+		memory_map--;
 	}
 
-	*map_key = 0;
+	if (map_key)
+		*map_key = efi_memory_map_key;
 
 	return EFI_SUCCESS;
 }
@@ -496,14 +514,13 @@ __weak void efi_add_known_memory(void)
 	}
 }
 
-int efi_memory_init(void)
+/* Add memory regions for U-Boot's memory and for the runtime services code */
+static void add_u_boot_and_runtime(void)
 {
 	unsigned long runtime_start, runtime_end, runtime_pages;
 	unsigned long uboot_start, uboot_pages;
 	unsigned long uboot_stack_size = 16 * 1024 * 1024;
 
-	efi_add_known_memory();
-
 	/* Add U-Boot */
 	uboot_start = (gd->start_addr_sp - uboot_stack_size) & ~EFI_PAGE_MASK;
 	uboot_pages = (gd->ram_top - uboot_start) >> EFI_PAGE_SHIFT;
@@ -516,6 +533,14 @@ int efi_memory_init(void)
 	runtime_pages = (runtime_end - runtime_start) >> EFI_PAGE_SHIFT;
 	efi_add_memory_map(runtime_start, runtime_pages,
 			   EFI_RUNTIME_SERVICES_CODE, false);
+}
+
+int efi_memory_init(void)
+{
+	efi_add_known_memory();
+
+	if (!IS_ENABLED(CONFIG_SANDBOX))
+		add_u_boot_and_runtime();
 
 #ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER
 	/* Request a 32bit 64MB bounce buffer region */

+ 54 - 29
lib/efi_loader/efi_runtime.c

@@ -8,6 +8,7 @@
 #include <common.h>
 #include <command.h>
 #include <dm.h>
+#include <elf.h>
 #include <efi_loader.h>
 #include <rtc.h>
 
@@ -32,19 +33,17 @@ static efi_status_t __efi_runtime EFIAPI efi_invalid_parameter(void);
  * TODO(sjg@chromium.org): These defines and structs should come from the elf
  * header for each arch (or a generic header) rather than being repeated here.
  */
-#if defined(CONFIG_ARM64)
-#define R_RELATIVE	1027
+#if defined(__aarch64__)
+#define R_RELATIVE	R_AARCH64_RELATIVE
 #define R_MASK		0xffffffffULL
 #define IS_RELA		1
-#elif defined(CONFIG_ARM)
-#define R_RELATIVE	23
+#elif defined(__arm__)
+#define R_RELATIVE	R_ARM_RELATIVE
 #define R_MASK		0xffULL
-#elif defined(CONFIG_X86)
-#include <asm/elf.h>
+#elif defined(__x86_64__) || defined(__i386__)
 #define R_RELATIVE	R_386_RELATIVE
 #define R_MASK		0xffULL
-#elif defined(CONFIG_RISCV)
-#include <elf.h>
+#elif defined(__riscv)
 #define R_RELATIVE	R_RISCV_RELATIVE
 #define R_MASK		0xffULL
 #define IS_RELA		1
@@ -55,12 +54,14 @@ struct dyn_sym {
 	u32 foo2;
 	u32 foo3;
 };
-#ifdef CONFIG_CPU_RISCV_32
+#if (__riscv_xlen == 32)
 #define R_ABSOLUTE	R_RISCV_32
 #define SYM_INDEX	8
-#else
+#elif (__riscv_xlen == 64)
 #define R_ABSOLUTE	R_RISCV_64
 #define SYM_INDEX	32
+#else
+#error unknown riscv target
 #endif
 #else
 #error Need to add relocation awareness
@@ -116,24 +117,41 @@ static void EFIAPI efi_reset_system_boottime(
 	while (1) { }
 }
 
+/**
+ * efi_get_time_boottime - get current time
+ *
+ * This function implements the GetTime runtime service.
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ *
+ * @time:		pointer to structure to receive current time
+ * @capabilities:	pointer to structure to receive RTC properties
+ * Return Value:	status code
+ */
 static efi_status_t EFIAPI efi_get_time_boottime(
 			struct efi_time *time,
 			struct efi_time_cap *capabilities)
 {
-#if defined(CONFIG_CMD_DATE) && defined(CONFIG_DM_RTC)
-	struct rtc_time tm;
+#ifdef CONFIG_DM_RTC
+	efi_status_t ret = EFI_SUCCESS;
 	int r;
+	struct rtc_time tm;
 	struct udevice *dev;
 
 	EFI_ENTRY("%p %p", time, capabilities);
 
-	r = uclass_get_device(UCLASS_RTC, 0, &dev);
-	if (r)
-		return EFI_EXIT(EFI_DEVICE_ERROR);
+	if (!time) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
 
-	r = dm_rtc_get(dev, &tm);
-	if (r)
-		return EFI_EXIT(EFI_DEVICE_ERROR);
+	r = uclass_get_device(UCLASS_RTC, 0, &dev);
+	if (!r)
+		r = dm_rtc_get(dev, &tm);
+	if (r) {
+		ret = EFI_DEVICE_ERROR;
+		goto out;
+	}
 
 	memset(time, 0, sizeof(*time));
 	time->year = tm.tm_year;
@@ -141,11 +159,23 @@ static efi_status_t EFIAPI efi_get_time_boottime(
 	time->day = tm.tm_mday;
 	time->hour = tm.tm_hour;
 	time->minute = tm.tm_min;
-	time->daylight = tm.tm_isdst;
-
-	return EFI_EXIT(EFI_SUCCESS);
+	time->second = tm.tm_sec;
+	time->daylight = EFI_TIME_ADJUST_DAYLIGHT;
+	if (tm.tm_isdst > 0)
+		time->daylight |= EFI_TIME_IN_DAYLIGHT;
+	time->timezone = EFI_UNSPECIFIED_TIMEZONE;
+
+	if (capabilities) {
+		/* Set reasonable dummy values */
+		capabilities->resolution = 1;		/* 1 Hz */
+		capabilities->accuracy = 100000000;	/* 100 ppm */
+		capabilities->sets_to_zero = false;
+	}
+out:
+	return EFI_EXIT(ret);
 #else
-	return EFI_DEVICE_ERROR;
+	EFI_ENTRY("%p %p", time, capabilities);
+	return EFI_EXIT(EFI_DEVICE_ERROR);
 #endif
 }
 
@@ -173,11 +203,6 @@ efi_status_t __weak __efi_runtime EFIAPI efi_get_time(
 	return EFI_DEVICE_ERROR;
 }
 
-efi_status_t __weak efi_get_time_init(void)
-{
-	return EFI_SUCCESS;
-}
-
 struct efi_runtime_detach_list_struct {
 	void *ptr;
 	void *patchto;
@@ -458,8 +483,8 @@ efi_status_t __efi_runtime EFIAPI efi_query_variable_info(
 struct efi_runtime_services __efi_runtime_data efi_runtime_services = {
 	.hdr = {
 		.signature = EFI_RUNTIME_SERVICES_SIGNATURE,
-		.revision = EFI_RUNTIME_SERVICES_REVISION,
-		.headersize = sizeof(struct efi_table_hdr),
+		.revision = EFI_SPECIFICATION_VERSION,
+		.headersize = sizeof(struct efi_runtime_services),
 	},
 	.get_time = &efi_get_time_boottime,
 	.set_time = (void *)&efi_device_error,

+ 9 - 2
lib/efi_loader/efi_smbios.c

@@ -26,8 +26,15 @@ efi_status_t efi_smbios_register(void)
 	/* Reserve 4kiB page for SMBIOS */
 	ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
 				 EFI_RUNTIME_SERVICES_DATA, 1, &dmi);
-	if (ret != EFI_SUCCESS)
-		return ret;
+
+	if (ret != EFI_SUCCESS) {
+		/* Could not find space in lowmem, use highmem instead */
+		ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+					 EFI_RUNTIME_SERVICES_DATA, 1, &dmi);
+
+		if (ret != EFI_SUCCESS)
+			return ret;
+	}
 
 	/*
 	 * Generate SMBIOS tables - we know that efi_allocate_pages() returns

+ 3 - 1
lib/efi_selftest/.gitignore

@@ -1,2 +1,4 @@
-efi_miniapp_file_image.h
+efi_miniapp_file_image_exit.h
+efi_miniapp_file_image_return.h
 *.efi
+*.so

+ 4 - 1
lib/efi_selftest/Makefile

@@ -13,8 +13,10 @@ CFLAGS_REMOVE_efi_selftest_miniapp_return.o := $(CFLAGS_NON_EFI) -Os
 obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += \
 efi_selftest.o \
 efi_selftest_bitblt.o \
+efi_selftest_config_table.o \
 efi_selftest_controllers.o \
 efi_selftest_console.o \
+efi_selftest_crc32.o \
 efi_selftest_devicepath.o \
 efi_selftest_devicepath_util.o \
 efi_selftest_events.o \
@@ -23,6 +25,7 @@ efi_selftest_exitbootservices.o \
 efi_selftest_fdt.o \
 efi_selftest_gop.o \
 efi_selftest_manageprotocols.o \
+efi_selftest_rtc.o \
 efi_selftest_snp.o \
 efi_selftest_textinput.o \
 efi_selftest_textoutput.o \
@@ -41,7 +44,7 @@ endif
 
 # TODO: As of v2018.01 the relocation code for the EFI application cannot
 # be built on x86_64.
-ifeq ($(CONFIG_X86_64),)
+ifeq ($(CONFIG_X86_64)$(CONFIG_SANDBOX),)
 
 ifneq ($(CONFIG_CMD_BOOTEFI_SELFTEST),)
 

+ 6 - 8
lib/efi_selftest/efi_selftest.c

@@ -8,9 +8,7 @@
 #include <efi_selftest.h>
 #include <vsprintf.h>
 
-/*
- * Constants for test step bitmap
- */
+/* Constants for test step bitmap */
 #define EFI_ST_SETUP	1
 #define EFI_ST_EXECUTE	2
 #define EFI_ST_TEARDOWN	4
@@ -26,7 +24,7 @@ static u16 reset_message[] = L"Selftest completed";
  *
  * The size of the memory map is determined.
  * Pool memory is allocated to copy the memory map.
- * The memory amp is copied and the map key is obtained.
+ * The memory map is copied and the map key is obtained.
  * The map key is used to exit the boot services.
  */
 void efi_st_exit_boot_services(void)
@@ -146,7 +144,7 @@ static int teardown(struct efi_unit_test *test, unsigned int *failures)
  * Check that a test exists.
  *
  * @testname:	name of the test
- * @return:	test
+ * @return:	test, or NULL if not found
  */
 static struct efi_unit_test *find_test(const u16 *testname)
 {
@@ -182,7 +180,7 @@ static void list_all_tests(void)
  *
  * @testname	name of a single selected test or NULL
  * @phase	test phase
- * @steps	steps to execute
+ * @steps	steps to execute (mask with bits from EFI_ST_...)
  * failures	returns EFI_ST_SUCCESS if all test steps succeeded
  */
 void efi_st_do_tests(const u16 *testname, unsigned int phase,
@@ -296,12 +294,12 @@ efi_status_t EFIAPI efi_selftest(efi_handle_t image_handle,
 	efi_st_printc(EFI_WHITE, "\nSummary: %u failures\n\n", failures);
 
 	/* Reset system */
-	efi_st_printf("Preparing for reset. Press any key.\n");
+	efi_st_printf("Preparing for reset. Press any key...\n");
 	efi_st_get_key();
 	runtime->reset_system(EFI_RESET_WARM, EFI_NOT_READY,
 			      sizeof(reset_message), reset_message);
 	efi_st_printf("\n");
-	efi_st_error("Reset failed.\n");
+	efi_st_error("Reset failed\n");
 
 	return EFI_UNSUPPORTED;
 }

+ 70 - 0
lib/efi_selftest/efi_selftest_block_device.c

@@ -309,11 +309,14 @@ static int execute(void)
 	efi_uintn_t buf_size;
 	char buf[16] __aligned(ARCH_DMA_MINALIGN);
 
+	/* Connect controller to virtual disk */
 	ret = boottime->connect_controller(disk_handle, NULL, NULL, 1);
 	if (ret != EFI_SUCCESS) {
 		efi_st_error("Failed to connect controller\n");
 		return EFI_ST_FAILURE;
 	}
+
+	/* Get the handle for the partition */
 	ret = boottime->locate_handle_buffer(
 				BY_PROTOCOL, &guid_device_path, NULL,
 				&no_handles, &handles);
@@ -347,6 +350,8 @@ static int execute(void)
 		efi_st_error("Partition handle not found\n");
 		return EFI_ST_FAILURE;
 	}
+
+	/* Open the simple file system protocol */
 	ret = boottime->open_protocol(handle_partition,
 				      &guid_simple_file_system_protocol,
 				      (void **)&file_system, NULL, NULL,
@@ -355,6 +360,8 @@ static int execute(void)
 		efi_st_error("Failed to open simple file system protocol\n");
 		return EFI_ST_FAILURE;
 	}
+
+	/* Open volume */
 	ret = file_system->open_volume(file_system, &root);
 	if (ret != EFI_SUCCESS) {
 		efi_st_error("Failed to open volume\n");
@@ -377,6 +384,8 @@ static int execute(void)
 			"Wrong volume label '%ps', expected 'U-BOOT TEST'\n",
 			system_info.info.volume_label);
 	}
+
+	/* Read file */
 	ret = root->open(root, &file, (s16 *)L"hello.txt", EFI_FILE_MODE_READ,
 			 0);
 	if (ret != EFI_SUCCESS) {
@@ -389,6 +398,11 @@ static int execute(void)
 		efi_st_error("Failed to read file\n");
 		return EFI_ST_FAILURE;
 	}
+	if (buf_size != 13) {
+		efi_st_error("Wrong number of bytes read: %u\n",
+			     (unsigned int)buf_size);
+		return EFI_ST_FAILURE;
+	}
 	if (efi_st_memcmp(buf, "Hello world!", 12)) {
 		efi_st_error("Unexpected file content\n");
 		return EFI_ST_FAILURE;
@@ -398,6 +412,62 @@ static int execute(void)
 		efi_st_error("Failed to close file\n");
 		return EFI_ST_FAILURE;
 	}
+
+#ifdef CONFIG_FAT_WRITE
+	/* Write file */
+	ret = root->open(root, &file, (s16 *)L"u-boot.txt",
+			 EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to open file\n");
+		return EFI_ST_FAILURE;
+	}
+	buf_size = 7;
+	boottime->set_mem(buf, sizeof(buf), 0);
+	boottime->copy_mem(buf, "U-Boot", buf_size);
+	ret = file->write(file, &buf_size, buf);
+	if (ret != EFI_SUCCESS || buf_size != 7) {
+		efi_st_error("Failed to write file\n");
+		return EFI_ST_FAILURE;
+	}
+	ret = file->close(file);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to close file\n");
+		return EFI_ST_FAILURE;
+	}
+
+	/* Verify file */
+	boottime->set_mem(buf, sizeof(buf), 0);
+	ret = root->open(root, &file, (s16 *)L"u-boot.txt", EFI_FILE_MODE_READ,
+			 0);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to open file\n");
+		return EFI_ST_FAILURE;
+	}
+	buf_size = sizeof(buf) - 1;
+	ret = file->read(file, &buf_size, buf);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to read file\n");
+		return EFI_ST_FAILURE;
+	}
+	if (buf_size != 7) {
+		efi_st_error("Wrong number of bytes read: %u\n",
+			     (unsigned int)buf_size);
+		return EFI_ST_FAILURE;
+	}
+	if (efi_st_memcmp(buf, "U-Boot", 7)) {
+		efi_st_error("Unexpected file content %s\n", buf);
+		return EFI_ST_FAILURE;
+	}
+	ret = file->close(file);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to close file\n");
+		return EFI_ST_FAILURE;
+	}
+#else
+	efi_st_todo("CONFIG_FAT_WRITE is not set\n");
+#endif /* CONFIG_FAT_WRITE */
+
+	/* Close volume */
 	ret = root->close(root);
 	if (ret != EFI_SUCCESS) {
 		efi_st_error("Failed to close volume\n");

+ 266 - 0
lib/efi_selftest/efi_selftest_config_table.c

@@ -0,0 +1,266 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_config_tables
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This test checks the following service:
+ * InstallConfigurationTable.
+ */
+
+#include <efi_selftest.h>
+
+static const struct efi_system_table *sys_table;
+static struct efi_boot_services *boottime;
+
+static efi_guid_t table_guid =
+	EFI_GUID(0xff1c3f9e, 0x795b, 0x1529, 0xf1, 0x55,
+		 0x17, 0x2e, 0x51, 0x6b, 0x49, 0x75);
+
+/*
+ * Notification function, increments the notfication count if parameter
+ * context is provided.
+ *
+ * @event	notified event
+ * @context	pointer to the notification count
+ */
+static void EFIAPI notify(struct efi_event *event, void *context)
+{
+	unsigned int *count = context;
+
+	if (count)
+		++*count;
+}
+
+/*
+ * Check crc32 of a table.
+ */
+static int check_table(const void *table)
+{
+	efi_status_t ret;
+	u32 crc32, res;
+	/* Casting from const to not const */
+	struct efi_table_hdr *hdr = (struct efi_table_hdr *)table;
+
+	crc32 = hdr->crc32;
+	/*
+	 * Setting the crc32 of the 'const' table to zero is easier than
+	 * copying
+	 */
+	hdr->crc32 = 0;
+	ret = boottime->calculate_crc32(table, hdr->headersize, &res);
+	/* Reset table crc32 so it stays constant */
+	hdr->crc32 = crc32;
+	if (ret != EFI_ST_SUCCESS) {
+		efi_st_error("CalculateCrc32 failed\n");
+		return EFI_ST_FAILURE;
+	}
+	if (res != crc32) {
+		efi_st_error("Incorrect CRC32\n");
+		return EFI_ST_FAILURE;
+	}
+	return EFI_ST_SUCCESS;
+}
+
+/*
+ * Setup unit test.
+ *
+ * @handle:	handle of the loaded image
+ * @systable:	system table
+ * @return:	EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+		 const struct efi_system_table *systable)
+{
+	sys_table = systable;
+	boottime = systable->boottime;
+
+	return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ * A table is installed, updated, removed. The table entry and the
+ * triggering of events is checked.
+ *
+ * @return:	EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+	efi_status_t ret;
+	unsigned int counter = 0;
+	struct efi_event *event;
+	void *table;
+	const unsigned int tables[2];
+	efi_uintn_t i;
+	efi_uintn_t tabcnt;
+	efi_uintn_t table_count = sys_table->nr_tables;
+
+	ret = boottime->create_event_ex(0, TPL_NOTIFY,
+					notify, (void *)&counter,
+					&table_guid, &event);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to create event\n");
+		return EFI_ST_FAILURE;
+	}
+
+	/* Try to delete non-existent table */
+	ret = boottime->install_configuration_table(&table_guid, NULL);
+	if (ret != EFI_NOT_FOUND) {
+		efi_st_error("Failed to detect missing table\n");
+		return EFI_ST_FAILURE;
+	}
+	if (counter) {
+		efi_st_error("Notification function was called.\n");
+		return EFI_ST_FAILURE;
+	}
+	/* Check if the event was signaled  */
+	ret = boottime->check_event(event);
+	if (ret == EFI_SUCCESS) {
+		efi_st_error("Event was signaled on EFI_NOT_FOUND\n");
+		return EFI_ST_FAILURE;
+	}
+	if (counter != 1) {
+		efi_st_error("Notification function was not called.\n");
+		return EFI_ST_FAILURE;
+	}
+	if (table_count != sys_table->nr_tables) {
+		efi_st_error("Incorrect table count %u, expected %u\n",
+			     (unsigned int)sys_table->nr_tables,
+			     (unsigned int)table_count);
+		return EFI_ST_FAILURE;
+	}
+
+	/* Install table */
+	ret = boottime->install_configuration_table(&table_guid,
+						    (void *)&tables[0]);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to install table\n");
+		return EFI_ST_FAILURE;
+	}
+	/* Check signaled state */
+	ret = boottime->check_event(event);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Event was not signaled on insert\n");
+		return EFI_ST_FAILURE;
+	}
+	if (++table_count != sys_table->nr_tables) {
+		efi_st_error("Incorrect table count %u, expected %u\n",
+			     (unsigned int)sys_table->nr_tables,
+			     (unsigned int)table_count);
+		return EFI_ST_FAILURE;
+	}
+	table = NULL;
+	for (i = 0; i < sys_table->nr_tables; ++i) {
+		if (!efi_st_memcmp(&sys_table->tables[i].guid, &table_guid,
+				   sizeof(efi_guid_t)))
+			table = sys_table->tables[i].table;
+	}
+	if (!table) {
+		efi_st_error("Installed table not found\n");
+		return EFI_ST_FAILURE;
+	}
+	if (table != &tables[0]) {
+		efi_st_error("Incorrect table address\n");
+		return EFI_ST_FAILURE;
+	}
+	if (check_table(sys_table) != EFI_ST_SUCCESS) {
+		efi_st_error("Checking system table\n");
+		return EFI_ST_FAILURE;
+	}
+
+	/* Update table */
+	ret = boottime->install_configuration_table(&table_guid,
+						    (void *)&tables[1]);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to update table\n");
+		return EFI_ST_FAILURE;
+	}
+	/* Check signaled state */
+	ret = boottime->check_event(event);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Event was not signaled on update\n");
+		return EFI_ST_FAILURE;
+	}
+	if (table_count != sys_table->nr_tables) {
+		efi_st_error("Incorrect table count %u, expected %u\n",
+			     (unsigned int)sys_table->nr_tables,
+			     (unsigned int)table_count);
+		return EFI_ST_FAILURE;
+	}
+	table = NULL;
+	tabcnt = 0;
+	for (i = 0; i < sys_table->nr_tables; ++i) {
+		if (!efi_st_memcmp(&sys_table->tables[i].guid, &table_guid,
+				   sizeof(efi_guid_t))) {
+			table = sys_table->tables[i].table;
+			++tabcnt;
+		}
+	}
+	if (!table) {
+		efi_st_error("Installed table not found\n");
+		return EFI_ST_FAILURE;
+	}
+	if (tabcnt > 1) {
+		efi_st_error("Duplicate table guid\n");
+		return EFI_ST_FAILURE;
+	}
+	if (table != &tables[1]) {
+		efi_st_error("Incorrect table address\n");
+		return EFI_ST_FAILURE;
+	}
+	if (check_table(sys_table) != EFI_ST_SUCCESS) {
+		efi_st_error("Checking system table\n");
+		return EFI_ST_FAILURE;
+	}
+
+	/* Delete table */
+	ret = boottime->install_configuration_table(&table_guid, NULL);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to delete table\n");
+		return EFI_ST_FAILURE;
+	}
+	/* Check signaled state */
+	ret = boottime->check_event(event);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Event was not signaled on delete\n");
+		return EFI_ST_FAILURE;
+	}
+	if (--table_count != sys_table->nr_tables) {
+		efi_st_error("Incorrect table count %u, expected %u\n",
+			     (unsigned int)sys_table->nr_tables,
+			     (unsigned int)table_count);
+		return EFI_ST_FAILURE;
+	}
+	table = NULL;
+	for (i = 0; i < sys_table->nr_tables; ++i) {
+		if (!efi_st_memcmp(&sys_table->tables[i].guid, &table_guid,
+				   sizeof(efi_guid_t))) {
+			table = sys_table->tables[i].table;
+		}
+	}
+	if (table) {
+		efi_st_error("Wrong table deleted\n");
+		return EFI_ST_FAILURE;
+	}
+
+	ret = boottime->close_event(event);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to close event\n");
+		return EFI_ST_FAILURE;
+	}
+	if (check_table(sys_table) != EFI_ST_SUCCESS) {
+		efi_st_error("Checking system table\n");
+		return EFI_ST_FAILURE;
+	}
+
+	return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(configtables) = {
+	.name = "configuration tables",
+	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+	.setup = setup,
+	.execute = execute,
+};

+ 22 - 11
lib/efi_selftest/efi_selftest_console.c

@@ -70,11 +70,12 @@ static void pointer(void *pointer, u16 **buf)
 /*
  * Print an unsigned 32bit value as decimal number to an u16 string
  *
- * @value: value to be printed
- * @buf: pointer to buffer address
- * on return position of terminating zero word
+ * @value:	value to be printed
+ * @prec:	minimum number of digits to display
+ * @buf:	pointer to buffer address
+ *		on return position of terminating zero word
  */
-static void uint2dec(u32 value, u16 **buf)
+static void uint2dec(u32 value, int prec, u16 **buf)
 {
 	u16 *pos = *buf;
 	int i;
@@ -93,7 +94,7 @@ static void uint2dec(u32 value, u16 **buf)
 	for (i = 0; i < 10; ++i) {
 		/* Write current digit */
 		c = f >> 60;
-		if (c || pos != *buf)
+		if (c || pos != *buf || 10 - i <= prec)
 			*pos++ = c + '0';
 		/* Eliminate current digit */
 		f &= 0xfffffffffffffff;
@@ -109,11 +110,12 @@ static void uint2dec(u32 value, u16 **buf)
 /*
  * Print a signed 32bit value as decimal number to an u16 string
  *
- * @value: value to be printed
- * @buf: pointer to buffer address
+ * @value:	value to be printed
+ * @prec:	minimum number of digits to display
+ * @buf:	pointer to buffer address
  * on return position of terminating zero word
  */
-static void int2dec(s32 value, u16 **buf)
+static void int2dec(s32 value, int prec, u16 **buf)
 {
 	u32 u;
 	u16 *pos = *buf;
@@ -124,7 +126,7 @@ static void int2dec(s32 value, u16 **buf)
 	} else {
 		u = value;
 	}
-	uint2dec(u, &pos);
+	uint2dec(u, prec, &pos);
 	*buf = pos;
 }
 
@@ -143,6 +145,7 @@ void efi_st_printc(int color, const char *fmt, ...)
 	u16 *pos = buf;
 	const char *s;
 	u16 *u;
+	int prec;
 
 	va_start(args, fmt);
 
@@ -172,12 +175,20 @@ void efi_st_printc(int color, const char *fmt, ...)
 			break;
 		case '%':
 			++c;
+			/* Parse precision */
+			if (*c == '.') {
+				++c;
+				prec = *c - '0';
+				++c;
+			} else {
+				prec = 0;
+			}
 			switch (*c) {
 			case '\0':
 				--c;
 				break;
 			case 'd':
-				int2dec(va_arg(args, s32), &pos);
+				int2dec(va_arg(args, s32), prec, &pos);
 				break;
 			case 'p':
 				++c;
@@ -209,7 +220,7 @@ void efi_st_printc(int color, const char *fmt, ...)
 					*pos++ = *s;
 				break;
 			case 'u':
-				uint2dec(va_arg(args, u32), &pos);
+				uint2dec(va_arg(args, u32), prec, &pos);
 				break;
 			default:
 				break;

+ 141 - 0
lib/efi_selftest/efi_selftest_crc32.c

@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_crc32
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This unit test checks the CalculateCrc32 bootservice and checks the
+ * headers of the system table, the boot services tablle, and the runtime
+ * services table before and after ExitBootServices().
+ */
+
+#include <efi_selftest.h>
+
+const struct efi_system_table *st;
+efi_status_t (EFIAPI *bs_crc32)(const void *data, efi_uintn_t data_size,
+				u32 *crc32);
+
+static int check_table(const void *table)
+{
+	efi_status_t ret;
+	u32 crc32, res;
+	/* Casting from const to not const */
+	struct efi_table_hdr *hdr = (struct efi_table_hdr *)table;
+
+	if (!hdr->signature) {
+		efi_st_error("Missing header signature\n");
+		return EFI_ST_FAILURE;
+	}
+	if (!hdr->revision) {
+		efi_st_error("Missing header revision\n");
+		return EFI_ST_FAILURE;
+	}
+	if (hdr->headersize <= sizeof(struct efi_table_hdr)) {
+		efi_st_error("Incorrect headersize value\n");
+		return EFI_ST_FAILURE;
+	}
+	if (hdr->reserved) {
+		efi_st_error("Reserved header field is not zero\n");
+		return EFI_ST_FAILURE;
+	}
+
+	crc32 = hdr->crc32;
+	/*
+	 * Setting the crc32 of the 'const' table to zero is easier than
+	 * copying
+	 */
+	hdr->crc32 = 0;
+	ret = bs_crc32(table, hdr->headersize, &res);
+	/* Reset table crc32 so it stays constant */
+	hdr->crc32 = crc32;
+	if (ret != EFI_ST_SUCCESS) {
+		efi_st_error("CalculateCrc32 failed\n");
+		return EFI_ST_FAILURE;
+	}
+	if (res != crc32) {
+		efi_st_error("Incorrect CRC32\n");
+		// return EFI_ST_FAILURE;
+	}
+	return EFI_ST_SUCCESS;
+}
+
+/*
+ * Setup unit test.
+ *
+ * Check that CalculateCrc32 is working correctly.
+ * Check tables before ExitBootServices().
+ *
+ * @handle:	handle of the loaded image
+ * @systable:	system table
+ * @return:	EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+		 const struct efi_system_table *systable)
+{
+	efi_status_t ret;
+	u32 res;
+
+	st = systable;
+	bs_crc32 = systable->boottime->calculate_crc32;
+
+	/* Check that CalculateCrc32 is working */
+	ret = bs_crc32("U-Boot", 6, &res);
+	if (ret != EFI_ST_SUCCESS) {
+		efi_st_error("CalculateCrc32 failed\n");
+		return EFI_ST_FAILURE;
+	}
+	if (res != 0x134b0db4) {
+		efi_st_error("Incorrect CRC32\n");
+		return EFI_ST_FAILURE;
+	}
+
+	/* Check tables before ExitBootServices() */
+	if (check_table(st) != EFI_ST_SUCCESS) {
+		efi_st_error("Checking system table\n");
+		return EFI_ST_FAILURE;
+	}
+	if (check_table(st->boottime) != EFI_ST_SUCCESS) {
+		efi_st_error("Checking boottime table\n");
+		return EFI_ST_FAILURE;
+	}
+	if (check_table(st->runtime) != EFI_ST_SUCCESS) {
+		efi_st_error("Checking runtime table\n");
+		return EFI_ST_FAILURE;
+	}
+
+	return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test
+ *
+ * Check tables after ExitBootServices()
+ *
+ * @return:	EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+	if (check_table(st) != EFI_ST_SUCCESS) {
+		efi_st_error("Checking system table\n");
+		return EFI_ST_FAILURE;
+	}
+	if (check_table(st->runtime) != EFI_ST_SUCCESS) {
+		efi_st_error("Checking runtime table\n");
+		return EFI_ST_FAILURE;
+	}
+
+	/*
+	 * We cannot call SetVirtualAddressMap() and recheck the runtime
+	 * table afterwards because this would invalidate the addresses of the
+	 * unit tests.
+	 */
+
+	return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(crc32) = {
+	.name = "crc32",
+	.phase = EFI_SETUP_BEFORE_BOOTTIME_EXIT,
+	.setup = setup,
+	.execute = execute,
+};

+ 67 - 0
lib/efi_selftest/efi_selftest_rtc.c

@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_rtc
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * Test the real time clock runtime services.
+ */
+
+#include <efi_selftest.h>
+
+#define EFI_ST_NO_RTC "Could not read real time clock\n"
+
+static struct efi_runtime_services *runtime;
+
+/*
+ * Setup unit test.
+ *
+ * @handle:	handle of the loaded image
+ * @systable:	system table
+ * @return:	EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+		 const struct efi_system_table *systable)
+{
+	runtime = systable->runtime;
+	return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Display current time.
+ *
+ * @return:	EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+	efi_status_t ret;
+	struct efi_time tm;
+
+	/* Display current time */
+	ret = runtime->get_time(&tm, NULL);
+	if (ret != EFI_SUCCESS) {
+#ifdef CONFIG_CMD_DATE
+		efi_st_error(EFI_ST_NO_RTC);
+		return EFI_ST_FAILURE;
+#else
+		efi_st_todo(EFI_ST_NO_RTC);
+		return EFI_ST_SUCCESS;
+#endif
+	} else {
+		efi_st_printf("Time according to real time clock: "
+			      "%.4u-%.2u-%.2u %.2u:%.2u:%.2u\n",
+			      tm.year, tm.month, tm.day,
+			      tm.hour, tm.minute, tm.second);
+	}
+
+	return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(rtc) = {
+	.name = "real time clock",
+	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+	.setup = setup,
+	.execute = execute,
+};

+ 4 - 1
lib/vsprintf.c

@@ -407,7 +407,10 @@ static char *uuid_string(char *buf, char *end, u8 *addr, int field_width,
 		break;
 	}
 
-	uuid_bin_to_str(addr, uuid, str_format);
+	if (addr)
+		uuid_bin_to_str(addr, uuid, str_format);
+	else
+		strcpy(uuid, "<NULL>");
 
 	return string(buf, end, uuid, field_width, precision, flags);
 }