All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v5 00/30] EFI payload / application support
@ 2016-03-04  0:09 Alexander Graf
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 01/30] thunderx: Calculate TCR dynamically Alexander Graf
                   ` (30 more replies)
  0 siblings, 31 replies; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:09 UTC (permalink / raw)
  To: u-boot

This is my (now very late) Christmas present for my openSUSE friends :).

U-Boot is a great project for embedded devices. However, convincing
everyone involved that only for "a few oddball ARM devices" we need to
support different configuration formats from grub2 when all other platforms
(PPC, System Z, x86) are standardized on a single format is a nightmare.

So we started to explore alternatives. At first, people tried to get
grub2 running using the u-boot api interface. However, that one didn't
support relocations, so you had to know where to link grub2 to at compile
time. It also seems to be broken more often than not. And on top of it all,
it's a one-off interface, so yet another thing to maintain.

That led to a nifty idea. What if we can just implement the EFI application
protocol on top of U-Boot? Then we could compile a single grub2 binary for
uEFI based systems and U-Boot based systems and as soon as that one's loaded,
everything looks and feels (almost) the same.

This patch set is the result of pursuing this endeavor.

  - I am successfully able to run grub2 and Linux EFI binaries with this code.
  - When enabled, the resulting U-Boot binary only grows by ~10kb,
    so it's very light weight.
  - It works on 32bit ARM and AArch64. 
  - All storage devices are directly accessible
  - No EFI variables
  - Removable media booting (search for /efi/boot/boota{a64,arm}.efi)
  - Everything in place for runtime service support

Of course, there are still a few things one could do on top:

  - Improve disk media detection (don't scan, use what information we have)
  - Add EFI variable support using NVRAM
  - Add GFX support
  - Make EFI Shell work ;)
  - Network device support
  - Support for payload exit

But so far, I'm very happy with the state of the patches. They completely
eliminate potential arguments against U-Boot internally and give users the
chance to run with the same level of comfort on all firmware types.

Version 5 was successfully tested to boot grub2 and Linux from there on a
beagle-xm. Please apply the arm64 mmu patch set if you want to run this on an
AArch64 system.

If you read this far and want to try out the patches, feel free to grab
the source from git at:

  https://github.com/agraf/u-boot efi-v5

v1 -> v2:
  - move memory allocation to separate patch
  - limit 32/64 to hosts that support it
  - check 32bit optional nt header magic
  - switch to GPLv2+
  - Fix typo s/does now/does not/
  - Add #ifdefs around header to allow inclusion when efi_loader is disabled
  - Add stub efi_restore_gd() function when efi_loader is disabled
  - Disable debug
  - Mark runtime region as such
  - Fix up memory map
  - Allow efi_restore_gd to be called before first efi entry
  - Add 32bit arm cache workaround
  - Move memory map to separate patch
  - Change BTS version to 2.5
  - Fix return values for a few callbacks to more EFI compliant ones
  - Change vendor to "Das U-Boot"
  - Add warning when truncating timer trigger
  - Add runtime detach
  - Enable runtime relocations
  - Add get_time
  - Fix relocation
  - Fix 32bit
  - Add am335x support
  - Move section definition to header
  - Add systab to runtime section
  - Add self-relocation hook table
  - Relocate efi_runtime section early during bootup
  - Fix return values for a number of callbacks to be more UEFI compliant
  - Move to block_drvr array
  - Fix header order
  - Document efi block object struct
  - Use calloc rather than malloc & memset
  - Default to y
  - New patches: 
    - disk/part.c: Expose list of available block drivers
    - arm64: Allow exceptions to return
    - arm64: Allow EFI payload code to take exceptions
    - efi_loader: Add DCACHE_OFF support for arm64
    - efi_loader: Add distro boot script for removable media

v2 -> v3:

  - Add EFIAPI to notify_function
  - Add access denied code
  - use efi_alloc
  - add EFIAPI to function prototypes
  - remove unused macros
  - reorder header inclusion
  - split relocation code into function
  - flush cache after loading
  - Use external efi_memory helpers
  - Add EFIAPI to function prototypes
  - Initialize event timer to -1ULL to prevent early firing
  - Document header
  - Move obj list to lib
  - Remove implicit guid table
  - Add guid compare function
  - Fix return values
  - Implement efi_wait_for_event
  - Add EFIAPI to function prototypes
  - Patch reset to NULL
  - Add EFIAPI to function prototypes
  - Document header
  - Add dm.h include
  - Remove non-dm rtc support
  - Return DEVICE_ERROR in rtc path
  - Adapt to newer u-boot block API
  - Add EFIAPI to function prototypes
  - Document header
  - Check for DEV_TYPE_UNKNOWN
  - Document 16byte limit for dp string
  - Move to new cmd directory
  - Add kconfig option
  - Fix comment style
  - Add help text
  - s/-1/-ENOENT
  - Move obj list to lib
  - Rewrite memory allocation and map
  - Document header
  - Add memory file
  - New files:
    - README patch
    - MAINTAINERS patch

v3 -> v4:

  - Add EFI_PAGE_MASK define
  - Use EFI_PAGE_SHIFT define
  - Flush icache after image load
  - Fix white space in pe header
  - s/polimorphic/polymorphic
  - return EFI_SUCCESS in efi_cout_enable_cursor()
  - Use EFI_PAGE_.* defines
  - Return EFI_OUT_OF_RESOURCES in efi_allocate_pages
  - Add readme section about config options
  - s/10kb/10KB/

v4 -> v5:

  - Provide icache flush stub for archs which don't have it
  - Mark fdt memory as boot services data
  - new patch: arm64: Replace fdt_name env variables with fdtfile
  - new patch: arm: Allow EFI payload code to take exceptions
  - new patch: efi_loader: Call fdt preparation functions
  - new patch: efi_loader: Pass proper device path in on boot
  - PoC converted JeOS-beagle and JeOS-beaglebone images to EFI
    -> http://download.opensuse.org/repositories/home:/algraf:/arm-efi/images/

Alexander Graf (30):
  thunderx: Calculate TCR dynamically
  arm64: Disable TTBR1 maps in EL1
  arm64: Make full va map code more dynamic
  thunderx: Move mmu table into board file
  zymqmp: Replace home grown mmu code with generic table approach
  tegra: Replace home grown mmu code with generic table approach
  vexpress64: Add MMU tables
  dwmmc: Increase retry timeout
  hikey: Add MMU tables
  arm64: Remove non-full-va map code
  arm64: Only allow dcache disabled in SPL builds
  disk/part.c: Expose list of available block drivers
  include/efi_api.h: Add more detailed API definitions
  efi_loader: Add PE image loader
  efi_loader: Add boot time services
  efi_loader: Add console interface
  efi_loader: Add runtime services
  efi_loader: Add disk interfaces
  efi_loader: Add "bootefi" command
  efi_loader: Implement memory allocation and map
  arm64: Allow exceptions to return
  arm64: Allow EFI payload code to take exceptions
  efi_loader: hook up in build environment
  efi_loader: Add distro boot script for removable media
  efi_loader: Add README section in README.efi
  efi_loader: Add MAINTAINERS entry
  arm64: Replace fdt_name env variables with fdtfile
  arm: Allow EFI payload code to take exceptions
  efi_loader: Call fdt preparation functions
  efi_loader: Pass proper device path in on boot

 MAINTAINERS                                    |   7 +
 arch/arm/config.mk                             |   4 +
 arch/arm/cpu/armv8/cache.S                     |  54 ++
 arch/arm/cpu/armv8/cache_v8.c                  | 551 +++++++++++++----
 arch/arm/cpu/armv8/exceptions.S                |  34 ++
 arch/arm/cpu/armv8/fsl-layerscape/cpu.c        |  37 +-
 arch/arm/cpu/armv8/u-boot.lds                  |  16 +
 arch/arm/cpu/armv8/zynqmp/cpu.c                | 217 ++-----
 arch/arm/cpu/u-boot.lds                        |  30 +
 arch/arm/include/asm/arch-fsl-layerscape/cpu.h |  94 +--
 arch/arm/include/asm/armv8/mmu.h               | 123 +---
 arch/arm/include/asm/global_data.h             |   7 +-
 arch/arm/include/asm/system.h                  |  12 +-
 arch/arm/lib/interrupts.c                      |   8 +
 arch/arm/lib/interrupts_64.c                   |   9 +
 arch/arm/lib/sections.c                        |   4 +
 arch/arm/mach-tegra/arm64-mmu.c                | 132 +----
 board/armltd/vexpress64/vexpress64.c           |  21 +
 board/cavium/thunderx/thunderx.c               |  24 +
 board/hisilicon/hikey/hikey.c                  |  21 +
 board/ti/am335x/u-boot.lds                     |  30 +
 cmd/Kconfig                                    |   7 +
 cmd/Makefile                                   |   1 +
 cmd/bootefi.c                                  | 202 +++++++
 cmd/fs.c                                       |   2 +
 common/board_r.c                               |   7 +
 common/image-fdt.c                             |   8 +-
 disk/part.c                                    |   7 +-
 doc/README.arm64                               |  20 -
 doc/README.efi                                 |  83 ++-
 drivers/mmc/dw_mmc.c                           |   2 +-
 include/config_distro_bootcmd.h                |  47 +-
 include/configs/hikey.h                        |   6 +-
 include/configs/thunderx_88xx.h                |  30 -
 include/configs/vexpress_aemv8a.h              |  15 +-
 include/efi.h                                  |   2 +
 include/efi_api.h                              | 198 +++++--
 include/efi_loader.h                           | 157 +++++
 include/part.h                                 |   8 +
 include/pe.h                                   | 263 +++++++++
 lib/Kconfig                                    |   1 +
 lib/Makefile                                   |   1 +
 lib/efi_loader/Kconfig                         |   9 +
 lib/efi_loader/Makefile                        |  12 +
 lib/efi_loader/efi_boottime.c                  | 781 +++++++++++++++++++++++++
 lib/efi_loader/efi_console.c                   | 360 ++++++++++++
 lib/efi_loader/efi_disk.c                      | 212 +++++++
 lib/efi_loader/efi_image_loader.c              | 188 ++++++
 lib/efi_loader/efi_memory.c                    | 319 ++++++++++
 lib/efi_loader/efi_runtime.c                   | 290 +++++++++
 50 files changed, 4003 insertions(+), 670 deletions(-)
 create mode 100644 cmd/bootefi.c
 create mode 100644 include/efi_loader.h
 create mode 100644 include/pe.h
 create mode 100644 lib/efi_loader/Kconfig
 create mode 100644 lib/efi_loader/Makefile
 create mode 100644 lib/efi_loader/efi_boottime.c
 create mode 100644 lib/efi_loader/efi_console.c
 create mode 100644 lib/efi_loader/efi_disk.c
 create mode 100644 lib/efi_loader/efi_image_loader.c
 create mode 100644 lib/efi_loader/efi_memory.c
 create mode 100644 lib/efi_loader/efi_runtime.c

-- 
1.8.5.6

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 01/30] thunderx: Calculate TCR dynamically
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
@ 2016-03-04  0:09 ` Alexander Graf
  2016-03-17  1:59   ` [U-Boot] [U-Boot,v5,01/30] " Tom Rini
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 02/30] arm64: Disable TTBR1 maps in EL1 Alexander Graf
                   ` (29 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:09 UTC (permalink / raw)
  To: u-boot

Based on the memory map we can determine a lot of hard coded fields of
TCR, like the maximum VA and max PA we want to support. Calculate those
dynamically to reduce the chance for pit falls.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 arch/arm/cpu/armv8/cache_v8.c    | 59 +++++++++++++++++++++++++++++++++++++++-
 arch/arm/include/asm/armv8/mmu.h |  6 +---
 include/configs/thunderx_88xx.h  |  3 --
 3 files changed, 59 insertions(+), 9 deletions(-)

diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c
index 71f0020..9229532 100644
--- a/arch/arm/cpu/armv8/cache_v8.c
+++ b/arch/arm/cpu/armv8/cache_v8.c
@@ -38,6 +38,58 @@ static struct mm_region mem_map[] = CONFIG_SYS_MEM_MAP;
 #define PTL1_ENTRIES CONFIG_SYS_PTL1_ENTRIES
 #define PTL2_ENTRIES CONFIG_SYS_PTL2_ENTRIES
 
+static u64 get_tcr(int el, u64 *pips, u64 *pva_bits)
+{
+	u64 max_addr = 0;
+	u64 ips, va_bits;
+	u64 tcr;
+	int i;
+
+	/* Find the largest address we need to support */
+	for (i = 0; i < ARRAY_SIZE(mem_map); i++)
+		max_addr = max(max_addr, mem_map[i].base + mem_map[i].size);
+
+	/* Calculate the maximum physical (and thus virtual) address */
+	if (max_addr > (1ULL << 44)) {
+		ips = 5;
+		va_bits = 48;
+	} else  if (max_addr > (1ULL << 42)) {
+		ips = 4;
+		va_bits = 44;
+	} else  if (max_addr > (1ULL << 40)) {
+		ips = 3;
+		va_bits = 42;
+	} else  if (max_addr > (1ULL << 36)) {
+		ips = 2;
+		va_bits = 40;
+	} else  if (max_addr > (1ULL << 32)) {
+		ips = 1;
+		va_bits = 36;
+	} else {
+		ips = 0;
+		va_bits = 32;
+	}
+
+	if (el == 1) {
+		tcr = TCR_EL1_RSVD | (ips << 32);
+	} else if (el == 2) {
+		tcr = TCR_EL2_RSVD | (ips << 16);
+	} else {
+		tcr = TCR_EL3_RSVD | (ips << 16);
+	}
+
+	/* PTWs cacheable, inner/outer WBWA and inner shareable */
+	tcr |= TCR_TG0_64K | TCR_SHARED_INNER | TCR_ORGN_WBWA | TCR_IRGN_WBWA;
+	tcr |= TCR_T0SZ(VA_BITS);
+
+	if (pips)
+		*pips = ips;
+	if (pva_bits)
+		*pva_bits = va_bits;
+
+	return tcr;
+}
+
 static void setup_pgtables(void)
 {
 	int l1_e, l2_e;
@@ -110,6 +162,10 @@ __weak void mmu_setup(void)
 	/* Set up page tables only on BSP */
 	if (coreid == BSP_COREID)
 		setup_pgtables();
+
+	el = current_el();
+	set_ttbr_tcr_mair(el, gd->arch.tlb_addr, get_tcr(el, NULL, NULL),
+			  MEMORY_ATTRIBUTES);
 #else
 	/* Setup an identity-mapping for all spaces */
 	for (i = 0; i < (PGTABLE_SIZE >> 3); i++) {
@@ -128,7 +184,6 @@ __weak void mmu_setup(void)
 		}
 	}
 
-#endif
 	/* load TTBR0 */
 	el = current_el();
 	if (el == 1) {
@@ -144,6 +199,8 @@ __weak void mmu_setup(void)
 				  TCR_EL3_RSVD | TCR_FLAGS | TCR_EL3_IPS_BITS,
 				  MEMORY_ATTRIBUTES);
 	}
+#endif
+
 	/* enable the mmu */
 	set_sctlr(get_sctlr() | CR_M);
 }
diff --git a/arch/arm/include/asm/armv8/mmu.h b/arch/arm/include/asm/armv8/mmu.h
index 897f010..39ff745 100644
--- a/arch/arm/include/asm/armv8/mmu.h
+++ b/arch/arm/include/asm/armv8/mmu.h
@@ -159,11 +159,6 @@
 #define TCR_EL1_IPS_BITS	(UL(3) << 32)	/* 42 bits physical address */
 #define TCR_EL2_IPS_BITS	(3 << 16)	/* 42 bits physical address */
 #define TCR_EL3_IPS_BITS	(3 << 16)	/* 42 bits physical address */
-#else
-#define TCR_EL1_IPS_BITS	CONFIG_SYS_TCR_EL1_IPS_BITS
-#define TCR_EL2_IPS_BITS	CONFIG_SYS_TCR_EL2_IPS_BITS
-#define TCR_EL3_IPS_BITS	CONFIG_SYS_TCR_EL3_IPS_BITS
-#endif
 
 /* PTWs cacheable, inner/outer WBWA and inner shareable */
 #define TCR_FLAGS		(TCR_TG0_64K |		\
@@ -171,6 +166,7 @@
 				TCR_ORGN_WBWA |		\
 				TCR_IRGN_WBWA |		\
 				TCR_T0SZ(VA_BITS))
+#endif
 
 #define TCR_EL1_RSVD		(1 << 31)
 #define TCR_EL2_RSVD		(1 << 31 | 1 << 23)
diff --git a/include/configs/thunderx_88xx.h b/include/configs/thunderx_88xx.h
index cece4dd..b9f93ad 100644
--- a/include/configs/thunderx_88xx.h
+++ b/include/configs/thunderx_88xx.h
@@ -50,9 +50,6 @@
 #define CONFIG_SYS_PGTABLE_SIZE		\
 	((CONFIG_SYS_PTL1_ENTRIES + \
 	  CONFIG_SYS_MEM_MAP_SIZE * CONFIG_SYS_PTL2_ENTRIES) * 8)
-#define CONFIG_SYS_TCR_EL1_IPS_BITS	(5UL << 32)
-#define CONFIG_SYS_TCR_EL2_IPS_BITS	(5 << 16)
-#define CONFIG_SYS_TCR_EL3_IPS_BITS	(5 << 16)
 
 /* Link Definitions */
 #define CONFIG_SYS_TEXT_BASE		0x00500000
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 02/30] arm64: Disable TTBR1 maps in EL1
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 01/30] thunderx: Calculate TCR dynamically Alexander Graf
@ 2016-03-04  0:09 ` Alexander Graf
  2016-03-17  1:59   ` [U-Boot] [U-Boot,v5,02/30] " Tom Rini
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 03/30] arm64: Make full va map code more dynamic Alexander Graf
                   ` (28 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:09 UTC (permalink / raw)
  To: u-boot

When running in EL1, AArch64 knows two page table maps. One with addresses
that start with all zeros (TTBR0) and one with addresses that start with all
ones (TTBR1).

In U-Boot we don't care about the high up maps, so just disable them to ensure
we don't walk an invalid page table by accident.

Reported-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
 arch/arm/cpu/armv8/cache_v8.c    | 2 +-
 arch/arm/include/asm/armv8/mmu.h | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c
index 9229532..d92f2d1 100644
--- a/arch/arm/cpu/armv8/cache_v8.c
+++ b/arch/arm/cpu/armv8/cache_v8.c
@@ -71,7 +71,7 @@ static u64 get_tcr(int el, u64 *pips, u64 *pva_bits)
 	}
 
 	if (el == 1) {
-		tcr = TCR_EL1_RSVD | (ips << 32);
+		tcr = TCR_EL1_RSVD | (ips << 32) | TCR_EPD1_DISABLE;
 	} else if (el == 2) {
 		tcr = TCR_EL2_RSVD | (ips << 16);
 	} else {
diff --git a/arch/arm/include/asm/armv8/mmu.h b/arch/arm/include/asm/armv8/mmu.h
index 39ff745..0080ae6 100644
--- a/arch/arm/include/asm/armv8/mmu.h
+++ b/arch/arm/include/asm/armv8/mmu.h
@@ -154,6 +154,7 @@
 #define TCR_TG0_4K		(0 << 14)
 #define TCR_TG0_64K		(1 << 14)
 #define TCR_TG0_16K		(2 << 14)
+#define TCR_EPD1_DISABLE	(1 << 23)
 
 #ifndef CONFIG_SYS_FULL_VA
 #define TCR_EL1_IPS_BITS	(UL(3) << 32)	/* 42 bits physical address */
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 03/30] arm64: Make full va map code more dynamic
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 01/30] thunderx: Calculate TCR dynamically Alexander Graf
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 02/30] arm64: Disable TTBR1 maps in EL1 Alexander Graf
@ 2016-03-04  0:09 ` Alexander Graf
  2016-03-17  1:59   ` [U-Boot] [U-Boot, v5, " Tom Rini
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 04/30] thunderx: Move mmu table into board file Alexander Graf
                   ` (27 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:09 UTC (permalink / raw)
  To: u-boot

The idea to generate our pages tables from an array of memory ranges
is very sound. However, instead of hard coding the code to create up
to 2 levels of 64k granule page tables, we really should just create
normal 4k page tables that allow us to set caching attributes on 2M
or 4k level later on.

So this patch moves the full_va mapping code to 4k page size and
makes it fully flexible to dynamically create as many levels as
necessary for a map (including dynamic 1G/2M pages). It also adds
support to dynamically split a large map into smaller ones when
some code wants to set dcache attributes.

With all this in place, there is very little reason to create your
own page tables in board specific files.

Signed-off-by: Alexander Graf <agraf@suse.de>

---

v1 -> v2:

  - Fix comment for create_table()
  - Rework page table size calculation
  - s/DPRINTF/debug/g
  - Improve panic messages

v2 -> v3:

  - Move PGTABLE_SIZE out of the ASSEMBLY section
  - Run pte splitting code in separate page table
  - Replace is_level in count_required_pts with more obvious pte_type

v3 -> v4:

  - Lv3 PTEs are always of type table
---
 arch/arm/cpu/armv8/cache.S         |  54 +++++
 arch/arm/cpu/armv8/cache_v8.c      | 453 ++++++++++++++++++++++++++++++++-----
 arch/arm/include/asm/armv8/mmu.h   |  68 +++---
 arch/arm/include/asm/global_data.h |   5 +-
 arch/arm/include/asm/system.h      |  14 +-
 include/configs/thunderx_88xx.h    |  14 +-
 6 files changed, 500 insertions(+), 108 deletions(-)

diff --git a/arch/arm/cpu/armv8/cache.S b/arch/arm/cpu/armv8/cache.S
index ab8c089..a9f4fec 100644
--- a/arch/arm/cpu/armv8/cache.S
+++ b/arch/arm/cpu/armv8/cache.S
@@ -10,6 +10,7 @@
 #include <asm-offsets.h>
 #include <config.h>
 #include <asm/macro.h>
+#include <asm/system.h>
 #include <linux/linkage.h>
 
 /*
@@ -160,3 +161,56 @@ ENTRY(__asm_flush_l3_cache)
 	ret
 ENDPROC(__asm_flush_l3_cache)
 	.weak	__asm_flush_l3_cache
+
+/*
+ * void __asm_switch_ttbr(ulong new_ttbr)
+ *
+ * Safely switches to a new page table.
+ */
+ENTRY(__asm_switch_ttbr)
+	/* x2 = SCTLR (alive throghout the function) */
+	switch_el x4, 3f, 2f, 1f
+3:	mrs	x2, sctlr_el3
+	b	0f
+2:	mrs	x2, sctlr_el2
+	b	0f
+1:	mrs	x2, sctlr_el1
+0:
+
+	/* Unset CR_M | CR_C | CR_I from SCTLR to disable all caches */
+	movn	x1, #(CR_M | CR_C | CR_I)
+	and	x1, x2, x1
+	switch_el x4, 3f, 2f, 1f
+3:	msr	sctlr_el3, x1
+	b	0f
+2:	msr	sctlr_el2, x1
+	b	0f
+1:	msr	sctlr_el1, x1
+0:	isb
+
+	/* This call only clobbers x30 (lr) and x9 (unused) */
+	mov	x3, x30
+	bl	__asm_invalidate_tlb_all
+
+	/* From here on we're running safely with caches disabled */
+
+	/* Set TTBR to our first argument */
+	switch_el x4, 3f, 2f, 1f
+3:	msr	ttbr0_el3, x0
+	b	0f
+2:	msr	ttbr0_el2, x0
+	b	0f
+1:	msr	ttbr0_el1, x0
+0:	isb
+
+	/* Restore original SCTLR and thus enable caches again */
+	switch_el x4, 3f, 2f, 1f
+3:	msr	sctlr_el3, x2
+	b	0f
+2:	msr	sctlr_el2, x2
+	b	0f
+1:	msr	sctlr_el1, x2
+0:	isb
+
+	ret	x3
+ENDPROC(__asm_switch_ttbr)
diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c
index d92f2d1..73628c9 100644
--- a/arch/arm/cpu/armv8/cache_v8.c
+++ b/arch/arm/cpu/armv8/cache_v8.c
@@ -2,6 +2,9 @@
  * (C) Copyright 2013
  * David Feng <fenghua@phytium.com.cn>
  *
+ * (C) Copyright 2016
+ * Alexander Graf <agraf@suse.de>
+ *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
@@ -13,31 +16,28 @@ DECLARE_GLOBAL_DATA_PTR;
 
 #ifndef CONFIG_SYS_DCACHE_OFF
 
-#ifdef CONFIG_SYS_FULL_VA
-static void set_ptl1_entry(u64 index, u64 ptl2_entry)
-{
-	u64 *pgd = (u64 *)gd->arch.tlb_addr;
-	u64 value;
-
-	value = ptl2_entry | PTL1_TYPE_TABLE;
-	pgd[index] = value;
-}
-
-static void set_ptl2_block(u64 ptl1, u64 bfn, u64 address, u64 memory_attrs)
-{
-	u64 *pmd = (u64 *)ptl1;
-	u64 value;
-
-	value = address | PTL2_TYPE_BLOCK | PTL2_BLOCK_AF;
-	value |= memory_attrs;
-	pmd[bfn] = value;
-}
+/*
+ *  With 4k page granule, a virtual address is split into 4 lookup parts
+ *  spanning 9 bits each:
+ *
+ *    _______________________________________________
+ *   |       |       |       |       |       |       |
+ *   |   0   |  Lv0  |  Lv1  |  Lv2  |  Lv3  |  off  |
+ *   |_______|_______|_______|_______|_______|_______|
+ *     63-48   47-39   38-30   29-21   20-12   11-00
+ *
+ *             mask        page size
+ *
+ *    Lv0: FF8000000000       --
+ *    Lv1:   7FC0000000       1G
+ *    Lv2:     3FE00000       2M
+ *    Lv3:       1FF000       4K
+ *    off:          FFF
+ */
 
+#ifdef CONFIG_SYS_FULL_VA
 static struct mm_region mem_map[] = CONFIG_SYS_MEM_MAP;
 
-#define PTL1_ENTRIES CONFIG_SYS_PTL1_ENTRIES
-#define PTL2_ENTRIES CONFIG_SYS_PTL2_ENTRIES
-
 static u64 get_tcr(int el, u64 *pips, u64 *pva_bits)
 {
 	u64 max_addr = 0;
@@ -79,8 +79,8 @@ static u64 get_tcr(int el, u64 *pips, u64 *pva_bits)
 	}
 
 	/* PTWs cacheable, inner/outer WBWA and inner shareable */
-	tcr |= TCR_TG0_64K | TCR_SHARED_INNER | TCR_ORGN_WBWA | TCR_IRGN_WBWA;
-	tcr |= TCR_T0SZ(VA_BITS);
+	tcr |= TCR_TG0_4K | TCR_SHARED_INNER | TCR_ORGN_WBWA | TCR_IRGN_WBWA;
+	tcr |= TCR_T0SZ(va_bits);
 
 	if (pips)
 		*pips = ips;
@@ -90,39 +90,302 @@ static u64 get_tcr(int el, u64 *pips, u64 *pva_bits)
 	return tcr;
 }
 
-static void setup_pgtables(void)
+#define MAX_PTE_ENTRIES 512
+
+static int pte_type(u64 *pte)
+{
+	return *pte & PTE_TYPE_MASK;
+}
+
+/* Returns the LSB number for a PTE on level <level> */
+static int level2shift(int level)
+{
+	/* Page is 12 bits wide, every level translates 9 bits */
+	return (12 + 9 * (3 - level));
+}
+
+static u64 *find_pte(u64 addr, int level)
 {
-	int l1_e, l2_e;
-	unsigned long pmd = 0;
-	unsigned long address;
-
-	/* Setup the PMD pointers */
-	for (l1_e = 0; l1_e < CONFIG_SYS_MEM_MAP_SIZE; l1_e++) {
-		gd->arch.pmd_addr[l1_e] = gd->arch.tlb_addr +
-						PTL1_ENTRIES * sizeof(u64);
-		gd->arch.pmd_addr[l1_e] += PTL2_ENTRIES * sizeof(u64) * l1_e;
-		gd->arch.pmd_addr[l1_e] = ALIGN(gd->arch.pmd_addr[l1_e],
-						0x10000UL);
+	int start_level = 0;
+	u64 *pte;
+	u64 idx;
+	u64 va_bits;
+	int i;
+
+	debug("addr=%llx level=%d\n", addr, level);
+
+	get_tcr(0, NULL, &va_bits);
+	if (va_bits < 39)
+		start_level = 1;
+
+	if (level < start_level)
+		return NULL;
+
+	/* Walk through all page table levels to find our PTE */
+	pte = (u64*)gd->arch.tlb_addr;
+	for (i = start_level; i < 4; i++) {
+		idx = (addr >> level2shift(i)) & 0x1FF;
+		pte += idx;
+		debug("idx=%llx PTE %p at level %d: %llx\n", idx, pte, i, *pte);
+
+		/* Found it */
+		if (i == level)
+			return pte;
+		/* PTE is no table (either invalid or block), can't traverse */
+		if (pte_type(pte) != PTE_TYPE_TABLE)
+			return NULL;
+		/* Off to the next level */
+		pte = (u64*)(*pte & 0x0000fffffffff000ULL);
 	}
 
-	/* Setup the page tables */
-	for (l1_e = 0; l1_e < PTL1_ENTRIES; l1_e++) {
-		if (mem_map[pmd].base ==
-			(uintptr_t)l1_e << PTL2_BITS) {
-			set_ptl1_entry(l1_e, gd->arch.pmd_addr[pmd]);
-
-			for (l2_e = 0; l2_e < PTL2_ENTRIES; l2_e++) {
-				address = mem_map[pmd].base
-					+ (uintptr_t)l2_e * BLOCK_SIZE;
-				set_ptl2_block(gd->arch.pmd_addr[pmd], l2_e,
-					       address, mem_map[pmd].attrs);
+	/* Should never reach here */
+	return NULL;
+}
+
+/* Returns and creates a new full table (512 entries) */
+static u64 *create_table(void)
+{
+	u64 *new_table = (u64*)gd->arch.tlb_fillptr;
+	u64 pt_len = MAX_PTE_ENTRIES * sizeof(u64);
+
+	/* Allocate MAX_PTE_ENTRIES pte entries */
+	gd->arch.tlb_fillptr += pt_len;
+
+	if (gd->arch.tlb_fillptr - gd->arch.tlb_addr > gd->arch.tlb_size)
+		panic("Insufficient RAM for page table: 0x%lx > 0x%lx. "
+		      "Please increase the size in get_page_table_size()",
+			gd->arch.tlb_fillptr - gd->arch.tlb_addr,
+			gd->arch.tlb_size);
+
+	/* Mark all entries as invalid */
+	memset(new_table, 0, pt_len);
+
+	return new_table;
+}
+
+static void set_pte_table(u64 *pte, u64 *table)
+{
+	/* Point *pte to the new table */
+	debug("Setting %p to addr=%p\n", pte, table);
+	*pte = PTE_TYPE_TABLE | (ulong)table;
+}
+
+/* Add one mm_region map entry to the page tables */
+static void add_map(struct mm_region *map)
+{
+	u64 *pte;
+	u64 addr = map->base;
+	u64 size = map->size;
+	u64 attrs = map->attrs | PTE_TYPE_BLOCK | PTE_BLOCK_AF;
+	u64 blocksize;
+	int level;
+	u64 *new_table;
+
+	while (size) {
+		pte = find_pte(addr, 0);
+		if (pte && (pte_type(pte) == PTE_TYPE_FAULT)) {
+			debug("Creating table for addr 0x%llx\n", addr);
+			new_table = create_table();
+			set_pte_table(pte, new_table);
+		}
+
+		for (level = 1; level < 4; level++) {
+			pte = find_pte(addr, level);
+			blocksize = 1ULL << level2shift(level);
+			debug("Checking if pte fits for addr=%llx size=%llx "
+			      "blocksize=%llx\n", addr, size, blocksize);
+			if (size >= blocksize && !(addr & (blocksize - 1))) {
+				/* Page fits, create block PTE */
+				debug("Setting PTE %p to block addr=%llx\n",
+				      pte, addr);
+				*pte = addr | attrs;
+				addr += blocksize;
+				size -= blocksize;
+				break;
+			} else if ((pte_type(pte) == PTE_TYPE_FAULT)) {
+				/* Page doesn't fit, create subpages */
+				debug("Creating subtable for addr 0x%llx "
+				      "blksize=%llx\n", addr, blocksize);
+				new_table = create_table();
+				set_pte_table(pte, new_table);
 			}
+		}
+	}
+}
+
+/* Splits a block PTE into table with subpages spanning the old block */
+static void split_block(u64 *pte, int level)
+{
+	u64 old_pte = *pte;
+	u64 *new_table;
+	u64 i = 0;
+	/* level describes the parent level, we need the child ones */
+	int levelshift = level2shift(level + 1);
+
+	if (pte_type(pte) != PTE_TYPE_BLOCK)
+		panic("PTE %p (%llx) is not a block. Some driver code wants to "
+		      "modify dcache settings for an range not covered in "
+		      "mem_map.", pte, old_pte);
+
+	new_table = create_table();
+	debug("Splitting pte %p (%llx) into %p\n", pte, old_pte, new_table);
+
+	for (i = 0; i < MAX_PTE_ENTRIES; i++) {
+		new_table[i] = old_pte | (i << levelshift);
+
+		/* Level 3 block PTEs have the table type */
+		if ((level + 1) == 3)
+			new_table[i] |= PTE_TYPE_TABLE;
+
+		debug("Setting new_table[%lld] = %llx\n", i, new_table[i]);
+	}
+
+	/* Set the new table into effect */
+	set_pte_table(pte, new_table);
+}
+
+enum pte_type {
+	PTE_INVAL,
+	PTE_BLOCK,
+	PTE_LEVEL,
+};
 
-			pmd++;
-		} else {
-			set_ptl1_entry(l1_e, 0);
+/*
+ * This is a recursively called function to count the number of
+ * page tables we need to cover a particular PTE range. If you
+ * call this with level = -1 you basically get the full 48 bit
+ * coverage.
+ */
+static int count_required_pts(u64 addr, int level, u64 maxaddr)
+{
+	int levelshift = level2shift(level);
+	u64 levelsize = 1ULL << levelshift;
+	u64 levelmask = levelsize - 1;
+	u64 levelend = addr + levelsize;
+	int r = 0;
+	int i;
+	enum pte_type pte_type = PTE_INVAL;
+
+	for (i = 0; i < ARRAY_SIZE(mem_map); i++) {
+		struct mm_region *map = &mem_map[i];
+		u64 start = map->base;
+		u64 end = start + map->size;
+
+		/* Check if the PTE would overlap with the map */
+		if (max(addr, start) <= min(levelend, end)) {
+			start = max(addr, start);
+			end = min(levelend, end);
+
+			/* We need a sub-pt for this level */
+			if ((start & levelmask) || (end & levelmask)) {
+				pte_type = PTE_LEVEL;
+				break;
+			}
+
+			/* Lv0 can not do block PTEs, so do levels here too */
+			if (level <= 0) {
+				pte_type = PTE_LEVEL;
+				break;
+			}
+
+			/* PTE is active, but fits into a block */
+			pte_type = PTE_BLOCK;
 		}
 	}
+
+	/*
+	 * Block PTEs@this level are already covered by the parent page
+	 * table, so we only need to count sub page tables.
+	 */
+	if (pte_type == PTE_LEVEL) {
+		int sublevel = level + 1;
+		u64 sublevelsize = 1ULL << level2shift(sublevel);
+
+		/* Account for the new sub page table ... */
+		r = 1;
+
+		/* ... and for all child page tables that one might have */
+		for (i = 0; i < MAX_PTE_ENTRIES; i++) {
+			r += count_required_pts(addr, sublevel, maxaddr);
+			addr += sublevelsize;
+
+			if (addr >= maxaddr) {
+				/*
+				 * We reached the end of address space, no need
+				 * to look any further.
+				 */
+				break;
+			}
+		}
+	}
+
+	return r;
+}
+
+/* Returns the estimated required size of all page tables */
+u64 get_page_table_size(void)
+{
+	u64 one_pt = MAX_PTE_ENTRIES * sizeof(u64);
+	u64 size = 0;
+	u64 va_bits;
+	int start_level = 0;
+
+	get_tcr(0, NULL, &va_bits);
+	if (va_bits < 39)
+		start_level = 1;
+
+	/* Account for all page tables we would need to cover our memory map */
+	size = one_pt * count_required_pts(0, start_level - 1, 1ULL << va_bits);
+
+	/*
+	 * We need to duplicate our page table once to have an emergency pt to
+	 * resort to when splitting page tables later on
+	 */
+	size *= 2;
+
+	/*
+	 * We may need to split page tables later on if dcache settings change,
+	 * so reserve up to 4 (random pick) page tables for that.
+	 */
+	size += one_pt * 4;
+
+	return size;
+}
+
+static void setup_pgtables(void)
+{
+	int i;
+
+	/*
+	 * Allocate the first level we're on with invalidate entries.
+	 * If the starting level is 0 (va_bits >= 39), then this is our
+	 * Lv0 page table, otherwise it's the entry Lv1 page table.
+	 */
+	create_table();
+
+	/* Now add all MMU table entries one after another to the table */
+	for (i = 0; i < ARRAY_SIZE(mem_map); i++)
+		add_map(&mem_map[i]);
+
+	/* Create the same thing once more for our emergency page table */
+	create_table();
+}
+
+static void setup_all_pgtables(void)
+{
+	u64 tlb_addr = gd->arch.tlb_addr;
+
+	/* Reset the fill ptr */
+	gd->arch.tlb_fillptr = tlb_addr;
+
+	/* Create normal system page tables */
+	setup_pgtables();
+
+	/* Create emergency page tables */
+	gd->arch.tlb_addr = gd->arch.tlb_fillptr;
+	setup_pgtables();
+	gd->arch.tlb_emerg = gd->arch.tlb_addr;
+	gd->arch.tlb_addr = tlb_addr;
 }
 
 #else
@@ -157,11 +420,9 @@ __weak void mmu_setup(void)
 	int el;
 
 #ifdef CONFIG_SYS_FULL_VA
-	unsigned long coreid = read_mpidr() & CONFIG_COREID_MASK;
-
-	/* Set up page tables only on BSP */
-	if (coreid == BSP_COREID)
-		setup_pgtables();
+	/* Set up page tables only once */
+	if (!gd->arch.tlb_fillptr)
+		setup_all_pgtables();
 
 	el = current_el();
 	set_ttbr_tcr_mair(el, gd->arch.tlb_addr, get_tcr(el, NULL, NULL),
@@ -311,6 +572,88 @@ void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
 	flush_dcache_range(start, end);
 	asm volatile("dsb sy");
 }
+#else
+static bool is_aligned(u64 addr, u64 size, u64 align)
+{
+	return !(addr & (align - 1)) && !(size & (align - 1));
+}
+
+static u64 set_one_region(u64 start, u64 size, u64 attrs, int level)
+{
+	int levelshift = level2shift(level);
+	u64 levelsize = 1ULL << levelshift;
+	u64 *pte = find_pte(start, level);
+
+	/* Can we can just modify the current level block PTE? */
+	if (is_aligned(start, size, levelsize)) {
+		*pte &= ~PMD_ATTRINDX_MASK;
+		*pte |= attrs;
+		debug("Set attrs=%llx pte=%p level=%d\n", attrs, pte, level);
+
+		return levelsize;
+	}
+
+	/* Unaligned or doesn't fit, maybe split block into table */
+	debug("addr=%llx level=%d pte=%p (%llx)\n", start, level, pte, *pte);
+
+	/* Maybe we need to split the block into a table */
+	if (pte_type(pte) == PTE_TYPE_BLOCK)
+		split_block(pte, level);
+
+	/* And then double-check it became a table or already is one */
+	if (pte_type(pte) != PTE_TYPE_TABLE)
+		panic("PTE %p (%llx) for addr=%llx should be a table",
+		      pte, *pte, start);
+
+	/* Roll on to the next page table level */
+	return 0;
+}
+
+void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
+				     enum dcache_option option)
+{
+	u64 attrs = PMD_ATTRINDX(option);
+	u64 real_start = start;
+	u64 real_size = size;
+
+	debug("start=%lx size=%lx\n", (ulong)start, (ulong)size);
+
+	/*
+	 * We can not modify page tables that we're currently running on,
+	 * so we first need to switch to the "emergency" page tables where
+	 * we can safely modify our primary page tables and then switch back
+	 */
+	__asm_switch_ttbr(gd->arch.tlb_emerg);
+
+	/*
+	 * Loop through the address range until we find a page granule that fits
+	 * our alignment constraints, then set it to the new cache attributes
+	 */
+	while (size > 0) {
+		int level;
+		u64 r;
+
+		for (level = 1; level < 4; level++) {
+			r = set_one_region(start, size, attrs, level);
+			if (r) {
+				/* PTE successfully replaced */
+				size -= r;
+				start += r;
+				break;
+			}
+		}
+
+	}
+
+	/* We're done modifying page tables, switch back to our primary ones */
+	__asm_switch_ttbr(gd->arch.tlb_addr);
+
+	/*
+	 * Make sure there's nothing stale in dcache for a region that might
+	 * have caches off now
+	 */
+	flush_dcache_range(real_start, real_start + real_size);
+}
 #endif
 
 #else	/* CONFIG_SYS_DCACHE_OFF */
diff --git a/arch/arm/include/asm/armv8/mmu.h b/arch/arm/include/asm/armv8/mmu.h
index 0080ae6..1c490dc 100644
--- a/arch/arm/include/asm/armv8/mmu.h
+++ b/arch/arm/include/asm/armv8/mmu.h
@@ -26,15 +26,9 @@
 #define VA_BITS			(42)	/* 42 bits virtual address */
 #else
 #define VA_BITS			CONFIG_SYS_VA_BITS
-#define PTL2_BITS		CONFIG_SYS_PTL2_BITS
+#define PTE_BLOCK_BITS		CONFIG_SYS_PTL2_BITS
 #endif
 
-/* PAGE_SHIFT determines the page size */
-#undef  PAGE_SIZE
-#define PAGE_SHIFT		16
-#define PAGE_SIZE		(1 << PAGE_SHIFT)
-#define PAGE_MASK		(~(PAGE_SIZE-1))
-
 /*
  * block/section address mask and size definitions.
  */
@@ -42,10 +36,21 @@
 #define SECTION_SHIFT		29
 #define SECTION_SIZE		(UL(1) << SECTION_SHIFT)
 #define SECTION_MASK		(~(SECTION_SIZE-1))
+
+/* PAGE_SHIFT determines the page size */
+#undef  PAGE_SIZE
+#define PAGE_SHIFT		16
+#define PAGE_SIZE		(1 << PAGE_SHIFT)
+#define PAGE_MASK		(~(PAGE_SIZE-1))
+
 #else
-#define BLOCK_SHIFT		CONFIG_SYS_BLOCK_SHIFT
-#define BLOCK_SIZE		(UL(1) << BLOCK_SHIFT)
-#define BLOCK_MASK		(~(BLOCK_SIZE-1))
+
+/* PAGE_SHIFT determines the page size */
+#undef  PAGE_SIZE
+#define PAGE_SHIFT		12
+#define PAGE_SIZE		(1 << PAGE_SHIFT)
+#define PAGE_MASK		(~(PAGE_SIZE-1))
+
 #endif
 
 /***************************************************************/
@@ -71,39 +76,28 @@
  */
 
 #ifdef CONFIG_SYS_FULL_VA
-/*
- * Level 1 descriptor (PGD).
- */
 
-#define PTL1_TYPE_MASK		(3 << 0)
-#define PTL1_TYPE_TABLE		(3 << 0)
-
-#define PTL1_TABLE_PXN		(1UL << 59)
-#define PTL1_TABLE_XN		(1UL << 60)
-#define PTL1_TABLE_AP		(1UL << 61)
-#define PTL1_TABLE_NS		(1UL << 63)
-
-
-/*
- * Level 2 descriptor (PMD).
- */
+#define PTE_TYPE_MASK		(3 << 0)
+#define PTE_TYPE_FAULT		(0 << 0)
+#define PTE_TYPE_TABLE		(3 << 0)
+#define PTE_TYPE_BLOCK		(1 << 0)
 
-#define PTL2_TYPE_MASK		(3 << 0)
-#define PTL2_TYPE_FAULT		(0 << 0)
-#define PTL2_TYPE_TABLE		(3 << 0)
-#define PTL2_TYPE_BLOCK		(1 << 0)
+#define PTE_TABLE_PXN		(1UL << 59)
+#define PTE_TABLE_XN		(1UL << 60)
+#define PTE_TABLE_AP		(1UL << 61)
+#define PTE_TABLE_NS		(1UL << 63)
 
 /*
  * Block
  */
-#define PTL2_MEMTYPE(x)		((x) << 2)
-#define PTL2_BLOCK_NON_SHARE	(0 << 8)
-#define PTL2_BLOCK_OUTER_SHARE	(2 << 8)
-#define PTL2_BLOCK_INNER_SHARE	(3 << 8)
-#define PTL2_BLOCK_AF		(1 << 10)
-#define PTL2_BLOCK_NG		(1 << 11)
-#define PTL2_BLOCK_PXN		(UL(1) << 53)
-#define PTL2_BLOCK_UXN		(UL(1) << 54)
+#define PTE_BLOCK_MEMTYPE(x)	((x) << 2)
+#define PTE_BLOCK_NON_SHARE	(0 << 8)
+#define PTE_BLOCK_OUTER_SHARE	(2 << 8)
+#define PTE_BLOCK_INNER_SHARE	(3 << 8)
+#define PTE_BLOCK_AF		(1 << 10)
+#define PTE_BLOCK_NG		(1 << 11)
+#define PTE_BLOCK_PXN		(UL(1) << 53)
+#define PTE_BLOCK_UXN		(UL(1) << 54)
 
 #else
 /*
diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
index dcfa098..259daa1 100644
--- a/arch/arm/include/asm/global_data.h
+++ b/arch/arm/include/asm/global_data.h
@@ -38,10 +38,11 @@ struct arch_global_data {
 	unsigned long long timer_reset_value;
 #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
 	unsigned long tlb_addr;
+	unsigned long tlb_size;
 #if defined(CONFIG_SYS_FULL_VA)
-	unsigned long pmd_addr[CONFIG_SYS_PTL1_ENTRIES];
+	unsigned long tlb_fillptr;
+	unsigned long tlb_emerg;
 #endif
-	unsigned long tlb_size;
 #endif
 
 #ifdef CONFIG_OMAP_COMMON
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index 026e7ef..9b1cbf2 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -17,18 +17,19 @@
 #define CR_WXN		(1 << 19)	/* Write Permision Imply XN	*/
 #define CR_EE		(1 << 25)	/* Exception (Big) Endian	*/
 
-#ifndef CONFIG_SYS_FULL_VA
-#define PGTABLE_SIZE	(0x10000)
-#else
-#define PGTABLE_SIZE	CONFIG_SYS_PGTABLE_SIZE
-#endif
-
 /* 2MB granularity */
 #define MMU_SECTION_SHIFT	21
 #define MMU_SECTION_SIZE	(1 << MMU_SECTION_SHIFT)
 
 #ifndef __ASSEMBLY__
 
+#ifndef CONFIG_SYS_FULL_VA
+#define PGTABLE_SIZE	(0x10000)
+#else
+u64 get_page_table_size(void);
+#define PGTABLE_SIZE	get_page_table_size()
+#endif
+
 enum dcache_option {
 	DCACHE_OFF = 0x3,
 };
@@ -97,6 +98,7 @@ void __asm_flush_dcache_range(u64 start, u64 end);
 void __asm_invalidate_tlb_all(void);
 void __asm_invalidate_icache_all(void);
 int __asm_flush_l3_cache(void);
+void __asm_switch_ttbr(u64 new_ttbr);
 
 void armv8_switch_to_el2(void);
 void armv8_switch_to_el1(void);
diff --git a/include/configs/thunderx_88xx.h b/include/configs/thunderx_88xx.h
index b9f93ad..20b25f7 100644
--- a/include/configs/thunderx_88xx.h
+++ b/include/configs/thunderx_88xx.h
@@ -22,21 +22,19 @@
 
 #define MEM_BASE			0x00500000
 
-#define CONFIG_COREID_MASK             0xffffff
-
 #define CONFIG_SYS_FULL_VA
 
 #define CONFIG_SYS_LOWMEM_BASE		MEM_BASE
 
 #define CONFIG_SYS_MEM_MAP		{{0x000000000000UL, 0x40000000000UL, \
-					  PTL2_MEMTYPE(MT_NORMAL) |	     \
-					  PTL2_BLOCK_NON_SHARE},	     \
+					  PTE_BLOCK_MEMTYPE(MT_NORMAL) |     \
+					  PTE_BLOCK_NON_SHARE},	     \
 					 {0x800000000000UL, 0x40000000000UL, \
-					  PTL2_MEMTYPE(MT_DEVICE_NGNRNE) |   \
-					  PTL2_BLOCK_NON_SHARE},	     \
+					  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | \
+					  PTE_BLOCK_NON_SHARE},	     \
 					 {0x840000000000UL, 0x40000000000UL, \
-					  PTL2_MEMTYPE(MT_DEVICE_NGNRNE) |   \
-					  PTL2_BLOCK_NON_SHARE},	     \
+					  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | \
+					  PTE_BLOCK_NON_SHARE},	     \
 					}
 
 #define CONFIG_SYS_MEM_MAP_SIZE		3
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 04/30] thunderx: Move mmu table into board file
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (2 preceding siblings ...)
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 03/30] arm64: Make full va map code more dynamic Alexander Graf
@ 2016-03-04  0:09 ` Alexander Graf
  2016-03-17  2:00   ` [U-Boot] [U-Boot, v5, " Tom Rini
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 05/30] zymqmp: Replace home grown mmu code with generic table approach Alexander Graf
                   ` (26 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:09 UTC (permalink / raw)
  To: u-boot

The MMU range table can vary depending on things we may only find
out at runtime. While the very simple ThunderX variant does not
change, other boards will, so move the definition from a static
entry in a header file to the board file.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 arch/arm/cpu/armv8/cache_v8.c    |  8 +++-----
 arch/arm/include/asm/armv8/mmu.h |  2 ++
 board/cavium/thunderx/thunderx.c | 24 ++++++++++++++++++++++++
 include/configs/thunderx_88xx.h  | 11 -----------
 4 files changed, 29 insertions(+), 16 deletions(-)

diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c
index 73628c9..55c6f2f 100644
--- a/arch/arm/cpu/armv8/cache_v8.c
+++ b/arch/arm/cpu/armv8/cache_v8.c
@@ -36,8 +36,6 @@ DECLARE_GLOBAL_DATA_PTR;
  */
 
 #ifdef CONFIG_SYS_FULL_VA
-static struct mm_region mem_map[] = CONFIG_SYS_MEM_MAP;
-
 static u64 get_tcr(int el, u64 *pips, u64 *pva_bits)
 {
 	u64 max_addr = 0;
@@ -46,7 +44,7 @@ static u64 get_tcr(int el, u64 *pips, u64 *pva_bits)
 	int i;
 
 	/* Find the largest address we need to support */
-	for (i = 0; i < ARRAY_SIZE(mem_map); i++)
+	for (i = 0; mem_map[i].size || mem_map[i].attrs; i++)
 		max_addr = max(max_addr, mem_map[i].base + mem_map[i].size);
 
 	/* Calculate the maximum physical (and thus virtual) address */
@@ -266,7 +264,7 @@ static int count_required_pts(u64 addr, int level, u64 maxaddr)
 	int i;
 	enum pte_type pte_type = PTE_INVAL;
 
-	for (i = 0; i < ARRAY_SIZE(mem_map); i++) {
+	for (i = 0; mem_map[i].size || mem_map[i].attrs; i++) {
 		struct mm_region *map = &mem_map[i];
 		u64 start = map->base;
 		u64 end = start + map->size;
@@ -364,7 +362,7 @@ static void setup_pgtables(void)
 	create_table();
 
 	/* Now add all MMU table entries one after another to the table */
-	for (i = 0; i < ARRAY_SIZE(mem_map); i++)
+	for (i = 0; mem_map[i].size || mem_map[i].attrs; i++)
 		add_map(&mem_map[i]);
 
 	/* Create the same thing once more for our emergency page table */
diff --git a/arch/arm/include/asm/armv8/mmu.h b/arch/arm/include/asm/armv8/mmu.h
index 1c490dc..06126c8 100644
--- a/arch/arm/include/asm/armv8/mmu.h
+++ b/arch/arm/include/asm/armv8/mmu.h
@@ -203,6 +203,8 @@ struct mm_region {
 	u64 size;
 	u64 attrs;
 };
+
+extern struct mm_region *mem_map;
 #endif
 
 #endif /* _ASM_ARMV8_MMU_H_ */
diff --git a/board/cavium/thunderx/thunderx.c b/board/cavium/thunderx/thunderx.c
index b926767..9131a38 100644
--- a/board/cavium/thunderx/thunderx.c
+++ b/board/cavium/thunderx/thunderx.c
@@ -10,6 +10,7 @@
 #include <linux/compiler.h>
 
 #include <cavium/atf.h>
+#include <asm/armv8/mmu.h>
 
 #if !CONFIG_IS_ENABLED(OF_CONTROL)
 #include <dm/platdata.h>
@@ -42,6 +43,29 @@ U_BOOT_DEVICE(thunderx_serial1) = {
 
 DECLARE_GLOBAL_DATA_PTR;
 
+static struct mm_region thunderx_mem_map[] = {
+	{
+		.base = 0x000000000000UL,
+		.size = 0x40000000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE,
+	}, {
+		.base = 0x800000000000UL,
+		.size = 0x40000000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE,
+	}, {
+		.base = 0x840000000000UL,
+		.size = 0x40000000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE,
+	}, {
+		/* List terminator */
+		0,
+	}
+};
+
+struct mm_region *mem_map = thunderx_mem_map;
+
 int board_init(void)
 {
 	return 0;
diff --git a/include/configs/thunderx_88xx.h b/include/configs/thunderx_88xx.h
index 20b25f7..64e4616 100644
--- a/include/configs/thunderx_88xx.h
+++ b/include/configs/thunderx_88xx.h
@@ -26,17 +26,6 @@
 
 #define CONFIG_SYS_LOWMEM_BASE		MEM_BASE
 
-#define CONFIG_SYS_MEM_MAP		{{0x000000000000UL, 0x40000000000UL, \
-					  PTE_BLOCK_MEMTYPE(MT_NORMAL) |     \
-					  PTE_BLOCK_NON_SHARE},	     \
-					 {0x800000000000UL, 0x40000000000UL, \
-					  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | \
-					  PTE_BLOCK_NON_SHARE},	     \
-					 {0x840000000000UL, 0x40000000000UL, \
-					  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | \
-					  PTE_BLOCK_NON_SHARE},	     \
-					}
-
 #define CONFIG_SYS_MEM_MAP_SIZE		3
 
 #define CONFIG_SYS_VA_BITS		48
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 05/30] zymqmp: Replace home grown mmu code with generic table approach
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (3 preceding siblings ...)
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 04/30] thunderx: Move mmu table into board file Alexander Graf
@ 2016-03-04  0:09 ` Alexander Graf
  2016-03-17  2:00   ` [U-Boot] [U-Boot, v5, " Tom Rini
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 06/30] tegra: " Alexander Graf
                   ` (25 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:09 UTC (permalink / raw)
  To: u-boot

Now that we have nice table driven page table creating code that gives
us everything we need, move to that.

Signed-off-by: Alexander Graf <agraf@suse.de>

---

v1 -> v2:

  - Move mmu tables into board file
---
 arch/arm/cpu/armv8/zynqmp/cpu.c | 217 +++++++++-------------------------------
 include/configs/xilinx_zynqmp.h |   2 +
 2 files changed, 50 insertions(+), 169 deletions(-)

diff --git a/arch/arm/cpu/armv8/zynqmp/cpu.c b/arch/arm/cpu/armv8/zynqmp/cpu.c
index c71f291..5dd3cd8 100644
--- a/arch/arm/cpu/armv8/zynqmp/cpu.c
+++ b/arch/arm/cpu/armv8/zynqmp/cpu.c
@@ -8,6 +8,7 @@
 #include <common.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/sys_proto.h>
+#include <asm/armv8/mmu.h>
 #include <asm/io.h>
 
 #define ZYNQ_SILICON_VER_MASK	0xF000
@@ -15,6 +16,53 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+static struct mm_region zynqmp_mem_map[] = {
+	{
+		.base = 0x0UL,
+		.size = 0x80000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_INNER_SHARE
+	}, {
+		.base = 0x80000000UL,
+		.size = 0x70000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		.base = 0xf8000000UL,
+		.size = 0x07e00000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		.base = 0xffe00000UL,
+		.size = 0x00200000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_INNER_SHARE
+	}, {
+		.base = 0x400000000UL,
+		.size = 0x200000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		.base = 0x600000000UL,
+		.size = 0x800000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_INNER_SHARE
+	}, {
+		.base = 0xe00000000UL,
+		.size = 0xf200000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		/* List terminator */
+		0,
+	}
+};
+struct mm_region *mem_map = zynqmp_mem_map;
+
 static unsigned int zynqmp_get_silicon_version_secure(void)
 {
 	u32 ver;
@@ -44,172 +92,3 @@ unsigned int zynqmp_get_silicon_version(void)
 
 	return ZYNQMP_CSU_VERSION_SILICON;
 }
-
-#ifndef CONFIG_SYS_DCACHE_OFF
-#include <asm/armv8/mmu.h>
-
-#define SECTION_SHIFT_L1	30UL
-#define SECTION_SHIFT_L2	21UL
-#define BLOCK_SIZE_L0		0x8000000000UL
-#define BLOCK_SIZE_L1		(1 << SECTION_SHIFT_L1)
-#define BLOCK_SIZE_L2		(1 << SECTION_SHIFT_L2)
-
-#define TCR_TG1_4K		(1 << 31)
-#define TCR_EPD1_DISABLE	(1 << 23)
-#define ZYNQMO_VA_BITS		40
-#define ZYNQMP_TCR		TCR_TG1_4K | \
-				TCR_EPD1_DISABLE | \
-				TCR_SHARED_OUTER | \
-				TCR_SHARED_INNER | \
-				TCR_IRGN_WBWA | \
-				TCR_ORGN_WBWA | \
-				TCR_T0SZ(ZYNQMO_VA_BITS)
-
-#define MEMORY_ATTR	PMD_SECT_AF | PMD_SECT_INNER_SHARE |	\
-			PMD_ATTRINDX(MT_NORMAL) |	\
-			PMD_TYPE_SECT
-#define DEVICE_ATTR	PMD_SECT_AF | PMD_SECT_PXN |	\
-			PMD_SECT_UXN | PMD_ATTRINDX(MT_DEVICE_NGNRNE) |	\
-			PMD_TYPE_SECT
-
-/* 4K size is required to place 512 entries in each level */
-#define TLB_TABLE_SIZE	0x1000
-
-struct attr_tbl {
-	u32 num;
-	u64 attr;
-};
-
-static struct attr_tbl attr_tbll1t0[4] = { {16, 0x0},
-					   {8, DEVICE_ATTR},
-					   {32, MEMORY_ATTR},
-					   {456, DEVICE_ATTR}
-					 };
-static struct attr_tbl attr_tbll2t3[4] = { {0x180, DEVICE_ATTR},
-					   {0x40, 0x0},
-					   {0x3F, DEVICE_ATTR},
-					   {0x1, MEMORY_ATTR}
-					 };
-
-/*
- * This mmu table looks as below
- * Level 0 table contains two entries to 512GB sizes. One is Level1 Table 0
- * and other Level1 Table1.
- * Level1 Table0 contains entries for each 1GB from 0 to 511GB.
- * Level1 Table1 contains entries for each 1GB from 512GB to 1TB.
- * Level2 Table0, Level2 Table1, Level2 Table2 and Level2 Table3 contains
- * entries for each 2MB starting from 0GB, 1GB, 2GB and 3GB respectively.
- */
-static void zynqmp_mmu_setup(void)
-{
-	int el;
-	u32 index_attr;
-	u64 i, section_l1t0, section_l1t1;
-	u64 section_l2t0, section_l2t1, section_l2t2, section_l2t3;
-	u64 *level0_table = (u64 *)gd->arch.tlb_addr;
-	u64 *level1_table_0 = (u64 *)(gd->arch.tlb_addr + TLB_TABLE_SIZE);
-	u64 *level1_table_1 = (u64 *)(gd->arch.tlb_addr + (2 * TLB_TABLE_SIZE));
-	u64 *level2_table_0 = (u64 *)(gd->arch.tlb_addr + (3 * TLB_TABLE_SIZE));
-	u64 *level2_table_1 = (u64 *)(gd->arch.tlb_addr + (4 * TLB_TABLE_SIZE));
-	u64 *level2_table_2 = (u64 *)(gd->arch.tlb_addr + (5 * TLB_TABLE_SIZE));
-	u64 *level2_table_3 = (u64 *)(gd->arch.tlb_addr + (6 * TLB_TABLE_SIZE));
-
-	level0_table[0] =
-		(u64)level1_table_0 | PMD_TYPE_TABLE;
-	level0_table[1] =
-		(u64)level1_table_1 | PMD_TYPE_TABLE;
-
-	/*
-	 * set level 1 table 0, covering 0 to 512GB
-	 * set level 1 table 1, covering 512GB to 1TB
-	 */
-	section_l1t0 = 0;
-	section_l1t1 = BLOCK_SIZE_L0;
-
-	index_attr = 0;
-	for (i = 0; i < 512; i++) {
-		level1_table_0[i] = section_l1t0;
-		level1_table_0[i] |= attr_tbll1t0[index_attr].attr;
-		attr_tbll1t0[index_attr].num--;
-		if (attr_tbll1t0[index_attr].num == 0)
-			index_attr++;
-		level1_table_1[i] = section_l1t1;
-		level1_table_1[i] |= DEVICE_ATTR;
-		section_l1t0 += BLOCK_SIZE_L1;
-		section_l1t1 += BLOCK_SIZE_L1;
-	}
-
-	level1_table_0[0] =
-		(u64)level2_table_0 | PMD_TYPE_TABLE;
-	level1_table_0[1] =
-		(u64)level2_table_1 | PMD_TYPE_TABLE;
-	level1_table_0[2] =
-		(u64)level2_table_2 | PMD_TYPE_TABLE;
-	level1_table_0[3] =
-		(u64)level2_table_3 | PMD_TYPE_TABLE;
-
-	section_l2t0 = 0;
-	section_l2t1 = section_l2t0 + BLOCK_SIZE_L1; /* 1GB */
-	section_l2t2 = section_l2t1 + BLOCK_SIZE_L1; /* 2GB */
-	section_l2t3 = section_l2t2 + BLOCK_SIZE_L1; /* 3GB */
-
-	index_attr = 0;
-
-	for (i = 0; i < 512; i++) {
-		level2_table_0[i] = section_l2t0 | MEMORY_ATTR;
-		level2_table_1[i] = section_l2t1 | MEMORY_ATTR;
-		level2_table_2[i] = section_l2t2 | DEVICE_ATTR;
-		level2_table_3[i] = section_l2t3 |
-				    attr_tbll2t3[index_attr].attr;
-		attr_tbll2t3[index_attr].num--;
-		if (attr_tbll2t3[index_attr].num == 0)
-			index_attr++;
-		section_l2t0 += BLOCK_SIZE_L2;
-		section_l2t1 += BLOCK_SIZE_L2;
-		section_l2t2 += BLOCK_SIZE_L2;
-		section_l2t3 += BLOCK_SIZE_L2;
-	}
-
-	/* flush new MMU table */
-	flush_dcache_range(gd->arch.tlb_addr,
-			   gd->arch.tlb_addr + gd->arch.tlb_size);
-
-	/* point TTBR to the new table */
-	el = current_el();
-	set_ttbr_tcr_mair(el, gd->arch.tlb_addr,
-			  ZYNQMP_TCR, MEMORY_ATTRIBUTES);
-
-	set_sctlr(get_sctlr() | CR_M);
-}
-
-int arch_cpu_init(void)
-{
-	icache_enable();
-	__asm_invalidate_dcache_all();
-	__asm_invalidate_tlb_all();
-	return 0;
-}
-
-/*
- * This function is called from lib/board.c.
- * It recreates MMU table in main memory. MMU and d-cache are enabled earlier.
- * There is no need to disable d-cache for this operation.
- */
-void enable_caches(void)
-{
-	/* The data cache is not active unless the mmu is enabled */
-	if (!(get_sctlr() & CR_M)) {
-		invalidate_dcache_all();
-		__asm_invalidate_tlb_all();
-		zynqmp_mmu_setup();
-	}
-	puts("Enabling Caches...\n");
-
-	set_sctlr(get_sctlr() | CR_C);
-}
-
-u64 *arch_get_page_table(void)
-{
-	return (u64 *)(gd->arch.tlb_addr + 0x3000);
-}
-#endif
diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h
index 1121ea4..727084f 100644
--- a/include/configs/xilinx_zynqmp.h
+++ b/include/configs/xilinx_zynqmp.h
@@ -29,6 +29,8 @@
 #define CONFIG_SYS_MEMTEST_START	CONFIG_SYS_SDRAM_BASE
 #define CONFIG_SYS_MEMTEST_END		CONFIG_SYS_SDRAM_SIZE
 
+#define CONFIG_SYS_FULL_VA
+
 /* Have release address at the end of 256MB for now */
 #define CPU_RELEASE_ADDR	0xFFFFFF0
 
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 06/30] tegra: Replace home grown mmu code with generic table approach
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (4 preceding siblings ...)
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 05/30] zymqmp: Replace home grown mmu code with generic table approach Alexander Graf
@ 2016-03-04  0:09 ` Alexander Graf
  2016-03-17  2:00   ` [U-Boot] [U-Boot, v5, " Tom Rini
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 07/30] vexpress64: Add MMU tables Alexander Graf
                   ` (24 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:09 UTC (permalink / raw)
  To: u-boot

Now that we have nice table driven page table creating code that gives
us everything we need, move to that.

Signed-off-by: Alexander Graf <agraf@suse.de>

---

v1 -> v2:

  - Move mmu tables into .c file
---
 arch/arm/mach-tegra/arm64-mmu.c   | 132 +++++---------------------------------
 include/configs/tegra210-common.h |   2 +
 2 files changed, 19 insertions(+), 115 deletions(-)

diff --git a/arch/arm/mach-tegra/arm64-mmu.c b/arch/arm/mach-tegra/arm64-mmu.c
index c227652..501c4f0 100644
--- a/arch/arm/mach-tegra/arm64-mmu.c
+++ b/arch/arm/mach-tegra/arm64-mmu.c
@@ -12,120 +12,22 @@
 #include <asm/system.h>
 #include <asm/armv8/mmu.h>
 
-DECLARE_GLOBAL_DATA_PTR;
-
-#define SECTION_SHIFT_L1	30UL
-#define SECTION_SHIFT_L2	21UL
-#define BLOCK_SIZE_L0		0x8000000000UL
-#define BLOCK_SIZE_L1		(1 << SECTION_SHIFT_L1)
-#define BLOCK_SIZE_L2		(1 << SECTION_SHIFT_L2)
-
-#define TCR_TG1_4K		(1 << 31)
-#define TCR_EPD1_DISABLE	(1 << 23)
-#define TEGRA_VA_BITS		40
-#define TEGRA_TCR		TCR_TG1_4K | \
-				TCR_EPD1_DISABLE | \
-				TCR_SHARED_OUTER | \
-				TCR_SHARED_INNER | \
-				TCR_IRGN_WBWA | \
-				TCR_ORGN_WBWA | \
-				TCR_T0SZ(TEGRA_VA_BITS)
-
-#define MEMORY_ATTR	PMD_SECT_AF | PMD_SECT_INNER_SHARE |	\
-			PMD_ATTRINDX(MT_NORMAL) |	\
-			PMD_TYPE_SECT
-#define DEVICE_ATTR	PMD_SECT_AF | PMD_SECT_PXN |	\
-			PMD_SECT_UXN | PMD_ATTRINDX(MT_DEVICE_NGNRNE) |	\
-			PMD_TYPE_SECT
-
-/* 4K size is required to place 512 entries in each level */
-#define TLB_TABLE_SIZE	0x1000
-
-/*
- * This mmu table looks as below
- * Level 0 table contains two entries to 512GB sizes. One is Level1 Table 0
- * and other Level1 Table1.
- * Level1 Table0 contains entries for each 1GB from 0 to 511GB.
- * Level1 Table1 contains entries for each 1GB from 512GB to 1TB.
- * Level2 Table0, Level2 Table1, Level2 Table2 and Level2 Table3 contains
- * entries for each 2MB starting from 0GB, 1GB, 2GB and 3GB respectively.
- */
-void mmu_setup(void)
-{
-	int el;
-	u64 i, section_l1t0, section_l1t1;
-	u64 section_l2t0, section_l2t1, section_l2t2, section_l2t3;
-	u64 *level0_table = (u64 *)gd->arch.tlb_addr;
-	u64 *level1_table_0 = (u64 *)(gd->arch.tlb_addr + TLB_TABLE_SIZE);
-	u64 *level1_table_1 = (u64 *)(gd->arch.tlb_addr + (2 * TLB_TABLE_SIZE));
-	u64 *level2_table_0 = (u64 *)(gd->arch.tlb_addr + (3 * TLB_TABLE_SIZE));
-	u64 *level2_table_1 = (u64 *)(gd->arch.tlb_addr + (4 * TLB_TABLE_SIZE));
-	u64 *level2_table_2 = (u64 *)(gd->arch.tlb_addr + (5 * TLB_TABLE_SIZE));
-	u64 *level2_table_3 = (u64 *)(gd->arch.tlb_addr + (6 * TLB_TABLE_SIZE));
-
-	/* Invalidate all table entries */
-	memset(level0_table, 0, PGTABLE_SIZE);
-
-	level0_table[0] =
-		(u64)level1_table_0 | PMD_TYPE_TABLE;
-	level0_table[1] =
-		(u64)level1_table_1 | PMD_TYPE_TABLE;
-
-	/*
-	 * set level 1 table 0, covering 0 to 512GB
-	 * set level 1 table 1, covering 512GB to 1TB
-	 */
-	section_l1t0 = 0;
-	section_l1t1 = BLOCK_SIZE_L0;
-
-	for (i = 0; i < 512; i++) {
-		level1_table_0[i] = section_l1t0;
-		if (i >= 4)
-			level1_table_0[i] |= MEMORY_ATTR;
-		level1_table_1[i] = section_l1t1;
-		level1_table_1[i] |= MEMORY_ATTR;
-		section_l1t0 += BLOCK_SIZE_L1;
-		section_l1t1 += BLOCK_SIZE_L1;
+static struct mm_region tegra_mem_map[] = {
+	{
+		.base = 0x0UL,
+		.size = 0x80000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		.base = 0x80000000UL,
+		.size = 0xff80000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_INNER_SHARE
+	}, {
+		/* List terminator */
+		0,
 	}
+};
 
-	level1_table_0[0] =
-		(u64)level2_table_0 | PMD_TYPE_TABLE;
-	level1_table_0[1] =
-		(u64)level2_table_1 | PMD_TYPE_TABLE;
-	level1_table_0[2] =
-		(u64)level2_table_2 | PMD_TYPE_TABLE;
-	level1_table_0[3] =
-		(u64)level2_table_3 | PMD_TYPE_TABLE;
-
-	section_l2t0 = 0;
-	section_l2t1 = section_l2t0 + BLOCK_SIZE_L1; /* 1GB */
-	section_l2t2 = section_l2t1 + BLOCK_SIZE_L1; /* 2GB */
-	section_l2t3 = section_l2t2 + BLOCK_SIZE_L1; /* 3GB */
-
-	for (i = 0; i < 512; i++) {
-		level2_table_0[i] = section_l2t0 | DEVICE_ATTR;
-		level2_table_1[i] = section_l2t1 | DEVICE_ATTR;
-		level2_table_2[i] = section_l2t2 | MEMORY_ATTR;
-		level2_table_3[i] = section_l2t3 | MEMORY_ATTR;
-		section_l2t0 += BLOCK_SIZE_L2;
-		section_l2t1 += BLOCK_SIZE_L2;
-		section_l2t2 += BLOCK_SIZE_L2;
-		section_l2t3 += BLOCK_SIZE_L2;
-	}
-
-	/* flush new MMU table */
-	flush_dcache_range(gd->arch.tlb_addr,
-			   gd->arch.tlb_addr + gd->arch.tlb_size);
-
-	/* point TTBR to the new table */
-	el = current_el();
-	set_ttbr_tcr_mair(el, gd->arch.tlb_addr,
-			  TEGRA_TCR, MEMORY_ATTRIBUTES);
-
-	set_sctlr(get_sctlr() | CR_M);
-}
-
-u64 *arch_get_page_table(void)
-{
-	return (u64 *)(gd->arch.tlb_addr + (3 * TLB_TABLE_SIZE));
-}
+struct mm_region *mem_map = tegra_mem_map;
diff --git a/include/configs/tegra210-common.h b/include/configs/tegra210-common.h
index 8f35a7b..2a6e317 100644
--- a/include/configs/tegra210-common.h
+++ b/include/configs/tegra210-common.h
@@ -13,6 +13,8 @@
 /* Cortex-A57 uses a cache line size of 64 bytes */
 #define CONFIG_SYS_CACHELINE_SIZE	64
 
+#define CONFIG_SYS_FULL_VA
+
 /*
  * NS16550 Configuration
  */
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 07/30] vexpress64: Add MMU tables
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (5 preceding siblings ...)
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 06/30] tegra: " Alexander Graf
@ 2016-03-04  0:09 ` Alexander Graf
  2016-03-17  2:00   ` [U-Boot] [U-Boot,v5,07/30] " Tom Rini
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 08/30] dwmmc: Increase retry timeout Alexander Graf
                   ` (23 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:09 UTC (permalink / raw)
  To: u-boot

There's no good excuse for running with caches disabled on AArch64,
so let's just move the vexpress64 target to enable the MMU and run
with caches on.

Signed-off-by: Alexander Graf <agraf@suse.de>

---

v1 -> v2:

  - Move tables to .c file
---
 board/armltd/vexpress64/vexpress64.c | 21 +++++++++++++++++++++
 include/configs/vexpress_aemv8a.h    |  6 +++---
 2 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/board/armltd/vexpress64/vexpress64.c b/board/armltd/vexpress64/vexpress64.c
index 6efc8c1..973b579 100644
--- a/board/armltd/vexpress64/vexpress64.c
+++ b/board/armltd/vexpress64/vexpress64.c
@@ -14,6 +14,7 @@
 #include <dm/platdata.h>
 #include <dm/platform_data/serial_pl01x.h>
 #include "pcie.h"
+#include <asm/armv8/mmu.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -28,6 +29,26 @@ U_BOOT_DEVICE(vexpress_serials) = {
 	.platdata = &serial_platdata,
 };
 
+static struct mm_region vexpress64_mem_map[] = {
+	{
+		.base = 0x0UL,
+		.size = 0x80000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		.base = 0x80000000UL,
+		.size = 0xff80000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_INNER_SHARE
+	}, {
+		/* List terminator */
+		0,
+	}
+};
+
+struct mm_region *mem_map = vexpress64_mem_map;
+
 /* This function gets replaced by platforms supporting PCIe.
  * The replacement function, eg. on Juno, initialises the PCIe bus.
  */
diff --git a/include/configs/vexpress_aemv8a.h b/include/configs/vexpress_aemv8a.h
index 133041b..ddb9848 100644
--- a/include/configs/vexpress_aemv8a.h
+++ b/include/configs/vexpress_aemv8a.h
@@ -19,9 +19,9 @@
 
 #define CONFIG_SUPPORT_RAW_INITRD
 
-/* Cache Definitions */
-#define CONFIG_SYS_DCACHE_OFF
-#define CONFIG_SYS_ICACHE_OFF
+/* MMU Definitions */
+#define CONFIG_SYS_CACHELINE_SIZE	64
+#define CONFIG_SYS_FULL_VA
 
 #define CONFIG_IDENT_STRING		" vexpress_aemv8a"
 #define CONFIG_BOOTP_VCI_STRING		"U-Boot.armv8.vexpress_aemv8a"
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 08/30] dwmmc: Increase retry timeout
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (6 preceding siblings ...)
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 07/30] vexpress64: Add MMU tables Alexander Graf
@ 2016-03-04  0:09 ` Alexander Graf
  2016-03-17  2:00   ` [U-Boot] [U-Boot,v5,08/30] " Tom Rini
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 09/30] hikey: Add MMU tables Alexander Graf
                   ` (22 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:09 UTC (permalink / raw)
  To: u-boot

When enable dcache on HiKey, we're running into MMC command timeouts
because our retry loop is now faster than the eMMC (or an external SD
card) can answer.

Increase the retry count to the same as the timeout value for status
reports.

The real fix is obviously to not base this whole thing on a cycle counter
but on real wall time, but that would be slightly more intrusive.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 drivers/mmc/dw_mmc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index 909e3ca..7329f40 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -189,7 +189,7 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 				 data ? DIV_ROUND_UP(data->blocks, 8) : 0);
 	int ret = 0, flags = 0, i;
 	unsigned int timeout = 100000;
-	u32 retry = 10000;
+	u32 retry = 100000;
 	u32 mask, ctrl;
 	ulong start = get_timer(0);
 	struct bounce_buffer bbstate;
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 09/30] hikey: Add MMU tables
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (7 preceding siblings ...)
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 08/30] dwmmc: Increase retry timeout Alexander Graf
@ 2016-03-04  0:09 ` Alexander Graf
  2016-03-17  2:00   ` [U-Boot] [U-Boot,v5,09/30] " Tom Rini
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 10/30] arm64: Remove non-full-va map code Alexander Graf
                   ` (21 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:09 UTC (permalink / raw)
  To: u-boot

The hikey runs with dcache disabled today. There really should be no reason
not to use caches on AArch64, so let's add MMU definitions and enable the
dcache.

Signed-off-by: Alexander Graf <agraf@suse.de>

---

v1 -> v2:

  - Move tables to .c file
---
 board/hisilicon/hikey/hikey.c | 21 +++++++++++++++++++++
 include/configs/hikey.h       |  5 +++--
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/board/hisilicon/hikey/hikey.c b/board/hisilicon/hikey/hikey.c
index c4ae40b..1edc807 100644
--- a/board/hisilicon/hikey/hikey.c
+++ b/board/hisilicon/hikey/hikey.c
@@ -19,6 +19,7 @@
 #include <asm/arch/periph.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/hi6220.h>
+#include <asm/armv8/mmu.h>
 
 /*TODO drop this table in favour of device tree */
 static const struct hikey_gpio_platdata hi6220_gpio[] = {
@@ -87,6 +88,26 @@ U_BOOT_DEVICE(hikey_seriala) = {
 	.platdata = &serial_platdata,
 };
 
+static struct mm_region hikey_mem_map[] = {
+	{
+		.base = 0x0UL,
+		.size = 0x80000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_INNER_SHARE
+	}, {
+		.base = 0x80000000UL,
+		.size = 0x80000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		/* List terminator */
+		0,
+	}
+};
+
+struct mm_region *mem_map = hikey_mem_map;
+
 #ifdef CONFIG_BOARD_EARLY_INIT_F
 int board_uart_init(void)
 {
diff --git a/include/configs/hikey.h b/include/configs/hikey.h
index 796861e..d33dcef 100644
--- a/include/configs/hikey.h
+++ b/include/configs/hikey.h
@@ -21,8 +21,9 @@
 
 #define CONFIG_SUPPORT_RAW_INITRD
 
-/* Cache Definitions */
-#define CONFIG_SYS_DCACHE_OFF
+/* MMU Definitions */
+#define CONFIG_SYS_CACHELINE_SIZE	64
+#define CONFIG_SYS_FULL_VA
 
 #define CONFIG_IDENT_STRING		"hikey"
 
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 10/30] arm64: Remove non-full-va map code
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (8 preceding siblings ...)
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 09/30] hikey: Add MMU tables Alexander Graf
@ 2016-03-04  0:09 ` Alexander Graf
  2016-03-17  2:00   ` [U-Boot] [U-Boot,v5,10/30] " Tom Rini
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 11/30] arm64: Only allow dcache disabled in SPL builds Alexander Graf
                   ` (20 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:09 UTC (permalink / raw)
  To: u-boot

By now the code to only have a single page table level with 64k page
size and 42 bit address space is no longer used by any board in tree,
so we can safely remove it.

To clean up code, move the layerscape mmu code to the new defines,
removing redundant field definitions.

Signed-off-by: Alexander Graf <agraf@suse.de>

---

v1 -> v2:

  - Add layerscape empty mmu table in .c file
---
 arch/arm/cpu/armv8/cache_v8.c                  | 90 ------------------------
 arch/arm/cpu/armv8/fsl-layerscape/cpu.c        | 37 ++++++++--
 arch/arm/include/asm/arch-fsl-layerscape/cpu.h | 94 +++++++++++++-------------
 arch/arm/include/asm/armv8/mmu.h               | 66 +-----------------
 arch/arm/include/asm/global_data.h             |  2 +-
 arch/arm/include/asm/system.h                  | 12 ++--
 doc/README.arm64                               | 20 ------
 include/configs/hikey.h                        |  1 -
 include/configs/tegra210-common.h              |  2 -
 include/configs/thunderx_88xx.h                | 14 ----
 include/configs/vexpress_aemv8a.h              |  1 -
 include/configs/xilinx_zynqmp.h                |  2 -
 12 files changed, 85 insertions(+), 256 deletions(-)

diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c
index 55c6f2f..df15e00 100644
--- a/arch/arm/cpu/armv8/cache_v8.c
+++ b/arch/arm/cpu/armv8/cache_v8.c
@@ -35,7 +35,6 @@ DECLARE_GLOBAL_DATA_PTR;
  *    off:          FFF
  */
 
-#ifdef CONFIG_SYS_FULL_VA
 static u64 get_tcr(int el, u64 *pips, u64 *pva_bits)
 {
 	u64 max_addr = 0;
@@ -386,38 +385,11 @@ static void setup_all_pgtables(void)
 	gd->arch.tlb_addr = tlb_addr;
 }
 
-#else
-
-inline void set_pgtable_section(u64 *page_table, u64 index, u64 section,
-			 u64 memory_type, u64 attribute)
-{
-	u64 value;
-
-	value = section | PMD_TYPE_SECT | PMD_SECT_AF;
-	value |= PMD_ATTRINDX(memory_type);
-	value |= attribute;
-	page_table[index] = value;
-}
-
-inline void set_pgtable_table(u64 *page_table, u64 index, u64 *table_addr)
-{
-	u64 value;
-
-	value = (u64)table_addr | PMD_TYPE_TABLE;
-	page_table[index] = value;
-}
-#endif
-
 /* to activate the MMU we need to set up virtual memory */
 __weak void mmu_setup(void)
 {
-#ifndef CONFIG_SYS_FULL_VA
-	bd_t *bd = gd->bd;
-	u64 *page_table = (u64 *)gd->arch.tlb_addr, i, j;
-#endif
 	int el;
 
-#ifdef CONFIG_SYS_FULL_VA
 	/* Set up page tables only once */
 	if (!gd->arch.tlb_fillptr)
 		setup_all_pgtables();
@@ -425,40 +397,6 @@ __weak void mmu_setup(void)
 	el = current_el();
 	set_ttbr_tcr_mair(el, gd->arch.tlb_addr, get_tcr(el, NULL, NULL),
 			  MEMORY_ATTRIBUTES);
-#else
-	/* Setup an identity-mapping for all spaces */
-	for (i = 0; i < (PGTABLE_SIZE >> 3); i++) {
-		set_pgtable_section(page_table, i, i << SECTION_SHIFT,
-				    MT_DEVICE_NGNRNE, PMD_SECT_NON_SHARE);
-	}
-
-	/* Setup an identity-mapping for all RAM space */
-	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
-		ulong start = bd->bi_dram[i].start;
-		ulong end = bd->bi_dram[i].start + bd->bi_dram[i].size;
-		for (j = start >> SECTION_SHIFT;
-		     j < end >> SECTION_SHIFT; j++) {
-			set_pgtable_section(page_table, j, j << SECTION_SHIFT,
-					    MT_NORMAL, PMD_SECT_NON_SHARE);
-		}
-	}
-
-	/* load TTBR0 */
-	el = current_el();
-	if (el == 1) {
-		set_ttbr_tcr_mair(el, gd->arch.tlb_addr,
-				  TCR_EL1_RSVD | TCR_FLAGS | TCR_EL1_IPS_BITS,
-				  MEMORY_ATTRIBUTES);
-	} else if (el == 2) {
-		set_ttbr_tcr_mair(el, gd->arch.tlb_addr,
-				  TCR_EL2_RSVD | TCR_FLAGS | TCR_EL2_IPS_BITS,
-				  MEMORY_ATTRIBUTES);
-	} else {
-		set_ttbr_tcr_mair(el, gd->arch.tlb_addr,
-				  TCR_EL3_RSVD | TCR_FLAGS | TCR_EL3_IPS_BITS,
-				  MEMORY_ATTRIBUTES);
-	}
-#endif
 
 	/* enable the mmu */
 	set_sctlr(get_sctlr() | CR_M);
@@ -544,33 +482,6 @@ u64 *__weak arch_get_page_table(void) {
 	return NULL;
 }
 
-#ifndef CONFIG_SYS_FULL_VA
-void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
-				     enum dcache_option option)
-{
-	u64 *page_table = arch_get_page_table();
-	u64 upto, end;
-
-	if (page_table == NULL)
-		return;
-
-	end = ALIGN(start + size, (1 << MMU_SECTION_SHIFT)) >>
-	      MMU_SECTION_SHIFT;
-	start = start >> MMU_SECTION_SHIFT;
-	for (upto = start; upto < end; upto++) {
-		page_table[upto] &= ~PMD_ATTRINDX_MASK;
-		page_table[upto] |= PMD_ATTRINDX(option);
-	}
-	asm volatile("dsb sy");
-	__asm_invalidate_tlb_all();
-	asm volatile("dsb sy");
-	asm volatile("isb");
-	start = start << MMU_SECTION_SHIFT;
-	end = end << MMU_SECTION_SHIFT;
-	flush_dcache_range(start, end);
-	asm volatile("dsb sy");
-}
-#else
 static bool is_aligned(u64 addr, u64 size, u64 align)
 {
 	return !(addr & (align - 1)) && !(size & (align - 1));
@@ -652,7 +563,6 @@ void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
 	 */
 	flush_dcache_range(real_start, real_start + real_size);
 }
-#endif
 
 #else	/* CONFIG_SYS_DCACHE_OFF */
 
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
index 6ea28ed..7404bd9 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
@@ -26,6 +26,14 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+static struct mm_region layerscape_mem_map[] = {
+	{
+		/* List terminator */
+		0,
+	}
+};
+struct mm_region *mem_map = layerscape_mem_map;
+
 void cpu_name(char *name)
 {
 	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
@@ -48,6 +56,25 @@ void cpu_name(char *name)
 }
 
 #ifndef CONFIG_SYS_DCACHE_OFF
+static void set_pgtable_section(u64 *page_table, u64 index, u64 section,
+			u64 memory_type, u64 attribute)
+{
+       u64 value;
+
+       value = section | PTE_TYPE_BLOCK | PTE_BLOCK_AF;
+       value |= PMD_ATTRINDX(memory_type);
+       value |= attribute;
+       page_table[index] = value;
+}
+
+static void set_pgtable_table(u64 *page_table, u64 index, u64 *table_addr)
+{
+       u64 value;
+
+       value = (u64)table_addr | PTE_TYPE_TABLE;
+       page_table[index] = value;
+}
+
 /*
  * Set the block entries according to the information of the table.
  */
@@ -114,10 +141,10 @@ static int find_table(const struct sys_mmu_table *list,
 
 		temp_base -= block_size;
 
-		if ((level_table[index - 1] & PMD_TYPE_MASK) ==
-		    PMD_TYPE_TABLE) {
+		if ((level_table[index - 1] & PTE_TYPE_MASK) ==
+		    PTE_TYPE_TABLE) {
 			level_table = (u64 *)(level_table[index - 1] &
-				      ~PMD_TYPE_MASK);
+				      ~PTE_TYPE_MASK);
 			level++;
 			continue;
 		} else {
@@ -220,7 +247,7 @@ static inline int final_secure_ddr(u64 *level0_table,
 	struct table_info table = {};
 	struct sys_mmu_table ddr_entry = {
 		0, 0, BLOCK_SIZE_L1, MT_NORMAL,
-		PMD_SECT_OUTER_SHARE | PMD_SECT_NS
+		PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
 	};
 	u64 index;
 
@@ -243,7 +270,7 @@ static inline int final_secure_ddr(u64 *level0_table,
 	ddr_entry.virt_addr = phys_addr;
 	ddr_entry.phys_addr = phys_addr;
 	ddr_entry.size = CONFIG_SYS_MEM_RESERVE_SECURE;
-	ddr_entry.attribute = PMD_SECT_OUTER_SHARE;
+	ddr_entry.attribute = PTE_BLOCK_OUTER_SHARE;
 	ret = find_table(&ddr_entry, &table, level0_table);
 	if (ret) {
 		printf("MMU error: could not find secure ddr table\n");
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/cpu.h b/arch/arm/include/asm/arch-fsl-layerscape/cpu.h
index 15ade84..93bbda3 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/cpu.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/cpu.h
@@ -117,48 +117,48 @@ static const struct sys_mmu_table early_mmu_table[] = {
 #ifdef CONFIG_FSL_LSCH3
 	{ CONFIG_SYS_FSL_CCSR_BASE, CONFIG_SYS_FSL_CCSR_BASE,
 	  CONFIG_SYS_FSL_CCSR_SIZE, MT_DEVICE_NGNRNE,
-	  PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN },
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
 	{ CONFIG_SYS_FSL_OCRAM_BASE, CONFIG_SYS_FSL_OCRAM_BASE,
-	  CONFIG_SYS_FSL_OCRAM_SIZE, MT_NORMAL, PMD_SECT_NON_SHARE },
+	  CONFIG_SYS_FSL_OCRAM_SIZE, MT_NORMAL, PTE_BLOCK_NON_SHARE },
 	/* For IFC Region #1, only the first 4MB is cache-enabled */
 	{ CONFIG_SYS_FSL_IFC_BASE1, CONFIG_SYS_FSL_IFC_BASE1,
-	  CONFIG_SYS_FSL_IFC_SIZE1_1, MT_NORMAL, PMD_SECT_NON_SHARE },
+	  CONFIG_SYS_FSL_IFC_SIZE1_1, MT_NORMAL, PTE_BLOCK_NON_SHARE },
 	{ CONFIG_SYS_FSL_IFC_BASE1 + CONFIG_SYS_FSL_IFC_SIZE1_1,
 	  CONFIG_SYS_FSL_IFC_BASE1 + CONFIG_SYS_FSL_IFC_SIZE1_1,
 	  CONFIG_SYS_FSL_IFC_SIZE1 - CONFIG_SYS_FSL_IFC_SIZE1_1,
-	  MT_DEVICE_NGNRNE, PMD_SECT_NON_SHARE },
+	  MT_DEVICE_NGNRNE, PTE_BLOCK_NON_SHARE },
 	{ CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FSL_IFC_BASE1,
-	  CONFIG_SYS_FSL_IFC_SIZE1, MT_DEVICE_NGNRNE, PMD_SECT_NON_SHARE },
+	  CONFIG_SYS_FSL_IFC_SIZE1, MT_DEVICE_NGNRNE, PTE_BLOCK_NON_SHARE },
 	{ CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1,
 	  CONFIG_SYS_FSL_DRAM_SIZE1, MT_NORMAL,
-	  PMD_SECT_OUTER_SHARE | PMD_SECT_NS },
+	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS },
 	/* Map IFC region #2 up to CONFIG_SYS_FLASH_BASE for NAND boot */
 	{ CONFIG_SYS_FSL_IFC_BASE2, CONFIG_SYS_FSL_IFC_BASE2,
 	  CONFIG_SYS_FLASH_BASE - CONFIG_SYS_FSL_IFC_BASE2,
-	  MT_DEVICE_NGNRNE, PMD_SECT_NON_SHARE },
+	  MT_DEVICE_NGNRNE, PTE_BLOCK_NON_SHARE },
 	{ CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_BASE,
 	  CONFIG_SYS_FSL_DCSR_SIZE, MT_DEVICE_NGNRNE,
-	  PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN },
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
 	{ CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_BASE2,
 	  CONFIG_SYS_FSL_DRAM_SIZE2, MT_NORMAL,
-	  PMD_SECT_OUTER_SHARE | PMD_SECT_NS },
+	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS },
 #elif defined(CONFIG_FSL_LSCH2)
 	{ CONFIG_SYS_FSL_CCSR_BASE, CONFIG_SYS_FSL_CCSR_BASE,
 	  CONFIG_SYS_FSL_CCSR_SIZE, MT_DEVICE_NGNRNE,
-	  PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN },
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
 	{ CONFIG_SYS_FSL_OCRAM_BASE, CONFIG_SYS_FSL_OCRAM_BASE,
-	  CONFIG_SYS_FSL_OCRAM_SIZE, MT_NORMAL, PMD_SECT_NON_SHARE },
+	  CONFIG_SYS_FSL_OCRAM_SIZE, MT_NORMAL, PTE_BLOCK_NON_SHARE },
 	{ CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_BASE,
 	  CONFIG_SYS_FSL_DCSR_SIZE, MT_DEVICE_NGNRNE,
-	  PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN },
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
 	{ CONFIG_SYS_FSL_QSPI_BASE, CONFIG_SYS_FSL_QSPI_BASE,
-	  CONFIG_SYS_FSL_QSPI_SIZE, MT_DEVICE_NGNRNE, PMD_SECT_NON_SHARE },
+	  CONFIG_SYS_FSL_QSPI_SIZE, MT_DEVICE_NGNRNE, PTE_BLOCK_NON_SHARE },
 	{ CONFIG_SYS_FSL_IFC_BASE, CONFIG_SYS_FSL_IFC_BASE,
-	  CONFIG_SYS_FSL_IFC_SIZE, MT_DEVICE_NGNRNE, PMD_SECT_NON_SHARE },
+	  CONFIG_SYS_FSL_IFC_SIZE, MT_DEVICE_NGNRNE, PTE_BLOCK_NON_SHARE },
 	{ CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1,
-	  CONFIG_SYS_FSL_DRAM_SIZE1, MT_NORMAL, PMD_SECT_OUTER_SHARE },
+	  CONFIG_SYS_FSL_DRAM_SIZE1, MT_NORMAL, PTE_BLOCK_OUTER_SHARE },
 	{ CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_BASE2,
-	  CONFIG_SYS_FSL_DRAM_SIZE2, MT_NORMAL, PMD_SECT_OUTER_SHARE },
+	  CONFIG_SYS_FSL_DRAM_SIZE2, MT_NORMAL, PTE_BLOCK_OUTER_SHARE },
 #endif
 };
 
@@ -166,96 +166,96 @@ static const struct sys_mmu_table final_mmu_table[] = {
 #ifdef CONFIG_FSL_LSCH3
 	{ CONFIG_SYS_FSL_CCSR_BASE, CONFIG_SYS_FSL_CCSR_BASE,
 	  CONFIG_SYS_FSL_CCSR_SIZE, MT_DEVICE_NGNRNE,
-	  PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN },
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
 	{ CONFIG_SYS_FSL_OCRAM_BASE, CONFIG_SYS_FSL_OCRAM_BASE,
-	  CONFIG_SYS_FSL_OCRAM_SIZE, MT_NORMAL, PMD_SECT_NON_SHARE },
+	  CONFIG_SYS_FSL_OCRAM_SIZE, MT_NORMAL, PTE_BLOCK_NON_SHARE },
 	{ CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1,
 	  CONFIG_SYS_FSL_DRAM_SIZE1, MT_NORMAL,
-	  PMD_SECT_OUTER_SHARE | PMD_SECT_NS },
+	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS },
 	{ CONFIG_SYS_FSL_QSPI_BASE2, CONFIG_SYS_FSL_QSPI_BASE2,
 	  CONFIG_SYS_FSL_QSPI_SIZE2, MT_DEVICE_NGNRNE,
-	  PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN },
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
 	{ CONFIG_SYS_FSL_IFC_BASE2, CONFIG_SYS_FSL_IFC_BASE2,
-	  CONFIG_SYS_FSL_IFC_SIZE2, MT_DEVICE_NGNRNE, PMD_SECT_NON_SHARE },
+	  CONFIG_SYS_FSL_IFC_SIZE2, MT_DEVICE_NGNRNE, PTE_BLOCK_NON_SHARE },
 	{ CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_BASE,
 	  CONFIG_SYS_FSL_DCSR_SIZE, MT_DEVICE_NGNRNE,
-	  PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN },
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
 	{ CONFIG_SYS_FSL_MC_BASE, CONFIG_SYS_FSL_MC_BASE,
 	  CONFIG_SYS_FSL_MC_SIZE, MT_DEVICE_NGNRNE,
-	  PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN },
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
 	{ CONFIG_SYS_FSL_NI_BASE, CONFIG_SYS_FSL_NI_BASE,
 	  CONFIG_SYS_FSL_NI_SIZE, MT_DEVICE_NGNRNE,
-	  PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN },
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
 	/* For QBMAN portal, only the first 64MB is cache-enabled */
 	{ CONFIG_SYS_FSL_QBMAN_BASE, CONFIG_SYS_FSL_QBMAN_BASE,
 	  CONFIG_SYS_FSL_QBMAN_SIZE_1, MT_NORMAL,
-	  PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN | PMD_SECT_NS },
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN | PTE_BLOCK_NS },
 	{ CONFIG_SYS_FSL_QBMAN_BASE + CONFIG_SYS_FSL_QBMAN_SIZE_1,
 	  CONFIG_SYS_FSL_QBMAN_BASE + CONFIG_SYS_FSL_QBMAN_SIZE_1,
 	  CONFIG_SYS_FSL_QBMAN_SIZE - CONFIG_SYS_FSL_QBMAN_SIZE_1,
-	  MT_DEVICE_NGNRNE, PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN },
+	  MT_DEVICE_NGNRNE, PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
 	{ CONFIG_SYS_PCIE1_PHYS_ADDR, CONFIG_SYS_PCIE1_PHYS_ADDR,
 	  CONFIG_SYS_PCIE1_PHYS_SIZE, MT_DEVICE_NGNRNE,
-	  PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN },
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
 	{ CONFIG_SYS_PCIE2_PHYS_ADDR, CONFIG_SYS_PCIE2_PHYS_ADDR,
 	  CONFIG_SYS_PCIE2_PHYS_SIZE, MT_DEVICE_NGNRNE,
-	  PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN },
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
 	{ CONFIG_SYS_PCIE3_PHYS_ADDR, CONFIG_SYS_PCIE3_PHYS_ADDR,
 	  CONFIG_SYS_PCIE3_PHYS_SIZE, MT_DEVICE_NGNRNE,
-	  PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN },
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
 #if defined(CONFIG_LS2080A) || defined(CONFIG_LS2085A)
 	{ CONFIG_SYS_PCIE4_PHYS_ADDR, CONFIG_SYS_PCIE4_PHYS_ADDR,
 	  CONFIG_SYS_PCIE4_PHYS_SIZE, MT_DEVICE_NGNRNE,
-	  PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN },
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
 #endif
 	{ CONFIG_SYS_FSL_WRIOP1_BASE, CONFIG_SYS_FSL_WRIOP1_BASE,
 	  CONFIG_SYS_FSL_WRIOP1_SIZE, MT_DEVICE_NGNRNE,
-	  PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN },
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
 	{ CONFIG_SYS_FSL_AIOP1_BASE, CONFIG_SYS_FSL_AIOP1_BASE,
 	  CONFIG_SYS_FSL_AIOP1_SIZE, MT_DEVICE_NGNRNE,
-	  PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN },
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
 	{ CONFIG_SYS_FSL_PEBUF_BASE, CONFIG_SYS_FSL_PEBUF_BASE,
 	  CONFIG_SYS_FSL_PEBUF_SIZE, MT_DEVICE_NGNRNE,
-	  PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN },
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
 	{ CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_BASE2,
 	  CONFIG_SYS_FSL_DRAM_SIZE2, MT_NORMAL,
-	  PMD_SECT_OUTER_SHARE | PMD_SECT_NS },
+	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS },
 #elif defined(CONFIG_FSL_LSCH2)
 	{ CONFIG_SYS_FSL_BOOTROM_BASE, CONFIG_SYS_FSL_BOOTROM_BASE,
 	  CONFIG_SYS_FSL_BOOTROM_SIZE, MT_DEVICE_NGNRNE,
-	  PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN },
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
 	{ CONFIG_SYS_FSL_CCSR_BASE, CONFIG_SYS_FSL_CCSR_BASE,
 	  CONFIG_SYS_FSL_CCSR_SIZE, MT_DEVICE_NGNRNE,
-	  PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN },
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
 	{ CONFIG_SYS_FSL_OCRAM_BASE, CONFIG_SYS_FSL_OCRAM_BASE,
-	  CONFIG_SYS_FSL_OCRAM_SIZE, MT_NORMAL, PMD_SECT_NON_SHARE },
+	  CONFIG_SYS_FSL_OCRAM_SIZE, MT_NORMAL, PTE_BLOCK_NON_SHARE },
 	{ CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_BASE,
 	  CONFIG_SYS_FSL_DCSR_SIZE, MT_DEVICE_NGNRNE,
-	  PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN },
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
 	{ CONFIG_SYS_FSL_QSPI_BASE, CONFIG_SYS_FSL_QSPI_BASE,
 	  CONFIG_SYS_FSL_QSPI_SIZE, MT_DEVICE_NGNRNE,
-	  PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN },
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
 	{ CONFIG_SYS_FSL_IFC_BASE, CONFIG_SYS_FSL_IFC_BASE,
-	  CONFIG_SYS_FSL_IFC_SIZE, MT_DEVICE_NGNRNE, PMD_SECT_NON_SHARE },
+	  CONFIG_SYS_FSL_IFC_SIZE, MT_DEVICE_NGNRNE, PTE_BLOCK_NON_SHARE },
 	{ CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1,
 	  CONFIG_SYS_FSL_DRAM_SIZE1, MT_NORMAL,
-	  PMD_SECT_OUTER_SHARE | PMD_SECT_NS },
+	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS },
 	{ CONFIG_SYS_FSL_QBMAN_BASE, CONFIG_SYS_FSL_QBMAN_BASE,
 	  CONFIG_SYS_FSL_QBMAN_SIZE, MT_DEVICE_NGNRNE,
-	  PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN },
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
 	{ CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_BASE2,
-	  CONFIG_SYS_FSL_DRAM_SIZE2, MT_NORMAL, PMD_SECT_OUTER_SHARE },
+	  CONFIG_SYS_FSL_DRAM_SIZE2, MT_NORMAL, PTE_BLOCK_OUTER_SHARE },
 	{ CONFIG_SYS_PCIE1_PHYS_ADDR, CONFIG_SYS_PCIE1_PHYS_ADDR,
 	  CONFIG_SYS_PCIE1_PHYS_SIZE, MT_DEVICE_NGNRNE,
-	  PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN },
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
 	{ CONFIG_SYS_PCIE2_PHYS_ADDR, CONFIG_SYS_PCIE2_PHYS_ADDR,
 	  CONFIG_SYS_PCIE2_PHYS_SIZE, MT_DEVICE_NGNRNE,
-	  PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN },
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
 	{ CONFIG_SYS_PCIE3_PHYS_ADDR, CONFIG_SYS_PCIE3_PHYS_ADDR,
 	  CONFIG_SYS_PCIE3_PHYS_SIZE, MT_DEVICE_NGNRNE,
-	  PMD_SECT_NON_SHARE | PMD_SECT_PXN | PMD_SECT_UXN },
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
 	{ CONFIG_SYS_FSL_DRAM_BASE3, CONFIG_SYS_FSL_DRAM_BASE3,
-	  CONFIG_SYS_FSL_DRAM_SIZE3, MT_NORMAL, PMD_SECT_OUTER_SHARE },
+	  CONFIG_SYS_FSL_DRAM_SIZE3, MT_NORMAL, PTE_BLOCK_OUTER_SHARE },
 #endif
 };
 #endif
diff --git a/arch/arm/include/asm/armv8/mmu.h b/arch/arm/include/asm/armv8/mmu.h
index 06126c8..0d08ed3 100644
--- a/arch/arm/include/asm/armv8/mmu.h
+++ b/arch/arm/include/asm/armv8/mmu.h
@@ -22,28 +22,12 @@
  * calculated specifically.
  */
 
-#ifndef CONFIG_SYS_FULL_VA
-#define VA_BITS			(42)	/* 42 bits virtual address */
-#else
 #define VA_BITS			CONFIG_SYS_VA_BITS
 #define PTE_BLOCK_BITS		CONFIG_SYS_PTL2_BITS
-#endif
 
 /*
  * block/section address mask and size definitions.
  */
-#ifndef CONFIG_SYS_FULL_VA
-#define SECTION_SHIFT		29
-#define SECTION_SIZE		(UL(1) << SECTION_SHIFT)
-#define SECTION_MASK		(~(SECTION_SIZE-1))
-
-/* PAGE_SHIFT determines the page size */
-#undef  PAGE_SIZE
-#define PAGE_SHIFT		16
-#define PAGE_SIZE		(1 << PAGE_SHIFT)
-#define PAGE_MASK		(~(PAGE_SIZE-1))
-
-#else
 
 /* PAGE_SHIFT determines the page size */
 #undef  PAGE_SIZE
@@ -51,8 +35,6 @@
 #define PAGE_SIZE		(1 << PAGE_SHIFT)
 #define PAGE_MASK		(~(PAGE_SIZE-1))
 
-#endif
-
 /***************************************************************/
 
 /*
@@ -75,8 +57,6 @@
  *
  */
 
-#ifdef CONFIG_SYS_FULL_VA
-
 #define PTE_TYPE_MASK		(3 << 0)
 #define PTE_TYPE_FAULT		(0 << 0)
 #define PTE_TYPE_TABLE		(3 << 0)
@@ -91,6 +71,7 @@
  * Block
  */
 #define PTE_BLOCK_MEMTYPE(x)	((x) << 2)
+#define PTE_BLOCK_NS            (1 << 5)
 #define PTE_BLOCK_NON_SHARE	(0 << 8)
 #define PTE_BLOCK_OUTER_SHARE	(2 << 8)
 #define PTE_BLOCK_INNER_SHARE	(3 << 8)
@@ -99,29 +80,6 @@
 #define PTE_BLOCK_PXN		(UL(1) << 53)
 #define PTE_BLOCK_UXN		(UL(1) << 54)
 
-#else
-/*
- * Level 2 descriptor (PMD).
- */
-#define PMD_TYPE_MASK		(3 << 0)
-#define PMD_TYPE_FAULT		(0 << 0)
-#define PMD_TYPE_TABLE		(3 << 0)
-#define PMD_TYPE_SECT		(1 << 0)
-
-/*
- * Section
- */
-#define PMD_SECT_NS		(1 << 5)
-#define PMD_SECT_NON_SHARE	(0 << 8)
-#define PMD_SECT_OUTER_SHARE	(2 << 8)
-#define PMD_SECT_INNER_SHARE	(3 << 8)
-#define PMD_SECT_AF		(1 << 10)
-#define PMD_SECT_NG		(1 << 11)
-#define PMD_SECT_PXN		(UL(1) << 53)
-#define PMD_SECT_UXN		(UL(1) << 54)
-
-#endif
-
 /*
  * AttrIndx[2:0]
  */
@@ -150,33 +108,11 @@
 #define TCR_TG0_16K		(2 << 14)
 #define TCR_EPD1_DISABLE	(1 << 23)
 
-#ifndef CONFIG_SYS_FULL_VA
-#define TCR_EL1_IPS_BITS	(UL(3) << 32)	/* 42 bits physical address */
-#define TCR_EL2_IPS_BITS	(3 << 16)	/* 42 bits physical address */
-#define TCR_EL3_IPS_BITS	(3 << 16)	/* 42 bits physical address */
-
-/* PTWs cacheable, inner/outer WBWA and inner shareable */
-#define TCR_FLAGS		(TCR_TG0_64K |		\
-				TCR_SHARED_INNER |	\
-				TCR_ORGN_WBWA |		\
-				TCR_IRGN_WBWA |		\
-				TCR_T0SZ(VA_BITS))
-#endif
-
 #define TCR_EL1_RSVD		(1 << 31)
 #define TCR_EL2_RSVD		(1 << 31 | 1 << 23)
 #define TCR_EL3_RSVD		(1 << 31 | 1 << 23)
 
 #ifndef __ASSEMBLY__
-#ifndef CONFIG_SYS_FULL_VA
-
-void set_pgtable_section(u64 *page_table, u64 index,
-			 u64 section, u64 memory_type,
-			 u64 attribute);
-void set_pgtable_table(u64 *page_table, u64 index,
-		       u64 *table_addr);
-
-#endif
 static inline void set_ttbr_tcr_mair(int el, u64 table, u64 tcr, u64 attr)
 {
 	asm volatile("dsb sy");
diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
index 259daa1..77d2653 100644
--- a/arch/arm/include/asm/global_data.h
+++ b/arch/arm/include/asm/global_data.h
@@ -39,7 +39,7 @@ struct arch_global_data {
 #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
 	unsigned long tlb_addr;
 	unsigned long tlb_size;
-#if defined(CONFIG_SYS_FULL_VA)
+#if defined(CONFIG_ARM64)
 	unsigned long tlb_fillptr;
 	unsigned long tlb_emerg;
 #endif
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index 9b1cbf2..ac1173d 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -17,18 +17,14 @@
 #define CR_WXN		(1 << 19)	/* Write Permision Imply XN	*/
 #define CR_EE		(1 << 25)	/* Exception (Big) Endian	*/
 
-/* 2MB granularity */
-#define MMU_SECTION_SHIFT	21
-#define MMU_SECTION_SIZE	(1 << MMU_SECTION_SHIFT)
-
 #ifndef __ASSEMBLY__
 
-#ifndef CONFIG_SYS_FULL_VA
-#define PGTABLE_SIZE	(0x10000)
-#else
 u64 get_page_table_size(void);
 #define PGTABLE_SIZE	get_page_table_size()
-#endif
+
+/* 2MB granularity */
+#define MMU_SECTION_SHIFT	21
+#define MMU_SECTION_SIZE	(1 << MMU_SECTION_SHIFT)
 
 enum dcache_option {
 	DCACHE_OFF = 0x3,
diff --git a/doc/README.arm64 b/doc/README.arm64
index de669cb..f658fa2 100644
--- a/doc/README.arm64
+++ b/doc/README.arm64
@@ -36,26 +36,6 @@ Notes
 6. CONFIG_ARM64 instead of CONFIG_ARMV8 is used to distinguish aarch64 and
    aarch32 specific codes.
 
-7. CONFIG_SYS_FULL_VA is used to enable 2-level page tables. For cores
-   supporting 64k pages it allows usage of full 48+ virtual/physical addresses
-
-   Enabling this option requires the following ones to be defined:
-       - CONFIG_SYS_MEM_MAP - an array of 'struct mm_region' describing the
-         system memory map (start, length, attributes)
-       - CONFIG_SYS_MEM_MAP_SIZE - number of entries in CONFIG_SYS_MEM_MAP
-       - CONFIG_SYS_PTL1_ENTRIES - number of 1st level page table entries
-       - CONFIG_SYS_PTL2_ENTRIES - number of 1nd level page table entries
-         for the largest CONFIG_SYS_MEM_MAP entry
-       - CONFIG_COREID_MASK - the mask value used to get the core from the
-         MPIDR_EL1 register
-       - CONFIG_SYS_PTL2_BITS - number of bits addressed by the 2nd level
-         page tables
-       - CONFIG_SYS_BLOCK_SHIFT - number of bits addressed by a single block
-         entry from L2 page tables
-       - CONFIG_SYS_PGTABLE_SIZE - total size of the page table
-       - CONFIG_SYS_TCR_EL{1,2,3}_IPS_BITS - the IPS field of the TCR_EL{1,2,3}
-
-
 
 
 Contributor
diff --git a/include/configs/hikey.h b/include/configs/hikey.h
index d33dcef..2d9ace9 100644
--- a/include/configs/hikey.h
+++ b/include/configs/hikey.h
@@ -23,7 +23,6 @@
 
 /* MMU Definitions */
 #define CONFIG_SYS_CACHELINE_SIZE	64
-#define CONFIG_SYS_FULL_VA
 
 #define CONFIG_IDENT_STRING		"hikey"
 
diff --git a/include/configs/tegra210-common.h b/include/configs/tegra210-common.h
index 2a6e317..8f35a7b 100644
--- a/include/configs/tegra210-common.h
+++ b/include/configs/tegra210-common.h
@@ -13,8 +13,6 @@
 /* Cortex-A57 uses a cache line size of 64 bytes */
 #define CONFIG_SYS_CACHELINE_SIZE	64
 
-#define CONFIG_SYS_FULL_VA
-
 /*
  * NS16550 Configuration
  */
diff --git a/include/configs/thunderx_88xx.h b/include/configs/thunderx_88xx.h
index 64e4616..736d0a5 100644
--- a/include/configs/thunderx_88xx.h
+++ b/include/configs/thunderx_88xx.h
@@ -22,22 +22,8 @@
 
 #define MEM_BASE			0x00500000
 
-#define CONFIG_SYS_FULL_VA
-
 #define CONFIG_SYS_LOWMEM_BASE		MEM_BASE
 
-#define CONFIG_SYS_MEM_MAP_SIZE		3
-
-#define CONFIG_SYS_VA_BITS		48
-#define CONFIG_SYS_PTL2_BITS		42
-#define CONFIG_SYS_BLOCK_SHIFT		29
-#define CONFIG_SYS_PTL1_ENTRIES		64
-#define CONFIG_SYS_PTL2_ENTRIES		8192
-
-#define CONFIG_SYS_PGTABLE_SIZE		\
-	((CONFIG_SYS_PTL1_ENTRIES + \
-	  CONFIG_SYS_MEM_MAP_SIZE * CONFIG_SYS_PTL2_ENTRIES) * 8)
-
 /* Link Definitions */
 #define CONFIG_SYS_TEXT_BASE		0x00500000
 #define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_SDRAM_BASE + 0x7fff0)
diff --git a/include/configs/vexpress_aemv8a.h b/include/configs/vexpress_aemv8a.h
index ddb9848..2949170 100644
--- a/include/configs/vexpress_aemv8a.h
+++ b/include/configs/vexpress_aemv8a.h
@@ -21,7 +21,6 @@
 
 /* MMU Definitions */
 #define CONFIG_SYS_CACHELINE_SIZE	64
-#define CONFIG_SYS_FULL_VA
 
 #define CONFIG_IDENT_STRING		" vexpress_aemv8a"
 #define CONFIG_BOOTP_VCI_STRING		"U-Boot.armv8.vexpress_aemv8a"
diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h
index 727084f..1121ea4 100644
--- a/include/configs/xilinx_zynqmp.h
+++ b/include/configs/xilinx_zynqmp.h
@@ -29,8 +29,6 @@
 #define CONFIG_SYS_MEMTEST_START	CONFIG_SYS_SDRAM_BASE
 #define CONFIG_SYS_MEMTEST_END		CONFIG_SYS_SDRAM_SIZE
 
-#define CONFIG_SYS_FULL_VA
-
 /* Have release address@the end of 256MB for now */
 #define CPU_RELEASE_ADDR	0xFFFFFF0
 
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 11/30] arm64: Only allow dcache disabled in SPL builds
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (9 preceding siblings ...)
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 10/30] arm64: Remove non-full-va map code Alexander Graf
@ 2016-03-04  0:09 ` Alexander Graf
  2016-03-17  2:01   ` [U-Boot] [U-Boot, v5, " Tom Rini
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 12/30] disk/part.c: Expose list of available block drivers Alexander Graf
                   ` (19 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:09 UTC (permalink / raw)
  To: u-boot

Now that we have an easy way to describe memory regions and enable the MMU,
there really shouldn't be anything holding people back from running with
caches enabled on AArch64. To make sure people catch early if they're missing
on the caching fun, give them a compile error.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 arch/arm/cpu/armv8/cache_v8.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c
index df15e00..d1bd06b 100644
--- a/arch/arm/cpu/armv8/cache_v8.c
+++ b/arch/arm/cpu/armv8/cache_v8.c
@@ -566,6 +566,15 @@ void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
 
 #else	/* CONFIG_SYS_DCACHE_OFF */
 
+/*
+ * For SPL builds, we may want to not have dcache enabled. Any real U-Boot
+ * running however really wants to have dcache and the MMU active. Check that
+ * everything is sane and give the developer a hint if it isn't.
+ */
+#ifndef CONFIG_SPL_BUILD
+#error Please describe your MMU layout in CONFIG_SYS_MEM_MAP and enable dcache.
+#endif
+
 void invalidate_dcache_all(void)
 {
 }
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 12/30] disk/part.c: Expose list of available block drivers
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (10 preceding siblings ...)
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 11/30] arm64: Only allow dcache disabled in SPL builds Alexander Graf
@ 2016-03-04  0:09 ` Alexander Graf
  2016-03-17  2:01   ` [U-Boot] [U-Boot, v5, " Tom Rini
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 13/30] include/efi_api.h: Add more detailed API definitions Alexander Graf
                   ` (18 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:09 UTC (permalink / raw)
  To: u-boot

We have a pretty nice and generic interface to ask for a specific block
device. However, that one is still based around the magic notion that
we know the driver name.

In order to be able to write fully generic disk access code, expose the
currently internal list to other source files so that they can scan through
all available block drivers.

Signed-off-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
Tested-by: Simon Glass <sjg@chromium.org>
---
 disk/part.c    | 7 +------
 include/part.h | 8 ++++++++
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/disk/part.c b/disk/part.c
index 1935b28..d265c2b 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -20,13 +20,8 @@
 #define PRINTF(fmt,args...)
 #endif
 
-struct block_drvr {
-	char *name;
-	block_dev_desc_t* (*get_dev)(int dev);
-	int (*select_hwpart)(int dev_num, int hwpart);
-};
 
-static const struct block_drvr block_drvr[] = {
+const struct block_drvr block_drvr[] = {
 #if defined(CONFIG_CMD_IDE)
 	{ .name = "ide", .get_dev = ide_get_dev, },
 #endif
diff --git a/include/part.h b/include/part.h
index dc23949..6e6205b 100644
--- a/include/part.h
+++ b/include/part.h
@@ -42,6 +42,12 @@ struct block_dev_desc {
 	void		*priv;		/* driver private struct pointer */
 };
 
+struct block_drvr {
+	char *name;
+	block_dev_desc_t* (*get_dev)(int dev);
+	int (*select_hwpart)(int dev_num, int hwpart);
+};
+
 #define BLOCK_CNT(size, block_dev_desc) (PAD_COUNT(size, block_dev_desc->blksz))
 #define PAD_TO_BLOCKSIZE(size, block_dev_desc) \
 	(PAD_SIZE(size, block_dev_desc->blksz))
@@ -123,6 +129,8 @@ int get_device(const char *ifname, const char *dev_str,
 int get_device_and_partition(const char *ifname, const char *dev_part_str,
 			     block_dev_desc_t **dev_desc,
 			     disk_partition_t *info, int allow_whole_dev);
+
+extern const struct block_drvr block_drvr[];
 #else
 static inline block_dev_desc_t *get_dev(const char *ifname, int dev)
 { return NULL; }
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 13/30] include/efi_api.h: Add more detailed API definitions
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (11 preceding siblings ...)
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 12/30] disk/part.c: Expose list of available block drivers Alexander Graf
@ 2016-03-04  0:09 ` Alexander Graf
  2016-03-17  2:01   ` [U-Boot] [U-Boot, v5, " Tom Rini
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 14/30] efi_loader: Add PE image loader Alexander Graf
                   ` (17 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:09 UTC (permalink / raw)
  To: u-boot

The EFI API header is great, but missing a good chunk of function prototype,
GUID defines and enum declarations.

This patch extends it to cover more of the EFI API. It's still not 100%
complete, but sufficient enough for our EFI payload interface.

Signed-off-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
Tested-by: Simon Glass <sjg@chromium.org>

---

v2 -> v3:

  - Add EFIAPI to notify_function
  - Add access denied code

v3 -> v4:

  - Add EFI_PAGE_MASK define
---
 include/efi.h     |   2 +
 include/efi_api.h | 198 ++++++++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 163 insertions(+), 37 deletions(-)

diff --git a/include/efi.h b/include/efi.h
index fcafda0..1dbc3b7 100644
--- a/include/efi.h
+++ b/include/efi.h
@@ -38,6 +38,7 @@ struct efi_device_path;
 #define EFI_WRITE_PROTECTED	(8 | (1UL << (BITS_PER_LONG - 1)))
 #define EFI_OUT_OF_RESOURCES	(9 | (1UL << (BITS_PER_LONG - 1)))
 #define EFI_NOT_FOUND		(14 | (1UL << (BITS_PER_LONG - 1)))
+#define EFI_ACCESS_DENIED	(15 | (1UL << (BITS_PER_LONG - 1)))
 #define EFI_SECURITY_VIOLATION	(26 | (1UL << (BITS_PER_LONG - 1)))
 
 typedef unsigned long efi_status_t;
@@ -139,6 +140,7 @@ enum {
 
 #define EFI_PAGE_SHIFT		12
 #define EFI_PAGE_SIZE		(1UL << EFI_PAGE_SHIFT)
+#define EFI_PAGE_MASK		(EFI_PAGE_SIZE - 1)
 
 struct efi_mem_desc {
 	u32 type;
diff --git a/include/efi_api.h b/include/efi_api.h
index 4fd17d6..03f6687 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -17,11 +17,18 @@
 
 #include <efi.h>
 
+/* Types and defines for EFI CreateEvent */
+enum efi_event_type {
+	EFI_TIMER_STOP = 0,
+	EFI_TIMER_PERIODIC = 1,
+	EFI_TIMER_RELATIVE = 2
+};
+
 /* EFI Boot Services table */
 struct efi_boot_services {
 	struct efi_table_hdr hdr;
-	void *raise_tpl;
-	void *restore_tpl;
+	efi_status_t (EFIAPI *raise_tpl)(unsigned long new_tpl);
+	void (EFIAPI *restore_tpl)(unsigned long old_tpl);
 
 	efi_status_t (EFIAPI *allocate_pages)(int, int, unsigned long,
 					      efi_physical_addr_t *);
@@ -32,21 +39,33 @@ struct efi_boot_services {
 	efi_status_t (EFIAPI *allocate_pool)(int, unsigned long, void **);
 	efi_status_t (EFIAPI *free_pool)(void *);
 
-	void *create_event;
-	void *set_timer;
-	efi_status_t(EFIAPI *wait_for_event)(unsigned long number_of_events,
-					     void *event, unsigned long *index);
-	void *signal_event;
-	void *close_event;
-	void *check_event;
-
-	void *install_protocol_interface;
-	void *reinstall_protocol_interface;
-	void *uninstall_protocol_interface;
+	efi_status_t (EFIAPI *create_event)(enum efi_event_type type,
+			unsigned long notify_tpl,
+			void (EFIAPI *notify_function) (void *event,
+							void *context),
+			void *notify_context, void **event);
+	efi_status_t (EFIAPI *set_timer)(void *event, int type,
+			uint64_t trigger_time);
+	efi_status_t (EFIAPI *wait_for_event)(unsigned long number_of_events,
+			void *event, unsigned long *index);
+	efi_status_t (EFIAPI *signal_event)(void *event);
+	efi_status_t (EFIAPI *close_event)(void *event);
+	efi_status_t (EFIAPI *check_event)(void *event);
+
+	efi_status_t (EFIAPI *install_protocol_interface)(
+			void **handle, efi_guid_t *protocol,
+			int protocol_interface_type, void *protocol_interface);
+	efi_status_t (EFIAPI *reinstall_protocol_interface)(
+			void *handle, efi_guid_t *protocol,
+			void *old_interface, void *new_interface);
+	efi_status_t (EFIAPI *uninstall_protocol_interface)(void *handle,
+			efi_guid_t *protocol, void *protocol_interface);
 	efi_status_t (EFIAPI *handle_protocol)(efi_handle_t, efi_guid_t *,
 					       void **);
 	void *reserved;
-	void *register_protocol_notify;
+	efi_status_t (EFIAPI *register_protocol_notify)(
+			efi_guid_t *protocol, void *event,
+			void **registration);
 	efi_status_t (EFIAPI *locate_handle)(
 			enum efi_locate_search_type search_type,
 			efi_guid_t *protocol, void *search_key,
@@ -54,7 +73,8 @@ struct efi_boot_services {
 	efi_status_t (EFIAPI *locate_device_path)(efi_guid_t *protocol,
 			struct efi_device_path **device_path,
 			efi_handle_t *device);
-	void *install_configuration_table;
+	efi_status_t (EFIAPI *install_configuration_table)(
+			efi_guid_t *guid, void *table);
 
 	efi_status_t (EFIAPI *load_image)(bool boot_policiy,
 			efi_handle_t parent_image,
@@ -66,17 +86,20 @@ struct efi_boot_services {
 	efi_status_t (EFIAPI *exit)(efi_handle_t handle,
 				    efi_status_t exit_status,
 				    unsigned long exitdata_size, s16 *exitdata);
-	void *unload_image;
+	efi_status_t (EFIAPI *unload_image)(void *image_handle);
 	efi_status_t (EFIAPI *exit_boot_services)(efi_handle_t, unsigned long);
 
 	efi_status_t (EFIAPI *get_next_monotonic_count)(u64 *count);
 	efi_status_t (EFIAPI *stall)(unsigned long usecs);
-	void *set_watchdog_timer;
+	efi_status_t (EFIAPI *set_watchdog_timer)(unsigned long timeout,
+			uint64_t watchdog_code, unsigned long data_size,
+			uint16_t *watchdog_data);
 	efi_status_t(EFIAPI *connect_controller)(efi_handle_t controller_handle,
 			efi_handle_t *driver_image_handle,
 			struct efi_device_path *remaining_device_path,
 			bool recursive);
-	void *disconnect_controller;
+	efi_status_t (EFIAPI *disconnect_controller)(void *controller_handle,
+			void *driver_image_handle, void *child_handle);
 #define EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL  0x00000001
 #define EFI_OPEN_PROTOCOL_GET_PROTOCOL        0x00000002
 #define EFI_OPEN_PROTOCOL_TEST_PROTOCOL       0x00000004
@@ -87,7 +110,9 @@ struct efi_boot_services {
 			efi_guid_t *protocol, void **interface,
 			efi_handle_t agent_handle,
 			efi_handle_t controller_handle, u32 attributes);
-	void *close_protocol;
+	efi_status_t (EFIAPI *close_protocol)(void *handle,
+			efi_guid_t *protocol, void *agent_handle,
+			void *controller_handle);
 	efi_status_t(EFIAPI *open_protocol_information)(efi_handle_t handle,
 			efi_guid_t *protocol,
 			struct efi_open_protocol_info_entry **entry_buffer,
@@ -99,12 +124,18 @@ struct efi_boot_services {
 			enum efi_locate_search_type search_type,
 			efi_guid_t *protocol, void *search_key,
 			unsigned long *no_handles, efi_handle_t **buffer);
-	void *locate_protocol;
-	void *install_multiple_protocol_interfaces;
-	void *uninstall_multiple_protocol_interfaces;
-	void *calculate_crc32;
-	void *copy_mem;
-	void *set_mem;
+	efi_status_t (EFIAPI *locate_protocol)(efi_guid_t *protocol,
+			void *registration, void **protocol_interface);
+	efi_status_t (EFIAPI *install_multiple_protocol_interfaces)(
+			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);
+	void (EFIAPI *copy_mem)(void *destination, void *source,
+			unsigned long length);
+	void (EFIAPI *set_mem)(void *buffer, unsigned long size,
+			uint8_t value);
 	void *create_event_ex;
 };
 
@@ -121,12 +152,19 @@ enum efi_reset_type {
 
 struct efi_runtime_services {
 	struct efi_table_hdr hdr;
-	void *get_time;
-	void *set_time;
-	void *get_wakeup_time;
-	void *set_wakeup_time;
-	void *set_virtual_address_map;
-	void *convert_pointer;
+	efi_status_t (EFIAPI *get_time)(struct efi_time *time,
+			struct efi_time_cap *capabilities);
+	efi_status_t (EFIAPI *set_time)(struct efi_time *time);
+	efi_status_t (EFIAPI *get_wakeup_time)(char *enabled, char *pending,
+			struct efi_time *time);
+	efi_status_t (EFIAPI *set_wakeup_time)(char enabled,
+			struct efi_time *time);
+	efi_status_t (EFIAPI *set_virtual_address_map)(
+			unsigned long memory_map_size,
+			unsigned long descriptor_size,
+			uint32_t descriptor_version,
+			struct efi_mem_desc *virtmap);
+	efi_status_t (*convert_pointer)(unsigned long dbg, void **address);
 	efi_status_t (EFIAPI *get_variable)(s16 *variable_name,
 			efi_guid_t *vendor, u32 *attributes,
 			unsigned long *data_size, void *data);
@@ -136,7 +174,8 @@ struct efi_runtime_services {
 	efi_status_t (EFIAPI *set_variable)(s16 *variable_name,
 			efi_guid_t *vendor, u32 attributes,
 			unsigned long data_size, void *data);
-	void *get_next_high_mono_count;
+	efi_status_t (EFIAPI *get_next_high_mono_count)(
+			uint32_t *high_count);
 	void (EFIAPI *reset_system)(enum efi_reset_type reset_type,
 				    efi_status_t reset_status,
 				    unsigned long data_size, void *reset_data);
@@ -154,6 +193,18 @@ struct efi_runtime_services {
 	EFI_GUID(0x5b1b31a1, 0x9562, 0x11d2, 0x8e, 0x3f, \
 		 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
 
+#define EFI_FDT_GUID \
+	EFI_GUID(0xb1b621d5, 0xf19c, 0x41a5, \
+		 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0)
+
+struct efi_configuration_table
+{
+	efi_guid_t guid;
+	void *table;
+};
+
+#define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL)
+
 struct efi_system_table {
 	struct efi_table_hdr hdr;
 	unsigned long fw_vendor;   /* physical addr of wchar_t vendor string */
@@ -163,13 +214,17 @@ struct efi_system_table {
 	unsigned long con_out_handle;
 	struct efi_simple_text_output_protocol *con_out;
 	unsigned long stderr_handle;
-	unsigned long std_err;
+	struct efi_simple_text_output_protocol *std_err;
 	struct efi_runtime_services *runtime;
 	struct efi_boot_services *boottime;
 	unsigned long nr_tables;
-	unsigned long tables;
+	struct efi_configuration_table *tables;
 };
 
+#define LOADED_IMAGE_GUID \
+	EFI_GUID(0x5b1b31a1, 0x9562, 0x11d2, \
+		 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+
 struct efi_loaded_image {
 	u32 revision;
 	void *parent_handle;
@@ -186,12 +241,60 @@ struct efi_loaded_image {
 	unsigned long unload;
 };
 
+#define DEVICE_PATH_GUID \
+	EFI_GUID(0x09576e91, 0x6d3f, 0x11d2, \
+		 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
+
+#define DEVICE_PATH_TYPE_END			0x7f
+#  define DEVICE_PATH_SUB_TYPE_END		0xff
+
 struct efi_device_path {
 	u8 type;
 	u8 sub_type;
 	u16 length;
 };
 
+#define DEVICE_PATH_TYPE_MEDIA_DEVICE		0x04
+#  define DEVICE_PATH_SUB_TYPE_FILE_PATH	0x04
+
+struct efi_device_path_file_path {
+	struct efi_device_path dp;
+	u16 str[16];
+};
+
+#define BLOCK_IO_GUID \
+	EFI_GUID(0x964e5b21, 0x6459, 0x11d2, \
+		 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+
+struct efi_block_io_media
+{
+	u32 media_id;
+	char removable_media;
+	char media_present;
+	char logical_partition;
+	char read_only;
+	char write_caching;
+	u8 pad[3];
+	u32 block_size;
+	u32 io_align;
+	u8 pad2[4];
+	u64 last_block;
+};
+
+struct efi_block_io {
+	u64 revision;
+	struct efi_block_io_media *media;
+	efi_status_t (EFIAPI *reset)(struct efi_block_io *this,
+			char extended_verification);
+	efi_status_t (EFIAPI *read_blocks)(struct efi_block_io *this,
+			u32 media_id, u64 lba, unsigned long buffer_size,
+			void *buffer);
+	efi_status_t (EFIAPI *write_blocks)(struct efi_block_io *this,
+			u32 media_id, u64 lba, unsigned long buffer_size,
+			void *buffer);
+	efi_status_t (EFIAPI *flush_blocks)(struct efi_block_io *this);
+};
+
 struct simple_text_output_mode {
 	s32 max_mode;
 	s32 mode;
@@ -206,8 +309,9 @@ struct efi_simple_text_output_protocol {
 	efi_status_t (EFIAPI *output_string)(
 			struct efi_simple_text_output_protocol *this,
 			const unsigned short *str);
-	void *test_string;
-
+	efi_status_t (EFIAPI *test_string)(
+			struct efi_simple_text_output_protocol *this,
+			const unsigned short *str);
 	efi_status_t(EFIAPI *query_mode)(
 			struct efi_simple_text_output_protocol *this,
 			unsigned long mode_number, unsigned long *columns,
@@ -223,7 +327,9 @@ struct efi_simple_text_output_protocol {
 	efi_status_t(EFIAPI *set_cursor_position) (
 			struct efi_simple_text_output_protocol *this,
 			unsigned long column, unsigned long row);
-	efi_status_t(EFIAPI *enable_cursor)(void *, bool enable);
+	efi_status_t(EFIAPI *enable_cursor)(
+			struct efi_simple_text_output_protocol *this,
+			bool enable);
 	struct simple_text_output_mode *mode;
 };
 
@@ -241,4 +347,22 @@ struct efi_simple_input_interface {
 	void *wait_for_key;
 };
 
+#define CONSOLE_CONTROL_GUID \
+	EFI_GUID(0xf42f7782, 0x12e, 0x4c12, \
+		 0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21)
+#define EFI_CONSOLE_MODE_TEXT	0
+#define EFI_CONSOLE_MODE_GFX	1
+
+struct efi_console_control_protocol
+{
+	efi_status_t (EFIAPI *get_mode)(
+			struct efi_console_control_protocol *this, int *mode,
+			char *uga_exists, char *std_in_locked);
+	efi_status_t (EFIAPI *set_mode)(
+			struct efi_console_control_protocol *this, int mode);
+	efi_status_t (EFIAPI *lock_std_in)(
+			struct efi_console_control_protocol *this,
+			uint16_t *password);
+};
+
 #endif
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 14/30] efi_loader: Add PE image loader
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (12 preceding siblings ...)
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 13/30] include/efi_api.h: Add more detailed API definitions Alexander Graf
@ 2016-03-04  0:09 ` Alexander Graf
  2016-03-17  2:01   ` [U-Boot] [U-Boot,v5,14/30] " Tom Rini
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 15/30] efi_loader: Add boot time services Alexander Graf
                   ` (16 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:09 UTC (permalink / raw)
  To: u-boot

EFI uses the PE binary format for its application images. Add support to EFI PE
binaries as well as all necessary bits for the "EFI image loader" interfaces.

Signed-off-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
Tested-by: Simon Glass <sjg@chromium.org>

---

v1 -> v2:

  - move memory allocation to separate patch
  - limit 32/64 to hosts that support it
  - check 32bit optional nt header magic
  - switch to GPL2+

v2 -> v3:

  - use efi_alloc
  - add EFIAPI to function prototypes
  - remove unused macros
  - reorder header inclusion
  - split relocation code into function
  - flush cache after loading

v3 -> v4:

  - Use EFI_PAGE_SHIFT define
  - Flush icache after image load
  - Fix white space in pe header

v4 -> v5:

  - Provide icache flush stub for archs which don't have it
---
 include/efi_loader.h              |  20 +++
 include/pe.h                      | 263 ++++++++++++++++++++++++++++++++++++++
 lib/efi_loader/efi_image_loader.c | 188 +++++++++++++++++++++++++++
 3 files changed, 471 insertions(+)
 create mode 100644 include/efi_loader.h
 create mode 100644 include/pe.h
 create mode 100644 lib/efi_loader/efi_image_loader.c

diff --git a/include/efi_loader.h b/include/efi_loader.h
new file mode 100644
index 0000000..5618185
--- /dev/null
+++ b/include/efi_loader.h
@@ -0,0 +1,20 @@
+/*
+ *  EFI application loader
+ *
+ *  Copyright (c) 2016 Alexander Graf
+ *
+ *  SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <part_efi.h>
+#include <efi_api.h>
+#include <linux/list.h>
+
+extern const efi_guid_t efi_guid_device_path;
+extern const efi_guid_t efi_guid_loaded_image;
+
+efi_status_t efi_return_handle(void *handle,
+		efi_guid_t *protocol, void **protocol_interface,
+		void *agent_handle, void *controller_handle,
+		uint32_t attributes);
+void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info);
diff --git a/include/pe.h b/include/pe.h
new file mode 100644
index 0000000..deb35a0
--- /dev/null
+++ b/include/pe.h
@@ -0,0 +1,263 @@
+/*
+ *  Portable Executable binary format structures
+ *
+ *  Copyright (c) 2016 Alexander Graf
+ *
+ *  Based on wine code
+ *
+ *  SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef _PE_H
+#define _PE_H
+
+typedef struct _IMAGE_DOS_HEADER {
+	uint16_t e_magic;	/* 00: MZ Header signature */
+	uint16_t e_cblp;	/* 02: Bytes on last page of file */
+	uint16_t e_cp;		/* 04: Pages in file */
+	uint16_t e_crlc;	/* 06: Relocations */
+	uint16_t e_cparhdr;	/* 08: Size of header in paragraphs */
+	uint16_t e_minalloc;	/* 0a: Minimum extra paragraphs needed */
+	uint16_t e_maxalloc;	/* 0c: Maximum extra paragraphs needed */
+	uint16_t e_ss;		/* 0e: Initial (relative) SS value */
+	uint16_t e_sp;		/* 10: Initial SP value */
+	uint16_t e_csum;	/* 12: Checksum */
+	uint16_t e_ip;		/* 14: Initial IP value */
+	uint16_t e_cs;		/* 16: Initial (relative) CS value */
+	uint16_t e_lfarlc;	/* 18: File address of relocation table */
+	uint16_t e_ovno;	/* 1a: Overlay number */
+	uint16_t e_res[4];	/* 1c: Reserved words */
+	uint16_t e_oemid;	/* 24: OEM identifier (for e_oeminfo) */
+	uint16_t e_oeminfo;	/* 26: OEM information; e_oemid specific */
+	uint16_t e_res2[10];	/* 28: Reserved words */
+	uint32_t e_lfanew;	/* 3c: Offset to extended header */
+} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
+
+#define IMAGE_DOS_SIGNATURE		0x5A4D     /* MZ   */
+#define IMAGE_NT_SIGNATURE		0x00004550 /* PE00 */
+
+#define IMAGE_FILE_MACHINE_ARM		0x01c0
+#define IMAGE_FILE_MACHINE_THUMB	0x01c2
+#define IMAGE_FILE_MACHINE_ARMNT	0x01c4
+#define IMAGE_FILE_MACHINE_AMD64	0x8664
+#define IMAGE_FILE_MACHINE_ARM64	0xaa64
+#define IMAGE_NT_OPTIONAL_HDR32_MAGIC	0x10b
+#define IMAGE_NT_OPTIONAL_HDR64_MAGIC	0x20b
+#define IMAGE_SUBSYSTEM_EFI_APPLICATION	10
+
+typedef struct _IMAGE_FILE_HEADER {
+	uint16_t Machine;
+	uint16_t NumberOfSections;
+	uint32_t TimeDateStamp;
+	uint32_t PointerToSymbolTable;
+	uint32_t NumberOfSymbols;
+	uint16_t SizeOfOptionalHeader;
+	uint16_t Characteristics;
+} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
+
+typedef struct _IMAGE_DATA_DIRECTORY {
+	uint32_t VirtualAddress;
+	uint32_t Size;
+} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
+
+#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
+
+typedef struct _IMAGE_OPTIONAL_HEADER64 {
+	uint16_t Magic; /* 0x20b */
+	uint8_t  MajorLinkerVersion;
+	uint8_t  MinorLinkerVersion;
+	uint32_t SizeOfCode;
+	uint32_t SizeOfInitializedData;
+	uint32_t SizeOfUninitializedData;
+	uint32_t AddressOfEntryPoint;
+	uint32_t BaseOfCode;
+	uint64_t ImageBase;
+	uint32_t SectionAlignment;
+	uint32_t FileAlignment;
+	uint16_t MajorOperatingSystemVersion;
+	uint16_t MinorOperatingSystemVersion;
+	uint16_t MajorImageVersion;
+	uint16_t MinorImageVersion;
+	uint16_t MajorSubsystemVersion;
+	uint16_t MinorSubsystemVersion;
+	uint32_t Win32VersionValue;
+	uint32_t SizeOfImage;
+	uint32_t SizeOfHeaders;
+	uint32_t CheckSum;
+	uint16_t Subsystem;
+	uint16_t DllCharacteristics;
+	uint64_t SizeOfStackReserve;
+	uint64_t SizeOfStackCommit;
+	uint64_t SizeOfHeapReserve;
+	uint64_t SizeOfHeapCommit;
+	uint32_t LoaderFlags;
+	uint32_t NumberOfRvaAndSizes;
+	IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
+} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;
+
+typedef struct _IMAGE_NT_HEADERS64 {
+	uint32_t Signature;
+	IMAGE_FILE_HEADER FileHeader;
+	IMAGE_OPTIONAL_HEADER64 OptionalHeader;
+} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;
+
+typedef struct _IMAGE_OPTIONAL_HEADER {
+
+	/* Standard fields */
+
+	uint16_t Magic; /* 0x10b or 0x107 */     /* 0x00 */
+	uint8_t  MajorLinkerVersion;
+	uint8_t  MinorLinkerVersion;
+	uint32_t SizeOfCode;
+	uint32_t SizeOfInitializedData;
+	uint32_t SizeOfUninitializedData;
+	uint32_t AddressOfEntryPoint;            /* 0x10 */
+	uint32_t BaseOfCode;
+	uint32_t BaseOfData;
+
+	/* NT additional fields */
+
+	uint32_t ImageBase;
+	uint32_t SectionAlignment;               /* 0x20 */
+	uint32_t FileAlignment;
+	uint16_t MajorOperatingSystemVersion;
+	uint16_t MinorOperatingSystemVersion;
+	uint16_t MajorImageVersion;
+	uint16_t MinorImageVersion;
+	uint16_t MajorSubsystemVersion;          /* 0x30 */
+	uint16_t MinorSubsystemVersion;
+	uint32_t Win32VersionValue;
+	uint32_t SizeOfImage;
+	uint32_t SizeOfHeaders;
+	uint32_t CheckSum;                       /* 0x40 */
+	uint16_t Subsystem;
+	uint16_t DllCharacteristics;
+	uint32_t SizeOfStackReserve;
+	uint32_t SizeOfStackCommit;
+	uint32_t SizeOfHeapReserve;              /* 0x50 */
+	uint32_t SizeOfHeapCommit;
+	uint32_t LoaderFlags;
+	uint32_t NumberOfRvaAndSizes;
+	IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; /* 0x60 */
+	/* 0xE0 */
+} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
+
+typedef struct _IMAGE_NT_HEADERS {
+	uint32_t Signature; /* "PE"\0\0 */       /* 0x00 */
+	IMAGE_FILE_HEADER FileHeader;         /* 0x04 */
+	IMAGE_OPTIONAL_HEADER32 OptionalHeader;       /* 0x18 */
+} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
+
+#define IMAGE_SIZEOF_SHORT_NAME 8
+
+typedef struct _IMAGE_SECTION_HEADER {
+	uint8_t	Name[IMAGE_SIZEOF_SHORT_NAME];
+	union {
+		uint32_t PhysicalAddress;
+		uint32_t VirtualSize;
+	} Misc;
+	uint32_t VirtualAddress;
+	uint32_t SizeOfRawData;
+	uint32_t PointerToRawData;
+	uint32_t PointerToRelocations;
+	uint32_t PointerToLinenumbers;
+	uint16_t NumberOfRelocations;
+	uint16_t NumberOfLinenumbers;
+	uint32_t Characteristics;
+} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
+
+#define IMAGE_DIRECTORY_ENTRY_BASERELOC         5
+
+typedef struct _IMAGE_BASE_RELOCATION
+{
+        uint32_t VirtualAddress;
+        uint32_t SizeOfBlock;
+        /* WORD TypeOffset[1]; */
+} IMAGE_BASE_RELOCATION,*PIMAGE_BASE_RELOCATION;
+
+typedef struct _IMAGE_RELOCATION
+{
+	union {
+		uint32_t VirtualAddress;
+		uint32_t RelocCount;
+	} DUMMYUNIONNAME;
+	uint32_t SymbolTableIndex;
+	uint16_t Type;
+} IMAGE_RELOCATION, *PIMAGE_RELOCATION;
+
+#define IMAGE_SIZEOF_RELOCATION 10
+
+/* generic relocation types */
+#define IMAGE_REL_BASED_ABSOLUTE                0
+#define IMAGE_REL_BASED_HIGH                    1
+#define IMAGE_REL_BASED_LOW                     2
+#define IMAGE_REL_BASED_HIGHLOW                 3
+#define IMAGE_REL_BASED_HIGHADJ                 4
+#define IMAGE_REL_BASED_MIPS_JMPADDR            5
+#define IMAGE_REL_BASED_ARM_MOV32A              5 /* yes, 5 too */
+#define IMAGE_REL_BASED_ARM_MOV32               5 /* yes, 5 too */
+#define IMAGE_REL_BASED_SECTION                 6
+#define IMAGE_REL_BASED_REL                     7
+#define IMAGE_REL_BASED_ARM_MOV32T              7 /* yes, 7 too */
+#define IMAGE_REL_BASED_THUMB_MOV32             7 /* yes, 7 too */
+#define IMAGE_REL_BASED_MIPS_JMPADDR16          9
+#define IMAGE_REL_BASED_IA64_IMM64              9 /* yes, 9 too */
+#define IMAGE_REL_BASED_DIR64                   10
+#define IMAGE_REL_BASED_HIGH3ADJ                11
+
+/* ARM relocation types */
+#define IMAGE_REL_ARM_ABSOLUTE          0x0000
+#define IMAGE_REL_ARM_ADDR              0x0001
+#define IMAGE_REL_ARM_ADDR32NB          0x0002
+#define IMAGE_REL_ARM_BRANCH24          0x0003
+#define IMAGE_REL_ARM_BRANCH11          0x0004
+#define IMAGE_REL_ARM_TOKEN             0x0005
+#define IMAGE_REL_ARM_GPREL12           0x0006
+#define IMAGE_REL_ARM_GPREL7            0x0007
+#define IMAGE_REL_ARM_BLX24             0x0008
+#define IMAGE_REL_ARM_BLX11             0x0009
+#define IMAGE_REL_ARM_SECTION           0x000E
+#define IMAGE_REL_ARM_SECREL            0x000F
+#define IMAGE_REL_ARM_MOV32A            0x0010
+#define IMAGE_REL_ARM_MOV32T            0x0011
+#define IMAGE_REL_ARM_BRANCH20T         0x0012
+#define IMAGE_REL_ARM_BRANCH24T         0x0014
+#define IMAGE_REL_ARM_BLX23T            0x0015
+
+/* ARM64 relocation types */
+#define IMAGE_REL_ARM64_ABSOLUTE        0x0000
+#define IMAGE_REL_ARM64_ADDR32          0x0001
+#define IMAGE_REL_ARM64_ADDR32NB        0x0002
+#define IMAGE_REL_ARM64_BRANCH26        0x0003
+#define IMAGE_REL_ARM64_PAGEBASE_REL21  0x0004
+#define IMAGE_REL_ARM64_REL21           0x0005
+#define IMAGE_REL_ARM64_PAGEOFFSET_12A  0x0006
+#define IMAGE_REL_ARM64_PAGEOFFSET_12L  0x0007
+#define IMAGE_REL_ARM64_SECREL          0x0008
+#define IMAGE_REL_ARM64_SECREL_LOW12A   0x0009
+#define IMAGE_REL_ARM64_SECREL_HIGH12A  0x000A
+#define IMAGE_REL_ARM64_SECREL_LOW12L   0x000B
+#define IMAGE_REL_ARM64_TOKEN           0x000C
+#define IMAGE_REL_ARM64_SECTION         0x000D
+#define IMAGE_REL_ARM64_ADDR64          0x000E
+
+/* AMD64 relocation types */
+#define IMAGE_REL_AMD64_ABSOLUTE        0x0000
+#define IMAGE_REL_AMD64_ADDR64          0x0001
+#define IMAGE_REL_AMD64_ADDR32          0x0002
+#define IMAGE_REL_AMD64_ADDR32NB        0x0003
+#define IMAGE_REL_AMD64_REL32           0x0004
+#define IMAGE_REL_AMD64_REL32_1         0x0005
+#define IMAGE_REL_AMD64_REL32_2         0x0006
+#define IMAGE_REL_AMD64_REL32_3         0x0007
+#define IMAGE_REL_AMD64_REL32_4         0x0008
+#define IMAGE_REL_AMD64_REL32_5         0x0009
+#define IMAGE_REL_AMD64_SECTION         0x000A
+#define IMAGE_REL_AMD64_SECREL          0x000B
+#define IMAGE_REL_AMD64_SECREL7         0x000C
+#define IMAGE_REL_AMD64_TOKEN           0x000D
+#define IMAGE_REL_AMD64_SREL32          0x000E
+#define IMAGE_REL_AMD64_PAIR            0x000F
+#define IMAGE_REL_AMD64_SSPAN32         0x0010
+
+#endif /* _PE_H */
diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
new file mode 100644
index 0000000..d558f5a
--- /dev/null
+++ b/lib/efi_loader/efi_image_loader.c
@@ -0,0 +1,188 @@
+/*
+ *  EFI image loader
+ *
+ *  based partly on wine code
+ *
+ *  Copyright (c) 2016 Alexander Graf
+ *
+ *  SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <efi_loader.h>
+#include <pe.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+const efi_guid_t efi_guid_device_path = DEVICE_PATH_GUID;
+const efi_guid_t efi_guid_loaded_image = LOADED_IMAGE_GUID;
+
+efi_status_t EFIAPI efi_return_handle(void *handle, efi_guid_t *protocol,
+			void **protocol_interface, void *agent_handle,
+			void *controller_handle, uint32_t attributes)
+{
+	EFI_ENTRY("%p, %p, %p, %p, %p, 0x%x", handle, protocol,
+		  protocol_interface, agent_handle, controller_handle,
+		  attributes);
+	*protocol_interface = handle;
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static void efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel,
+			unsigned long rel_size, void *efi_reloc)
+{
+	const IMAGE_BASE_RELOCATION *end;
+	int i;
+
+	end = (const IMAGE_BASE_RELOCATION *)((const char *)rel + rel_size);
+	while (rel < end - 1 && rel->SizeOfBlock) {
+		const uint16_t *relocs = (const uint16_t *)(rel + 1);
+		i = (rel->SizeOfBlock - sizeof(*rel)) / sizeof(uint16_t);
+		while (i--) {
+			uint16_t offset = (*relocs & 0xfff) +
+					  rel->VirtualAddress;
+			int type = *relocs >> EFI_PAGE_SHIFT;
+			unsigned long delta = (unsigned long)efi_reloc;
+			uint64_t *x64 = efi_reloc + offset;
+			uint32_t *x32 = efi_reloc + offset;
+			uint16_t *x16 = efi_reloc + offset;
+
+			switch (type) {
+			case IMAGE_REL_BASED_ABSOLUTE:
+				break;
+			case IMAGE_REL_BASED_HIGH:
+				*x16 += ((uint32_t)delta) >> 16;
+				break;
+			case IMAGE_REL_BASED_LOW:
+				*x16 += (uint16_t)delta;
+				break;
+			case IMAGE_REL_BASED_HIGHLOW:
+				*x32 += (uint32_t)delta;
+				break;
+			case IMAGE_REL_BASED_DIR64:
+				*x64 += (uint64_t)delta;
+				break;
+			default:
+				printf("Unknown Relocation off %x type %x\n",
+				       offset, type);
+			}
+			relocs++;
+		}
+		rel = (const IMAGE_BASE_RELOCATION *)relocs;
+	}
+}
+
+void __weak invalidate_icache_all(void)
+{
+	/* If the system doesn't support icache_all flush, cross our fingers */
+}
+
+/*
+ * This function loads all sections from a PE binary into a newly reserved
+ * piece of memory. On successful load it then returns the entry point for
+ * the binary. Otherwise NULL.
+ */
+void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info)
+{
+	IMAGE_NT_HEADERS32 *nt;
+	IMAGE_DOS_HEADER *dos;
+	IMAGE_SECTION_HEADER *sections;
+	int num_sections;
+	void *efi_reloc;
+	int i;
+	const IMAGE_BASE_RELOCATION *rel;
+	unsigned long rel_size;
+	int rel_idx = IMAGE_DIRECTORY_ENTRY_BASERELOC;
+	void *entry;
+	uint64_t image_size;
+	unsigned long virt_size = 0;
+	bool can_run_nt64 = true;
+	bool can_run_nt32 = true;
+
+#if defined(CONFIG_ARM64)
+	can_run_nt32 = false;
+#elif defined(CONFIG_ARM)
+	can_run_nt64 = false;
+#endif
+
+	dos = efi;
+	if (dos->e_magic != IMAGE_DOS_SIGNATURE) {
+		printf("%s: Invalid DOS Signature\n", __func__);
+		return NULL;
+	}
+
+	nt = (void *) ((char *)efi + dos->e_lfanew);
+	if (nt->Signature != IMAGE_NT_SIGNATURE) {
+		printf("%s: Invalid NT Signature\n", __func__);
+		return NULL;
+	}
+
+	/* Calculate upper virtual address boundary */
+	num_sections = nt->FileHeader.NumberOfSections;
+	sections = (void *)&nt->OptionalHeader +
+			    nt->FileHeader.SizeOfOptionalHeader;
+
+	for (i = num_sections - 1; i >= 0; i--) {
+		IMAGE_SECTION_HEADER *sec = &sections[i];
+		virt_size = max_t(unsigned long, virt_size,
+				  sec->VirtualAddress + sec->Misc.VirtualSize);
+	}
+
+	/* Read 32/64bit specific header bits */
+	if (can_run_nt64 &&
+	    (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)) {
+		IMAGE_NT_HEADERS64 *nt64 = (void *)nt;
+		IMAGE_OPTIONAL_HEADER64 *opt = &nt64->OptionalHeader;
+		image_size = opt->SizeOfImage;
+		efi_reloc = efi_alloc(virt_size, EFI_LOADER_DATA);
+		if (!efi_reloc) {
+			printf("%s: Could not allocate %ld bytes\n",
+				__func__, virt_size);
+			return NULL;
+		}
+		entry = efi_reloc + opt->AddressOfEntryPoint;
+		rel_size = opt->DataDirectory[rel_idx].Size;
+		rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress;
+	} else if (can_run_nt32 &&
+		   (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)) {
+		IMAGE_OPTIONAL_HEADER32 *opt = &nt->OptionalHeader;
+		image_size = opt->SizeOfImage;
+		efi_reloc = efi_alloc(virt_size, EFI_LOADER_DATA);
+		if (!efi_reloc) {
+			printf("%s: Could not allocate %ld bytes\n",
+				__func__, virt_size);
+			return NULL;
+		}
+		entry = efi_reloc + opt->AddressOfEntryPoint;
+		rel_size = opt->DataDirectory[rel_idx].Size;
+		rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress;
+	} else {
+		printf("%s: Invalid optional header magic %x\n", __func__,
+		       nt->OptionalHeader.Magic);
+		return NULL;
+	}
+
+	/* Load sections into RAM */
+	for (i = num_sections - 1; i >= 0; i--) {
+		IMAGE_SECTION_HEADER *sec = &sections[i];
+		memset(efi_reloc + sec->VirtualAddress, 0,
+		       sec->Misc.VirtualSize);
+		memcpy(efi_reloc + sec->VirtualAddress,
+		       efi + sec->PointerToRawData,
+		       sec->SizeOfRawData);
+	}
+
+	/* Run through relocations */
+	efi_loader_relocate(rel, rel_size, efi_reloc);
+
+	/* Flush cache */
+	flush_cache((ulong)efi_reloc, virt_size);
+	invalidate_icache_all();
+
+	/* Populate the loaded image interface bits */
+	loaded_image_info->image_base = efi;
+	loaded_image_info->image_size = image_size;
+
+	return entry;
+}
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 15/30] efi_loader: Add boot time services
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (13 preceding siblings ...)
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 14/30] efi_loader: Add PE image loader Alexander Graf
@ 2016-03-04  0:09 ` Alexander Graf
  2016-03-17  2:01   ` [U-Boot] [U-Boot,v5,15/30] " Tom Rini
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 16/30] efi_loader: Add console interface Alexander Graf
                   ` (15 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:09 UTC (permalink / raw)
  To: u-boot

When an EFI application runs, it has access to a few descriptor and callback
tables to instruct the EFI compliant firmware to do things for it. The bulk
of those interfaces are "boot time services". They handle all object management,
and memory allocation.

This patch adds support for the boot time services and also exposes a system
table, which is the point of entry descriptor table for EFI payloads.

Signed-off-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
Tested-by: Simon Glass <sjg@chromium.org>

---

v1 -> v2:

  - Fix typo s/does now/does not/
  - Add #ifdefs around header to allow inclusion when efi_loader is disabled
  - Add stub efi_restore_gd() function when efi_loader is disabled
  - Disable debug
  - Mark runtime region as such
  - Fix up memory map
  - Allow efi_restore_gd to be called before first efi entry
  - Add 32bit arm cache workaround
  - Move memory map to separate patch
  - Change BTS version to 2.5
  - Fix return values for a few callbacks to more EFI compliant ones
  - Change vendor to "Das U-Boot"
  - Add warning when truncating timer trigger
  - Move to GPLv2+

v2 -> v3:

  - Use external efi_memory helpers
  - Add EFIAPI to function prototypes
  - Initialize event timer to -1ULL to prevent early firing
  - Document header
  - Move obj list to lib
  - Remove implicit guid table
  - Add guid compare function
  - Fix return values
  - Implement efi_wait_for_event
  - Implement efi_install_configuration_table

v3 -> v4:

  - s/polimorphic/polymorphic
---
 include/efi_loader.h          |  84 +++++
 lib/efi_loader/efi_boottime.c | 781 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 865 insertions(+)
 create mode 100644 lib/efi_loader/efi_boottime.c

diff --git a/include/efi_loader.h b/include/efi_loader.h
index 5618185..d63fa3a 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -6,15 +6,99 @@
  *  SPDX-License-Identifier:     GPL-2.0+
  */
 
+#include <common.h>
 #include <part_efi.h>
 #include <efi_api.h>
+
+#ifdef CONFIG_EFI_LOADER
+
 #include <linux/list.h>
 
+/* #define DEBUG_EFI */
+
+#ifdef DEBUG_EFI
+#define EFI_ENTRY(format, ...) do { \
+	efi_restore_gd(); \
+	printf("EFI: Entry %s(" format ")\n", __func__, ##__VA_ARGS__); \
+	} while(0)
+#else
+#define EFI_ENTRY(format, ...) do { \
+	efi_restore_gd(); \
+	} while(0)
+#endif
+
+#define EFI_EXIT(ret) efi_exit_func(ret);
+
+extern struct efi_system_table systab;
+
 extern const efi_guid_t efi_guid_device_path;
 extern const efi_guid_t efi_guid_loaded_image;
 
+/*
+ * While UEFI objects can have callbacks, you can also call functions on
+ * protocols (classes) themselves. This struct maps a protocol GUID to its
+ * interface (usually a struct with callback functions).
+ */
+struct efi_class_map {
+	const efi_guid_t *guid;
+	const void *interface;
+};
+
+/*
+ * When the UEFI payload wants to open a protocol on an object to get its
+ * interface (usually a struct with callback functions), this struct maps the
+ * protocol GUID to the respective protocol handler open function for that
+ * object protocol combination.
+ */
+struct efi_handler {
+	const efi_guid_t *guid;
+	efi_status_t (EFIAPI *open)(void *handle,
+			efi_guid_t *protocol, void **protocol_interface,
+			void *agent_handle, void *controller_handle,
+			uint32_t attributes);
+};
+
+/*
+ * UEFI has a poor man's OO model where one "object" can be polymorphic and have
+ * multiple different protocols (classes) attached to it.
+ *
+ * This struct is the parent struct for all of our actual implementation objects
+ * that can include it to make themselves an EFI object
+ */
+struct efi_object {
+	/* Every UEFI object is part of a global object list */
+	struct list_head link;
+	/* We support up to 4 "protocols" an object can be accessed through */
+	struct efi_handler protocols[4];
+	/* The object spawner can either use this for data or as identifier */
+	void *handle;
+};
+
+/* This list contains all UEFI objects we know of */
+extern struct list_head efi_obj_list;
+
+/*
+ * Stub implementation for a protocol opener that just returns the handle as
+ * interface
+ */
 efi_status_t efi_return_handle(void *handle,
 		efi_guid_t *protocol, void **protocol_interface,
 		void *agent_handle, void *controller_handle,
 		uint32_t attributes);
+/* Called from places to check whether a timer expired */
+void efi_timer_check(void);
+/* PE loader implementation */
 void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info);
+/* Called once to store the pristine gd pointer */
+void efi_save_gd(void);
+/* Called from EFI_ENTRY on callback entry to put gd into the gd register */
+void efi_restore_gd(void);
+/* Called from EFI_EXIT on callback exit to restore the gd register */
+efi_status_t efi_exit_func(efi_status_t ret);
+
+#else /* defined(EFI_LOADER) */
+
+/* No loader configured, stub out EFI_ENTRY */
+static inline void efi_restore_gd(void) { }
+
+#endif
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
new file mode 100644
index 0000000..e60fae9
--- /dev/null
+++ b/lib/efi_loader/efi_boottime.c
@@ -0,0 +1,781 @@
+/*
+ *  EFI application boot time services
+ *
+ *  Copyright (c) 2016 Alexander Graf
+ *
+ *  SPDX-License-Identifier:     GPL-2.0+
+ */
+
+/* #define DEBUG_EFI */
+
+#include <common.h>
+#include <efi_loader.h>
+#include <malloc.h>
+#include <asm/global_data.h>
+#include <libfdt_env.h>
+#include <u-boot/crc.h>
+#include <bootm.h>
+#include <inttypes.h>
+#include <watchdog.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* This list contains all the EFI objects our payload has access to */
+LIST_HEAD(efi_obj_list);
+
+/*
+ * If we're running on nasty systems (32bit ARM booting into non-EFI Linux)
+ * we need to do trickery with caches. Since we don't want to break the EFI
+ * aware boot path, only apply hacks when loading exiting directly (breaking
+ * direct Linux EFI booting along the way - oh well).
+ */
+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_conf_table[1];
+
+/*
+ * The "gd" pointer lives in a register on ARM and AArch64 that we declare
+ * fixed when compiling U-Boot. However, the payload does not know about that
+ * restriction so we need to manually swap its and our view of that register on
+ * EFI callback entry/exit.
+ */
+static volatile void *efi_gd, *app_gd;
+
+/* Called from do_bootefi_exec() */
+void efi_save_gd(void)
+{
+	efi_gd = gd;
+}
+
+/* Called on every callback entry */
+void efi_restore_gd(void)
+{
+	/* Only restore if we're already in EFI context */
+	if (!efi_gd)
+		return;
+
+	if (gd != efi_gd)
+		app_gd = gd;
+	gd = efi_gd;
+}
+
+/* Called on every callback exit */
+efi_status_t efi_exit_func(efi_status_t ret)
+{
+	gd = app_gd;
+	return ret;
+}
+
+static efi_status_t efi_unsupported(const char *funcname)
+{
+#ifdef DEBUG_EFI
+	printf("EFI: App called into unimplemented function %s\n", funcname);
+#endif
+	return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static int guidcmp(const efi_guid_t *g1, const efi_guid_t *g2)
+{
+	return memcmp(g1, g2, sizeof(efi_guid_t));
+}
+
+static unsigned long EFIAPI efi_raise_tpl(unsigned long new_tpl)
+{
+	EFI_ENTRY("0x%lx", new_tpl);
+	return EFI_EXIT(0);
+}
+
+static void EFIAPI efi_restore_tpl(unsigned long old_tpl)
+{
+	EFI_ENTRY("0x%lx", old_tpl);
+	EFI_EXIT(efi_unsupported(__func__));
+}
+
+efi_status_t EFIAPI efi_allocate_pages_ext(int type, int memory_type,
+					   unsigned long pages,
+					   uint64_t *memory)
+{
+	efi_status_t r;
+
+	EFI_ENTRY("%d, %d, 0x%lx, %p", type, memory_type, pages, memory);
+	r = efi_allocate_pages(type, memory_type, pages, memory);
+	return EFI_EXIT(r);
+}
+
+efi_status_t EFIAPI efi_free_pages_ext(uint64_t memory, unsigned long pages)
+{
+	efi_status_t r;
+
+	EFI_ENTRY("%"PRIx64", 0x%lx", memory, pages);
+	r = efi_free_pages(memory, pages);
+	return EFI_EXIT(r);
+}
+
+efi_status_t EFIAPI efi_get_memory_map_ext(unsigned long *memory_map_size,
+					   struct efi_mem_desc *memory_map,
+					   unsigned long *map_key,
+					   unsigned long *descriptor_size,
+					   uint32_t *descriptor_version)
+{
+	efi_status_t r;
+
+	EFI_ENTRY("%p, %p, %p, %p, %p", memory_map_size, memory_map,
+		  map_key, descriptor_size, descriptor_version);
+	r = efi_get_memory_map(memory_map_size, memory_map, map_key,
+			       descriptor_size, descriptor_version);
+	return EFI_EXIT(r);
+}
+
+static efi_status_t EFIAPI efi_allocate_pool(int pool_type, unsigned long size,
+					     void **buffer)
+{
+	return efi_allocate_pages(0, pool_type, (size + 0xfff) >> 12, (void*)buffer);
+}
+
+static efi_status_t EFIAPI efi_free_pool(void *buffer)
+{
+	return efi_free_pages((ulong)buffer, 0);
+}
+
+/*
+ * Our event capabilities are very limited. Only support a single
+ * event to exist, so we don't need to maintain lists.
+ */
+static struct {
+	enum efi_event_type type;
+	u32 trigger_type;
+	u32 trigger_time;
+	u64 trigger_next;
+	unsigned long notify_tpl;
+	void (*notify_function) (void *event, void *context);
+	void *notify_context;
+} efi_event = {
+	/* Disable timers on bootup */
+	.trigger_next = -1ULL,
+};
+
+static efi_status_t EFIAPI efi_create_event(
+			enum efi_event_type type, ulong notify_tpl,
+			void (*notify_function) (void *event, void *context),
+			void *notify_context, void **event)
+{
+	EFI_ENTRY("%d, 0x%lx, %p, %p", type, notify_tpl, notify_function,
+		  notify_context);
+	if (efi_event.notify_function) {
+		/* We only support one event at a time */
+		return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+	}
+
+	efi_event.type = type;
+	efi_event.notify_tpl = notify_tpl;
+	efi_event.notify_function = notify_function;
+	efi_event.notify_context = notify_context;
+	*event = &efi_event;
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+/*
+ * Our timers have to work without interrupts, so we check whenever keyboard
+ * input or disk accesses happen if enough time elapsed for it to fire.
+ */
+void efi_timer_check(void)
+{
+	u64 now = timer_get_us();
+
+	if (now >= efi_event.trigger_next) {
+		/* Triggering! */
+		if (efi_event.trigger_type == EFI_TIMER_PERIODIC)
+			efi_event.trigger_next += efi_event.trigger_time / 10;
+		efi_event.notify_function(&efi_event, efi_event.notify_context);
+	}
+
+	WATCHDOG_RESET();
+}
+
+static efi_status_t EFIAPI efi_set_timer(void *event, int type,
+					 uint64_t trigger_time)
+{
+	/* We don't have 64bit division available everywhere, so limit timer
+	 * distances to 32bit bits. */
+	u32 trigger32 = trigger_time;
+
+	EFI_ENTRY("%p, %d, %"PRIx64, event, type, trigger_time);
+
+	if (trigger32 < trigger_time) {
+		printf("WARNING: Truncating timer from %"PRIx64" to %x\n",
+		       trigger_time, trigger32);
+	}
+
+	if (event != &efi_event) {
+		/* We only support one event@a time */
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+	}
+
+	switch (type) {
+	case EFI_TIMER_STOP:
+		efi_event.trigger_next = -1ULL;
+		break;
+	case EFI_TIMER_PERIODIC:
+	case EFI_TIMER_RELATIVE:
+		efi_event.trigger_next = timer_get_us() + (trigger32 / 10);
+		break;
+	default:
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+	}
+	efi_event.trigger_type = type;
+	efi_event.trigger_time = trigger_time;
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_wait_for_event(unsigned long num_events,
+					      void *event, unsigned long *index)
+{
+	u64 now;
+
+	EFI_ENTRY("%ld, %p, %p", num_events, event, index);
+
+	now = timer_get_us();
+	while (now < efi_event.trigger_next) { }
+	efi_timer_check();
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_signal_event(void *event)
+{
+	EFI_ENTRY("%p", event);
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_close_event(void *event)
+{
+	EFI_ENTRY("%p", event);
+	efi_event.trigger_next = -1ULL;
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_check_event(void *event)
+{
+	EFI_ENTRY("%p", event);
+	return EFI_EXIT(EFI_NOT_READY);
+}
+
+static efi_status_t EFIAPI efi_install_protocol_interface(void **handle,
+			efi_guid_t *protocol, int protocol_interface_type,
+			void *protocol_interface)
+{
+	EFI_ENTRY("%p, %p, %d, %p", handle, protocol, protocol_interface_type,
+		  protocol_interface);
+	return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+}
+static efi_status_t EFIAPI efi_reinstall_protocol_interface(void *handle,
+			efi_guid_t *protocol, void *old_interface,
+			void *new_interface)
+{
+	EFI_ENTRY("%p, %p, %p, %p", handle, protocol, old_interface,
+		  new_interface);
+	return EFI_EXIT(EFI_ACCESS_DENIED);
+}
+
+static efi_status_t EFIAPI efi_uninstall_protocol_interface(void *handle,
+			efi_guid_t *protocol, void *protocol_interface)
+{
+	EFI_ENTRY("%p, %p, %p", handle, protocol, protocol_interface);
+	return EFI_EXIT(EFI_NOT_FOUND);
+}
+
+static efi_status_t EFIAPI efi_register_protocol_notify(efi_guid_t *protocol,
+							void *event,
+							void **registration)
+{
+	EFI_ENTRY("%p, %p, %p", protocol, event, registration);
+	return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+}
+
+static int efi_search(enum efi_locate_search_type search_type,
+		      efi_guid_t *protocol, void *search_key,
+		      struct efi_object *efiobj)
+{
+	int i;
+
+	switch (search_type) {
+	case all_handles:
+		return 0;
+	case by_register_notify:
+		return -1;
+	case by_protocol:
+		for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) {
+			const efi_guid_t *guid = efiobj->protocols[i].guid;
+			if (guid && !guidcmp(guid, protocol))
+				return 0;
+		}
+		return -1;
+	}
+
+	return -1;
+}
+
+static efi_status_t EFIAPI efi_locate_handle(
+			enum efi_locate_search_type search_type,
+			efi_guid_t *protocol, void *search_key,
+			unsigned long *buffer_size, efi_handle_t *buffer)
+{
+	struct list_head *lhandle;
+	unsigned long size = 0;
+
+	EFI_ENTRY("%d, %p, %p, %p, %p", search_type, protocol, search_key,
+		  buffer_size, buffer);
+
+	/* Count how much space we need */
+	list_for_each(lhandle, &efi_obj_list) {
+		struct efi_object *efiobj;
+		efiobj = list_entry(lhandle, struct efi_object, link);
+		if (!efi_search(search_type, protocol, search_key, efiobj)) {
+			size += sizeof(void*);
+		}
+	}
+
+	if (*buffer_size < size) {
+		*buffer_size = size;
+		return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
+	}
+
+	/* Then fill the array */
+	list_for_each(lhandle, &efi_obj_list) {
+		struct efi_object *efiobj;
+		efiobj = list_entry(lhandle, struct efi_object, link);
+		if (!efi_search(search_type, protocol, search_key, efiobj)) {
+			*(buffer++) = efiobj->handle;
+		}
+	}
+
+	*buffer_size = size;
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_locate_device_path(efi_guid_t *protocol,
+			struct efi_device_path **device_path,
+			efi_handle_t *device)
+{
+	EFI_ENTRY("%p, %p, %p", protocol, device_path, device);
+	return EFI_EXIT(EFI_NOT_FOUND);
+}
+
+static efi_status_t EFIAPI efi_install_configuration_table(efi_guid_t *guid,
+							   void *table)
+{
+	int i;
+
+	EFI_ENTRY("%p, %p", guid, table);
+
+	/* Check for guid override */
+	for (i = 0; i < systab.nr_tables; i++) {
+		if (!guidcmp(guid, &efi_conf_table[i].guid)) {
+			efi_conf_table[i].table = table;
+			return EFI_EXIT(EFI_SUCCESS);
+		}
+	}
+
+	/* No override, check for overflow */
+	if (i >= ARRAY_SIZE(efi_conf_table))
+		return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+
+	/* Add a new entry */
+	memcpy(&efi_conf_table[i].guid, guid, sizeof(*guid));
+	efi_conf_table[i].table = table;
+	systab.nr_tables = i;
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_load_image(bool boot_policy,
+					  efi_handle_t parent_image,
+					  struct efi_device_path *file_path,
+					  void *source_buffer,
+					  unsigned long source_size,
+					  efi_handle_t *image_handle)
+{
+	static struct efi_object loaded_image_info_obj = {
+		.protocols = {
+			{
+				.guid = &efi_guid_loaded_image,
+				.open = &efi_return_handle,
+			},
+		},
+	};
+	struct efi_loaded_image *info;
+	struct efi_object *obj;
+
+	EFI_ENTRY("%d, %p, %p, %p, %ld, %p", boot_policy, parent_image,
+		  file_path, source_buffer, source_size, image_handle);
+	info = malloc(sizeof(*info));
+	obj = malloc(sizeof(loaded_image_info_obj));
+	memset(info, 0, sizeof(*info));
+	memcpy(obj, &loaded_image_info_obj, sizeof(loaded_image_info_obj));
+	obj->handle = info;
+	info->file_path = file_path;
+	info->reserved = efi_load_pe(source_buffer, info);
+	if (!info->reserved) {
+		free(info);
+		free(obj);
+		return EFI_EXIT(EFI_UNSUPPORTED);
+	}
+
+	*image_handle = info;
+	list_add_tail(&obj->link, &efi_obj_list);
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
+					   unsigned long *exit_data_size,
+					   s16 **exit_data)
+{
+	ulong (*entry)(void *image_handle, struct efi_system_table *st);
+	struct efi_loaded_image *info = image_handle;
+
+	EFI_ENTRY("%p, %p, %p", image_handle, exit_data_size, exit_data);
+	entry = info->reserved;
+
+	efi_is_direct_boot = false;
+
+	/* call the image! */
+	entry(image_handle, &systab);
+
+	/* Should usually never get here */
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_exit(void *image_handle, long exit_status,
+				    unsigned long exit_data_size,
+				    uint16_t *exit_data)
+{
+	EFI_ENTRY("%p, %ld, %ld, %p", image_handle, exit_status,
+		  exit_data_size, exit_data);
+	return EFI_EXIT(efi_unsupported(__func__));
+}
+
+static struct efi_object *efi_search_obj(void *handle)
+{
+	struct list_head *lhandle;
+
+	list_for_each(lhandle, &efi_obj_list) {
+		struct efi_object *efiobj;
+		efiobj = list_entry(lhandle, struct efi_object, link);
+		if (efiobj->handle == handle)
+			return efiobj;
+	}
+
+	return NULL;
+}
+
+static efi_status_t EFIAPI efi_unload_image(void *image_handle)
+{
+	struct efi_object *efiobj;
+
+	EFI_ENTRY("%p", image_handle);
+	efiobj = efi_search_obj(image_handle);
+	if (efiobj)
+		list_del(&efiobj->link);
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static void efi_exit_caches(void)
+{
+#if defined(CONFIG_ARM) && !defined(CONFIG_ARM64)
+	/*
+	 * Grub on 32bit ARM needs to have caches disabled before jumping into
+	 * a zImage, but does not know of all cache layers. Give it a hand.
+	 */
+	if (efi_is_direct_boot)
+		cleanup_before_linux();
+#endif
+}
+
+static efi_status_t EFIAPI efi_exit_boot_services(void *image_handle,
+						  unsigned long map_key)
+{
+	EFI_ENTRY("%p, %ld", image_handle, map_key);
+
+	/* Fix up caches for EFI payloads if necessary */
+	efi_exit_caches();
+
+	/* This stops all lingering devices */
+	bootm_disable_interrupts();
+
+	/* Give the payload some time to boot */
+	WATCHDOG_RESET();
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_get_next_monotonic_count(uint64_t *count)
+{
+	static uint64_t mono = 0;
+	EFI_ENTRY("%p", count);
+	*count = mono++;
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_stall(unsigned long microseconds)
+{
+	EFI_ENTRY("%ld", microseconds);
+	udelay(microseconds);
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_set_watchdog_timer(unsigned long timeout,
+						  uint64_t watchdog_code,
+						  unsigned long data_size,
+						  uint16_t *watchdog_data)
+{
+	EFI_ENTRY("%ld, 0x%"PRIx64", %ld, %p", timeout, watchdog_code,
+		  data_size, watchdog_data);
+	return EFI_EXIT(efi_unsupported(__func__));
+}
+
+static efi_status_t EFIAPI efi_connect_controller(
+			efi_handle_t controller_handle,
+			efi_handle_t *driver_image_handle,
+			struct efi_device_path *remain_device_path,
+			bool recursive)
+{
+	EFI_ENTRY("%p, %p, %p, %d", controller_handle, driver_image_handle,
+		  remain_device_path, recursive);
+	return EFI_EXIT(EFI_NOT_FOUND);
+}
+
+static efi_status_t EFIAPI efi_disconnect_controller(void *controller_handle,
+						     void *driver_image_handle,
+						     void *child_handle)
+{
+	EFI_ENTRY("%p, %p, %p", controller_handle, driver_image_handle,
+		  child_handle);
+	return EFI_EXIT(EFI_INVALID_PARAMETER);
+}
+
+static efi_status_t EFIAPI efi_close_protocol(void *handle,
+					      efi_guid_t *protocol,
+					      void *agent_handle,
+					      void *controller_handle)
+{
+	EFI_ENTRY("%p, %p, %p, %p", handle, protocol, agent_handle,
+		  controller_handle);
+	return EFI_EXIT(EFI_NOT_FOUND);
+}
+
+static efi_status_t EFIAPI efi_open_protocol_information(efi_handle_t handle,
+			efi_guid_t *protocol,
+			struct efi_open_protocol_info_entry **entry_buffer,
+			unsigned long *entry_count)
+{
+	EFI_ENTRY("%p, %p, %p, %p", handle, protocol, entry_buffer,
+		  entry_count);
+	return EFI_EXIT(EFI_NOT_FOUND);
+}
+
+static efi_status_t EFIAPI efi_protocols_per_handle(void *handle,
+			efi_guid_t ***protocol_buffer,
+			unsigned long *protocol_buffer_count)
+{
+	EFI_ENTRY("%p, %p, %p", handle, protocol_buffer,
+		  protocol_buffer_count);
+	return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+}
+
+static efi_status_t EFIAPI efi_locate_handle_buffer(
+			enum efi_locate_search_type search_type,
+			efi_guid_t *protocol, void *search_key,
+			unsigned long *no_handles, efi_handle_t **buffer)
+{
+	EFI_ENTRY("%d, %p, %p, %p, %p", search_type, protocol, search_key,
+		  no_handles, buffer);
+	return EFI_EXIT(EFI_NOT_FOUND);
+}
+
+static struct efi_class_map efi_class_maps[] = {
+	{
+		.guid = &efi_guid_console_control,
+		.interface = &efi_console_control
+	},
+};
+
+static efi_status_t EFIAPI efi_locate_protocol(efi_guid_t *protocol,
+					       void *registration,
+					       void **protocol_interface)
+{
+	int i;
+
+	EFI_ENTRY("%p, %p, %p", protocol, registration, protocol_interface);
+	for (i = 0; i < ARRAY_SIZE(efi_class_maps); i++) {
+		struct efi_class_map *curmap = &efi_class_maps[i];
+		if (!guidcmp(protocol, curmap->guid)) {
+			*protocol_interface = (void*)curmap->interface;
+			return EFI_EXIT(EFI_SUCCESS);
+		}
+	}
+
+	return EFI_EXIT(EFI_NOT_FOUND);
+}
+
+static efi_status_t EFIAPI efi_install_multiple_protocol_interfaces(
+			void **handle, ...)
+{
+	EFI_ENTRY("%p", handle);
+	return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+}
+
+static efi_status_t EFIAPI efi_uninstall_multiple_protocol_interfaces(
+			void *handle, ...)
+{
+	EFI_ENTRY("%p", handle);
+	return EFI_EXIT(EFI_INVALID_PARAMETER);
+}
+
+static efi_status_t EFIAPI efi_calculate_crc32(void *data,
+					       unsigned long data_size,
+					       uint32_t *crc32_p)
+{
+	EFI_ENTRY("%p, %ld", data, data_size);
+	*crc32_p = crc32(0, data, data_size);
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static void EFIAPI efi_copy_mem(void *destination, void *source,
+				unsigned long length)
+{
+	EFI_ENTRY("%p, %p, %ld", destination, source, length);
+	memcpy(destination, source, length);
+}
+
+static void EFIAPI efi_set_mem(void *buffer, unsigned long size, uint8_t value)
+{
+	EFI_ENTRY("%p, %ld, 0x%x", buffer, size, value);
+	memset(buffer, value, size);
+}
+
+static efi_status_t EFIAPI efi_open_protocol(
+			void *handle, efi_guid_t *protocol,
+			void **protocol_interface, void *agent_handle,
+			void *controller_handle, uint32_t attributes)
+{
+	struct list_head *lhandle;
+	int i;
+	efi_status_t r = EFI_UNSUPPORTED;
+
+	EFI_ENTRY("%p, %p, %p, %p, %p, 0x%x", handle, protocol,
+		  protocol_interface, agent_handle, controller_handle,
+		  attributes);
+	list_for_each(lhandle, &efi_obj_list) {
+		struct efi_object *efiobj;
+		efiobj = list_entry(lhandle, struct efi_object, link);
+
+		if (efiobj->handle != handle)
+			continue;
+
+		for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) {
+			struct efi_handler *handler = &efiobj->protocols[i];
+			const efi_guid_t *hprotocol = handler->guid;
+			if (!hprotocol)
+				break;
+			if (!guidcmp(hprotocol, protocol)) {
+				r = handler->open(handle, protocol,
+				    protocol_interface, agent_handle,
+				    controller_handle, attributes);
+				goto out;
+			}
+		}
+	}
+
+out:
+	return EFI_EXIT(r);
+}
+
+static efi_status_t EFIAPI efi_handle_protocol(void *handle,
+					       efi_guid_t *protocol,
+					       void **protocol_interface)
+{
+	EFI_ENTRY("%p, %p, %p", handle, protocol, protocol_interface);
+	return efi_open_protocol(handle, protocol, protocol_interface,
+				 NULL, NULL, 0);
+}
+
+static const struct efi_boot_services efi_boot_services = {
+	.hdr = {
+		.headersize = sizeof(struct efi_table_hdr),
+	},
+	.raise_tpl = efi_raise_tpl,
+	.restore_tpl = efi_restore_tpl,
+	.allocate_pages = efi_allocate_pages_ext,
+	.free_pages = efi_free_pages_ext,
+	.get_memory_map = efi_get_memory_map_ext,
+	.allocate_pool = efi_allocate_pool,
+	.free_pool = efi_free_pool,
+	.create_event = efi_create_event,
+	.set_timer = efi_set_timer,
+	.wait_for_event = efi_wait_for_event,
+	.signal_event = efi_signal_event,
+	.close_event = efi_close_event,
+	.check_event = efi_check_event,
+	.install_protocol_interface = efi_install_protocol_interface,
+	.reinstall_protocol_interface = efi_reinstall_protocol_interface,
+	.uninstall_protocol_interface = efi_uninstall_protocol_interface,
+	.handle_protocol = efi_handle_protocol,
+	.reserved = NULL,
+	.register_protocol_notify = efi_register_protocol_notify,
+	.locate_handle = efi_locate_handle,
+	.locate_device_path = efi_locate_device_path,
+	.install_configuration_table = efi_install_configuration_table,
+	.load_image = efi_load_image,
+	.start_image = efi_start_image,
+	.exit = (void*)efi_exit,
+	.unload_image = efi_unload_image,
+	.exit_boot_services = efi_exit_boot_services,
+	.get_next_monotonic_count = efi_get_next_monotonic_count,
+	.stall = efi_stall,
+	.set_watchdog_timer = efi_set_watchdog_timer,
+	.connect_controller = efi_connect_controller,
+	.disconnect_controller = efi_disconnect_controller,
+	.open_protocol = efi_open_protocol,
+	.close_protocol = efi_close_protocol,
+	.open_protocol_information = efi_open_protocol_information,
+	.protocols_per_handle = efi_protocols_per_handle,
+	.locate_handle_buffer = efi_locate_handle_buffer,
+	.locate_protocol = efi_locate_protocol,
+	.install_multiple_protocol_interfaces = efi_install_multiple_protocol_interfaces,
+	.uninstall_multiple_protocol_interfaces = efi_uninstall_multiple_protocol_interfaces,
+	.calculate_crc32 = efi_calculate_crc32,
+	.copy_mem = efi_copy_mem,
+	.set_mem = efi_set_mem,
+};
+
+
+static uint16_t firmware_vendor[] =
+	{ 'D','a','s',' ','U','-','b','o','o','t',0 };
+
+struct efi_system_table systab = {
+	.hdr = {
+		.signature = EFI_SYSTEM_TABLE_SIGNATURE,
+		.revision = 0x20005, /* 2.5 */
+		.headersize = sizeof(struct efi_table_hdr),
+	},
+	.fw_vendor = (long)firmware_vendor,
+	.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,
+};
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 16/30] efi_loader: Add console interface
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (14 preceding siblings ...)
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 15/30] efi_loader: Add boot time services Alexander Graf
@ 2016-03-04  0:10 ` Alexander Graf
  2016-03-17  2:01   ` [U-Boot] [U-Boot,v5,16/30] " Tom Rini
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 17/30] efi_loader: Add runtime services Alexander Graf
                   ` (14 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:10 UTC (permalink / raw)
  To: u-boot

One of the basic EFI interfaces is the console interface. Using it an EFI
application can interface with the user. This patch implements an EFI console
interface using getc() and putc().

Today, we only implement text based consoles. We also convert the EFI Unicode
characters to UTF-8 on the fly, hoping that everyone managed to jump on the
train by now.

Signed-off-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
Tested-by: Simon Glass <sjg@chromium.org>

---

v1 -> v2:

  - Move to GPLv2+

v2 -> v3:

  - Add EFIAPI to function prototypes

v3 -> v4:

  - return EFI_SUCCESS in efi_cout_enable_cursor()
---
 include/efi_loader.h         |   5 +
 lib/efi_loader/efi_console.c | 360 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 365 insertions(+)
 create mode 100644 lib/efi_loader/efi_console.c

diff --git a/include/efi_loader.h b/include/efi_loader.h
index d63fa3a..b4e82ac 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -31,6 +31,11 @@
 
 extern struct efi_system_table systab;
 
+extern const struct efi_simple_text_output_protocol efi_con_out;
+extern const struct efi_simple_input_interface efi_con_in;
+extern const struct efi_console_control_protocol efi_console_control;
+
+extern const efi_guid_t efi_guid_console_control;
 extern const efi_guid_t efi_guid_device_path;
 extern const efi_guid_t efi_guid_loaded_image;
 
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c
new file mode 100644
index 0000000..2e0228c
--- /dev/null
+++ b/lib/efi_loader/efi_console.c
@@ -0,0 +1,360 @@
+/*
+ *  EFI application console interface
+ *
+ *  Copyright (c) 2016 Alexander Graf
+ *
+ *  SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <efi_loader.h>
+
+/* If we can't determine the console size, default to 80x24 */
+static int console_columns = 80;
+static int console_rows = 24;
+static bool console_size_queried;
+
+const efi_guid_t efi_guid_console_control = CONSOLE_CONTROL_GUID;
+
+#define cESC '\x1b'
+#define ESC "\x1b"
+
+static efi_status_t EFIAPI efi_cin_get_mode(
+			struct efi_console_control_protocol *this,
+			int *mode, char *uga_exists, char *std_in_locked)
+{
+	EFI_ENTRY("%p, %p, %p, %p", this, mode, uga_exists, std_in_locked);
+
+	if (mode)
+		*mode = EFI_CONSOLE_MODE_TEXT;
+	if (uga_exists)
+		*uga_exists = 0;
+	if (std_in_locked)
+		*std_in_locked = 0;
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_cin_set_mode(
+			struct efi_console_control_protocol *this, int mode)
+{
+	EFI_ENTRY("%p, %d", this, mode);
+	return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static efi_status_t EFIAPI efi_cin_lock_std_in(
+			struct efi_console_control_protocol *this,
+			uint16_t *password)
+{
+	EFI_ENTRY("%p, %p", this, password);
+	return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+const struct efi_console_control_protocol efi_console_control = {
+	.get_mode = efi_cin_get_mode,
+	.set_mode = efi_cin_set_mode,
+	.lock_std_in = efi_cin_lock_std_in,
+};
+
+static struct simple_text_output_mode efi_con_mode = {
+	.max_mode = 0,
+	.mode = 0,
+	.attribute = 0,
+	.cursor_column = 0,
+	.cursor_row = 0,
+	.cursor_visible = 1,
+};
+
+static int term_read_reply(int *n, int maxnum, char end_char)
+{
+	char c;
+	int i = 0;
+
+	c = getc();
+	if (c != cESC)
+		return -1;
+	c = getc();
+	if (c != '[')
+		return -1;
+
+	n[0] = 0;
+	while (1) {
+		c = getc();
+		if (c == ';') {
+			i++;
+			if (i >= maxnum)
+				return -1;
+			n[i] = 0;
+			continue;
+		} else if (c == end_char) {
+			break;
+		} else if (c > '9' || c < '0') {
+			return -1;
+		}
+
+		/* Read one more decimal position */
+		n[i] *= 10;
+		n[i] += c - '0';
+	}
+
+	return 0;
+}
+
+static efi_status_t EFIAPI efi_cout_reset(
+			struct efi_simple_text_output_protocol *this,
+			char extended_verification)
+{
+	EFI_ENTRY("%p, %d", this, extended_verification);
+	return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static void print_unicode_in_utf8(u16 c)
+{
+	char utf8[4] = { 0 };
+	char *b = utf8;
+
+	if (c < 0x80) {
+		*(b++) = c;
+	} else if (c < 0x800) {
+		*(b++) = 192 + c / 64;
+		*(b++) = 128 + c % 64;
+	} else {
+		*(b++) = 224 + c / 4096;
+		*(b++) = 128 + c / 64 % 64;
+		*(b++) = 128 + c % 64;
+	}
+
+	puts(utf8);
+}
+
+static efi_status_t EFIAPI efi_cout_output_string(
+			struct efi_simple_text_output_protocol *this,
+			const unsigned short *string)
+{
+	u16 ch;
+
+	EFI_ENTRY("%p, %p", this, string);
+	for (;(ch = *string); string++) {
+		print_unicode_in_utf8(ch);
+		efi_con_mode.cursor_column++;
+		if (ch == '\n') {
+			efi_con_mode.cursor_column = 1;
+			efi_con_mode.cursor_row++;
+		} else if (efi_con_mode.cursor_column > console_columns) {
+			efi_con_mode.cursor_column = 1;
+			efi_con_mode.cursor_row++;
+		}
+		if (efi_con_mode.cursor_row > console_rows) {
+			efi_con_mode.cursor_row = console_rows;
+		}
+	}
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_cout_test_string(
+			struct efi_simple_text_output_protocol *this,
+			const unsigned short *string)
+{
+	EFI_ENTRY("%p, %p", this, string);
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_cout_query_mode(
+			struct efi_simple_text_output_protocol *this,
+			unsigned long mode_number, unsigned long *columns,
+			unsigned long *rows)
+{
+	EFI_ENTRY("%p, %ld, %p, %p", this, mode_number, columns, rows);
+
+	if (!console_size_queried) {
+		/* Ask the terminal about its size */
+		int n[3];
+		u64 timeout;
+
+		console_size_queried = true;
+
+		/* Empty input buffer */
+		while (tstc())
+			getc();
+
+		printf(ESC"[18t");
+
+		/* Check if we have a terminal that understands */
+		timeout = timer_get_us() + 1000000;
+		while (!tstc())
+			if (timer_get_us() > timeout)
+				goto out;
+
+		/* Read {depth,rows,cols} */
+		if (term_read_reply(n, 3, 't')) {
+			goto out;
+		}
+
+		console_columns = n[2];
+		console_rows = n[1];
+	}
+
+out:
+	if (columns)
+		*columns = console_columns;
+	if (rows)
+		*rows = console_rows;
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_cout_set_mode(
+			struct efi_simple_text_output_protocol *this,
+			unsigned long mode_number)
+{
+	EFI_ENTRY("%p, %ld", this, mode_number);
+
+	/* We only support text output for now */
+	if (mode_number == EFI_CONSOLE_MODE_TEXT)
+		return EFI_EXIT(EFI_SUCCESS);
+
+	return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static efi_status_t EFIAPI efi_cout_set_attribute(
+			struct efi_simple_text_output_protocol *this,
+			unsigned long attribute)
+{
+	EFI_ENTRY("%p, %lx", this, attribute);
+
+	/* Just ignore attributes (colors) for now */
+	return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static efi_status_t EFIAPI efi_cout_clear_screen(
+			struct efi_simple_text_output_protocol *this)
+{
+	EFI_ENTRY("%p", this);
+
+	printf(ESC"[2J");
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_cout_set_cursor_position(
+			struct efi_simple_text_output_protocol *this,
+			unsigned long column, unsigned long row)
+{
+	EFI_ENTRY("%p, %ld, %ld", this, column, row);
+
+	printf(ESC"[%d;%df", (int)row, (int)column);
+	efi_con_mode.cursor_column = column;
+	efi_con_mode.cursor_row = row;
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_cout_enable_cursor(
+			struct efi_simple_text_output_protocol *this,
+			bool enable)
+{
+	EFI_ENTRY("%p, %d", this, enable);
+
+	printf(ESC"[?25%c", enable ? 'h' : 'l');
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+const struct efi_simple_text_output_protocol efi_con_out = {
+	.reset = efi_cout_reset,
+	.output_string = efi_cout_output_string,
+	.test_string = efi_cout_test_string,
+	.query_mode = efi_cout_query_mode,
+	.set_mode = efi_cout_set_mode,
+	.set_attribute = efi_cout_set_attribute,
+	.clear_screen = efi_cout_clear_screen,
+	.set_cursor_position = efi_cout_set_cursor_position,
+	.enable_cursor = efi_cout_enable_cursor,
+	.mode = (void*)&efi_con_mode,
+};
+
+static efi_status_t EFIAPI efi_cin_reset(
+			struct efi_simple_input_interface *this,
+			bool extended_verification)
+{
+	EFI_ENTRY("%p, %d", this, extended_verification);
+	return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static efi_status_t EFIAPI efi_cin_read_key_stroke(
+			struct efi_simple_input_interface *this,
+			struct efi_input_key *key)
+{
+	struct efi_input_key pressed_key = {
+		.scan_code = 0,
+		.unicode_char = 0,
+	};
+	char ch;
+
+	EFI_ENTRY("%p, %p", this, key);
+
+	/* We don't do interrupts, so check for timers cooperatively */
+	efi_timer_check();
+
+	if (!tstc()) {
+		/* No key pressed */
+		return EFI_EXIT(EFI_NOT_READY);
+	}
+
+	ch = getc();
+	if (ch == cESC) {
+		/* Escape Sequence */
+		ch = getc();
+		switch (ch) {
+		case cESC: /* ESC */
+			pressed_key.scan_code = 23;
+			break;
+		case 'O': /* F1 - F4 */
+			pressed_key.scan_code = getc() - 'P' + 11;
+			break;
+		case 'a'...'z':
+			ch = ch - 'a';
+			break;
+		case '[':
+			ch = getc();
+			switch (ch) {
+			case 'A'...'D': /* up, down right, left */
+				pressed_key.scan_code = ch - 'A' + 1;
+				break;
+			case 'F': /* End */
+				pressed_key.scan_code = 6;
+				break;
+			case 'H': /* Home */
+				pressed_key.scan_code = 5;
+				break;
+			case '1': /* F5 - F8 */
+				pressed_key.scan_code = getc() - '0' + 11;
+				getc();
+				break;
+			case '2': /* F9 - F12 */
+				pressed_key.scan_code = getc() - '0' + 19;
+				getc();
+				break;
+			case '3': /* DEL */
+				pressed_key.scan_code = 8;
+				getc();
+				break;
+			}
+			break;
+		}
+	} else if (ch == 0x7f) {
+		/* Backspace */
+		ch = 0x08;
+	}
+	pressed_key.unicode_char = ch;
+	*key = pressed_key;
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+const struct efi_simple_input_interface efi_con_in = {
+	.reset = efi_cin_reset,
+	.read_key_stroke = efi_cin_read_key_stroke,
+	.wait_for_key = NULL,
+};
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 17/30] efi_loader: Add runtime services
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (15 preceding siblings ...)
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 16/30] efi_loader: Add console interface Alexander Graf
@ 2016-03-04  0:10 ` Alexander Graf
  2016-03-17  2:01   ` [U-Boot] [U-Boot,v5,17/30] " Tom Rini
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 18/30] efi_loader: Add disk interfaces Alexander Graf
                   ` (13 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:10 UTC (permalink / raw)
  To: u-boot

After booting has finished, EFI allows firmware to still interact with the OS
using the "runtime services". These callbacks live in a separate address space,
since they are available long after U-Boot has been overwritten by the OS.

This patch adds enough framework for arbitrary code inside of U-Boot to become
a runtime service with the right section attributes set. For now, we don't make
use of it yet though.

We could maybe in the future map U-boot environment variables to EFI variables
here.

Signed-off-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
Tested-by: Simon Glass <sjg@chromium.org>

---

v1 -> v2:

  - Fix runtime service sections
  - Add runtime detach
  - Enable runtime relocations
  - Add get_time
  - Fix relocation
  - Fix 32bit
  - Add am335x support
  - Move section definition to header
  - Add systab to runtime section
  - Add self-relocation hook table
  - Fix self-relocation
  - Relocate efi_runtime section early during bootup
  - Fix return values for a number of callbacks to be more UEFI compliant
  - Move to GPLv2+

v2 -> v3:

  - Patch reset to NULL
  - Add EFIAPI to function prototypes
  - Document header
  - Add dm.h include
  - Remove non-dm rtc support
  - Return DEVICE_ERROR in rtc path
---
 arch/arm/config.mk            |   4 +
 arch/arm/cpu/armv8/u-boot.lds |  16 +++
 arch/arm/cpu/u-boot.lds       |  30 +++++
 arch/arm/lib/sections.c       |   4 +
 board/ti/am335x/u-boot.lds    |  30 +++++
 common/board_r.c              |   4 +
 include/efi_loader.h          |  17 +++
 lib/efi_loader/efi_boottime.c |   6 +-
 lib/efi_loader/efi_runtime.c  | 290 ++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 398 insertions(+), 3 deletions(-)
 create mode 100644 lib/efi_loader/efi_runtime.c

diff --git a/arch/arm/config.mk b/arch/arm/config.mk
index 8fa57ec..9af6c37 100644
--- a/arch/arm/config.mk
+++ b/arch/arm/config.mk
@@ -122,6 +122,10 @@ ifdef CONFIG_OF_EMBED
 OBJCOPYFLAGS += -j .dtb.init.rodata
 endif
 
+ifdef CONFIG_EFI_LOADER
+OBJCOPYFLAGS += -j .efi_runtime -j .efi_runtime_rel
+endif
+
 ifneq ($(CONFIG_IMX_CONFIG),)
 ifdef CONFIG_SPL
 ifndef CONFIG_SPL_BUILD
diff --git a/arch/arm/cpu/armv8/u-boot.lds b/arch/arm/cpu/armv8/u-boot.lds
index 4c12222..fd15ad5 100644
--- a/arch/arm/cpu/armv8/u-boot.lds
+++ b/arch/arm/cpu/armv8/u-boot.lds
@@ -42,6 +42,22 @@ 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)
+                __efi_runtime_rel_stop = .;
+	}
+
+	. = ALIGN(8);
+
 	.image_copy_end :
 	{
 		*(.__image_copy_end)
diff --git a/arch/arm/cpu/u-boot.lds b/arch/arm/cpu/u-boot.lds
index e148ab7..13aa4fa 100644
--- a/arch/arm/cpu/u-boot.lds
+++ b/arch/arm/cpu/u-boot.lds
@@ -90,6 +90,36 @@ 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)
+	}
+
+	.efi_runtime_rel_stop :
+	{
+		*(.__efi_runtime_rel_stop)
+	}
+
+	. = ALIGN(4);
+
 	.image_copy_end :
 	{
 		*(.__image_copy_end)
diff --git a/arch/arm/lib/sections.c b/arch/arm/lib/sections.c
index a1205c3..6a94522 100644
--- a/arch/arm/lib/sections.c
+++ b/arch/arm/lib/sections.c
@@ -27,4 +27,8 @@ char __rel_dyn_start[0] __attribute__((section(".__rel_dyn_start")));
 char __rel_dyn_end[0] __attribute__((section(".__rel_dyn_end")));
 char __secure_start[0] __attribute__((section(".__secure_start")));
 char __secure_end[0] __attribute__((section(".__secure_end")));
+char __efi_runtime_start[0] __attribute__((section(".__efi_runtime_start")));
+char __efi_runtime_stop[0] __attribute__((section(".__efi_runtime_stop")));
+char __efi_runtime_rel_start[0] __attribute__((section(".__efi_runtime_rel_start")));
+char __efi_runtime_rel_stop[0] __attribute__((section(".__efi_runtime_rel_stop")));
 char _end[0] __attribute__((section(".__end")));
diff --git a/board/ti/am335x/u-boot.lds b/board/ti/am335x/u-boot.lds
index 78f294a..a56cc82 100644
--- a/board/ti/am335x/u-boot.lds
+++ b/board/ti/am335x/u-boot.lds
@@ -59,6 +59,36 @@ 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)
+	}
+
+	.efi_runtime_rel_stop :
+	{
+		*(.__efi_runtime_rel_stop)
+	}
+
+	. = ALIGN(4);
+
 	.image_copy_end :
 	{
 		*(.__image_copy_end)
diff --git a/common/board_r.c b/common/board_r.c
index 52a9b26..6432d23 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -65,6 +65,7 @@
 #ifdef CONFIG_AVR32
 #include <asm/arch/mmu.h>
 #endif
+#include <efi_loader.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -177,6 +178,9 @@ static int initr_reloc_global_data(void)
 	*/
 	gd->fdt_blob += gd->reloc_off;
 #endif
+#ifdef CONFIG_EFI_LOADER
+	efi_runtime_relocate(gd->relocaddr, NULL);
+#endif
 
 	return 0;
 }
diff --git a/include/efi_loader.h b/include/efi_loader.h
index b4e82ac..3a71a77 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -29,6 +29,7 @@
 
 #define EFI_EXIT(ret) efi_exit_func(ret);
 
+extern struct efi_runtime_services efi_runtime_services;
 extern struct efi_system_table systab;
 
 extern const struct efi_simple_text_output_protocol efi_con_out;
@@ -39,6 +40,9 @@ extern const efi_guid_t efi_guid_console_control;
 extern const efi_guid_t efi_guid_device_path;
 extern const efi_guid_t efi_guid_loaded_image;
 
+extern unsigned int __efi_runtime_start, __efi_runtime_stop;
+extern unsigned int __efi_runtime_rel_start, __efi_runtime_rel_stop;
+
 /*
  * While UEFI objects can have callbacks, you can also call functions on
  * protocols (classes) themselves. This struct maps a protocol GUID to its
@@ -100,9 +104,22 @@ void efi_save_gd(void);
 void efi_restore_gd(void);
 /* Called from EFI_EXIT on callback exit to restore the gd register */
 efi_status_t efi_exit_func(efi_status_t ret);
+/* Call this to relocate the runtime section to an address space */
+void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map);
+
+/*
+ * 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_TEXT __attribute__ ((section ("efi_runtime_text")))
 
 #else /* defined(EFI_LOADER) */
 
+/* Without CONFIG_EFI_LOADER we don't have a runtime section, stub it out */
+#define EFI_RUNTIME_DATA
+#define EFI_RUNTIME_TEXT
+
 /* No loader configured, stub out EFI_ENTRY */
 static inline void efi_restore_gd(void) { }
 
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index e60fae9..87400de 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -39,7 +39,7 @@ static bool efi_is_direct_boot = true;
  * 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_conf_table[1];
+static struct efi_configuration_table EFI_RUNTIME_DATA efi_conf_table[1];
 
 /*
  * The "gd" pointer lives in a register on ARM and AArch64 that we declare
@@ -761,10 +761,10 @@ static const struct efi_boot_services efi_boot_services = {
 };
 
 
-static uint16_t firmware_vendor[] =
+static uint16_t EFI_RUNTIME_DATA firmware_vendor[] =
 	{ 'D','a','s',' ','U','-','b','o','o','t',0 };
 
-struct efi_system_table systab = {
+struct efi_system_table EFI_RUNTIME_DATA systab = {
 	.hdr = {
 		.signature = EFI_SYSTEM_TABLE_SIGNATURE,
 		.revision = 0x20005, /* 2.5 */
diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c
new file mode 100644
index 0000000..22bcd08
--- /dev/null
+++ b/lib/efi_loader/efi_runtime.c
@@ -0,0 +1,290 @@
+/*
+ *  EFI application runtime services
+ *
+ *  Copyright (c) 2016 Alexander Graf
+ *
+ *  SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <efi_loader.h>
+#include <rtc.h>
+#include <asm/global_data.h>
+
+/* For manual relocation support */
+DECLARE_GLOBAL_DATA_PTR;
+
+static efi_status_t EFI_RUNTIME_TEXT EFIAPI efi_unimplemented(void);
+static efi_status_t EFI_RUNTIME_TEXT EFIAPI efi_device_error(void);
+static efi_status_t EFI_RUNTIME_TEXT EFIAPI efi_invalid_parameter(void);
+
+#if defined(CONFIG_ARM64)
+#define R_RELATIVE	1027
+#define R_MASK		0xffffffffULL
+#define IS_RELA		1
+#elif defined(CONFIG_ARM)
+#define R_RELATIVE	23
+#define R_MASK		0xffULL
+#else
+#error Need to add relocation awareness
+#endif
+
+struct elf_rel {
+	ulong *offset;
+	ulong info;
+};
+
+struct elf_rela {
+	ulong *offset;
+	ulong info;
+	long addend;
+};
+
+/*
+ * EFI Runtime code lives in 2 stages. In the first stage, U-Boot and an EFI
+ * payload are running concurrently at the same time. In this mode, we can
+ * handle a good number of runtime callbacks
+ */
+
+static void EFIAPI efi_reset_system(enum efi_reset_type reset_type,
+				    efi_status_t reset_status,
+				    unsigned long data_size, void *reset_data)
+{
+	EFI_ENTRY("%d %lx %lx %p", reset_type, reset_status, data_size,
+		  reset_data);
+
+	switch (reset_type) {
+	case EFI_RESET_COLD:
+	case EFI_RESET_WARM:
+		do_reset(NULL, 0, 0, NULL);
+		break;
+	case EFI_RESET_SHUTDOWN:
+		/* We don't have anything to map this to */
+		break;
+	}
+
+	EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_get_time(struct efi_time *time,
+					struct efi_time_cap *capabilities)
+{
+#if defined(CONFIG_CMD_DATE) && defined(CONFIG_DM_RTC)
+	struct rtc_time tm;
+	int r;
+	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);
+
+	r = dm_rtc_get(dev, &tm);
+	if (r)
+		return EFI_EXIT(EFI_DEVICE_ERROR);
+
+	memset(time, 0, sizeof(*time));
+	time->year = tm.tm_year;
+	time->month = tm.tm_mon;
+	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);
+#else
+	return EFI_DEVICE_ERROR;
+#endif
+}
+
+struct efi_runtime_detach_list_struct {
+	void *ptr;
+	void *patchto;
+};
+
+static const struct efi_runtime_detach_list_struct efi_runtime_detach_list[] = {
+	{
+		/* do_reset is gone */
+		.ptr = &efi_runtime_services.reset_system,
+		.patchto = NULL,
+	}, {
+		/* invalidate_*cache_all are gone */
+		.ptr = &efi_runtime_services.set_virtual_address_map,
+		.patchto = &efi_invalid_parameter,
+	}, {
+		/* RTC accessors are gone */
+		.ptr = &efi_runtime_services.get_time,
+		.patchto = &efi_device_error,
+	},
+};
+
+static bool efi_runtime_tobedetached(void *p)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(efi_runtime_detach_list); i++)
+		if (efi_runtime_detach_list[i].ptr == p)
+			return true;
+
+	return false;
+}
+
+static void efi_runtime_detach(ulong offset)
+{
+	int i;
+	ulong patchoff = offset - (ulong)gd->relocaddr;
+
+	for (i = 0; i < ARRAY_SIZE(efi_runtime_detach_list); i++) {
+		ulong patchto = (ulong)efi_runtime_detach_list[i].patchto;
+		ulong *p = efi_runtime_detach_list[i].ptr;
+		ulong newaddr = patchto ? (patchto + patchoff) : 0;
+
+#ifdef DEBUG_EFI
+		printf("%s: Setting %p to %lx\n", __func__, p, newaddr);
+#endif
+		*p = newaddr;
+	}
+}
+
+/* Relocate EFI runtime to uboot_reloc_base = offset */
+void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map)
+{
+#ifdef IS_RELA
+	struct elf_rela *rel = (void*)&__efi_runtime_rel_start;
+#else
+	struct elf_rel *rel = (void*)&__efi_runtime_rel_start;
+	static ulong lastoff = CONFIG_SYS_TEXT_BASE;
+#endif
+
+#ifdef DEBUG_EFI
+	printf("%s: Relocating to offset=%lx\n", __func__, offset);
+#endif
+
+	for (; (ulong)rel < (ulong)&__efi_runtime_rel_stop; rel++) {
+		ulong base = CONFIG_SYS_TEXT_BASE;
+		ulong *p;
+		ulong newaddr;
+
+		p = (void*)((ulong)rel->offset - base) + gd->relocaddr;
+
+		if ((rel->info & R_MASK) != R_RELATIVE) {
+			continue;
+		}
+
+#ifdef IS_RELA
+		newaddr = rel->addend + offset - CONFIG_SYS_TEXT_BASE;
+#else
+		newaddr = *p - lastoff + offset;
+#endif
+
+		/* Check if the relocation is inside bounds */
+		if (map && ((newaddr < map->virtual_start) ||
+		    newaddr > (map->virtual_start + (map->num_pages << 12)))) {
+			if (!efi_runtime_tobedetached(p))
+				printf("U-Boot EFI: Relocation@%p is out of "
+				       "range (%lx)\n", p, newaddr);
+			continue;
+		}
+
+#ifdef DEBUG_EFI
+		printf("%s: Setting %p to %lx\n", __func__, p, newaddr);
+#endif
+
+		*p = newaddr;
+		flush_dcache_range((ulong)p, (ulong)&p[1]);
+	}
+
+#ifndef IS_RELA
+	lastoff = offset;
+#endif
+
+        invalidate_icache_all();
+}
+
+static efi_status_t EFIAPI efi_set_virtual_address_map(
+			unsigned long memory_map_size,
+			unsigned long descriptor_size,
+			uint32_t descriptor_version,
+			struct efi_mem_desc *virtmap)
+{
+	ulong runtime_start = (ulong)&__efi_runtime_start & ~0xfffULL;
+	int n = memory_map_size / descriptor_size;
+	int i;
+
+	EFI_ENTRY("%lx %lx %x %p", memory_map_size, descriptor_size,
+		  descriptor_version, virtmap);
+
+	for (i = 0; i < n; i++) {
+		struct efi_mem_desc *map;
+
+		map = (void*)virtmap + (descriptor_size * i);
+		if (map->type == EFI_RUNTIME_SERVICES_CODE) {
+			ulong new_offset = map->virtual_start - (runtime_start - gd->relocaddr);
+
+			efi_runtime_relocate(new_offset, map);
+			/* Once we're virtual, we can no longer handle
+			   complex callbacks */
+			efi_runtime_detach(new_offset);
+			return EFI_EXIT(EFI_SUCCESS);
+		}
+	}
+
+	return EFI_EXIT(EFI_INVALID_PARAMETER);
+}
+
+/*
+ * In the second stage, U-Boot has disappeared. To isolate our runtime code
+ * that at this point still exists from the rest, we put it into a special
+ * section.
+ *
+ *        !!WARNING!!
+ *
+ * This means that we can not rely on any code outside of this file in any
+ * function or variable below this line.
+ *
+ * Please keep everything fully self-contained and annotated with
+ * EFI_RUNTIME_TEXT and EFI_RUNTIME_DATA markers.
+ */
+
+/*
+ * Relocate the EFI runtime stub to a different place. We need to call this
+ * the first time we expose the runtime interface to a user and on set virtual
+ * address map calls.
+ */
+
+static efi_status_t EFI_RUNTIME_TEXT EFIAPI efi_unimplemented(void)
+{
+	return EFI_UNSUPPORTED;
+}
+
+static efi_status_t EFI_RUNTIME_TEXT EFIAPI efi_device_error(void)
+{
+	return EFI_DEVICE_ERROR;
+}
+
+static efi_status_t EFI_RUNTIME_TEXT EFIAPI efi_invalid_parameter(void)
+{
+	return EFI_INVALID_PARAMETER;
+}
+
+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),
+	},
+	.get_time = &efi_get_time,
+	.set_time = (void *)&efi_device_error,
+	.get_wakeup_time = (void *)&efi_unimplemented,
+	.set_wakeup_time = (void *)&efi_unimplemented,
+	.set_virtual_address_map = &efi_set_virtual_address_map,
+	.convert_pointer = (void *)&efi_invalid_parameter,
+	.get_variable = (void *)&efi_device_error,
+	.get_next_variable = (void *)&efi_device_error,
+	.set_variable = (void *)&efi_device_error,
+	.get_next_high_mono_count = (void *)&efi_device_error,
+	.reset_system = &efi_reset_system,
+};
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 18/30] efi_loader: Add disk interfaces
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (16 preceding siblings ...)
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 17/30] efi_loader: Add runtime services Alexander Graf
@ 2016-03-04  0:10 ` Alexander Graf
  2016-03-17  2:01   ` [U-Boot] [U-Boot,v5,18/30] " Tom Rini
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 19/30] efi_loader: Add "bootefi" command Alexander Graf
                   ` (12 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:10 UTC (permalink / raw)
  To: u-boot

A EFI applications usually want to access storage devices to load data from.

This patch adds support for EFI disk interfaces. It loops through all block
storage interfaces known to U-Boot and creates an EFI object for each existing
one. EFI applications can then through these objects call U-Boot's read and
write functions.

Signed-off-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
Tested-by: Simon Glass <sjg@chromium.org>

---

v1 -> v2:

  - Move to block_drvr array
  - Move to GPLv2+
  - Fix header order
  - Document efi block object struct
  - Use calloc rather than malloc & memset

v2 -> v3:

  - Adapt to newer u-boot block API
  - Add EFIAPI to function prototypes
  - Document header
  - Check for DEV_TYPE_UNKNOWN
  - Document 16byte limit for dp string
---
 include/efi_loader.h      |   2 +
 lib/efi_loader/efi_disk.c | 218 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 220 insertions(+)
 create mode 100644 lib/efi_loader/efi_disk.c

diff --git a/include/efi_loader.h b/include/efi_loader.h
index 3a71a77..32e0632 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -86,6 +86,8 @@ struct efi_object {
 /* This list contains all UEFI objects we know of */
 extern struct list_head efi_obj_list;
 
+/* Called by bootefi to make all disk storage accessible as EFI objects */
+int efi_disk_register(void);
 /*
  * Stub implementation for a protocol opener that just returns the handle as
  * interface
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
new file mode 100644
index 0000000..f93fcb2
--- /dev/null
+++ b/lib/efi_loader/efi_disk.c
@@ -0,0 +1,218 @@
+/*
+ *  EFI application disk support
+ *
+ *  Copyright (c) 2016 Alexander Graf
+ *
+ *  SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <efi_loader.h>
+#include <inttypes.h>
+#include <part.h>
+#include <malloc.h>
+
+static const efi_guid_t efi_block_io_guid = BLOCK_IO_GUID;
+
+struct efi_disk_obj {
+	/* Generic EFI object parent class data */
+	struct efi_object parent;
+	/* EFI Interface callback struct for block I/O */
+	struct efi_block_io ops;
+	/* U-Boot ifname for block device */
+	const char *ifname;
+	/* U-Boot dev_index for block device */
+	int dev_index;
+	/* EFI Interface Media descriptor struct, referenced by ops */
+	struct efi_block_io_media media;
+	/* EFI device path to this block device */
+	struct efi_device_path_file_path *dp;
+};
+
+static void ascii2unicode(u16 *unicode, char *ascii)
+{
+	while (*ascii)
+		*(unicode++) = *(ascii++);
+}
+
+static efi_status_t efi_disk_open_block(void *handle, efi_guid_t *protocol,
+			void **protocol_interface, void *agent_handle,
+			void *controller_handle, uint32_t attributes)
+{
+	struct efi_disk_obj *diskobj = handle;
+
+	*protocol_interface = &diskobj->ops;
+
+	return EFI_SUCCESS;
+}
+
+static efi_status_t efi_disk_open_dp(void *handle, efi_guid_t *protocol,
+			void **protocol_interface, void *agent_handle,
+			void *controller_handle, uint32_t attributes)
+{
+	struct efi_disk_obj *diskobj = handle;
+
+	*protocol_interface = diskobj->dp;
+
+	return EFI_SUCCESS;
+}
+
+static efi_status_t EFIAPI efi_disk_reset(struct efi_block_io *this,
+			char extended_verification)
+{
+	EFI_ENTRY("%p, %x", this, extended_verification);
+	return EFI_EXIT(EFI_DEVICE_ERROR);
+}
+
+enum efi_disk_direction {
+	EFI_DISK_READ,
+	EFI_DISK_WRITE,
+};
+
+static efi_status_t EFIAPI efi_disk_rw_blocks(struct efi_block_io *this,
+			u32 media_id, u64 lba, unsigned long buffer_size,
+			void *buffer, enum efi_disk_direction direction)
+{
+	struct efi_disk_obj *diskobj;
+	struct block_dev_desc *desc;
+	int blksz;
+	int blocks;
+	unsigned long n;
+
+	EFI_ENTRY("%p, %x, %"PRIx64", %lx, %p", this, media_id, lba,
+		  buffer_size, buffer);
+
+	diskobj = container_of(this, struct efi_disk_obj, ops);
+	if (!(desc = get_dev(diskobj->ifname, diskobj->dev_index)))
+		return EFI_EXIT(EFI_DEVICE_ERROR);
+	blksz = desc->blksz;
+	blocks = buffer_size / blksz;
+
+#ifdef DEBUG_EFI
+	printf("EFI: %s:%d blocks=%x lba=%"PRIx64" blksz=%x dir=%d\n", __func__,
+	       __LINE__, blocks, lba, blksz, direction);
+#endif
+
+	/* We only support full block access */
+	if (buffer_size & (blksz - 1))
+		return EFI_EXIT(EFI_DEVICE_ERROR);
+
+	if (direction == EFI_DISK_READ)
+		n = desc->block_read(desc, lba, blocks, buffer);
+	else
+		n = desc->block_write(desc, lba, blocks, buffer);
+
+	/* We don't do interrupts, so check for timers cooperatively */
+	efi_timer_check();
+
+#ifdef DEBUG_EFI
+	printf("EFI: %s:%d n=%lx blocks=%x\n", __func__, __LINE__, n, blocks);
+#endif
+	if (n != blocks)
+		return EFI_EXIT(EFI_DEVICE_ERROR);
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t efi_disk_read_blocks(struct efi_block_io *this,
+			u32 media_id, u64 lba, unsigned long buffer_size,
+			void *buffer)
+{
+	return efi_disk_rw_blocks(this, media_id, lba, buffer_size, buffer,
+				  EFI_DISK_READ);
+}
+
+static efi_status_t efi_disk_write_blocks(struct efi_block_io *this,
+			u32 media_id, u64 lba, unsigned long buffer_size,
+			void *buffer)
+{
+	return efi_disk_rw_blocks(this, media_id, lba, buffer_size, buffer,
+				  EFI_DISK_WRITE);
+}
+
+static efi_status_t EFIAPI efi_disk_flush_blocks(struct efi_block_io *this)
+{
+	/* We always write synchronously */
+	EFI_ENTRY("%p", this);
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static const struct efi_block_io block_io_disk_template = {
+	.reset = &efi_disk_reset,
+	.read_blocks = &efi_disk_read_blocks,
+	.write_blocks = &efi_disk_write_blocks,
+	.flush_blocks = &efi_disk_flush_blocks,
+};
+
+/*
+ * U-Boot doesn't have a list of all online disk devices. So when running our
+ * EFI payload, we scan through all of the potentially available ones and
+ * store them in our object pool.
+ *
+ * This gets called from do_bootefi_exec().
+ */
+int efi_disk_register(void)
+{
+	const struct block_drvr *cur_drvr;
+	int i;
+	int disks = 0;
+
+	/* Search for all available disk devices */
+	for (cur_drvr = block_drvr; cur_drvr->name; cur_drvr++) {
+		printf("Scanning disks on %s...\n", cur_drvr->name);
+		for (i = 0; i < 4; i++) {
+			block_dev_desc_t *desc;
+			struct efi_disk_obj *diskobj;
+			struct efi_device_path_file_path *dp;
+			int objlen = sizeof(*diskobj) + (sizeof(*dp) * 2);
+			char devname[16] = { 0 }; /* dp->str is u16[16] long */
+
+			desc = get_dev(cur_drvr->name, i);
+			if (!desc)
+				continue;
+			if (desc->type == DEV_TYPE_UNKNOWN)
+				continue;
+
+			diskobj = calloc(1, objlen);
+
+			/* Fill in object data */
+			diskobj->parent.protocols[0].guid = &efi_block_io_guid;
+			diskobj->parent.protocols[0].open = efi_disk_open_block;
+			diskobj->parent.protocols[1].guid = &efi_guid_device_path;
+			diskobj->parent.protocols[1].open = efi_disk_open_dp;
+			diskobj->parent.handle = diskobj;
+			diskobj->ops = block_io_disk_template;
+			diskobj->ifname = cur_drvr->name;
+			diskobj->dev_index = i;
+
+			/* Fill in EFI IO Media info (for read/write callbacks) */
+			diskobj->media.removable_media = desc->removable;
+			diskobj->media.media_present = 1;
+			diskobj->media.block_size = desc->blksz;
+			diskobj->media.io_align = desc->blksz;
+			diskobj->media.last_block = desc->lba;
+			diskobj->ops.media = &diskobj->media;
+
+			/* Fill in device path */
+			dp = (void*)&diskobj[1];
+			diskobj->dp = dp;
+			dp[0].dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
+			dp[0].dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH;
+			dp[0].dp.length = sizeof(*dp);
+			snprintf(devname, sizeof(devname), "%s%d",
+				 cur_drvr->name, i);
+			ascii2unicode(dp[0].str, devname);
+
+			dp[1].dp.type = DEVICE_PATH_TYPE_END;
+			dp[1].dp.sub_type = DEVICE_PATH_SUB_TYPE_END;
+			dp[1].dp.length = sizeof(*dp);
+
+			/* Hook up to the device list */
+			list_add_tail(&diskobj->parent.link, &efi_obj_list);
+			disks++;
+		}
+	}
+	printf("Found %d disks\n", disks);
+
+	return 0;
+}
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 19/30] efi_loader: Add "bootefi" command
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (17 preceding siblings ...)
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 18/30] efi_loader: Add disk interfaces Alexander Graf
@ 2016-03-04  0:10 ` Alexander Graf
  2016-03-09 23:27   ` [U-Boot] [PATCH v6 " Alexander Graf
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 20/30] efi_loader: Implement memory allocation and map Alexander Graf
                   ` (11 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:10 UTC (permalink / raw)
  To: u-boot

In order to execute an EFI application, we need to bridge the gap between
U-Boot's notion of executing images and EFI's notion of doing the same.

The best path forward IMHO here is to stick completely to the way U-Boot
deals with payloads. You manually load them using whatever method to RAM
and then have a simple boot command to execute them. So in our case, you
would do

  # load mmc 0:1 $loadaddr grub.efi
  # bootefi $loadaddr

which then gets you into a grub shell. Fdt information known to U-boot
via the fdt addr command is also passed to the EFI payload.

Signed-off-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
Tested-by: Simon Glass <sjg@chromium.org>

---

v1 -> v2:

  - Move to GPLv2+

v2 -> v3:

  - Move to new cmd directory
  - Add kconfig option
  - Fix comment style
  - Add help text
  - s/-1/-ENOENT
  - Move obj list to lib

v4 -> v5:

  - Mark fdt memory as boot services data
---
 cmd/Kconfig   |   7 +++
 cmd/Makefile  |   1 +
 cmd/bootefi.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 186 insertions(+)
 create mode 100644 cmd/bootefi.c

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 2ed0263..7cdff04 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -148,6 +148,13 @@ config CMD_BOOTM
 	help
 	  Boot an application image from the memory.
 
+config CMD_BOOTEFI
+	bool "bootefi"
+	depends on EFI_LOADER
+	default y
+	help
+	  Boot an EFI image from memory.
+
 config CMD_ELF
 	bool "bootelf, bootvx"
 	default y
diff --git a/cmd/Makefile b/cmd/Makefile
index 03f7e0a..7604621 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_CMD_SOURCE) += source.o
 obj-$(CONFIG_CMD_BDI) += bdinfo.o
 obj-$(CONFIG_CMD_BEDBUG) += bedbug.o
 obj-$(CONFIG_CMD_BMP) += bmp.o
+obj-$(CONFIG_CMD_BOOTEFI) += bootefi.o
 obj-$(CONFIG_CMD_BOOTMENU) += bootmenu.o
 obj-$(CONFIG_CMD_BOOTLDR) += bootldr.o
 obj-$(CONFIG_CMD_BOOTSTAGE) += bootstage.o
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
new file mode 100644
index 0000000..2a40fb0
--- /dev/null
+++ b/cmd/bootefi.c
@@ -0,0 +1,178 @@
+/*
+ *  EFI application loader
+ *
+ *  Copyright (c) 2016 Alexander Graf
+ *
+ *  SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <efi_loader.h>
+#include <errno.h>
+#include <libfdt.h>
+#include <libfdt_env.h>
+
+/*
+ * When booting using the "bootefi" command, we don't know which
+ * physical device the file came from. So we create a pseudo-device
+ * called "bootefi" with the device path /bootefi.
+ *
+ * In addition to the originating device we also declare the file path
+ * of "bootefi" based loads to be /bootefi.
+ */
+static struct efi_device_path_file_path bootefi_dummy_path[] = {
+	{
+		.dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE,
+		.dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH,
+		.dp.length = sizeof(bootefi_dummy_path[0]),
+		.str = { 'b','o','o','t','e','f','i' },
+	}, {
+		.dp.type = DEVICE_PATH_TYPE_END,
+		.dp.sub_type = DEVICE_PATH_SUB_TYPE_END,
+		.dp.length = sizeof(bootefi_dummy_path[0]),
+	}
+};
+
+static efi_status_t bootefi_open_dp(void *handle, efi_guid_t *protocol,
+			void **protocol_interface, void *agent_handle,
+			void *controller_handle, uint32_t attributes)
+{
+	*protocol_interface = bootefi_dummy_path;
+	return EFI_SUCCESS;
+}
+
+/* The EFI loaded_image interface for the image executed via "bootefi" */
+static struct efi_loaded_image loaded_image_info = {
+	.device_handle = bootefi_dummy_path,
+	.file_path = bootefi_dummy_path,
+};
+
+/* The EFI object struct for the image executed via "bootefi" */
+static struct efi_object loaded_image_info_obj = {
+	.handle = &loaded_image_info,
+	.protocols = {
+		{
+			/*
+			 * When asking for the loaded_image interface, just
+			 * return handle which points to loaded_image_info
+			 */
+			.guid = &efi_guid_loaded_image,
+			.open = &efi_return_handle,
+		},
+		{
+			/*
+			 * When asking for the device path interface, return
+			 * bootefi_dummy_path
+			 */
+			.guid = &efi_guid_device_path,
+			.open = &bootefi_open_dp,
+		},
+	},
+};
+
+/* The EFI object struct for the device the "bootefi" image was loaded from */
+static struct efi_object bootefi_device_obj = {
+	.handle = bootefi_dummy_path,
+	.protocols = {
+		{
+			/* When asking for the device path interface, return
+			 * bootefi_dummy_path */
+			.guid = &efi_guid_device_path,
+			.open = &bootefi_open_dp,
+		}
+	},
+};
+
+/*
+ * Load an EFI payload into a newly allocated piece of memory, register all
+ * EFI objects it would want to access and jump to it.
+ */
+static unsigned long do_bootefi_exec(void *efi)
+{
+	ulong (*entry)(void *image_handle, struct efi_system_table *st);
+	ulong fdt_pages, fdt_size, fdt_start, fdt_end;
+
+	/*
+	 * gd lives in a fixed register which may get clobbered while we execute
+	 * the payload. So save it here and restore it on every callback entry
+	 */
+	efi_save_gd();
+
+	/* Update system table to point to our currently loaded FDT */
+
+	if (working_fdt) {
+		systab.tables[0].guid = EFI_FDT_GUID;
+		systab.tables[0].table = working_fdt;
+		systab.nr_tables = 1;
+
+		/* And reserve the space in the memory map */
+		fdt_start = ((ulong)working_fdt) & ~EFI_PAGE_MASK;
+		fdt_end = ((ulong)working_fdt) + fdt_totalsize(working_fdt);
+		fdt_size = (fdt_end - fdt_start) + EFI_PAGE_MASK;
+		fdt_pages = fdt_size >> EFI_PAGE_SHIFT;
+		efi_add_memory_map(fdt_start, fdt_pages,
+				   EFI_BOOT_SERVICES_DATA, true);
+
+	} else {
+		printf("WARNING: No device tree loaded, expect boot to fail\n");
+		systab.nr_tables = 0;
+	}
+
+	/* Load the EFI payload */
+	entry = efi_load_pe(efi, &loaded_image_info);
+	if (!entry)
+		return -ENOENT;
+
+	/* Initialize and populate EFI object list */
+	INIT_LIST_HEAD(&efi_obj_list);
+	list_add_tail(&loaded_image_info_obj.link, &efi_obj_list);
+	list_add_tail(&bootefi_device_obj.link, &efi_obj_list);
+#ifdef CONFIG_PARTITIONS
+	efi_disk_register();
+#endif
+
+	/* Call our payload! */
+#ifdef DEBUG_EFI
+	printf("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry);
+#endif
+	return entry(&loaded_image_info, &systab);
+}
+
+
+/* Interpreter command to boot an arbitrary EFI image from memory */
+static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	char *saddr;
+	unsigned long addr;
+	int r = 0;
+
+	if (argc < 2)
+		return 1;
+	saddr = argv[1];
+
+	addr = simple_strtoul(saddr, NULL, 16);
+
+	printf("## Starting EFI application@0x%08lx ...\n", addr);
+	r = do_bootefi_exec((void *)addr);
+	printf("## Application terminated, r = %d\n", r);
+
+	if (r != 0)
+		r = 1;
+
+	return r;
+}
+
+static char bootefi_help_text[] =
+	"<image address>\n"
+	"  - boot EFI payload stored at address <image address>\n"
+	"\n"
+	"Since most EFI payloads want to have a device tree provided, please\n"
+	"make sure you load a device tree using the fdt addr command before\n"
+	"executing bootefi.\n";
+
+U_BOOT_CMD(
+	bootefi, 2, 0, do_bootefi,
+	"Boots an EFI payload from memory\n",
+	bootefi_help_text
+);
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 20/30] efi_loader: Implement memory allocation and map
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (18 preceding siblings ...)
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 19/30] efi_loader: Add "bootefi" command Alexander Graf
@ 2016-03-04  0:10 ` Alexander Graf
  2016-03-17  2:02   ` [U-Boot] [U-Boot, v5, " Tom Rini
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 21/30] arm64: Allow exceptions to return Alexander Graf
                   ` (10 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:10 UTC (permalink / raw)
  To: u-boot

The EFI loader needs to maintain views of memory - general system memory
windows as well as used locations inside those and potential runtime service
MMIO windows.

To manage all of these, add a few helpers that maintain an internal
representation of the map the similar to how the EFI API later on reports
it to the application.

For allocations, the scheme is very simple. We basically allow allocations
to replace chunks of previously done maps, so that a new LOADER_DATA
allocation for example can remove a piece of the RAM map. When no specific
address is given, we just take the highest possible address in the lowest
RAM map that fits the allocation size.

Signed-off-by: Alexander Graf <agraf@suse.de>
Tested-by: Simon Glass <sjg@chromium.org>

---

v2 -> v3:

  - Rewrite memory allocation and map
  - Document header

v3 -> v4:

  - Use EFI_PAGE_.* defines
  - Return EFI_OUT_OF_RESOURCES in efi_allocate_pages
---
 common/board_r.c            |   3 +
 include/efi_loader.h        |  19 +++
 lib/efi_loader/efi_memory.c | 319 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 341 insertions(+)
 create mode 100644 lib/efi_loader/efi_memory.c

diff --git a/common/board_r.c b/common/board_r.c
index 6432d23..2cb6836 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -795,6 +795,9 @@ init_fnc_t init_sequence_r[] = {
 #ifdef CONFIG_CLOCKS
 	set_cpu_clk_info, /* Setup clock information */
 #endif
+#ifdef CONFIG_EFI_LOADER
+	efi_memory_init,
+#endif
 	stdio_init_tables,
 	initr_serial,
 	initr_announce,
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 32e0632..e344566 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -109,6 +109,25 @@ efi_status_t efi_exit_func(efi_status_t ret);
 /* Call this to relocate the runtime section to an address space */
 void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map);
 
+/* Generic EFI memory allocator, call this to get memory */
+void *efi_alloc(uint64_t len, int memory_type);
+/* More specific EFI memory allocator, called by EFI payloads */
+efi_status_t efi_allocate_pages(int type, int memory_type, unsigned long pages,
+				uint64_t *memory);
+/* EFI memory free function. Not implemented today */
+efi_status_t efi_free_pages(uint64_t memory, unsigned long pages);
+/* Returns the EFI memory map */
+efi_status_t efi_get_memory_map(unsigned long *memory_map_size,
+				struct efi_mem_desc *memory_map,
+				unsigned long *map_key,
+				unsigned long *descriptor_size,
+				uint32_t *descriptor_version);
+/* Adds a range into the EFI memory map */
+uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type,
+			    bool overlap_only_ram);
+/* Called by board init to initialize the EFI memory map */
+int efi_memory_init(void);
+
 /*
  * 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
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
new file mode 100644
index 0000000..c82b53f
--- /dev/null
+++ b/lib/efi_loader/efi_memory.c
@@ -0,0 +1,319 @@
+/*
+ *  EFI application memory management
+ *
+ *  Copyright (c) 2016 Alexander Graf
+ *
+ *  SPDX-License-Identifier:     GPL-2.0+
+ */
+
+/* #define DEBUG_EFI */
+
+#include <common.h>
+#include <efi_loader.h>
+#include <malloc.h>
+#include <asm/global_data.h>
+#include <libfdt_env.h>
+#include <inttypes.h>
+#include <watchdog.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct efi_mem_list {
+	struct list_head link;
+	struct efi_mem_desc desc;
+};
+
+/* This list contains all memory map items */
+LIST_HEAD(efi_mem);
+
+/*
+ * Unmaps all memory occupied by the carve_desc region from the
+ * list entry pointed to by map.
+ *
+ * Returns 1 if carving was performed or 0 if the regions don't overlap.
+ * Returns -1 if it would affect non-RAM regions but overlap_only_ram is set.
+ * Carving is only guaranteed to complete when all regions return 0.
+ */
+static int efi_mem_carve_out(struct efi_mem_list *map,
+			     struct efi_mem_desc *carve_desc,
+			     bool overlap_only_ram)
+{
+	struct efi_mem_list *newmap;
+	struct efi_mem_desc *map_desc = &map->desc;
+	uint64_t map_start = map_desc->physical_start;
+	uint64_t map_end = map_start + (map_desc->num_pages << EFI_PAGE_SHIFT);
+	uint64_t carve_start = carve_desc->physical_start;
+	uint64_t carve_end = carve_start +
+			     (carve_desc->num_pages << EFI_PAGE_SHIFT);
+
+	/* check whether we're overlapping */
+	if ((carve_end <= map_start) || (carve_start >= map_end))
+		return 0;
+
+	/* We're overlapping with non-RAM, warn the caller if desired */
+	if (overlap_only_ram && (map_desc->type != EFI_CONVENTIONAL_MEMORY))
+		return -1;
+
+	/* Sanitize carve_start and carve_end to lie within our bounds */
+	carve_start = max(carve_start, map_start);
+	carve_end = min(carve_end, map_end);
+
+	/* Carving at the beginning of our map? Just move it! */
+	if (carve_start == map_start) {
+		if (map_end == carve_end) {
+			/* Full overlap, just remove map */
+			list_del(&map->link);
+		}
+
+		map_desc->physical_start = carve_end;
+		map_desc->num_pages = (map_end - carve_end) >> EFI_PAGE_SHIFT;
+		return 1;
+	}
+
+	/*
+	 * Overlapping maps, just split the list map at carve_start,
+	 * it will get moved or removed in the next iteration.
+	 *
+	 * [ map_desc |__carve_start__| newmap ]
+	 */
+
+	/* Create a new map from [ carve_start ... map_end ] */
+	newmap = calloc(1, sizeof(*newmap));
+	newmap->desc = map->desc;
+	newmap->desc.physical_start = carve_start;
+	newmap->desc.num_pages = (map_end - carve_start) >> EFI_PAGE_SHIFT;
+        list_add_tail(&newmap->link, &efi_mem);
+
+	/* Shrink the map to [ map_start ... carve_start ] */
+	map_desc->num_pages = (carve_start - map_start) >> EFI_PAGE_SHIFT;
+
+	return 1;
+}
+
+uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type,
+			    bool overlap_only_ram)
+{
+	struct list_head *lhandle;
+	struct efi_mem_list *newlist;
+	bool do_carving;
+
+	if (!pages)
+		return start;
+
+	newlist = calloc(1, sizeof(*newlist));
+	newlist->desc.type = memory_type;
+	newlist->desc.physical_start = start;
+	newlist->desc.virtual_start = start;
+	newlist->desc.num_pages = pages;
+
+	switch (memory_type) {
+	case EFI_RUNTIME_SERVICES_CODE:
+	case EFI_RUNTIME_SERVICES_DATA:
+		newlist->desc.attribute = (1 << EFI_MEMORY_WB_SHIFT) |
+					  (1ULL << EFI_MEMORY_RUNTIME_SHIFT);
+		break;
+	case EFI_MMAP_IO:
+		newlist->desc.attribute = 1ULL << EFI_MEMORY_RUNTIME_SHIFT;
+		break;
+	default:
+		newlist->desc.attribute = 1 << EFI_MEMORY_WB_SHIFT;
+		break;
+	}
+
+	/* Add our new map */
+	do {
+		do_carving = false;
+		list_for_each(lhandle, &efi_mem) {
+			struct efi_mem_list *lmem;
+			int r;
+
+			lmem = list_entry(lhandle, struct efi_mem_list, link);
+			r = efi_mem_carve_out(lmem, &newlist->desc,
+					      overlap_only_ram);
+			if (r < 0) {
+				return 0;
+			} else if (r) {
+				do_carving = true;
+				break;
+			}
+		}
+	} while (do_carving);
+
+	/* Add our new map */
+        list_add_tail(&newlist->link, &efi_mem);
+
+	return start;
+}
+
+static uint64_t efi_find_free_memory(uint64_t len, uint64_t max_addr)
+{
+	struct list_head *lhandle;
+
+	list_for_each(lhandle, &efi_mem) {
+		struct efi_mem_list *lmem = list_entry(lhandle,
+			struct efi_mem_list, link);
+		struct efi_mem_desc *desc = &lmem->desc;
+		uint64_t desc_len = desc->num_pages << EFI_PAGE_SHIFT;
+		uint64_t desc_end = desc->physical_start + desc_len;
+		uint64_t curmax = min(max_addr, desc_end);
+		uint64_t ret = curmax - len;
+
+		/* We only take memory from free RAM */
+		if (desc->type != EFI_CONVENTIONAL_MEMORY)
+			continue;
+
+		/* Out of bounds for max_addr */
+		if ((ret + len) > max_addr)
+			continue;
+
+		/* Out of bounds for upper map limit */
+		if ((ret + len) > desc_end)
+			continue;
+
+		/* Out of bounds for lower map limit */
+		if (ret < desc->physical_start)
+			continue;
+
+		/* Return the highest address in this map within bounds */
+		return ret;
+	}
+
+	return 0;
+}
+
+efi_status_t efi_allocate_pages(int type, int memory_type,
+				unsigned long pages, uint64_t *memory)
+{
+	u64 len = pages << EFI_PAGE_SHIFT;
+	efi_status_t r = EFI_SUCCESS;
+	uint64_t addr;
+
+	switch (type) {
+	case 0:
+		/* Any page */
+		addr = efi_find_free_memory(len, gd->ram_top);
+		if (!addr) {
+			r = EFI_NOT_FOUND;
+			break;
+		}
+		break;
+	case 1:
+		/* Max address */
+		addr = efi_find_free_memory(len, *memory);
+		if (!addr) {
+			r = EFI_NOT_FOUND;
+			break;
+		}
+		break;
+	case 2:
+		/* Exact address, reserve it. The addr is already in *memory. */
+		addr = *memory;
+		break;
+	default:
+		/* UEFI doesn't specify other allocation types */
+		r = EFI_INVALID_PARAMETER;
+		break;
+	}
+
+	if (r == EFI_SUCCESS) {
+		uint64_t ret;
+
+		/* Reserve that map in our memory maps */
+		ret = efi_add_memory_map(addr, pages, memory_type, true);
+		if (ret == addr) {
+			*memory = addr;
+		} else {
+			/* Map would overlap, bail out */
+			r = EFI_OUT_OF_RESOURCES;
+		}
+	}
+
+	return r;
+}
+
+void *efi_alloc(uint64_t len, int memory_type)
+{
+	uint64_t ret = 0;
+	uint64_t pages = (len + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
+	efi_status_t r;
+
+	r = efi_allocate_pages(0, memory_type, pages, &ret);
+	if (r == EFI_SUCCESS)
+		return (void*)(uintptr_t)ret;
+
+	return NULL;
+}
+
+efi_status_t efi_free_pages(uint64_t memory, unsigned long pages)
+{
+	/* We don't free, let's cross our fingers we have plenty RAM */
+	return EFI_SUCCESS;
+}
+
+efi_status_t efi_get_memory_map(unsigned long *memory_map_size,
+			       struct efi_mem_desc *memory_map,
+			       unsigned long *map_key,
+			       unsigned long *descriptor_size,
+			       uint32_t *descriptor_version)
+{
+	ulong map_size = 0;
+	struct list_head *lhandle;
+
+	list_for_each(lhandle, &efi_mem)
+		map_size += sizeof(struct efi_mem_desc);
+
+	*memory_map_size = map_size;
+
+	if (descriptor_size)
+		*descriptor_size = sizeof(struct efi_mem_desc);
+
+	if (*memory_map_size < map_size)
+		return EFI_BUFFER_TOO_SMALL;
+
+	/* Copy list into array */
+	if (memory_map) {
+		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++;
+		}
+	}
+
+	return EFI_SUCCESS;
+}
+
+int efi_memory_init(void)
+{
+	uint64_t runtime_start, runtime_end, runtime_pages;
+	uint64_t uboot_start, uboot_pages;
+	uint64_t uboot_stack_size = 16 * 1024 * 1024;
+	int i;
+
+	/* Add RAM */
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+		u64 ram_start = gd->bd->bi_dram[i].start;
+		u64 ram_size = gd->bd->bi_dram[i].size;
+		u64 start = (ram_start + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;
+		u64 pages = (ram_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
+
+		efi_add_memory_map(start, pages, EFI_CONVENTIONAL_MEMORY,
+				   false);
+	}
+
+	/* 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;
+	efi_add_memory_map(uboot_start, uboot_pages, EFI_LOADER_DATA, false);
+
+	/* Add Runtime Services */
+	runtime_start = (ulong)&__efi_runtime_start & ~EFI_PAGE_MASK;
+	runtime_end = (ulong)&__efi_runtime_stop;
+	runtime_end = (runtime_end + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;
+	runtime_pages = (runtime_end - runtime_start) >> EFI_PAGE_SHIFT;
+	efi_add_memory_map(runtime_start, runtime_pages,
+			   EFI_RUNTIME_SERVICES_CODE, false);
+
+	return 0;
+}
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 21/30] arm64: Allow exceptions to return
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (19 preceding siblings ...)
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 20/30] efi_loader: Implement memory allocation and map Alexander Graf
@ 2016-03-04  0:10 ` Alexander Graf
  2016-03-17  2:02   ` [U-Boot] [U-Boot,v5,21/30] " Tom Rini
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 22/30] arm64: Allow EFI payload code to take exceptions Alexander Graf
                   ` (9 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:10 UTC (permalink / raw)
  To: u-boot

Our current arm64 exception handlers all panic and never return to the
exception triggering code.

But if any handler wanted to continue execution after fixups, it would
need help from the exception handling code to restore all registers.

This patch implements that help. With this code, exception handlers on
aarch64 can successfully return to the place the exception happened (or
somewhere else if they modify elr).

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 arch/arm/cpu/armv8/exceptions.S | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/arch/arm/cpu/armv8/exceptions.S b/arch/arm/cpu/armv8/exceptions.S
index baf9401..4f4f526 100644
--- a/arch/arm/cpu/armv8/exceptions.S
+++ b/arch/arm/cpu/armv8/exceptions.S
@@ -82,31 +82,65 @@ vectors:
 _do_bad_sync:
 	exception_entry
 	bl	do_bad_sync
+	b	exception_exit
 
 _do_bad_irq:
 	exception_entry
 	bl	do_bad_irq
+	b	exception_exit
 
 _do_bad_fiq:
 	exception_entry
 	bl	do_bad_fiq
+	b	exception_exit
 
 _do_bad_error:
 	exception_entry
 	bl	do_bad_error
+	b	exception_exit
 
 _do_sync:
 	exception_entry
 	bl	do_sync
+	b	exception_exit
 
 _do_irq:
 	exception_entry
 	bl	do_irq
+	b	exception_exit
 
 _do_fiq:
 	exception_entry
 	bl	do_fiq
+	b	exception_exit
 
 _do_error:
 	exception_entry
 	bl	do_error
+	b	exception_exit
+
+exception_exit:
+	ldp	x2, x0, [sp],#16
+	switch_el x11, 3f, 2f, 1f
+3:	msr	elr_el3, x2
+	b	0f
+2:	msr	elr_el2, x2
+	b	0f
+1:	msr	elr_el1, x2
+0:
+	ldp	x1, x2, [sp],#16
+	ldp	x3, x4, [sp],#16
+	ldp	x5, x6, [sp],#16
+	ldp	x7, x8, [sp],#16
+	ldp	x9, x10, [sp],#16
+	ldp	x11, x12, [sp],#16
+	ldp	x13, x14, [sp],#16
+	ldp	x15, x16, [sp],#16
+	ldp	x17, x18, [sp],#16
+	ldp	x19, x20, [sp],#16
+	ldp	x21, x22, [sp],#16
+	ldp	x23, x24, [sp],#16
+	ldp	x25, x26, [sp],#16
+	ldp	x27, x28, [sp],#16
+	ldp	x29, x30, [sp],#16
+	eret
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 22/30] arm64: Allow EFI payload code to take exceptions
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (20 preceding siblings ...)
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 21/30] arm64: Allow exceptions to return Alexander Graf
@ 2016-03-04  0:10 ` Alexander Graf
  2016-03-17  2:02   ` [U-Boot] [U-Boot, v5, " Tom Rini
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 23/30] efi_loader: hook up in build environment Alexander Graf
                   ` (8 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:10 UTC (permalink / raw)
  To: u-boot

There are 2 ways an EFI payload could return into u-boot:

  - Callback function
  - Exception

While in EFI payload mode, x18 is owned by the payload and may not contain
a valid pointer to gd, so we need to fix it up. We do that properly for the
payload to callback path already.

This patch also adds gd pointer restoral for the exception path.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 arch/arm/lib/interrupts_64.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/lib/interrupts_64.c b/arch/arm/lib/interrupts_64.c
index b476722..7c9cfce 100644
--- a/arch/arm/lib/interrupts_64.c
+++ b/arch/arm/lib/interrupts_64.c
@@ -7,6 +7,7 @@
 
 #include <common.h>
 #include <linux/compiler.h>
+#include <efi_loader.h>
 
 
 int interrupt_init(void)
@@ -41,6 +42,7 @@ void show_regs(struct pt_regs *regs)
  */
 void do_bad_sync(struct pt_regs *pt_regs, unsigned int esr)
 {
+	efi_restore_gd();
 	printf("Bad mode in \"Synchronous Abort\" handler, esr 0x%08x\n", esr);
 	show_regs(pt_regs);
 	panic("Resetting CPU ...\n");
@@ -51,6 +53,7 @@ void do_bad_sync(struct pt_regs *pt_regs, unsigned int esr)
  */
 void do_bad_irq(struct pt_regs *pt_regs, unsigned int esr)
 {
+	efi_restore_gd();
 	printf("Bad mode in \"Irq\" handler, esr 0x%08x\n", esr);
 	show_regs(pt_regs);
 	panic("Resetting CPU ...\n");
@@ -61,6 +64,7 @@ void do_bad_irq(struct pt_regs *pt_regs, unsigned int esr)
  */
 void do_bad_fiq(struct pt_regs *pt_regs, unsigned int esr)
 {
+	efi_restore_gd();
 	printf("Bad mode in \"Fiq\" handler, esr 0x%08x\n", esr);
 	show_regs(pt_regs);
 	panic("Resetting CPU ...\n");
@@ -71,6 +75,7 @@ void do_bad_fiq(struct pt_regs *pt_regs, unsigned int esr)
  */
 void do_bad_error(struct pt_regs *pt_regs, unsigned int esr)
 {
+	efi_restore_gd();
 	printf("Bad mode in \"Error\" handler, esr 0x%08x\n", esr);
 	show_regs(pt_regs);
 	panic("Resetting CPU ...\n");
@@ -81,6 +86,7 @@ void do_bad_error(struct pt_regs *pt_regs, unsigned int esr)
  */
 void do_sync(struct pt_regs *pt_regs, unsigned int esr)
 {
+	efi_restore_gd();
 	printf("\"Synchronous Abort\" handler, esr 0x%08x\n", esr);
 	show_regs(pt_regs);
 	panic("Resetting CPU ...\n");
@@ -91,6 +97,7 @@ void do_sync(struct pt_regs *pt_regs, unsigned int esr)
  */
 void do_irq(struct pt_regs *pt_regs, unsigned int esr)
 {
+	efi_restore_gd();
 	printf("\"Irq\" handler, esr 0x%08x\n", esr);
 	show_regs(pt_regs);
 	panic("Resetting CPU ...\n");
@@ -101,6 +108,7 @@ void do_irq(struct pt_regs *pt_regs, unsigned int esr)
  */
 void do_fiq(struct pt_regs *pt_regs, unsigned int esr)
 {
+	efi_restore_gd();
 	printf("\"Fiq\" handler, esr 0x%08x\n", esr);
 	show_regs(pt_regs);
 	panic("Resetting CPU ...\n");
@@ -114,6 +122,7 @@ void do_fiq(struct pt_regs *pt_regs, unsigned int esr)
  */
 void __weak do_error(struct pt_regs *pt_regs, unsigned int esr)
 {
+	efi_restore_gd();
 	printf("\"Error\" handler, esr 0x%08x\n", esr);
 	show_regs(pt_regs);
 	panic("Resetting CPU ...\n");
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 23/30] efi_loader: hook up in build environment
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (21 preceding siblings ...)
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 22/30] arm64: Allow EFI payload code to take exceptions Alexander Graf
@ 2016-03-04  0:10 ` Alexander Graf
  2016-03-17  2:02   ` [U-Boot] [U-Boot, v5, " Tom Rini
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 24/30] efi_loader: Add distro boot script for removable media Alexander Graf
                   ` (7 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:10 UTC (permalink / raw)
  To: u-boot

Now that we have all the bits and pieces ready for EFI payload loading
support, hook them up in Makefiles and KConfigs so that we can build.

Signed-off-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
Tested-by: Simon Glass <sjg@chromium.org>

---

v1 -> v2:

  - Move to GPLv2+
  - Default to y

v2 -> v3:

  - Add memory file
---
 lib/Kconfig             |  1 +
 lib/Makefile            |  1 +
 lib/efi_loader/Kconfig  |  9 +++++++++
 lib/efi_loader/Makefile | 12 ++++++++++++
 4 files changed, 23 insertions(+)
 create mode 100644 lib/efi_loader/Kconfig
 create mode 100644 lib/efi_loader/Makefile

diff --git a/lib/Kconfig b/lib/Kconfig
index c7eab46..a67df3c 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -129,5 +129,6 @@ config ERRNO_STR
 	  - if errno is negative - a pointer to errno related message
 
 source lib/efi/Kconfig
+source lib/efi_loader/Kconfig
 
 endmenu
diff --git a/lib/Makefile b/lib/Makefile
index 1e21bcc..4aaa2ea 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -8,6 +8,7 @@
 ifndef CONFIG_SPL_BUILD
 
 obj-$(CONFIG_EFI) += efi/
+obj-$(CONFIG_EFI_LOADER) += efi_loader/
 obj-$(CONFIG_RSA) += rsa/
 obj-$(CONFIG_LZMA) += lzma/
 obj-$(CONFIG_LZO) += lzo/
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
new file mode 100644
index 0000000..6da1c7f
--- /dev/null
+++ b/lib/efi_loader/Kconfig
@@ -0,0 +1,9 @@
+config EFI_LOADER
+	bool "Support running EFI Applications in U-Boot"
+	depends on ARM64 ||?ARM
+	default y
+	help
+	  Select this option if you want to run EFI applications (like grub2)
+	  on top of U-Boot. If this option is enabled, U-Boot will expose EFI
+	  interfaces to a loaded EFI application, enabling it to reuse U-Boot's
+	  device drivers.
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
new file mode 100644
index 0000000..28725a2
--- /dev/null
+++ b/lib/efi_loader/Makefile
@@ -0,0 +1,12 @@
+#
+# (C) Copyright 2016 Alexander Graf
+#
+#  SPDX-License-Identifier:     GPL-2.0+
+#
+
+# This file only gets included with CONFIG_EFI_LOADER set, so all
+# object inclusion implicitly depends on it
+
+obj-y += efi_image_loader.o efi_boottime.o efi_runtime.o efi_console.o
+obj-y += efi_memory.o
+obj-$(CONFIG_PARTITIONS) += efi_disk.o
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 24/30] efi_loader: Add distro boot script for removable media
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (22 preceding siblings ...)
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 23/30] efi_loader: hook up in build environment Alexander Graf
@ 2016-03-04  0:10 ` Alexander Graf
  2016-03-09 23:05   ` Alexander Graf
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 25/30] efi_loader: Add README section in README.efi Alexander Graf
                   ` (6 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:10 UTC (permalink / raw)
  To: u-boot

UEFI defines a simple boot protocol for removable media. There we should look
at the EFI (first GPT FAT) partition and search for /efi/boot/bootXXX.efi with
XXX being different between different platforms (x86, x64, arm, aa64, ...).

This patch implements a simple version of that protocol for the default distro
boot script. With this we can automatically boot from valid UEFI enabled
removable media.

Because from all I could see U-Boot by default doesn't deliver device tree
blobs with its firmware, we also need to load the dtb from somewhere. Traverse
the same EFI partition for an fdt file that fits our current board so that
an OS receives a valid device tree when booted automatically.

Signed-off-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 include/config_distro_bootcmd.h | 47 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 46 insertions(+), 1 deletion(-)

diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h
index 37c6b43..c19f1b0 100644
--- a/include/config_distro_bootcmd.h
+++ b/include/config_distro_bootcmd.h
@@ -90,6 +90,48 @@
 	BOOT_TARGET_DEVICES_references_UBIFS_without_CONFIG_CMD_UBIFS
 #endif
 
+#ifdef CONFIG_EFI_LOADER
+#if defined(CONFIG_ARM64)
+#define BOOTEFI_NAME "bootaa64.efi"
+#elif defined(CONFIG_ARM)
+#define BOOTEFI_NAME "bootarm.efi"
+#endif
+#endif
+
+#ifdef BOOTEFI_NAME
+#define BOOTENV_SHARED_EFI                                                \
+	"boot_efi_binary="                                                \
+		"load ${devtype} ${devnum}:${distro_bootpart} "           \
+			"${kernel_addr_r} efi/boot/"BOOTEFI_NAME"; "      \
+		"bootefi ${kernel_addr_r}\0"                              \
+	\
+	"load_efi_dtb="                                                   \
+		"load ${devtype} ${devnum}:${distro_bootpart} "           \
+			"${fdt_addr_r} ${prefix}${fdt_name}; "           \
+		"fdt addr ${fdt_addr_r}\0"                                \
+	\
+	"efi_dtb_prefixes=/ /dtb/ /dtb/current/\0"                        \
+	"scan_dev_for_efi="                                               \
+		"for prefix in ${efi_dtb_prefixes}; do "                  \
+			"if test -e ${devtype} "                          \
+					"${devnum}:${distro_bootpart} "   \
+					"${prefix}${fdt_name}; then "     \
+				"run load_efi_dtb; "                      \
+			"fi;"                                             \
+		"done;"                                                   \
+		"if test -e ${devtype} ${devnum}:${distro_bootpart} "     \
+					"efi/boot/"BOOTEFI_NAME"; then "  \
+				"echo Found EFI removable media binary "  \
+					"efi/boot/"BOOTEFI_NAME"; "       \
+				"run boot_efi_binary; "                   \
+				"echo EFI LOAD FAILED: continuing...; "   \
+		"fi; "
+#define SCAN_DEV_FOR_EFI "run scan_dev_for_efi;"
+#else
+#define BOOTENV_SHARED_EFI
+#define SCAN_DEV_FOR_EFI
+#endif
+
 #ifdef CONFIG_CMD_SATA
 #define BOOTENV_SHARED_SATA	BOOTENV_SHARED_BLKDEV(sata)
 #define BOOTENV_DEV_SATA	BOOTENV_DEV_BLKDEV
@@ -217,6 +259,7 @@
 	BOOTENV_SHARED_SCSI \
 	BOOTENV_SHARED_IDE \
 	BOOTENV_SHARED_UBIFS \
+	BOOTENV_SHARED_EFI \
 	"boot_prefixes=/ /boot/\0" \
 	"boot_scripts=boot.scr.uimg boot.scr\0" \
 	"boot_script_dhcp=boot.scr.uimg\0" \
@@ -258,7 +301,9 @@
 		"for prefix in ${boot_prefixes}; do "                     \
 			"run scan_dev_for_extlinux; "                     \
 			"run scan_dev_for_scripts; "                      \
-		"done\0"                                                  \
+		"done;"                                                   \
+		SCAN_DEV_FOR_EFI                                          \
+		"\0"                                                      \
 	\
 	"scan_dev_for_boot_part="                                         \
 		"part list ${devtype} ${devnum} -bootable devplist; "     \
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 25/30] efi_loader: Add README section in README.efi
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (23 preceding siblings ...)
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 24/30] efi_loader: Add distro boot script for removable media Alexander Graf
@ 2016-03-04  0:10 ` Alexander Graf
  2016-03-17  2:02   ` [U-Boot] [U-Boot, v5, " Tom Rini
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 26/30] efi_loader: Add MAINTAINERS entry Alexander Graf
                   ` (5 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:10 UTC (permalink / raw)
  To: u-boot

To preserve all cover letter knowledge of the status on UEFI payload
support, let's add some sections to README.efi.

Signed-off-by: Alexander Graf <agraf@suse.de>

v3 -> v4:

  - Add section about config options
  - s/10kb/10KB/
---
 doc/README.efi | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 82 insertions(+), 1 deletion(-)

diff --git a/doc/README.efi b/doc/README.efi
index 23a3cdd..1fd3f00 100644
--- a/doc/README.efi
+++ b/doc/README.efi
@@ -4,6 +4,28 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
+=========== Table of Contents ===========
+
+  1  U-Boot on EFI
+  1.1  In God's Name, Why?
+  1.2  Status
+  1.3  Build Instructions
+  1.4  Trying it out
+  1.5  Inner workings
+  1.6  EFI Application
+  1.7  EFI Payload
+  1.8  Tables
+  1.9  Interrupts
+  1.10 32/64-bit
+  1.11 Future work
+  1.12 Where is the code?
+
+  2  EFI on U-Boot
+  2.1  In God's Name, Why?
+  2.2  How do I get it?
+  2.3  Status
+  2.4  Future work
+
 U-Boot on EFI
 =============
 This document provides information about U-Boot running on top of EFI, either
@@ -234,7 +256,6 @@ board/efi/efi-x86/efi.c
 common/cmd_efi.c
 	the 'efi' command
 
-
 --
 Ben Stoltz, Simon Glass
 Google, Inc
@@ -242,3 +263,63 @@ July 2015
 
 [1] http://www.qemu.org
 [2] http://www.tianocore.org/ovmf/
+
+-------------------------------------------------------------------------------
+
+EFI on U-Boot
+=============
+
+In addition to support for running U-Boot as a UEFI application, U-Boot itself
+can also expose the UEFI interfaces and thus allow UEFI payloads to run under
+it.
+
+In God's Name, Why?
+-------------------
+
+With this support in place, you can run any UEFI payload (such as the Linux
+kernel, grub2 or gummiboot) on U-Boot. This dramatically simplifies boot loader
+configuration, as U-Boot based systems now look and feel (almost) the same way
+as TianoCore based systems.
+
+How do I get it?
+----------------
+
+EFI support for 32bit ARM and AArch64 is already included in U-Boot. All you
+need to do is enable
+
+  CONFIG_CMD_BOOTEFI=y
+  CONFIG_EFI_LOADER=y
+
+in your .config file and you will automatically get a bootefi command to run
+an efi application as well as snippet in the default distro boot script that
+scans for removable media efi binaries as fallback.
+
+Status
+------
+
+I am successfully able to run grub2 and Linux EFI binaries with this code on
+ARMv7 as well as AArch64 systems.
+
+When enabled, the resulting U-Boot binary only grows by ~10KB, so it's very
+light weight.
+
+All storage devices are directly accessible from the uEFI payload
+
+Removable media booting (search for /efi/boot/boota{a64,arm}.efi) is supported.
+
+Simple use cases like "Plug this SD card into my ARM device and it just
+boots into grub which boots into Linux", work very well.
+
+Future work
+-----------
+
+Of course, there are still a few things one could do on top:
+
+   - Improve disk media detection (don't scan, use what information we
+have)
+   - Add EFI variable support using NVRAM
+   - Add GFX support
+   - Make EFI Shell work
+   - Network device support
+   - Support for payload exit
+   - Payload Watchdog support
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 26/30] efi_loader: Add MAINTAINERS entry
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (24 preceding siblings ...)
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 25/30] efi_loader: Add README section in README.efi Alexander Graf
@ 2016-03-04  0:10 ` Alexander Graf
  2016-03-17  2:02   ` [U-Boot] [U-Boot,v5,26/30] " Tom Rini
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 27/30] arm64: Replace fdt_name env variables with fdtfile Alexander Graf
                   ` (4 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:10 UTC (permalink / raw)
  To: u-boot

Now that everything's in place, let's add myself as the maintainer for
the efi payload support.

Signed-off-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 9d447ea..32f97b2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -230,6 +230,13 @@ F:	drivers/core/
 F:	include/dm/
 F:	test/dm/
 
+EFI PAYLOAD
+M:	Alexander Graf <agraf@suse.de>
+S:	Maintained
+F:	include/efi_loader.h
+F:	lib/efi_loader/
+F:	cmd/bootefi.c
+
 FLATTENED DEVICE TREE
 M:	Simon Glass <sjg@chromium.org>
 S:	Maintained
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 27/30] arm64: Replace fdt_name env variables with fdtfile
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (25 preceding siblings ...)
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 26/30] efi_loader: Add MAINTAINERS entry Alexander Graf
@ 2016-03-04  0:10 ` Alexander Graf
  2016-03-17  2:02   ` [U-Boot] [U-Boot, v5, " Tom Rini
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 28/30] arm: Allow EFI payload code to take exceptions Alexander Graf
                   ` (3 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:10 UTC (permalink / raw)
  To: u-boot

The commonly defined environment variable to determine the device tree
file name is called fdtfile rather than fdt_name. Replace all occurences
of fdt_name with fdtfile.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 include/config_distro_bootcmd.h   |  4 ++--
 include/configs/hikey.h           |  2 +-
 include/configs/vexpress_aemv8a.h | 10 +++++-----
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h
index c19f1b0..e7d7002 100644
--- a/include/config_distro_bootcmd.h
+++ b/include/config_distro_bootcmd.h
@@ -107,7 +107,7 @@
 	\
 	"load_efi_dtb="                                                   \
 		"load ${devtype} ${devnum}:${distro_bootpart} "           \
-			"${fdt_addr_r} ${prefix}${fdt_name}; "           \
+			"${fdt_addr_r} ${prefix}${fdtfile}; "             \
 		"fdt addr ${fdt_addr_r}\0"                                \
 	\
 	"efi_dtb_prefixes=/ /dtb/ /dtb/current/\0"                        \
@@ -115,7 +115,7 @@
 		"for prefix in ${efi_dtb_prefixes}; do "                  \
 			"if test -e ${devtype} "                          \
 					"${devnum}:${distro_bootpart} "   \
-					"${prefix}${fdt_name}; then "     \
+					"${prefix}${fdtfile}; then "      \
 				"run load_efi_dtb; "                      \
 			"fi;"                                             \
 		"done;"                                                   \
diff --git a/include/configs/hikey.h b/include/configs/hikey.h
index 2d9ace9..f3ae0dd 100644
--- a/include/configs/hikey.h
+++ b/include/configs/hikey.h
@@ -121,7 +121,7 @@
 #define CONFIG_EXTRA_ENV_SETTINGS	\
 				"kernel_name=Image\0"	\
 				"kernel_addr_r=0x00080000\0" \
-				"fdt_name=hi6220-hikey.dtb\0" \
+				"fdtfile=hi6220-hikey.dtb\0" \
 				"fdt_addr_r=0x02000000\0" \
 				"fdt_high=0xffffffffffffffff\0" \
 				"initrd_high=0xffffffffffffffff\0" \
diff --git a/include/configs/vexpress_aemv8a.h b/include/configs/vexpress_aemv8a.h
index 2949170..3e588c0 100644
--- a/include/configs/vexpress_aemv8a.h
+++ b/include/configs/vexpress_aemv8a.h
@@ -191,7 +191,7 @@
 				"kernel_addr=0x80080000\0" \
 				"initrd_name=ramdisk.img\0"	\
 				"initrd_addr=0x84000000\0"	\
-				"fdt_name=board.dtb\0" \
+				"fdtfile=board.dtb\0" \
 				"fdt_alt_name=juno\0" \
 				"fdt_addr=0x83000000\0" \
 				"fdt_high=0xffffffffffffffff\0" \
@@ -213,10 +213,10 @@
 				"${kernel_name}; "\
 				"  afs load ${kernel_alt_name} ${kernel_addr};"\
 				"fi ; "\
-				"afs load  ${fdt_name} ${fdt_addr} ; " \
+				"afs load  ${fdtfile} ${fdt_addr} ; " \
 				"if test $? -eq 1; then "\
 				"  echo Loading ${fdt_alt_name} instead of "\
-				"${fdt_name}; "\
+				"${fdtfile}; "\
 				"  afs load ${fdt_alt_name} ${fdt_addr}; "\
 				"fi ; "\
 				"fdt addr ${fdt_addr}; fdt resize; " \
@@ -235,7 +235,7 @@
 				"kernel_addr=0x80080000\0"	\
 				"initrd_name=ramdisk.img\0"	\
 				"initrd_addr=0x88000000\0"	\
-				"fdt_name=devtree.dtb\0"	\
+				"fdtfile=devtree.dtb\0"		\
 				"fdt_addr=0x83000000\0"		\
 				"fdt_high=0xffffffffffffffff\0"	\
 				"initrd_high=0xffffffffffffffff\0"
@@ -245,7 +245,7 @@
 				"loglevel=9"
 
 #define CONFIG_BOOTCOMMAND	"smhload ${kernel_name} ${kernel_addr}; " \
-				"smhload ${fdt_name} ${fdt_addr}; " \
+				"smhload ${fdtfile} ${fdt_addr}; " \
 				"smhload ${initrd_name} ${initrd_addr} "\
 				"initrd_end; " \
 				"fdt addr ${fdt_addr}; fdt resize; " \
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 28/30] arm: Allow EFI payload code to take exceptions
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (26 preceding siblings ...)
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 27/30] arm64: Replace fdt_name env variables with fdtfile Alexander Graf
@ 2016-03-04  0:10 ` Alexander Graf
  2016-03-17  2:03   ` [U-Boot] [U-Boot, v5, " Tom Rini
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 29/30] efi_loader: Call fdt preparation functions Alexander Graf
                   ` (2 subsequent siblings)
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:10 UTC (permalink / raw)
  To: u-boot

There are 2 ways an EFI payload could return into u-boot:

  - Callback function
  - Exception

While in EFI payload mode, r9 is owned by the payload and may not contain
a valid pointer to gd, so we need to fix it up. We do that properly for the
payload to callback path already.

This patch also adds gd pointer restoral for the exception path.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 arch/arm/lib/interrupts.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/lib/interrupts.c b/arch/arm/lib/interrupts.c
index ec3fb77..ed83043 100644
--- a/arch/arm/lib/interrupts.c
+++ b/arch/arm/lib/interrupts.c
@@ -22,6 +22,7 @@
 #include <common.h>
 #include <asm/proc-armv/ptrace.h>
 #include <asm/u-boot-arm.h>
+#include <efi_loader.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -165,6 +166,7 @@ void show_regs (struct pt_regs *regs)
 
 void do_undefined_instruction (struct pt_regs *pt_regs)
 {
+	efi_restore_gd();
 	printf ("undefined instruction\n");
 	show_regs (pt_regs);
 	bad_mode ();
@@ -172,6 +174,7 @@ void do_undefined_instruction (struct pt_regs *pt_regs)
 
 void do_software_interrupt (struct pt_regs *pt_regs)
 {
+	efi_restore_gd();
 	printf ("software interrupt\n");
 	show_regs (pt_regs);
 	bad_mode ();
@@ -179,6 +182,7 @@ void do_software_interrupt (struct pt_regs *pt_regs)
 
 void do_prefetch_abort (struct pt_regs *pt_regs)
 {
+	efi_restore_gd();
 	printf ("prefetch abort\n");
 	show_regs (pt_regs);
 	bad_mode ();
@@ -186,6 +190,7 @@ void do_prefetch_abort (struct pt_regs *pt_regs)
 
 void do_data_abort (struct pt_regs *pt_regs)
 {
+	efi_restore_gd();
 	printf ("data abort\n");
 	show_regs (pt_regs);
 	bad_mode ();
@@ -193,6 +198,7 @@ void do_data_abort (struct pt_regs *pt_regs)
 
 void do_not_used (struct pt_regs *pt_regs)
 {
+	efi_restore_gd();
 	printf ("not used\n");
 	show_regs (pt_regs);
 	bad_mode ();
@@ -200,6 +206,7 @@ void do_not_used (struct pt_regs *pt_regs)
 
 void do_fiq (struct pt_regs *pt_regs)
 {
+	efi_restore_gd();
 	printf ("fast interrupt request\n");
 	show_regs (pt_regs);
 	bad_mode ();
@@ -208,6 +215,7 @@ void do_fiq (struct pt_regs *pt_regs)
 #ifndef CONFIG_USE_IRQ
 void do_irq (struct pt_regs *pt_regs)
 {
+	efi_restore_gd();
 	printf ("interrupt request\n");
 	show_regs (pt_regs);
 	bad_mode ();
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 29/30] efi_loader: Call fdt preparation functions
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (27 preceding siblings ...)
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 28/30] arm: Allow EFI payload code to take exceptions Alexander Graf
@ 2016-03-04  0:10 ` Alexander Graf
  2016-03-17  2:03   ` [U-Boot] [U-Boot, v5, " Tom Rini
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 30/30] efi_loader: Pass proper device path in on boot Alexander Graf
  2016-03-04  9:19 ` [U-Boot] [PATCH] efi_loader: Reserve 2 additional pages for fdt Alexander Graf
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:10 UTC (permalink / raw)
  To: u-boot

We have a nice framework around image fils to prepare a device tree
for OS execution. That one patches in missing device tree nodes and
fixes up the memory range bits.

We need to call that one from the EFI boot path too to get all those
nice fixups. This patch adds the call.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 cmd/bootefi.c      | 8 ++++++++
 common/image-fdt.c | 8 +++++---
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 2a40fb0..7fce1d0 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -92,6 +92,7 @@ static unsigned long do_bootefi_exec(void *efi)
 {
 	ulong (*entry)(void *image_handle, struct efi_system_table *st);
 	ulong fdt_pages, fdt_size, fdt_start, fdt_end;
+	bootm_headers_t img = { 0 };
 
 	/*
 	 * gd lives in a fixed register which may get clobbered while we execute
@@ -102,6 +103,13 @@ static unsigned long do_bootefi_exec(void *efi)
 	/* Update system table to point to our currently loaded FDT */
 
 	if (working_fdt) {
+		/* Prepare fdt for payload */
+		if (image_setup_libfdt(&img, working_fdt, 0, NULL)) {
+			printf("ERROR: Failed to process device tree\n");
+			return -EINVAL;
+		}
+
+		/* Link to it in the efi tables */
 		systab.tables[0].guid = EFI_FDT_GUID;
 		systab.tables[0].table = working_fdt;
 		systab.nr_tables = 1;
diff --git a/common/image-fdt.c b/common/image-fdt.c
index 79fa655..5a1b432 100644
--- a/common/image-fdt.c
+++ b/common/image-fdt.c
@@ -502,8 +502,9 @@ int image_setup_libfdt(bootm_headers_t *images, void *blob,
 	fdt_fixup_ethernet(blob);
 
 	/* Delete the old LMB reservation */
-	lmb_free(lmb, (phys_addr_t)(u32)(uintptr_t)blob,
-		 (phys_size_t)fdt_totalsize(blob));
+	if (lmb)
+		lmb_free(lmb, (phys_addr_t)(u32)(uintptr_t)blob,
+			 (phys_size_t)fdt_totalsize(blob));
 
 	ret = fdt_shrink_to_minimum(blob);
 	if (ret < 0)
@@ -515,7 +516,8 @@ int image_setup_libfdt(bootm_headers_t *images, void *blob,
 		fdt_set_totalsize(blob, of_size);
 	}
 	/* Create a new LMB reservation */
-	lmb_reserve(lmb, (ulong)blob, of_size);
+	if (lmb)
+		lmb_reserve(lmb, (ulong)blob, of_size);
 
 	fdt_initrd(blob, *initrd_start, *initrd_end);
 	if (!ft_verify_fdt(blob))
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 30/30] efi_loader: Pass proper device path in on boot
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (28 preceding siblings ...)
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 29/30] efi_loader: Call fdt preparation functions Alexander Graf
@ 2016-03-04  0:10 ` Alexander Graf
  2016-03-17  2:03   ` [U-Boot] [U-Boot, v5, " Tom Rini
  2016-03-04  9:19 ` [U-Boot] [PATCH] efi_loader: Reserve 2 additional pages for fdt Alexander Graf
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  0:10 UTC (permalink / raw)
  To: u-boot

EFI payloads can query for the device they were booted from. Because
we have a disconnect between loading binaries and running binaries,
we passed in a dummy device path so far.

Unfortunately that breaks grub2's logic to find its configuration
file from the same device it was booted from.

This patch adds logic to have the "load" command call into our efi
code to set the device path to the one we last loaded a binary from.

With this grub2 properly detects where we got booted from and can
find its configuration file, even when searching by-partition.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 cmd/bootefi.c             | 34 +++++++++++++++++++++++++---------
 cmd/fs.c                  |  2 ++
 include/efi_loader.h      | 10 ++++++++++
 lib/efi_loader/efi_disk.c |  6 ------
 4 files changed, 37 insertions(+), 15 deletions(-)

diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 7fce1d0..de17e49 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -21,16 +21,16 @@
  * In addition to the originating device we also declare the file path
  * of "bootefi" based loads to be /bootefi.
  */
-static struct efi_device_path_file_path bootefi_dummy_path[] = {
+static struct efi_device_path_file_path bootefi_image_path[] = {
 	{
 		.dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE,
 		.dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH,
-		.dp.length = sizeof(bootefi_dummy_path[0]),
+		.dp.length = sizeof(bootefi_image_path[0]),
 		.str = { 'b','o','o','t','e','f','i' },
 	}, {
 		.dp.type = DEVICE_PATH_TYPE_END,
 		.dp.sub_type = DEVICE_PATH_SUB_TYPE_END,
-		.dp.length = sizeof(bootefi_dummy_path[0]),
+		.dp.length = sizeof(bootefi_image_path[0]),
 	}
 };
 
@@ -38,14 +38,14 @@ static efi_status_t bootefi_open_dp(void *handle, efi_guid_t *protocol,
 			void **protocol_interface, void *agent_handle,
 			void *controller_handle, uint32_t attributes)
 {
-	*protocol_interface = bootefi_dummy_path;
+	*protocol_interface = bootefi_image_path;
 	return EFI_SUCCESS;
 }
 
 /* The EFI loaded_image interface for the image executed via "bootefi" */
 static struct efi_loaded_image loaded_image_info = {
-	.device_handle = bootefi_dummy_path,
-	.file_path = bootefi_dummy_path,
+	.device_handle = bootefi_image_path,
+	.file_path = bootefi_image_path,
 };
 
 /* The EFI object struct for the image executed via "bootefi" */
@@ -63,7 +63,7 @@ static struct efi_object loaded_image_info_obj = {
 		{
 			/*
 			 * When asking for the device path interface, return
-			 * bootefi_dummy_path
+			 * bootefi_image_path
 			 */
 			.guid = &efi_guid_device_path,
 			.open = &bootefi_open_dp,
@@ -73,11 +73,11 @@ static struct efi_object loaded_image_info_obj = {
 
 /* The EFI object struct for the device the "bootefi" image was loaded from */
 static struct efi_object bootefi_device_obj = {
-	.handle = bootefi_dummy_path,
+	.handle = bootefi_image_path,
 	.protocols = {
 		{
 			/* When asking for the device path interface, return
-			 * bootefi_dummy_path */
+			 * bootefi_image_path */
 			.guid = &efi_guid_device_path,
 			.open = &bootefi_open_dp,
 		}
@@ -184,3 +184,19 @@ U_BOOT_CMD(
 	"Boots an EFI payload from memory\n",
 	bootefi_help_text
 );
+
+void efi_set_bootdev(const char *dev, const char *devnr)
+{
+	char devname[16] = { 0 }; /* dp->str is u16[16] long */
+	char *colon;
+
+	/* Assemble the condensed device name we use in efi_disk.c */
+	snprintf(devname, sizeof(devname), "%s%s", dev, devnr);
+	colon = strchr(devname, ':');
+	if (colon)
+		*colon = '\0';
+
+	/* Patch the bootefi_image_path to the target device */
+	memset(bootefi_image_path[0].str, 0, sizeof(bootefi_image_path[0].str));
+	ascii2unicode(bootefi_image_path[0].str, devname);
+}
diff --git a/cmd/fs.c b/cmd/fs.c
index 8f8f1b2..be8f289 100644
--- a/cmd/fs.c
+++ b/cmd/fs.c
@@ -9,6 +9,7 @@
 #include <common.h>
 #include <command.h>
 #include <fs.h>
+#include <efi_loader.h>
 
 static int do_size_wrapper(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
@@ -26,6 +27,7 @@ U_BOOT_CMD(
 static int do_load_wrapper(cmd_tbl_t *cmdtp, int flag, int argc,
 				char * const argv[])
 {
+	efi_set_bootdev(argv[1], (argc > 2) ? argv[2] : "");
 	return do_load(cmdtp, flag, argc, argv, FS_TYPE_ANY);
 }
 
diff --git a/include/efi_loader.h b/include/efi_loader.h
index e344566..385239b 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -108,6 +108,8 @@ void efi_restore_gd(void);
 efi_status_t efi_exit_func(efi_status_t ret);
 /* Call this to relocate the runtime section to an address space */
 void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map);
+/* Call this to set the current device name */
+void efi_set_bootdev(const char *dev, const char *devnr);
 
 /* Generic EFI memory allocator, call this to get memory */
 void *efi_alloc(uint64_t len, int memory_type);
@@ -128,6 +130,13 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type,
 /* Called by board init to initialize the EFI memory map */
 int efi_memory_init(void);
 
+/* Convert strings from normal C strings to uEFI strings */
+static inline void ascii2unicode(u16 *unicode, char *ascii)
+{
+	while (*ascii)
+		*(unicode++) = *(ascii++);
+}
+
 /*
  * 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
@@ -143,5 +152,6 @@ int efi_memory_init(void);
 
 /* No loader configured, stub out EFI_ENTRY */
 static inline void efi_restore_gd(void) { }
+static inline void efi_set_bootdev(const char *dev, const char *devnr) { }
 
 #endif
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index f93fcb2..9bdfad3 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -29,12 +29,6 @@ struct efi_disk_obj {
 	struct efi_device_path_file_path *dp;
 };
 
-static void ascii2unicode(u16 *unicode, char *ascii)
-{
-	while (*ascii)
-		*(unicode++) = *(ascii++);
-}
-
 static efi_status_t efi_disk_open_block(void *handle, efi_guid_t *protocol,
 			void **protocol_interface, void *agent_handle,
 			void *controller_handle, uint32_t attributes)
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH] efi_loader: Reserve 2 additional pages for fdt
  2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
                   ` (29 preceding siblings ...)
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 30/30] efi_loader: Pass proper device path in on boot Alexander Graf
@ 2016-03-04  9:19 ` Alexander Graf
  2016-03-04  9:41   ` Leif Lindholm
  30 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-04  9:19 UTC (permalink / raw)
  To: u-boot

We mark the device tree as reserved today, spanning exactly the amount
of space it needs. If some other piece of code (like grub2) comes in and
wants to modify the device tree to for example add a kernel command line
though, it might assume that it has some space to do so.

So let's just reserve 2 additional pages for the device tree to play nicely.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 cmd/bootefi.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index de17e49..faa6978 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -119,6 +119,8 @@ static unsigned long do_bootefi_exec(void *efi)
 		fdt_end = ((ulong)working_fdt) + fdt_totalsize(working_fdt);
 		fdt_size = (fdt_end - fdt_start) + EFI_PAGE_MASK;
 		fdt_pages = fdt_size >> EFI_PAGE_SHIFT;
+		/* Give a bootloader the chance to modify the device tree */
+		fdt_pages += 2;
 		efi_add_memory_map(fdt_start, fdt_pages,
 				   EFI_BOOT_SERVICES_DATA, true);
 
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH] efi_loader: Reserve 2 additional pages for fdt
  2016-03-04  9:19 ` [U-Boot] [PATCH] efi_loader: Reserve 2 additional pages for fdt Alexander Graf
@ 2016-03-04  9:41   ` Leif Lindholm
  0 siblings, 0 replies; 67+ messages in thread
From: Leif Lindholm @ 2016-03-04  9:41 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 10:19:10AM +0100, Alexander Graf wrote:
> We mark the device tree as reserved today, spanning exactly the amount
> of space it needs. If some other piece of code (like grub2) comes in and
> wants to modify the device tree to for example add a kernel command line
> though, it might assume that it has some space to do so.
> 
> So let's just reserve 2 additional pages for the device tree to play nicely.

I presume this was triggered by something you found on AArch32 grub,
booting a kernel without EFI stub?
If so, the issue will go away once I fix the AArch32 grub to use the
AArch64 loader for kernel images with the EFI stub. Could you possibly
send an email to grub-devel, or raise a ticket directly on the
savannah bugtracker if you have an account?
This fix really should go into 2.02 release.

Regardless, this seems like it provides a potential optimisation
opportunity for such agents, to use the tree in place instead of
always allocating more memory.

> Signed-off-by: Alexander Graf <agraf@suse.de>
> ---
>  cmd/bootefi.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/cmd/bootefi.c b/cmd/bootefi.c
> index de17e49..faa6978 100644
> --- a/cmd/bootefi.c
> +++ b/cmd/bootefi.c
> @@ -119,6 +119,8 @@ static unsigned long do_bootefi_exec(void *efi)
>  		fdt_end = ((ulong)working_fdt) + fdt_totalsize(working_fdt);
>  		fdt_size = (fdt_end - fdt_start) + EFI_PAGE_MASK;
>  		fdt_pages = fdt_size >> EFI_PAGE_SHIFT;
> +		/* Give a bootloader the chance to modify the device tree */
> +		fdt_pages += 2;
>  		efi_add_memory_map(fdt_start, fdt_pages,
>  				   EFI_BOOT_SERVICES_DATA, true);
>  
> -- 
> 1.8.5.6
> 

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 24/30] efi_loader: Add distro boot script for removable media
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 24/30] efi_loader: Add distro boot script for removable media Alexander Graf
@ 2016-03-09 23:05   ` Alexander Graf
  2016-03-09 23:16     ` Tom Rini
  0 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-09 23:05 UTC (permalink / raw)
  To: u-boot



On 04.03.16 01:10, Alexander Graf wrote:
> UEFI defines a simple boot protocol for removable media. There we should look
> at the EFI (first GPT FAT) partition and search for /efi/boot/bootXXX.efi with
> XXX being different between different platforms (x86, x64, arm, aa64, ...).
> 
> This patch implements a simple version of that protocol for the default distro
> boot script. With this we can automatically boot from valid UEFI enabled
> removable media.
> 
> Because from all I could see U-Boot by default doesn't deliver device tree
> blobs with its firmware, we also need to load the dtb from somewhere. Traverse
> the same EFI partition for an fdt file that fits our current board so that
> an OS receives a valid device tree when booted automatically.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> ---
>  include/config_distro_bootcmd.h | 47 ++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 46 insertions(+), 1 deletion(-)
> 
> diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h
> index 37c6b43..c19f1b0 100644
> --- a/include/config_distro_bootcmd.h
> +++ b/include/config_distro_bootcmd.h
> @@ -90,6 +90,48 @@
>  	BOOT_TARGET_DEVICES_references_UBIFS_without_CONFIG_CMD_UBIFS
>  #endif
>  
> +#ifdef CONFIG_EFI_LOADER
> +#if defined(CONFIG_ARM64)
> +#define BOOTEFI_NAME "bootaa64.efi"
> +#elif defined(CONFIG_ARM)
> +#define BOOTEFI_NAME "bootarm.efi"
> +#endif
> +#endif
> +
> +#ifdef BOOTEFI_NAME
> +#define BOOTENV_SHARED_EFI                                                \
> +	"boot_efi_binary="                                                \
> +		"load ${devtype} ${devnum}:${distro_bootpart} "           \
> +			"${kernel_addr_r} efi/boot/"BOOTEFI_NAME"; "      \
> +		"bootefi ${kernel_addr_r}\0"                              \
> +	\
> +	"load_efi_dtb="                                                   \
> +		"load ${devtype} ${devnum}:${distro_bootpart} "           \
> +			"${fdt_addr_r} ${prefix}${fdt_name}; "           \
> +		"fdt addr ${fdt_addr_r}\0"                                \
> +	\
> +	"efi_dtb_prefixes=/ /dtb/ /dtb/current/\0"                        \
> +	"scan_dev_for_efi="                                               \
> +		"for prefix in ${efi_dtb_prefixes}; do "                  \
> +			"if test -e ${devtype} "                          \
> +					"${devnum}:${distro_bootpart} "   \
> +					"${prefix}${fdt_name}; then "     \
> +				"run load_efi_dtb; "                      \
> +			"fi;"                                             \
> +		"done;"                                                   \
> +		"if test -e ${devtype} ${devnum}:${distro_bootpart} "     \
> +					"efi/boot/"BOOTEFI_NAME"; then "  \
> +				"echo Found EFI removable media binary "  \
> +					"efi/boot/"BOOTEFI_NAME"; "       \
> +				"run boot_efi_binary; "                   \
> +				"echo EFI LOAD FAILED: continuing...; "   \
> +		"fi; "

Whoever applies this, please also apply the patch below on top and
squash it in (or tell me to resend). Without the fix, we end up slurping
the boot_prefix variable into the scan_dev_for_efi variable.


Alex

diff --git a/include/config_distro_bootcmd.h
b/include/config_distro_bootcmd.h
index e7d7002..ad9045e 100644
--- a/include/config_distro_bootcmd.h
+++ b/include/config_distro_bootcmd.h
@@ -125,7 +125,7 @@
                                        "efi/boot/"BOOTEFI_NAME"; "       \
                                "run boot_efi_binary; "                   \
                                "echo EFI LOAD FAILED: continuing...; "   \
-               "fi; "
+               "fi; \0"
 #define SCAN_DEV_FOR_EFI "run scan_dev_for_efi;"
 #else
 #define BOOTENV_SHARED_EFI

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v5 24/30] efi_loader: Add distro boot script for removable media
  2016-03-09 23:05   ` Alexander Graf
@ 2016-03-09 23:16     ` Tom Rini
  2016-03-09 23:26       ` [U-Boot] [PATCH v6 " Alexander Graf
  0 siblings, 1 reply; 67+ messages in thread
From: Tom Rini @ 2016-03-09 23:16 UTC (permalink / raw)
  To: u-boot

On Thu, Mar 10, 2016 at 12:05:12AM +0100, Alexander Graf wrote:
> 
> 
> On 04.03.16 01:10, Alexander Graf wrote:
> > UEFI defines a simple boot protocol for removable media. There we should look
> > at the EFI (first GPT FAT) partition and search for /efi/boot/bootXXX.efi with
> > XXX being different between different platforms (x86, x64, arm, aa64, ...).
> > 
> > This patch implements a simple version of that protocol for the default distro
> > boot script. With this we can automatically boot from valid UEFI enabled
> > removable media.
> > 
> > Because from all I could see U-Boot by default doesn't deliver device tree
> > blobs with its firmware, we also need to load the dtb from somewhere. Traverse
> > the same EFI partition for an fdt file that fits our current board so that
> > an OS receives a valid device tree when booted automatically.
> > 
> > Signed-off-by: Alexander Graf <agraf@suse.de>
> > Reviewed-by: Simon Glass <sjg@chromium.org>
> > ---
> >  include/config_distro_bootcmd.h | 47 ++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 46 insertions(+), 1 deletion(-)
> > 
> > diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h
> > index 37c6b43..c19f1b0 100644
> > --- a/include/config_distro_bootcmd.h
> > +++ b/include/config_distro_bootcmd.h
> > @@ -90,6 +90,48 @@
> >  	BOOT_TARGET_DEVICES_references_UBIFS_without_CONFIG_CMD_UBIFS
> >  #endif
> >  
> > +#ifdef CONFIG_EFI_LOADER
> > +#if defined(CONFIG_ARM64)
> > +#define BOOTEFI_NAME "bootaa64.efi"
> > +#elif defined(CONFIG_ARM)
> > +#define BOOTEFI_NAME "bootarm.efi"
> > +#endif
> > +#endif
> > +
> > +#ifdef BOOTEFI_NAME
> > +#define BOOTENV_SHARED_EFI                                                \
> > +	"boot_efi_binary="                                                \
> > +		"load ${devtype} ${devnum}:${distro_bootpart} "           \
> > +			"${kernel_addr_r} efi/boot/"BOOTEFI_NAME"; "      \
> > +		"bootefi ${kernel_addr_r}\0"                              \
> > +	\
> > +	"load_efi_dtb="                                                   \
> > +		"load ${devtype} ${devnum}:${distro_bootpart} "           \
> > +			"${fdt_addr_r} ${prefix}${fdt_name}; "           \
> > +		"fdt addr ${fdt_addr_r}\0"                                \
> > +	\
> > +	"efi_dtb_prefixes=/ /dtb/ /dtb/current/\0"                        \
> > +	"scan_dev_for_efi="                                               \
> > +		"for prefix in ${efi_dtb_prefixes}; do "                  \
> > +			"if test -e ${devtype} "                          \
> > +					"${devnum}:${distro_bootpart} "   \
> > +					"${prefix}${fdt_name}; then "     \
> > +				"run load_efi_dtb; "                      \
> > +			"fi;"                                             \
> > +		"done;"                                                   \
> > +		"if test -e ${devtype} ${devnum}:${distro_bootpart} "     \
> > +					"efi/boot/"BOOTEFI_NAME"; then "  \
> > +				"echo Found EFI removable media binary "  \
> > +					"efi/boot/"BOOTEFI_NAME"; "       \
> > +				"run boot_efi_binary; "                   \
> > +				"echo EFI LOAD FAILED: continuing...; "   \
> > +		"fi; "
> 
> Whoever applies this, please also apply the patch below on top and
> squash it in (or tell me to resend). Without the fix, we end up slurping
> the boot_prefix variable into the scan_dev_for_efi variable.
> 
> 
> Alex
> 
> diff --git a/include/config_distro_bootcmd.h
> b/include/config_distro_bootcmd.h
> index e7d7002..ad9045e 100644
> --- a/include/config_distro_bootcmd.h
> +++ b/include/config_distro_bootcmd.h
> @@ -125,7 +125,7 @@
>                                         "efi/boot/"BOOTEFI_NAME"; "       \
>                                 "run boot_efi_binary; "                   \
>                                 "echo EFI LOAD FAILED: continuing...; "   \
> -               "fi; "
> +               "fi; \0"
>  #define SCAN_DEV_FOR_EFI "run scan_dev_for_efi;"
>  #else
>  #define BOOTENV_SHARED_EFI

Please make just a v6 of this patch and re-post, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160309/b5772c93/attachment.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v6 24/30] efi_loader: Add distro boot script for removable media
  2016-03-09 23:16     ` Tom Rini
@ 2016-03-09 23:26       ` Alexander Graf
  2016-03-17  2:02         ` [U-Boot] [U-Boot, v6, " Tom Rini
  0 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-09 23:26 UTC (permalink / raw)
  To: u-boot

UEFI defines a simple boot protocol for removable media. There we should look
at the EFI (first GPT FAT) partition and search for /efi/boot/bootXXX.efi with
XXX being different between different platforms (x86, x64, arm, aa64, ...).

This patch implements a simple version of that protocol for the default distro
boot script. With this we can automatically boot from valid UEFI enabled
removable media.

Because from all I could see U-Boot by default doesn't deliver device tree
blobs with its firmware, we also need to load the dtb from somewhere. Traverse
the same EFI partition for an fdt file that fits our current board so that
an OS receives a valid device tree when booted automatically.

Signed-off-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

v5 -> v6:

  - Fix missing 0-terminator
---
 include/config_distro_bootcmd.h | 47 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 46 insertions(+), 1 deletion(-)

diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h
index 37c6b43..5792d29 100644
--- a/include/config_distro_bootcmd.h
+++ b/include/config_distro_bootcmd.h
@@ -90,6 +90,48 @@
 	BOOT_TARGET_DEVICES_references_UBIFS_without_CONFIG_CMD_UBIFS
 #endif
 
+#ifdef CONFIG_EFI_LOADER
+#if defined(CONFIG_ARM64)
+#define BOOTEFI_NAME "bootaa64.efi"
+#elif defined(CONFIG_ARM)
+#define BOOTEFI_NAME "bootarm.efi"
+#endif
+#endif
+
+#ifdef BOOTEFI_NAME
+#define BOOTENV_SHARED_EFI                                                \
+	"boot_efi_binary="                                                \
+		"load ${devtype} ${devnum}:${distro_bootpart} "           \
+			"${kernel_addr_r} efi/boot/"BOOTEFI_NAME"; "      \
+		"bootefi ${kernel_addr_r}\0"                              \
+	\
+	"load_efi_dtb="                                                   \
+		"load ${devtype} ${devnum}:${distro_bootpart} "           \
+			"${fdt_addr_r} ${prefix}${fdt_name}; "           \
+		"fdt addr ${fdt_addr_r}\0"                                \
+	\
+	"efi_dtb_prefixes=/ /dtb/ /dtb/current/\0"                        \
+	"scan_dev_for_efi="                                               \
+		"for prefix in ${efi_dtb_prefixes}; do "                  \
+			"if test -e ${devtype} "                          \
+					"${devnum}:${distro_bootpart} "   \
+					"${prefix}${fdt_name}; then "     \
+				"run load_efi_dtb; "                      \
+			"fi;"                                             \
+		"done;"                                                   \
+		"if test -e ${devtype} ${devnum}:${distro_bootpart} "     \
+					"efi/boot/"BOOTEFI_NAME"; then "  \
+				"echo Found EFI removable media binary "  \
+					"efi/boot/"BOOTEFI_NAME"; "       \
+				"run boot_efi_binary; "                   \
+				"echo EFI LOAD FAILED: continuing...; "   \
+		"fi; \0"
+#define SCAN_DEV_FOR_EFI "run scan_dev_for_efi;"
+#else
+#define BOOTENV_SHARED_EFI
+#define SCAN_DEV_FOR_EFI
+#endif
+
 #ifdef CONFIG_CMD_SATA
 #define BOOTENV_SHARED_SATA	BOOTENV_SHARED_BLKDEV(sata)
 #define BOOTENV_DEV_SATA	BOOTENV_DEV_BLKDEV
@@ -217,6 +259,7 @@
 	BOOTENV_SHARED_SCSI \
 	BOOTENV_SHARED_IDE \
 	BOOTENV_SHARED_UBIFS \
+	BOOTENV_SHARED_EFI \
 	"boot_prefixes=/ /boot/\0" \
 	"boot_scripts=boot.scr.uimg boot.scr\0" \
 	"boot_script_dhcp=boot.scr.uimg\0" \
@@ -258,7 +301,9 @@
 		"for prefix in ${boot_prefixes}; do "                     \
 			"run scan_dev_for_extlinux; "                     \
 			"run scan_dev_for_scripts; "                      \
-		"done\0"                                                  \
+		"done;"                                                   \
+		SCAN_DEV_FOR_EFI                                          \
+		"\0"                                                      \
 	\
 	"scan_dev_for_boot_part="                                         \
 		"part list ${devtype} ${devnum} -bootable devplist; "     \
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [PATCH v6 19/30] efi_loader: Add "bootefi" command
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 19/30] efi_loader: Add "bootefi" command Alexander Graf
@ 2016-03-09 23:27   ` Alexander Graf
  2016-03-17  2:01     ` [U-Boot] [U-Boot,v6,19/30] " Tom Rini
  0 siblings, 1 reply; 67+ messages in thread
From: Alexander Graf @ 2016-03-09 23:27 UTC (permalink / raw)
  To: u-boot

In order to execute an EFI application, we need to bridge the gap between
U-Boot's notion of executing images and EFI's notion of doing the same.

The best path forward IMHO here is to stick completely to the way U-Boot
deals with payloads. You manually load them using whatever method to RAM
and then have a simple boot command to execute them. So in our case, you
would do

  # load mmc 0:1 $loadaddr grub.efi
  # bootefi $loadaddr

which then gets you into a grub shell. Fdt information known to U-boot
via the fdt addr command is also passed to the EFI payload.

Signed-off-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
Tested-by: Simon Glass <sjg@chromium.org>

---

v1 -> v2:

  - Move to GPLv2+

v2 -> v3:

  - Move to new cmd directory
  - Add kconfig option
  - Fix comment style
  - Add help text
  - s/-1/-ENOENT
  - Move obj list to lib

v4 -> v5:

  - Mark fdt memory as boot services data

v5 -> v6:

  - Reserve 2 additional pages for fdt

---
 cmd/Kconfig   |   7 +++
 cmd/Makefile  |   1 +
 cmd/bootefi.c | 180 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 188 insertions(+)
 create mode 100644 cmd/bootefi.c

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 2ed0263..7cdff04 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -148,6 +148,13 @@ config CMD_BOOTM
 	help
 	  Boot an application image from the memory.
 
+config CMD_BOOTEFI
+	bool "bootefi"
+	depends on EFI_LOADER
+	default y
+	help
+	  Boot an EFI image from memory.
+
 config CMD_ELF
 	bool "bootelf, bootvx"
 	default y
diff --git a/cmd/Makefile b/cmd/Makefile
index 03f7e0a..7604621 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_CMD_SOURCE) += source.o
 obj-$(CONFIG_CMD_BDI) += bdinfo.o
 obj-$(CONFIG_CMD_BEDBUG) += bedbug.o
 obj-$(CONFIG_CMD_BMP) += bmp.o
+obj-$(CONFIG_CMD_BOOTEFI) += bootefi.o
 obj-$(CONFIG_CMD_BOOTMENU) += bootmenu.o
 obj-$(CONFIG_CMD_BOOTLDR) += bootldr.o
 obj-$(CONFIG_CMD_BOOTSTAGE) += bootstage.o
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
new file mode 100644
index 0000000..38a1b46
--- /dev/null
+++ b/cmd/bootefi.c
@@ -0,0 +1,180 @@
+/*
+ *  EFI application loader
+ *
+ *  Copyright (c) 2016 Alexander Graf
+ *
+ *  SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <efi_loader.h>
+#include <errno.h>
+#include <libfdt.h>
+#include <libfdt_env.h>
+
+/*
+ * When booting using the "bootefi" command, we don't know which
+ * physical device the file came from. So we create a pseudo-device
+ * called "bootefi" with the device path /bootefi.
+ *
+ * In addition to the originating device we also declare the file path
+ * of "bootefi" based loads to be /bootefi.
+ */
+static struct efi_device_path_file_path bootefi_dummy_path[] = {
+	{
+		.dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE,
+		.dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH,
+		.dp.length = sizeof(bootefi_dummy_path[0]),
+		.str = { 'b','o','o','t','e','f','i' },
+	}, {
+		.dp.type = DEVICE_PATH_TYPE_END,
+		.dp.sub_type = DEVICE_PATH_SUB_TYPE_END,
+		.dp.length = sizeof(bootefi_dummy_path[0]),
+	}
+};
+
+static efi_status_t bootefi_open_dp(void *handle, efi_guid_t *protocol,
+			void **protocol_interface, void *agent_handle,
+			void *controller_handle, uint32_t attributes)
+{
+	*protocol_interface = bootefi_dummy_path;
+	return EFI_SUCCESS;
+}
+
+/* The EFI loaded_image interface for the image executed via "bootefi" */
+static struct efi_loaded_image loaded_image_info = {
+	.device_handle = bootefi_dummy_path,
+	.file_path = bootefi_dummy_path,
+};
+
+/* The EFI object struct for the image executed via "bootefi" */
+static struct efi_object loaded_image_info_obj = {
+	.handle = &loaded_image_info,
+	.protocols = {
+		{
+			/*
+			 * When asking for the loaded_image interface, just
+			 * return handle which points to loaded_image_info
+			 */
+			.guid = &efi_guid_loaded_image,
+			.open = &efi_return_handle,
+		},
+		{
+			/*
+			 * When asking for the device path interface, return
+			 * bootefi_dummy_path
+			 */
+			.guid = &efi_guid_device_path,
+			.open = &bootefi_open_dp,
+		},
+	},
+};
+
+/* The EFI object struct for the device the "bootefi" image was loaded from */
+static struct efi_object bootefi_device_obj = {
+	.handle = bootefi_dummy_path,
+	.protocols = {
+		{
+			/* When asking for the device path interface, return
+			 * bootefi_dummy_path */
+			.guid = &efi_guid_device_path,
+			.open = &bootefi_open_dp,
+		}
+	},
+};
+
+/*
+ * Load an EFI payload into a newly allocated piece of memory, register all
+ * EFI objects it would want to access and jump to it.
+ */
+static unsigned long do_bootefi_exec(void *efi)
+{
+	ulong (*entry)(void *image_handle, struct efi_system_table *st);
+	ulong fdt_pages, fdt_size, fdt_start, fdt_end;
+
+	/*
+	 * gd lives in a fixed register which may get clobbered while we execute
+	 * the payload. So save it here and restore it on every callback entry
+	 */
+	efi_save_gd();
+
+	/* Update system table to point to our currently loaded FDT */
+
+	if (working_fdt) {
+		systab.tables[0].guid = EFI_FDT_GUID;
+		systab.tables[0].table = working_fdt;
+		systab.nr_tables = 1;
+
+		/* And reserve the space in the memory map */
+		fdt_start = ((ulong)working_fdt) & ~EFI_PAGE_MASK;
+		fdt_end = ((ulong)working_fdt) + fdt_totalsize(working_fdt);
+		fdt_size = (fdt_end - fdt_start) + EFI_PAGE_MASK;
+		fdt_pages = fdt_size >> EFI_PAGE_SHIFT;
+		/* Give a bootloader the chance to modify the device tree */
+		fdt_pages += 2;
+		efi_add_memory_map(fdt_start, fdt_pages,
+				   EFI_BOOT_SERVICES_DATA, true);
+
+	} else {
+		printf("WARNING: No device tree loaded, expect boot to fail\n");
+		systab.nr_tables = 0;
+	}
+
+	/* Load the EFI payload */
+	entry = efi_load_pe(efi, &loaded_image_info);
+	if (!entry)
+		return -ENOENT;
+
+	/* Initialize and populate EFI object list */
+	INIT_LIST_HEAD(&efi_obj_list);
+	list_add_tail(&loaded_image_info_obj.link, &efi_obj_list);
+	list_add_tail(&bootefi_device_obj.link, &efi_obj_list);
+#ifdef CONFIG_PARTITIONS
+	efi_disk_register();
+#endif
+
+	/* Call our payload! */
+#ifdef DEBUG_EFI
+	printf("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry);
+#endif
+	return entry(&loaded_image_info, &systab);
+}
+
+
+/* Interpreter command to boot an arbitrary EFI image from memory */
+static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	char *saddr;
+	unsigned long addr;
+	int r = 0;
+
+	if (argc < 2)
+		return 1;
+	saddr = argv[1];
+
+	addr = simple_strtoul(saddr, NULL, 16);
+
+	printf("## Starting EFI application@0x%08lx ...\n", addr);
+	r = do_bootefi_exec((void *)addr);
+	printf("## Application terminated, r = %d\n", r);
+
+	if (r != 0)
+		r = 1;
+
+	return r;
+}
+
+static char bootefi_help_text[] =
+	"<image address>\n"
+	"  - boot EFI payload stored at address <image address>\n"
+	"\n"
+	"Since most EFI payloads want to have a device tree provided, please\n"
+	"make sure you load a device tree using the fdt addr command before\n"
+	"executing bootefi.\n";
+
+U_BOOT_CMD(
+	bootefi, 2, 0, do_bootefi,
+	"Boots an EFI payload from memory\n",
+	bootefi_help_text
+);
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot,v5,01/30] thunderx: Calculate TCR dynamically
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 01/30] thunderx: Calculate TCR dynamically Alexander Graf
@ 2016-03-17  1:59   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  1:59 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:09:45AM +0100, Alexander Graf wrote:

> Based on the memory map we can determine a lot of hard coded fields of
> TCR, like the maximum VA and max PA we want to support. Calculate those
> dynamically to reduce the chance for pit falls.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/6f4dd32f/attachment.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot,v5,02/30] arm64: Disable TTBR1 maps in EL1
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 02/30] arm64: Disable TTBR1 maps in EL1 Alexander Graf
@ 2016-03-17  1:59   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  1:59 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:09:46AM +0100, Alexander Graf wrote:

> When running in EL1, AArch64 knows two page table maps. One with addresses
> that start with all zeros (TTBR0) and one with addresses that start with all
> ones (TTBR1).
> 
> In U-Boot we don't care about the high up maps, so just disable them to ensure
> we don't walk an invalid page table by accident.
> 
> Reported-by: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Alexander Graf <agraf@suse.de>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/f86cdedd/attachment.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot, v5, 03/30] arm64: Make full va map code more dynamic
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 03/30] arm64: Make full va map code more dynamic Alexander Graf
@ 2016-03-17  1:59   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  1:59 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:09:47AM +0100, Alexander Graf wrote:

> The idea to generate our pages tables from an array of memory ranges
> is very sound. However, instead of hard coding the code to create up
> to 2 levels of 64k granule page tables, we really should just create
> normal 4k page tables that allow us to set caching attributes on 2M
> or 4k level later on.
> 
> So this patch moves the full_va mapping code to 4k page size and
> makes it fully flexible to dynamically create as many levels as
> necessary for a map (including dynamic 1G/2M pages). It also adds
> support to dynamically split a large map into smaller ones when
> some code wants to set dcache attributes.
> 
> With all this in place, there is very little reason to create your
> own page tables in board specific files.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/2d4e847a/attachment.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot, v5, 04/30] thunderx: Move mmu table into board file
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 04/30] thunderx: Move mmu table into board file Alexander Graf
@ 2016-03-17  2:00   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:00 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:09:48AM +0100, Alexander Graf wrote:

> The MMU range table can vary depending on things we may only find
> out at runtime. While the very simple ThunderX variant does not
> change, other boards will, so move the definition from a static
> entry in a header file to the board file.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/f1232861/attachment.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot, v5, 05/30] zymqmp: Replace home grown mmu code with generic table approach
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 05/30] zymqmp: Replace home grown mmu code with generic table approach Alexander Graf
@ 2016-03-17  2:00   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:00 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:09:49AM +0100, Alexander Graf wrote:

> Now that we have nice table driven page table creating code that gives
> us everything we need, move to that.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/bcec26ea/attachment.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot, v5, 06/30] tegra: Replace home grown mmu code with generic table approach
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 06/30] tegra: " Alexander Graf
@ 2016-03-17  2:00   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:00 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:09:50AM +0100, Alexander Graf wrote:

> Now that we have nice table driven page table creating code that gives
> us everything we need, move to that.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/32b650b5/attachment.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot,v5,07/30] vexpress64: Add MMU tables
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 07/30] vexpress64: Add MMU tables Alexander Graf
@ 2016-03-17  2:00   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:00 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:09:51AM +0100, Alexander Graf wrote:

> There's no good excuse for running with caches disabled on AArch64,
> so let's just move the vexpress64 target to enable the MMU and run
> with caches on.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/ac25d195/attachment.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot,v5,08/30] dwmmc: Increase retry timeout
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 08/30] dwmmc: Increase retry timeout Alexander Graf
@ 2016-03-17  2:00   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:00 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:09:52AM +0100, Alexander Graf wrote:

> When enable dcache on HiKey, we're running into MMC command timeouts
> because our retry loop is now faster than the eMMC (or an external SD
> card) can answer.
> 
> Increase the retry count to the same as the timeout value for status
> reports.
> 
> The real fix is obviously to not base this whole thing on a cycle counter
> but on real wall time, but that would be slightly more intrusive.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/46cdcc3c/attachment.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot,v5,09/30] hikey: Add MMU tables
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 09/30] hikey: Add MMU tables Alexander Graf
@ 2016-03-17  2:00   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:00 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:09:53AM +0100, Alexander Graf wrote:

> The hikey runs with dcache disabled today. There really should be no reason
> not to use caches on AArch64, so let's add MMU definitions and enable the
> dcache.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/c47cc1c0/attachment.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot,v5,10/30] arm64: Remove non-full-va map code
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 10/30] arm64: Remove non-full-va map code Alexander Graf
@ 2016-03-17  2:00   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:00 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:09:54AM +0100, Alexander Graf wrote:

> By now the code to only have a single page table level with 64k page
> size and 42 bit address space is no longer used by any board in tree,
> so we can safely remove it.
> 
> To clean up code, move the layerscape mmu code to the new defines,
> removing redundant field definitions.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/20fec9e0/attachment.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot, v5, 11/30] arm64: Only allow dcache disabled in SPL builds
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 11/30] arm64: Only allow dcache disabled in SPL builds Alexander Graf
@ 2016-03-17  2:01   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:01 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:09:55AM +0100, Alexander Graf wrote:

> Now that we have an easy way to describe memory regions and enable the MMU,
> there really shouldn't be anything holding people back from running with
> caches enabled on AArch64. To make sure people catch early if they're missing
> on the caching fun, give them a compile error.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/1ff15e5a/attachment.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot, v5, 12/30] disk/part.c: Expose list of available block drivers
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 12/30] disk/part.c: Expose list of available block drivers Alexander Graf
@ 2016-03-17  2:01   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:01 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:09:56AM +0100, Alexander Graf wrote:

> We have a pretty nice and generic interface to ask for a specific block
> device. However, that one is still based around the magic notion that
> we know the driver name.
> 
> In order to be able to write fully generic disk access code, expose the
> currently internal list to other source files so that they can scan through
> all available block drivers.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Tested-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/b44c76cc/attachment.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot, v5, 13/30] include/efi_api.h: Add more detailed API definitions
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 13/30] include/efi_api.h: Add more detailed API definitions Alexander Graf
@ 2016-03-17  2:01   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:01 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:09:57AM +0100, Alexander Graf wrote:

> The EFI API header is great, but missing a good chunk of function prototype,
> GUID defines and enum declarations.
> 
> This patch extends it to cover more of the EFI API. It's still not 100%
> complete, but sufficient enough for our EFI payload interface.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Tested-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/7a984def/attachment.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot,v5,14/30] efi_loader: Add PE image loader
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 14/30] efi_loader: Add PE image loader Alexander Graf
@ 2016-03-17  2:01   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:01 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:09:58AM +0100, Alexander Graf wrote:

> EFI uses the PE binary format for its application images. Add support to EFI PE
> binaries as well as all necessary bits for the "EFI image loader" interfaces.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Tested-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/fc2e2354/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot,v5,15/30] efi_loader: Add boot time services
  2016-03-04  0:09 ` [U-Boot] [PATCH v5 15/30] efi_loader: Add boot time services Alexander Graf
@ 2016-03-17  2:01   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:01 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:09:59AM +0100, Alexander Graf wrote:

> When an EFI application runs, it has access to a few descriptor and callback
> tables to instruct the EFI compliant firmware to do things for it. The bulk
> of those interfaces are "boot time services". They handle all object management,
> and memory allocation.
> 
> This patch adds support for the boot time services and also exposes a system
> table, which is the point of entry descriptor table for EFI payloads.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Tested-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/ae89449e/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot,v5,16/30] efi_loader: Add console interface
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 16/30] efi_loader: Add console interface Alexander Graf
@ 2016-03-17  2:01   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:01 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:10:00AM +0100, Alexander Graf wrote:

> One of the basic EFI interfaces is the console interface. Using it an EFI
> application can interface with the user. This patch implements an EFI console
> interface using getc() and putc().
> 
> Today, we only implement text based consoles. We also convert the EFI Unicode
> characters to UTF-8 on the fly, hoping that everyone managed to jump on the
> train by now.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Tested-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/6ecf6de8/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot,v5,17/30] efi_loader: Add runtime services
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 17/30] efi_loader: Add runtime services Alexander Graf
@ 2016-03-17  2:01   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:01 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:10:01AM +0100, Alexander Graf wrote:

> After booting has finished, EFI allows firmware to still interact with the OS
> using the "runtime services". These callbacks live in a separate address space,
> since they are available long after U-Boot has been overwritten by the OS.
> 
> This patch adds enough framework for arbitrary code inside of U-Boot to become
> a runtime service with the right section attributes set. For now, we don't make
> use of it yet though.
> 
> We could maybe in the future map U-boot environment variables to EFI variables
> here.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Tested-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/22ba2053/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot,v5,18/30] efi_loader: Add disk interfaces
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 18/30] efi_loader: Add disk interfaces Alexander Graf
@ 2016-03-17  2:01   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:01 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:10:02AM +0100, Alexander Graf wrote:

> A EFI applications usually want to access storage devices to load data from.
> 
> This patch adds support for EFI disk interfaces. It loops through all block
> storage interfaces known to U-Boot and creates an EFI object for each existing
> one. EFI applications can then through these objects call U-Boot's read and
> write functions.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Tested-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/a3446ccc/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot,v6,19/30] efi_loader: Add "bootefi" command
  2016-03-09 23:27   ` [U-Boot] [PATCH v6 " Alexander Graf
@ 2016-03-17  2:01     ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:01 UTC (permalink / raw)
  To: u-boot

On Thu, Mar 10, 2016 at 12:27:20AM +0100, Alexander Graf wrote:

> In order to execute an EFI application, we need to bridge the gap between
> U-Boot's notion of executing images and EFI's notion of doing the same.
> 
> The best path forward IMHO here is to stick completely to the way U-Boot
> deals with payloads. You manually load them using whatever method to RAM
> and then have a simple boot command to execute them. So in our case, you
> would do
> 
>   # load mmc 0:1 $loadaddr grub.efi
>   # bootefi $loadaddr
> 
> which then gets you into a grub shell. Fdt information known to U-boot
> via the fdt addr command is also passed to the EFI payload.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Tested-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/3a7de93a/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot, v5, 20/30] efi_loader: Implement memory allocation and map
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 20/30] efi_loader: Implement memory allocation and map Alexander Graf
@ 2016-03-17  2:02   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:02 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:10:04AM +0100, Alexander Graf wrote:

> The EFI loader needs to maintain views of memory - general system memory
> windows as well as used locations inside those and potential runtime service
> MMIO windows.
> 
> To manage all of these, add a few helpers that maintain an internal
> representation of the map the similar to how the EFI API later on reports
> it to the application.
> 
> For allocations, the scheme is very simple. We basically allow allocations
> to replace chunks of previously done maps, so that a new LOADER_DATA
> allocation for example can remove a piece of the RAM map. When no specific
> address is given, we just take the highest possible address in the lowest
> RAM map that fits the allocation size.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>
> Tested-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/81f00d57/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot,v5,21/30] arm64: Allow exceptions to return
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 21/30] arm64: Allow exceptions to return Alexander Graf
@ 2016-03-17  2:02   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:02 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:10:05AM +0100, Alexander Graf wrote:

> Our current arm64 exception handlers all panic and never return to the
> exception triggering code.
> 
> But if any handler wanted to continue execution after fixups, it would
> need help from the exception handling code to restore all registers.
> 
> This patch implements that help. With this code, exception handlers on
> aarch64 can successfully return to the place the exception happened (or
> somewhere else if they modify elr).
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/3a603b01/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot, v5, 22/30] arm64: Allow EFI payload code to take exceptions
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 22/30] arm64: Allow EFI payload code to take exceptions Alexander Graf
@ 2016-03-17  2:02   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:02 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:10:06AM +0100, Alexander Graf wrote:

> There are 2 ways an EFI payload could return into u-boot:
> 
>   - Callback function
>   - Exception
> 
> While in EFI payload mode, x18 is owned by the payload and may not contain
> a valid pointer to gd, so we need to fix it up. We do that properly for the
> payload to callback path already.
> 
> This patch also adds gd pointer restoral for the exception path.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/2c02556d/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot, v5, 23/30] efi_loader: hook up in build environment
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 23/30] efi_loader: hook up in build environment Alexander Graf
@ 2016-03-17  2:02   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:02 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:10:07AM +0100, Alexander Graf wrote:

> Now that we have all the bits and pieces ready for EFI payload loading
> support, hook them up in Makefiles and KConfigs so that we can build.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Tested-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/1e10d4f7/attachment.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot, v6, 24/30] efi_loader: Add distro boot script for removable media
  2016-03-09 23:26       ` [U-Boot] [PATCH v6 " Alexander Graf
@ 2016-03-17  2:02         ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:02 UTC (permalink / raw)
  To: u-boot

On Thu, Mar 10, 2016 at 12:26:15AM +0100, Alexander Graf wrote:

> UEFI defines a simple boot protocol for removable media. There we should look
> at the EFI (first GPT FAT) partition and search for /efi/boot/bootXXX.efi with
> XXX being different between different platforms (x86, x64, arm, aa64, ...).
> 
> This patch implements a simple version of that protocol for the default distro
> boot script. With this we can automatically boot from valid UEFI enabled
> removable media.
> 
> Because from all I could see U-Boot by default doesn't deliver device tree
> blobs with its firmware, we also need to load the dtb from somewhere. Traverse
> the same EFI partition for an fdt file that fits our current board so that
> an OS receives a valid device tree when booted automatically.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/05aec607/attachment.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot, v5, 25/30] efi_loader: Add README section in README.efi
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 25/30] efi_loader: Add README section in README.efi Alexander Graf
@ 2016-03-17  2:02   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:02 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:10:09AM +0100, Alexander Graf wrote:

> To preserve all cover letter knowledge of the status on UEFI payload
> support, let's add some sections to README.efi.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>
> 
> v3 -> v4:
> 
>   - Add section about config options
>   - s/10kb/10KB/

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/0e157d73/attachment.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot,v5,26/30] efi_loader: Add MAINTAINERS entry
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 26/30] efi_loader: Add MAINTAINERS entry Alexander Graf
@ 2016-03-17  2:02   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:02 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:10:10AM +0100, Alexander Graf wrote:

> Now that everything's in place, let's add myself as the maintainer for
> the efi payload support.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/51d42a2c/attachment.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot, v5, 27/30] arm64: Replace fdt_name env variables with fdtfile
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 27/30] arm64: Replace fdt_name env variables with fdtfile Alexander Graf
@ 2016-03-17  2:02   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:02 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:10:11AM +0100, Alexander Graf wrote:

> The commonly defined environment variable to determine the device tree
> file name is called fdtfile rather than fdt_name. Replace all occurences
> of fdt_name with fdtfile.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/ec817184/attachment.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot, v5, 28/30] arm: Allow EFI payload code to take exceptions
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 28/30] arm: Allow EFI payload code to take exceptions Alexander Graf
@ 2016-03-17  2:03   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:03 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:10:12AM +0100, Alexander Graf wrote:

> There are 2 ways an EFI payload could return into u-boot:
> 
>   - Callback function
>   - Exception
> 
> While in EFI payload mode, r9 is owned by the payload and may not contain
> a valid pointer to gd, so we need to fix it up. We do that properly for the
> payload to callback path already.
> 
> This patch also adds gd pointer restoral for the exception path.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/eb705dbc/attachment.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot, v5, 29/30] efi_loader: Call fdt preparation functions
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 29/30] efi_loader: Call fdt preparation functions Alexander Graf
@ 2016-03-17  2:03   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:03 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:10:13AM +0100, Alexander Graf wrote:

> We have a nice framework around image fils to prepare a device tree
> for OS execution. That one patches in missing device tree nodes and
> fixes up the memory range bits.
> 
> We need to call that one from the EFI boot path too to get all those
> nice fixups. This patch adds the call.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/e8250d7e/attachment.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [U-Boot] [U-Boot, v5, 30/30] efi_loader: Pass proper device path in on boot
  2016-03-04  0:10 ` [U-Boot] [PATCH v5 30/30] efi_loader: Pass proper device path in on boot Alexander Graf
@ 2016-03-17  2:03   ` Tom Rini
  0 siblings, 0 replies; 67+ messages in thread
From: Tom Rini @ 2016-03-17  2:03 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 04, 2016 at 01:10:14AM +0100, Alexander Graf wrote:

> EFI payloads can query for the device they were booted from. Because
> we have a disconnect between loading binaries and running binaries,
> we passed in a dummy device path so far.
> 
> Unfortunately that breaks grub2's logic to find its configuration
> file from the same device it was booted from.
> 
> This patch adds logic to have the "load" command call into our efi
> code to set the device path to the one we last loaded a binary from.
> 
> With this grub2 properly detects where we got booted from and can
> find its configuration file, even when searching by-partition.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160316/be3ca1a1/attachment.sig>

^ permalink raw reply	[flat|nested] 67+ messages in thread

end of thread, other threads:[~2016-03-17  2:03 UTC | newest]

Thread overview: 67+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-03-04  0:09 [U-Boot] [PATCH v5 00/30] EFI payload / application support Alexander Graf
2016-03-04  0:09 ` [U-Boot] [PATCH v5 01/30] thunderx: Calculate TCR dynamically Alexander Graf
2016-03-17  1:59   ` [U-Boot] [U-Boot,v5,01/30] " Tom Rini
2016-03-04  0:09 ` [U-Boot] [PATCH v5 02/30] arm64: Disable TTBR1 maps in EL1 Alexander Graf
2016-03-17  1:59   ` [U-Boot] [U-Boot,v5,02/30] " Tom Rini
2016-03-04  0:09 ` [U-Boot] [PATCH v5 03/30] arm64: Make full va map code more dynamic Alexander Graf
2016-03-17  1:59   ` [U-Boot] [U-Boot, v5, " Tom Rini
2016-03-04  0:09 ` [U-Boot] [PATCH v5 04/30] thunderx: Move mmu table into board file Alexander Graf
2016-03-17  2:00   ` [U-Boot] [U-Boot, v5, " Tom Rini
2016-03-04  0:09 ` [U-Boot] [PATCH v5 05/30] zymqmp: Replace home grown mmu code with generic table approach Alexander Graf
2016-03-17  2:00   ` [U-Boot] [U-Boot, v5, " Tom Rini
2016-03-04  0:09 ` [U-Boot] [PATCH v5 06/30] tegra: " Alexander Graf
2016-03-17  2:00   ` [U-Boot] [U-Boot, v5, " Tom Rini
2016-03-04  0:09 ` [U-Boot] [PATCH v5 07/30] vexpress64: Add MMU tables Alexander Graf
2016-03-17  2:00   ` [U-Boot] [U-Boot,v5,07/30] " Tom Rini
2016-03-04  0:09 ` [U-Boot] [PATCH v5 08/30] dwmmc: Increase retry timeout Alexander Graf
2016-03-17  2:00   ` [U-Boot] [U-Boot,v5,08/30] " Tom Rini
2016-03-04  0:09 ` [U-Boot] [PATCH v5 09/30] hikey: Add MMU tables Alexander Graf
2016-03-17  2:00   ` [U-Boot] [U-Boot,v5,09/30] " Tom Rini
2016-03-04  0:09 ` [U-Boot] [PATCH v5 10/30] arm64: Remove non-full-va map code Alexander Graf
2016-03-17  2:00   ` [U-Boot] [U-Boot,v5,10/30] " Tom Rini
2016-03-04  0:09 ` [U-Boot] [PATCH v5 11/30] arm64: Only allow dcache disabled in SPL builds Alexander Graf
2016-03-17  2:01   ` [U-Boot] [U-Boot, v5, " Tom Rini
2016-03-04  0:09 ` [U-Boot] [PATCH v5 12/30] disk/part.c: Expose list of available block drivers Alexander Graf
2016-03-17  2:01   ` [U-Boot] [U-Boot, v5, " Tom Rini
2016-03-04  0:09 ` [U-Boot] [PATCH v5 13/30] include/efi_api.h: Add more detailed API definitions Alexander Graf
2016-03-17  2:01   ` [U-Boot] [U-Boot, v5, " Tom Rini
2016-03-04  0:09 ` [U-Boot] [PATCH v5 14/30] efi_loader: Add PE image loader Alexander Graf
2016-03-17  2:01   ` [U-Boot] [U-Boot,v5,14/30] " Tom Rini
2016-03-04  0:09 ` [U-Boot] [PATCH v5 15/30] efi_loader: Add boot time services Alexander Graf
2016-03-17  2:01   ` [U-Boot] [U-Boot,v5,15/30] " Tom Rini
2016-03-04  0:10 ` [U-Boot] [PATCH v5 16/30] efi_loader: Add console interface Alexander Graf
2016-03-17  2:01   ` [U-Boot] [U-Boot,v5,16/30] " Tom Rini
2016-03-04  0:10 ` [U-Boot] [PATCH v5 17/30] efi_loader: Add runtime services Alexander Graf
2016-03-17  2:01   ` [U-Boot] [U-Boot,v5,17/30] " Tom Rini
2016-03-04  0:10 ` [U-Boot] [PATCH v5 18/30] efi_loader: Add disk interfaces Alexander Graf
2016-03-17  2:01   ` [U-Boot] [U-Boot,v5,18/30] " Tom Rini
2016-03-04  0:10 ` [U-Boot] [PATCH v5 19/30] efi_loader: Add "bootefi" command Alexander Graf
2016-03-09 23:27   ` [U-Boot] [PATCH v6 " Alexander Graf
2016-03-17  2:01     ` [U-Boot] [U-Boot,v6,19/30] " Tom Rini
2016-03-04  0:10 ` [U-Boot] [PATCH v5 20/30] efi_loader: Implement memory allocation and map Alexander Graf
2016-03-17  2:02   ` [U-Boot] [U-Boot, v5, " Tom Rini
2016-03-04  0:10 ` [U-Boot] [PATCH v5 21/30] arm64: Allow exceptions to return Alexander Graf
2016-03-17  2:02   ` [U-Boot] [U-Boot,v5,21/30] " Tom Rini
2016-03-04  0:10 ` [U-Boot] [PATCH v5 22/30] arm64: Allow EFI payload code to take exceptions Alexander Graf
2016-03-17  2:02   ` [U-Boot] [U-Boot, v5, " Tom Rini
2016-03-04  0:10 ` [U-Boot] [PATCH v5 23/30] efi_loader: hook up in build environment Alexander Graf
2016-03-17  2:02   ` [U-Boot] [U-Boot, v5, " Tom Rini
2016-03-04  0:10 ` [U-Boot] [PATCH v5 24/30] efi_loader: Add distro boot script for removable media Alexander Graf
2016-03-09 23:05   ` Alexander Graf
2016-03-09 23:16     ` Tom Rini
2016-03-09 23:26       ` [U-Boot] [PATCH v6 " Alexander Graf
2016-03-17  2:02         ` [U-Boot] [U-Boot, v6, " Tom Rini
2016-03-04  0:10 ` [U-Boot] [PATCH v5 25/30] efi_loader: Add README section in README.efi Alexander Graf
2016-03-17  2:02   ` [U-Boot] [U-Boot, v5, " Tom Rini
2016-03-04  0:10 ` [U-Boot] [PATCH v5 26/30] efi_loader: Add MAINTAINERS entry Alexander Graf
2016-03-17  2:02   ` [U-Boot] [U-Boot,v5,26/30] " Tom Rini
2016-03-04  0:10 ` [U-Boot] [PATCH v5 27/30] arm64: Replace fdt_name env variables with fdtfile Alexander Graf
2016-03-17  2:02   ` [U-Boot] [U-Boot, v5, " Tom Rini
2016-03-04  0:10 ` [U-Boot] [PATCH v5 28/30] arm: Allow EFI payload code to take exceptions Alexander Graf
2016-03-17  2:03   ` [U-Boot] [U-Boot, v5, " Tom Rini
2016-03-04  0:10 ` [U-Boot] [PATCH v5 29/30] efi_loader: Call fdt preparation functions Alexander Graf
2016-03-17  2:03   ` [U-Boot] [U-Boot, v5, " Tom Rini
2016-03-04  0:10 ` [U-Boot] [PATCH v5 30/30] efi_loader: Pass proper device path in on boot Alexander Graf
2016-03-17  2:03   ` [U-Boot] [U-Boot, v5, " Tom Rini
2016-03-04  9:19 ` [U-Boot] [PATCH] efi_loader: Reserve 2 additional pages for fdt Alexander Graf
2016-03-04  9:41   ` Leif Lindholm

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.