All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/10] arm64: UEFI support
@ 2014-04-04 18:45 ` Leif Lindholm
  0 siblings, 0 replies; 55+ messages in thread
From: Leif Lindholm @ 2014-04-04 18:45 UTC (permalink / raw)
  To: linux-arm-kernel, linux-efi; +Cc: linux-kernel, Leif Lindholm

This set adds support for UEFI to the arm64 port - a stub loader, as
well as runtime services support for efivars.

It depends on some core EFI patches currently in linux-next.

This includes bits shared between arm and arm64 support.
Remaining bits required for arm support will be submitted separately.

Changes from previous version:
- Enter_virtual_mode() is now an early initcall.
- UEFI Reserved regions now preserved.
- Bugfix for dtb= support with SecureBoot.
- Stub now flushes instruction cache by address for kernel image area.
- CONFIG_EFI_STUB merged into CONFIG_EFI since they are interdependent.
- EFI_DEVICE_TREE_GUID renamed DEVICE_TREE_GUID.
- Minor cleanups.

Ard Biesheuvel (1):
  efi/arm64: ignore dtb= when UEFI SecureBoot is enabled

Leif Lindholm (1):
  doc: arm: add UEFI support documentation

Mark Salter (6):
  lib: add fdt_empty_tree.c
  efi: add helper function to get UEFI params from FDT
  arm64: Add function to create identity mappings
  arm64: efi: add EFI stub
  doc: arm64: add description of EFI stub support
  arm64: add EFI runtime services

Roy Franz (2):
  doc: efi-stub.txt updates for ARM
  efi: Add shared FDT related functions for ARM/ARM64

 Documentation/arm/00-INDEX             |    2 +
 Documentation/arm/uefi.txt             |   64 +++++
 Documentation/arm64/booting.txt        |    4 +
 Documentation/efi-stub.txt             |   33 ++-
 arch/arm64/Kconfig                     |   21 ++
 arch/arm64/include/asm/efi.h           |   14 +
 arch/arm64/include/asm/mmu.h           |    2 +
 arch/arm64/kernel/Makefile             |    3 +
 arch/arm64/kernel/efi-entry.S          |  100 +++++++
 arch/arm64/kernel/efi-stub.c           |   97 +++++++
 arch/arm64/kernel/efi.c                |  469 ++++++++++++++++++++++++++++++++
 arch/arm64/kernel/head.S               |  112 ++++++++
 arch/arm64/kernel/setup.c              |    5 +
 arch/arm64/mm/mmu.c                    |   65 +++--
 drivers/firmware/efi/Kconfig           |    7 +
 drivers/firmware/efi/arm-stub.c        |  255 +++++++++++++++++
 drivers/firmware/efi/efi-stub-helper.c |   24 ++
 drivers/firmware/efi/efi.c             |   79 ++++++
 drivers/firmware/efi/fdt.c             |  269 ++++++++++++++++++
 include/linux/efi.h                    |   12 +
 lib/Makefile                           |    3 +-
 lib/fdt_empty_tree.c                   |    2 +
 22 files changed, 1616 insertions(+), 26 deletions(-)
 create mode 100644 Documentation/arm/uefi.txt
 create mode 100644 arch/arm64/include/asm/efi.h
 create mode 100644 arch/arm64/kernel/efi-entry.S
 create mode 100644 arch/arm64/kernel/efi-stub.c
 create mode 100644 arch/arm64/kernel/efi.c
 create mode 100644 drivers/firmware/efi/arm-stub.c
 create mode 100644 drivers/firmware/efi/fdt.c
 create mode 100644 lib/fdt_empty_tree.c

-- 
1.7.10.4


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

* [PATCH v3 00/10] arm64: UEFI support
@ 2014-04-04 18:45 ` Leif Lindholm
  0 siblings, 0 replies; 55+ messages in thread
From: Leif Lindholm @ 2014-04-04 18:45 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Leif Lindholm

This set adds support for UEFI to the arm64 port - a stub loader, as
well as runtime services support for efivars.

It depends on some core EFI patches currently in linux-next.

This includes bits shared between arm and arm64 support.
Remaining bits required for arm support will be submitted separately.

Changes from previous version:
- Enter_virtual_mode() is now an early initcall.
- UEFI Reserved regions now preserved.
- Bugfix for dtb= support with SecureBoot.
- Stub now flushes instruction cache by address for kernel image area.
- CONFIG_EFI_STUB merged into CONFIG_EFI since they are interdependent.
- EFI_DEVICE_TREE_GUID renamed DEVICE_TREE_GUID.
- Minor cleanups.

Ard Biesheuvel (1):
  efi/arm64: ignore dtb= when UEFI SecureBoot is enabled

Leif Lindholm (1):
  doc: arm: add UEFI support documentation

Mark Salter (6):
  lib: add fdt_empty_tree.c
  efi: add helper function to get UEFI params from FDT
  arm64: Add function to create identity mappings
  arm64: efi: add EFI stub
  doc: arm64: add description of EFI stub support
  arm64: add EFI runtime services

Roy Franz (2):
  doc: efi-stub.txt updates for ARM
  efi: Add shared FDT related functions for ARM/ARM64

 Documentation/arm/00-INDEX             |    2 +
 Documentation/arm/uefi.txt             |   64 +++++
 Documentation/arm64/booting.txt        |    4 +
 Documentation/efi-stub.txt             |   33 ++-
 arch/arm64/Kconfig                     |   21 ++
 arch/arm64/include/asm/efi.h           |   14 +
 arch/arm64/include/asm/mmu.h           |    2 +
 arch/arm64/kernel/Makefile             |    3 +
 arch/arm64/kernel/efi-entry.S          |  100 +++++++
 arch/arm64/kernel/efi-stub.c           |   97 +++++++
 arch/arm64/kernel/efi.c                |  469 ++++++++++++++++++++++++++++++++
 arch/arm64/kernel/head.S               |  112 ++++++++
 arch/arm64/kernel/setup.c              |    5 +
 arch/arm64/mm/mmu.c                    |   65 +++--
 drivers/firmware/efi/Kconfig           |    7 +
 drivers/firmware/efi/arm-stub.c        |  255 +++++++++++++++++
 drivers/firmware/efi/efi-stub-helper.c |   24 ++
 drivers/firmware/efi/efi.c             |   79 ++++++
 drivers/firmware/efi/fdt.c             |  269 ++++++++++++++++++
 include/linux/efi.h                    |   12 +
 lib/Makefile                           |    3 +-
 lib/fdt_empty_tree.c                   |    2 +
 22 files changed, 1616 insertions(+), 26 deletions(-)
 create mode 100644 Documentation/arm/uefi.txt
 create mode 100644 arch/arm64/include/asm/efi.h
 create mode 100644 arch/arm64/kernel/efi-entry.S
 create mode 100644 arch/arm64/kernel/efi-stub.c
 create mode 100644 arch/arm64/kernel/efi.c
 create mode 100644 drivers/firmware/efi/arm-stub.c
 create mode 100644 drivers/firmware/efi/fdt.c
 create mode 100644 lib/fdt_empty_tree.c

-- 
1.7.10.4

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

* [PATCH v3 00/10] arm64: UEFI support
@ 2014-04-04 18:45 ` Leif Lindholm
  0 siblings, 0 replies; 55+ messages in thread
From: Leif Lindholm @ 2014-04-04 18:45 UTC (permalink / raw)
  To: linux-arm-kernel

This set adds support for UEFI to the arm64 port - a stub loader, as
well as runtime services support for efivars.

It depends on some core EFI patches currently in linux-next.

This includes bits shared between arm and arm64 support.
Remaining bits required for arm support will be submitted separately.

Changes from previous version:
- Enter_virtual_mode() is now an early initcall.
- UEFI Reserved regions now preserved.
- Bugfix for dtb= support with SecureBoot.
- Stub now flushes instruction cache by address for kernel image area.
- CONFIG_EFI_STUB merged into CONFIG_EFI since they are interdependent.
- EFI_DEVICE_TREE_GUID renamed DEVICE_TREE_GUID.
- Minor cleanups.

Ard Biesheuvel (1):
  efi/arm64: ignore dtb= when UEFI SecureBoot is enabled

Leif Lindholm (1):
  doc: arm: add UEFI support documentation

Mark Salter (6):
  lib: add fdt_empty_tree.c
  efi: add helper function to get UEFI params from FDT
  arm64: Add function to create identity mappings
  arm64: efi: add EFI stub
  doc: arm64: add description of EFI stub support
  arm64: add EFI runtime services

Roy Franz (2):
  doc: efi-stub.txt updates for ARM
  efi: Add shared FDT related functions for ARM/ARM64

 Documentation/arm/00-INDEX             |    2 +
 Documentation/arm/uefi.txt             |   64 +++++
 Documentation/arm64/booting.txt        |    4 +
 Documentation/efi-stub.txt             |   33 ++-
 arch/arm64/Kconfig                     |   21 ++
 arch/arm64/include/asm/efi.h           |   14 +
 arch/arm64/include/asm/mmu.h           |    2 +
 arch/arm64/kernel/Makefile             |    3 +
 arch/arm64/kernel/efi-entry.S          |  100 +++++++
 arch/arm64/kernel/efi-stub.c           |   97 +++++++
 arch/arm64/kernel/efi.c                |  469 ++++++++++++++++++++++++++++++++
 arch/arm64/kernel/head.S               |  112 ++++++++
 arch/arm64/kernel/setup.c              |    5 +
 arch/arm64/mm/mmu.c                    |   65 +++--
 drivers/firmware/efi/Kconfig           |    7 +
 drivers/firmware/efi/arm-stub.c        |  255 +++++++++++++++++
 drivers/firmware/efi/efi-stub-helper.c |   24 ++
 drivers/firmware/efi/efi.c             |   79 ++++++
 drivers/firmware/efi/fdt.c             |  269 ++++++++++++++++++
 include/linux/efi.h                    |   12 +
 lib/Makefile                           |    3 +-
 lib/fdt_empty_tree.c                   |    2 +
 22 files changed, 1616 insertions(+), 26 deletions(-)
 create mode 100644 Documentation/arm/uefi.txt
 create mode 100644 arch/arm64/include/asm/efi.h
 create mode 100644 arch/arm64/kernel/efi-entry.S
 create mode 100644 arch/arm64/kernel/efi-stub.c
 create mode 100644 arch/arm64/kernel/efi.c
 create mode 100644 drivers/firmware/efi/arm-stub.c
 create mode 100644 drivers/firmware/efi/fdt.c
 create mode 100644 lib/fdt_empty_tree.c

-- 
1.7.10.4

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

* [PATCH v3 01/10] lib: add fdt_empty_tree.c
  2014-04-04 18:45 ` Leif Lindholm
@ 2014-04-04 18:45   ` Leif Lindholm
  -1 siblings, 0 replies; 55+ messages in thread
From: Leif Lindholm @ 2014-04-04 18:45 UTC (permalink / raw)
  To: linux-arm-kernel, linux-efi
  Cc: linux-kernel, Mark Salter, Leif Lindholm, Andrew Morton

From: Mark Salter <msalter@redhat.com>

CONFIG_LIBFDT support does not include fdt_empty_tree.c which is
needed by arm64 EFI stub. Add it to libfdt_files.

Signed-off-by: Mark Salter <msalter@redhat.com>
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
---
 lib/Makefile         |    3 ++-
 lib/fdt_empty_tree.c |    2 ++
 2 files changed, 4 insertions(+), 1 deletion(-)
 create mode 100644 lib/fdt_empty_tree.c

diff --git a/lib/Makefile b/lib/Makefile
index 02da5b6..5f5b6a2 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -149,7 +149,8 @@ obj-$(CONFIG_GENERIC_NET_UTILS) += net_utils.o
 
 obj-$(CONFIG_STMP_DEVICE) += stmp_device.o
 
-libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o
+libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o \
+	       fdt_empty_tree.o
 $(foreach file, $(libfdt_files), \
 	$(eval CFLAGS_$(file) = -I$(src)/../scripts/dtc/libfdt))
 lib-$(CONFIG_LIBFDT) += $(libfdt_files)
diff --git a/lib/fdt_empty_tree.c b/lib/fdt_empty_tree.c
new file mode 100644
index 0000000..5d30c58
--- /dev/null
+++ b/lib/fdt_empty_tree.c
@@ -0,0 +1,2 @@
+#include <linux/libfdt_env.h>
+#include "../scripts/dtc/libfdt/fdt_empty_tree.c"
-- 
1.7.10.4


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

* [PATCH v3 01/10] lib: add fdt_empty_tree.c
@ 2014-04-04 18:45   ` Leif Lindholm
  0 siblings, 0 replies; 55+ messages in thread
From: Leif Lindholm @ 2014-04-04 18:45 UTC (permalink / raw)
  To: linux-arm-kernel

From: Mark Salter <msalter@redhat.com>

CONFIG_LIBFDT support does not include fdt_empty_tree.c which is
needed by arm64 EFI stub. Add it to libfdt_files.

Signed-off-by: Mark Salter <msalter@redhat.com>
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
---
 lib/Makefile         |    3 ++-
 lib/fdt_empty_tree.c |    2 ++
 2 files changed, 4 insertions(+), 1 deletion(-)
 create mode 100644 lib/fdt_empty_tree.c

diff --git a/lib/Makefile b/lib/Makefile
index 02da5b6..5f5b6a2 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -149,7 +149,8 @@ obj-$(CONFIG_GENERIC_NET_UTILS) += net_utils.o
 
 obj-$(CONFIG_STMP_DEVICE) += stmp_device.o
 
-libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o
+libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o \
+	       fdt_empty_tree.o
 $(foreach file, $(libfdt_files), \
 	$(eval CFLAGS_$(file) = -I$(src)/../scripts/dtc/libfdt))
 lib-$(CONFIG_LIBFDT) += $(libfdt_files)
diff --git a/lib/fdt_empty_tree.c b/lib/fdt_empty_tree.c
new file mode 100644
index 0000000..5d30c58
--- /dev/null
+++ b/lib/fdt_empty_tree.c
@@ -0,0 +1,2 @@
+#include <linux/libfdt_env.h>
+#include "../scripts/dtc/libfdt/fdt_empty_tree.c"
-- 
1.7.10.4

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

* [PATCH v3 02/10] doc: efi-stub.txt updates for ARM
  2014-04-04 18:45 ` Leif Lindholm
  (?)
@ 2014-04-04 18:45   ` Leif Lindholm
  -1 siblings, 0 replies; 55+ messages in thread
From: Leif Lindholm @ 2014-04-04 18:45 UTC (permalink / raw)
  To: linux-arm-kernel, linux-efi; +Cc: linux-kernel, Roy Franz, Leif Lindholm

From: Roy Franz <roy.franz@linaro.org>

Update efi-stub.txt documentation to be more general
and not x86 specific.  Add ARM only "dtb=" command
line option description.

Signed-off-by: Roy Franz <roy.franz@linaro.org>
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Acked-by: Grant Likely <grant.likely@linaro.org>
---
 Documentation/efi-stub.txt |   27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/Documentation/efi-stub.txt b/Documentation/efi-stub.txt
index c628788..26be7b0 100644
--- a/Documentation/efi-stub.txt
+++ b/Documentation/efi-stub.txt
@@ -1,13 +1,16 @@
 			  The EFI Boot Stub
 		     ---------------------------
 
-On the x86 platform, a bzImage can masquerade as a PE/COFF image,
-thereby convincing EFI firmware loaders to load it as an EFI
-executable. The code that modifies the bzImage header, along with the
-EFI-specific entry point that the firmware loader jumps to are
-collectively known as the "EFI boot stub", and live in
+On the x86 and ARM platforms, a kernel zImage/bzImage can masquerade
+as a PE/COFF image, thereby convincing EFI firmware loaders to load
+it as an EFI executable. The code that modifies the bzImage header,
+along with the EFI-specific entry point that the firmware loader
+jumps to are collectively known as the "EFI boot stub", and live in
 arch/x86/boot/header.S and arch/x86/boot/compressed/eboot.c,
-respectively.
+respectively. For ARM the EFI stub is implemented in
+arch/arm/boot/compressed/efi-header.S and
+arch/arm/boot/compressed/efi-stub.c. EFI stub code that is shared
+between architectures is in drivers/firmware/efi/efi-stub-helper.c.
 
 By using the EFI boot stub it's possible to boot a Linux kernel
 without the use of a conventional EFI boot loader, such as grub or
@@ -23,7 +26,9 @@ The bzImage located in arch/x86/boot/bzImage must be copied to the EFI
 System Partition (ESP) and renamed with the extension ".efi". Without
 the extension the EFI firmware loader will refuse to execute it. It's
 not possible to execute bzImage.efi from the usual Linux file systems
-because EFI firmware doesn't have support for them.
+because EFI firmware doesn't have support for them. For ARM the
+arch/arm/boot/zImage should be copied to the system partition, and it
+may not need to be renamed.
 
 
 **** Passing kernel parameters from the EFI shell
@@ -63,3 +68,11 @@ Notice how bzImage.efi can be specified with a relative path. That's
 because the image we're executing is interpreted by the EFI shell,
 which understands relative paths, whereas the rest of the command line
 is passed to bzImage.efi.
+
+
+**** The "dtb=" option
+
+For the ARM architecture, we also need to be able to provide a device
+tree to the kernel. This is done with the "dtb=" command line option,
+and is processed in the same manner as the "initrd=" option that is
+described above.
-- 
1.7.10.4


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

* [PATCH v3 02/10] doc: efi-stub.txt updates for ARM
@ 2014-04-04 18:45   ` Leif Lindholm
  0 siblings, 0 replies; 55+ messages in thread
From: Leif Lindholm @ 2014-04-04 18:45 UTC (permalink / raw)
  To: linux-arm-kernel, linux-efi; +Cc: Roy Franz, linux-kernel, Leif Lindholm

From: Roy Franz <roy.franz@linaro.org>

Update efi-stub.txt documentation to be more general
and not x86 specific.  Add ARM only "dtb=" command
line option description.

Signed-off-by: Roy Franz <roy.franz@linaro.org>
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Acked-by: Grant Likely <grant.likely@linaro.org>
---
 Documentation/efi-stub.txt |   27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/Documentation/efi-stub.txt b/Documentation/efi-stub.txt
index c628788..26be7b0 100644
--- a/Documentation/efi-stub.txt
+++ b/Documentation/efi-stub.txt
@@ -1,13 +1,16 @@
 			  The EFI Boot Stub
 		     ---------------------------
 
-On the x86 platform, a bzImage can masquerade as a PE/COFF image,
-thereby convincing EFI firmware loaders to load it as an EFI
-executable. The code that modifies the bzImage header, along with the
-EFI-specific entry point that the firmware loader jumps to are
-collectively known as the "EFI boot stub", and live in
+On the x86 and ARM platforms, a kernel zImage/bzImage can masquerade
+as a PE/COFF image, thereby convincing EFI firmware loaders to load
+it as an EFI executable. The code that modifies the bzImage header,
+along with the EFI-specific entry point that the firmware loader
+jumps to are collectively known as the "EFI boot stub", and live in
 arch/x86/boot/header.S and arch/x86/boot/compressed/eboot.c,
-respectively.
+respectively. For ARM the EFI stub is implemented in
+arch/arm/boot/compressed/efi-header.S and
+arch/arm/boot/compressed/efi-stub.c. EFI stub code that is shared
+between architectures is in drivers/firmware/efi/efi-stub-helper.c.
 
 By using the EFI boot stub it's possible to boot a Linux kernel
 without the use of a conventional EFI boot loader, such as grub or
@@ -23,7 +26,9 @@ The bzImage located in arch/x86/boot/bzImage must be copied to the EFI
 System Partition (ESP) and renamed with the extension ".efi". Without
 the extension the EFI firmware loader will refuse to execute it. It's
 not possible to execute bzImage.efi from the usual Linux file systems
-because EFI firmware doesn't have support for them.
+because EFI firmware doesn't have support for them. For ARM the
+arch/arm/boot/zImage should be copied to the system partition, and it
+may not need to be renamed.
 
 
 **** Passing kernel parameters from the EFI shell
@@ -63,3 +68,11 @@ Notice how bzImage.efi can be specified with a relative path. That's
 because the image we're executing is interpreted by the EFI shell,
 which understands relative paths, whereas the rest of the command line
 is passed to bzImage.efi.
+
+
+**** The "dtb=" option
+
+For the ARM architecture, we also need to be able to provide a device
+tree to the kernel. This is done with the "dtb=" command line option,
+and is processed in the same manner as the "initrd=" option that is
+described above.
-- 
1.7.10.4

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

* [PATCH v3 02/10] doc: efi-stub.txt updates for ARM
@ 2014-04-04 18:45   ` Leif Lindholm
  0 siblings, 0 replies; 55+ messages in thread
From: Leif Lindholm @ 2014-04-04 18:45 UTC (permalink / raw)
  To: linux-arm-kernel

From: Roy Franz <roy.franz@linaro.org>

Update efi-stub.txt documentation to be more general
and not x86 specific.  Add ARM only "dtb=" command
line option description.

Signed-off-by: Roy Franz <roy.franz@linaro.org>
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Acked-by: Grant Likely <grant.likely@linaro.org>
---
 Documentation/efi-stub.txt |   27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/Documentation/efi-stub.txt b/Documentation/efi-stub.txt
index c628788..26be7b0 100644
--- a/Documentation/efi-stub.txt
+++ b/Documentation/efi-stub.txt
@@ -1,13 +1,16 @@
 			  The EFI Boot Stub
 		     ---------------------------
 
-On the x86 platform, a bzImage can masquerade as a PE/COFF image,
-thereby convincing EFI firmware loaders to load it as an EFI
-executable. The code that modifies the bzImage header, along with the
-EFI-specific entry point that the firmware loader jumps to are
-collectively known as the "EFI boot stub", and live in
+On the x86 and ARM platforms, a kernel zImage/bzImage can masquerade
+as a PE/COFF image, thereby convincing EFI firmware loaders to load
+it as an EFI executable. The code that modifies the bzImage header,
+along with the EFI-specific entry point that the firmware loader
+jumps to are collectively known as the "EFI boot stub", and live in
 arch/x86/boot/header.S and arch/x86/boot/compressed/eboot.c,
-respectively.
+respectively. For ARM the EFI stub is implemented in
+arch/arm/boot/compressed/efi-header.S and
+arch/arm/boot/compressed/efi-stub.c. EFI stub code that is shared
+between architectures is in drivers/firmware/efi/efi-stub-helper.c.
 
 By using the EFI boot stub it's possible to boot a Linux kernel
 without the use of a conventional EFI boot loader, such as grub or
@@ -23,7 +26,9 @@ The bzImage located in arch/x86/boot/bzImage must be copied to the EFI
 System Partition (ESP) and renamed with the extension ".efi". Without
 the extension the EFI firmware loader will refuse to execute it. It's
 not possible to execute bzImage.efi from the usual Linux file systems
-because EFI firmware doesn't have support for them.
+because EFI firmware doesn't have support for them. For ARM the
+arch/arm/boot/zImage should be copied to the system partition, and it
+may not need to be renamed.
 
 
 **** Passing kernel parameters from the EFI shell
@@ -63,3 +68,11 @@ Notice how bzImage.efi can be specified with a relative path. That's
 because the image we're executing is interpreted by the EFI shell,
 which understands relative paths, whereas the rest of the command line
 is passed to bzImage.efi.
+
+
+**** The "dtb=" option
+
+For the ARM architecture, we also need to be able to provide a device
+tree to the kernel. This is done with the "dtb=" command line option,
+and is processed in the same manner as the "initrd=" option that is
+described above.
-- 
1.7.10.4

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

* [PATCH v3 03/10] efi: add helper function to get UEFI params from FDT
  2014-04-04 18:45 ` Leif Lindholm
@ 2014-04-04 18:45   ` Leif Lindholm
  -1 siblings, 0 replies; 55+ messages in thread
From: Leif Lindholm @ 2014-04-04 18:45 UTC (permalink / raw)
  To: linux-arm-kernel, linux-efi
  Cc: linux-kernel, Mark Salter, Leif Lindholm, Matt Fleming

From: Mark Salter <msalter@redhat.com>

ARM and ARM64 architectures use the device tree to pass UEFI parameters
from stub to kernel. These parameters are things known to the stub but
not discoverable by the kernel after the stub calls ExitBootSerives().
There is a helper function in:

   drivers/firmware/efi/fdt.c

which the stub uses to add the UEFI parameters to the device tree.
This patch adds a complimentary helper function which UEFI runtime
support may use to retrieve the parameters from the device tree.
If an architecture wants to use this helper, it should select
CONFIG_UEFI_PARAMS_FROM_FDT.

Signed-off-by: Mark Salter <msalter@redhat.com>
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Matt Fleming <matt.fleming@intel.com>
---
 drivers/firmware/efi/Kconfig |    7 ++++
 drivers/firmware/efi/efi.c   |   79 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/efi.h          |    9 +++++
 3 files changed, 95 insertions(+)

diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 1e75f48..d3fe28d 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -47,6 +47,13 @@ config EFI_RUNTIME_MAP
 
 	  See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map.
 
+config UEFI_PARAMS_FROM_FDT
+	bool
+	help
+	  Select this config option from the architecture Kconfig if
+	  the EFI runtime support gets system table address, memory
+          map address, and other parameters from the device tree.
+
 endmenu
 
 config UEFI_CPER
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index af20f17..ece6197 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -20,6 +20,8 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/efi.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
 #include <linux/io.h>
 
 struct efi __read_mostly efi = {
@@ -318,3 +320,80 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables)
 
 	return 0;
 }
+
+#ifdef CONFIG_UEFI_PARAMS_FROM_FDT
+
+#define UEFI_PARAM(name, prop, field)			   \
+	{						   \
+		{ name },				   \
+		{ prop },				   \
+		offsetof(struct efi_fdt_params, field),    \
+		FIELD_SIZEOF(struct efi_fdt_params, field) \
+	}
+
+static __initdata struct {
+	const char name[32];
+	const char propname[32];
+	int offset;
+	int size;
+} dt_params[] = {
+	UEFI_PARAM("System Table", "linux,uefi-system-table", system_table),
+	UEFI_PARAM("MemMap Address", "linux,uefi-mmap-start", mmap),
+	UEFI_PARAM("MemMap Size", "linux,uefi-mmap-size", mmap_size),
+	UEFI_PARAM("MemMap Desc. Size", "linux,uefi-mmap-desc-size", desc_size),
+	UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver)
+};
+
+struct param_info {
+	int verbose;
+	void *params;
+};
+
+static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
+				       int depth, void *data)
+{
+	struct param_info *info = data;
+	void *prop, *dest;
+	unsigned long len;
+	u64 val;
+	int i;
+
+	if (depth != 1 ||
+	    (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
+		return 0;
+
+	pr_info("Getting parameters from FDT:\n");
+
+	for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
+		prop = of_get_flat_dt_prop(node, dt_params[i].propname, &len);
+		if (!prop) {
+			pr_err("Can't find %s in device tree!\n",
+			       dt_params[i].name);
+			return 0;
+		}
+		dest = info->params + dt_params[i].offset;
+
+		val = of_read_number(prop, len / sizeof(u32));
+
+		if (dt_params[i].size == sizeof(u32))
+			*(u32 *)dest = val;
+		else
+			*(u64 *)dest = val;
+
+		if (info->verbose)
+			pr_info("  %s: 0x%0*llx\n", dt_params[i].name,
+				dt_params[i].size * 2, val);
+	}
+	return 1;
+}
+
+int __init efi_get_fdt_params(struct efi_fdt_params *params, int verbose)
+{
+	struct param_info info;
+
+	info.verbose = verbose;
+	info.params = params;
+
+	return of_scan_flat_dt(fdt_find_uefi_params, &info);
+}
+#endif /* CONFIG_UEFI_PARAMS_FROM_FDT */
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 82d0abb..4f52ac6 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -664,6 +664,14 @@ struct efi_memory_map {
 	unsigned long desc_size;
 };
 
+struct efi_fdt_params {
+	u64 system_table;
+	u64 mmap;
+	u32 mmap_size;
+	u32 desc_size;
+	u32 desc_ver;
+};
+
 typedef struct {
 	u32 revision;
 	u32 parent_handle;
@@ -861,6 +869,7 @@ extern void efi_initialize_iomem_resources(struct resource *code_resource,
 extern void efi_get_time(struct timespec *now);
 extern int efi_set_rtc_mmss(const struct timespec *now);
 extern void efi_reserve_boot_services(void);
+extern int efi_get_fdt_params(struct efi_fdt_params *params, int verbose);
 extern struct efi_memory_map memmap;
 
 /* Iterate through an efi_memory_map */
-- 
1.7.10.4


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

* [PATCH v3 03/10] efi: add helper function to get UEFI params from FDT
@ 2014-04-04 18:45   ` Leif Lindholm
  0 siblings, 0 replies; 55+ messages in thread
From: Leif Lindholm @ 2014-04-04 18:45 UTC (permalink / raw)
  To: linux-arm-kernel

From: Mark Salter <msalter@redhat.com>

ARM and ARM64 architectures use the device tree to pass UEFI parameters
from stub to kernel. These parameters are things known to the stub but
not discoverable by the kernel after the stub calls ExitBootSerives().
There is a helper function in:

   drivers/firmware/efi/fdt.c

which the stub uses to add the UEFI parameters to the device tree.
This patch adds a complimentary helper function which UEFI runtime
support may use to retrieve the parameters from the device tree.
If an architecture wants to use this helper, it should select
CONFIG_UEFI_PARAMS_FROM_FDT.

Signed-off-by: Mark Salter <msalter@redhat.com>
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Matt Fleming <matt.fleming@intel.com>
---
 drivers/firmware/efi/Kconfig |    7 ++++
 drivers/firmware/efi/efi.c   |   79 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/efi.h          |    9 +++++
 3 files changed, 95 insertions(+)

diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 1e75f48..d3fe28d 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -47,6 +47,13 @@ config EFI_RUNTIME_MAP
 
 	  See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map.
 
+config UEFI_PARAMS_FROM_FDT
+	bool
+	help
+	  Select this config option from the architecture Kconfig if
+	  the EFI runtime support gets system table address, memory
+          map address, and other parameters from the device tree.
+
 endmenu
 
 config UEFI_CPER
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index af20f17..ece6197 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -20,6 +20,8 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/efi.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
 #include <linux/io.h>
 
 struct efi __read_mostly efi = {
@@ -318,3 +320,80 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables)
 
 	return 0;
 }
+
+#ifdef CONFIG_UEFI_PARAMS_FROM_FDT
+
+#define UEFI_PARAM(name, prop, field)			   \
+	{						   \
+		{ name },				   \
+		{ prop },				   \
+		offsetof(struct efi_fdt_params, field),    \
+		FIELD_SIZEOF(struct efi_fdt_params, field) \
+	}
+
+static __initdata struct {
+	const char name[32];
+	const char propname[32];
+	int offset;
+	int size;
+} dt_params[] = {
+	UEFI_PARAM("System Table", "linux,uefi-system-table", system_table),
+	UEFI_PARAM("MemMap Address", "linux,uefi-mmap-start", mmap),
+	UEFI_PARAM("MemMap Size", "linux,uefi-mmap-size", mmap_size),
+	UEFI_PARAM("MemMap Desc. Size", "linux,uefi-mmap-desc-size", desc_size),
+	UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver)
+};
+
+struct param_info {
+	int verbose;
+	void *params;
+};
+
+static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
+				       int depth, void *data)
+{
+	struct param_info *info = data;
+	void *prop, *dest;
+	unsigned long len;
+	u64 val;
+	int i;
+
+	if (depth != 1 ||
+	    (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen at 0") != 0))
+		return 0;
+
+	pr_info("Getting parameters from FDT:\n");
+
+	for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
+		prop = of_get_flat_dt_prop(node, dt_params[i].propname, &len);
+		if (!prop) {
+			pr_err("Can't find %s in device tree!\n",
+			       dt_params[i].name);
+			return 0;
+		}
+		dest = info->params + dt_params[i].offset;
+
+		val = of_read_number(prop, len / sizeof(u32));
+
+		if (dt_params[i].size == sizeof(u32))
+			*(u32 *)dest = val;
+		else
+			*(u64 *)dest = val;
+
+		if (info->verbose)
+			pr_info("  %s: 0x%0*llx\n", dt_params[i].name,
+				dt_params[i].size * 2, val);
+	}
+	return 1;
+}
+
+int __init efi_get_fdt_params(struct efi_fdt_params *params, int verbose)
+{
+	struct param_info info;
+
+	info.verbose = verbose;
+	info.params = params;
+
+	return of_scan_flat_dt(fdt_find_uefi_params, &info);
+}
+#endif /* CONFIG_UEFI_PARAMS_FROM_FDT */
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 82d0abb..4f52ac6 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -664,6 +664,14 @@ struct efi_memory_map {
 	unsigned long desc_size;
 };
 
+struct efi_fdt_params {
+	u64 system_table;
+	u64 mmap;
+	u32 mmap_size;
+	u32 desc_size;
+	u32 desc_ver;
+};
+
 typedef struct {
 	u32 revision;
 	u32 parent_handle;
@@ -861,6 +869,7 @@ extern void efi_initialize_iomem_resources(struct resource *code_resource,
 extern void efi_get_time(struct timespec *now);
 extern int efi_set_rtc_mmss(const struct timespec *now);
 extern void efi_reserve_boot_services(void);
+extern int efi_get_fdt_params(struct efi_fdt_params *params, int verbose);
 extern struct efi_memory_map memmap;
 
 /* Iterate through an efi_memory_map */
-- 
1.7.10.4

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

* [PATCH v3 04/10] arm64: Add function to create identity mappings
  2014-04-04 18:45 ` Leif Lindholm
@ 2014-04-04 18:45   ` Leif Lindholm
  -1 siblings, 0 replies; 55+ messages in thread
From: Leif Lindholm @ 2014-04-04 18:45 UTC (permalink / raw)
  To: linux-arm-kernel, linux-efi
  Cc: linux-kernel, Mark Salter, Leif Lindholm, Catalin Marinas

From: Mark Salter <msalter@redhat.com>

At boot time, before switching to a virtual UEFI memory map, firmware
expects UEFI memory and IO regions to be identity mapped whenever
kernel makes runtime services calls. The existing early boot code
creates an identity map of kernel text/data but this is not sufficient
for UEFI. This patch adds a create_id_mapping() function which reuses
the core code of the existing create_mapping().

Signed-off-by: Mark Salter <msalter@redhat.com>
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
---
 arch/arm64/include/asm/mmu.h |    2 ++
 arch/arm64/mm/mmu.c          |   65 ++++++++++++++++++++++++++++++------------
 2 files changed, 49 insertions(+), 18 deletions(-)

diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index f600d40..29ed1d8 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -28,5 +28,7 @@ extern void paging_init(void);
 extern void setup_mm_for_reboot(void);
 extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt);
 extern void init_mem_pgprot(void);
+/* create an identity mapping for memory (or io if map_io is true) */
+extern void create_id_mapping(phys_addr_t addr, phys_addr_t size, int map_io);
 
 #endif
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 6b7e895..357956a 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -168,7 +168,8 @@ static void __init *early_alloc(unsigned long sz)
 }
 
 static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
-				  unsigned long end, unsigned long pfn)
+				  unsigned long end, unsigned long pfn,
+				  pgprot_t prot)
 {
 	pte_t *pte;
 
@@ -180,16 +181,28 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
 
 	pte = pte_offset_kernel(pmd, addr);
 	do {
-		set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
+		set_pte(pte, pfn_pte(pfn, prot));
 		pfn++;
 	} while (pte++, addr += PAGE_SIZE, addr != end);
 }
 
 static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
-				  unsigned long end, phys_addr_t phys)
+				  unsigned long end, phys_addr_t phys,
+				  int map_io)
 {
 	pmd_t *pmd;
 	unsigned long next;
+	pmdval_t prot_sect;
+	pgprot_t prot_pte;
+
+	if (map_io) {
+		prot_sect = PMD_TYPE_SECT | PMD_SECT_AF |
+			    PMD_ATTRINDX(MT_DEVICE_nGnRE);
+		prot_pte = __pgprot(PROT_DEVICE_nGnRE);
+	} else {
+		prot_sect = prot_sect_kernel;
+		prot_pte = PAGE_KERNEL_EXEC;
+	}
 
 	/*
 	 * Check for initial section mappings in the pgd/pud and remove them.
@@ -205,7 +218,7 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
 		/* try section mapping first */
 		if (((addr | next | phys) & ~SECTION_MASK) == 0) {
 			pmd_t old_pmd =*pmd;
-			set_pmd(pmd, __pmd(phys | prot_sect_kernel));
+			set_pmd(pmd, __pmd(phys | prot_sect));
 			/*
 			 * Check for previous table entries created during
 			 * boot (__create_page_tables) and flush them.
@@ -213,21 +226,23 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
 			if (!pmd_none(old_pmd))
 				flush_tlb_all();
 		} else {
-			alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys));
+			alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys),
+				       prot_pte);
 		}
 		phys += next - addr;
 	} while (pmd++, addr = next, addr != end);
 }
 
 static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
-				  unsigned long end, unsigned long phys)
+				  unsigned long end, unsigned long phys,
+				  int map_io)
 {
 	pud_t *pud = pud_offset(pgd, addr);
 	unsigned long next;
 
 	do {
 		next = pud_addr_end(addr, end);
-		alloc_init_pmd(pud, addr, next, phys);
+		alloc_init_pmd(pud, addr, next, phys, map_io);
 		phys += next - addr;
 	} while (pud++, addr = next, addr != end);
 }
@@ -236,30 +251,44 @@ static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
  * Create the page directory entries and any necessary page tables for the
  * mapping specified by 'md'.
  */
-static void __init create_mapping(phys_addr_t phys, unsigned long virt,
-				  phys_addr_t size)
+static void __init __create_mapping(pgd_t *pgd, phys_addr_t phys,
+				    unsigned long virt, phys_addr_t size,
+				    int map_io)
 {
 	unsigned long addr, length, end, next;
-	pgd_t *pgd;
-
-	if (virt < VMALLOC_START) {
-		pr_warning("BUG: not creating mapping for 0x%016llx at 0x%016lx - outside kernel range\n",
-			   phys, virt);
-		return;
-	}
 
 	addr = virt & PAGE_MASK;
 	length = PAGE_ALIGN(size + (virt & ~PAGE_MASK));
 
-	pgd = pgd_offset_k(addr);
 	end = addr + length;
 	do {
 		next = pgd_addr_end(addr, end);
-		alloc_init_pud(pgd, addr, next, phys);
+		alloc_init_pud(pgd, addr, next, phys, map_io);
 		phys += next - addr;
 	} while (pgd++, addr = next, addr != end);
 }
 
+static void __init create_mapping(phys_addr_t phys, unsigned long virt,
+				  phys_addr_t size)
+{
+	if (virt < VMALLOC_START) {
+		pr_warn("BUG: not creating mapping for 0x%016llx at 0x%016lx - outside kernel range\n",
+			phys, virt);
+		return;
+	}
+	__create_mapping(pgd_offset_k(virt & PAGE_MASK), phys, virt, size, 0);
+}
+
+void __init create_id_mapping(phys_addr_t addr, phys_addr_t size, int map_io)
+{
+	if ((addr >> PGDIR_SHIFT) >= ARRAY_SIZE(idmap_pg_dir)) {
+		pr_warn("BUG: not creating id mapping for 0x%016llx\n", addr);
+		return;
+	}
+	__create_mapping(&idmap_pg_dir[pgd_index(addr)],
+			 addr, addr, size, map_io);
+}
+
 static void __init map_mem(void)
 {
 	struct memblock_region *reg;
-- 
1.7.10.4


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

* [PATCH v3 04/10] arm64: Add function to create identity mappings
@ 2014-04-04 18:45   ` Leif Lindholm
  0 siblings, 0 replies; 55+ messages in thread
From: Leif Lindholm @ 2014-04-04 18:45 UTC (permalink / raw)
  To: linux-arm-kernel

From: Mark Salter <msalter@redhat.com>

At boot time, before switching to a virtual UEFI memory map, firmware
expects UEFI memory and IO regions to be identity mapped whenever
kernel makes runtime services calls. The existing early boot code
creates an identity map of kernel text/data but this is not sufficient
for UEFI. This patch adds a create_id_mapping() function which reuses
the core code of the existing create_mapping().

Signed-off-by: Mark Salter <msalter@redhat.com>
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
---
 arch/arm64/include/asm/mmu.h |    2 ++
 arch/arm64/mm/mmu.c          |   65 ++++++++++++++++++++++++++++++------------
 2 files changed, 49 insertions(+), 18 deletions(-)

diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index f600d40..29ed1d8 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -28,5 +28,7 @@ extern void paging_init(void);
 extern void setup_mm_for_reboot(void);
 extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt);
 extern void init_mem_pgprot(void);
+/* create an identity mapping for memory (or io if map_io is true) */
+extern void create_id_mapping(phys_addr_t addr, phys_addr_t size, int map_io);
 
 #endif
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 6b7e895..357956a 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -168,7 +168,8 @@ static void __init *early_alloc(unsigned long sz)
 }
 
 static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
-				  unsigned long end, unsigned long pfn)
+				  unsigned long end, unsigned long pfn,
+				  pgprot_t prot)
 {
 	pte_t *pte;
 
@@ -180,16 +181,28 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
 
 	pte = pte_offset_kernel(pmd, addr);
 	do {
-		set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
+		set_pte(pte, pfn_pte(pfn, prot));
 		pfn++;
 	} while (pte++, addr += PAGE_SIZE, addr != end);
 }
 
 static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
-				  unsigned long end, phys_addr_t phys)
+				  unsigned long end, phys_addr_t phys,
+				  int map_io)
 {
 	pmd_t *pmd;
 	unsigned long next;
+	pmdval_t prot_sect;
+	pgprot_t prot_pte;
+
+	if (map_io) {
+		prot_sect = PMD_TYPE_SECT | PMD_SECT_AF |
+			    PMD_ATTRINDX(MT_DEVICE_nGnRE);
+		prot_pte = __pgprot(PROT_DEVICE_nGnRE);
+	} else {
+		prot_sect = prot_sect_kernel;
+		prot_pte = PAGE_KERNEL_EXEC;
+	}
 
 	/*
 	 * Check for initial section mappings in the pgd/pud and remove them.
@@ -205,7 +218,7 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
 		/* try section mapping first */
 		if (((addr | next | phys) & ~SECTION_MASK) == 0) {
 			pmd_t old_pmd =*pmd;
-			set_pmd(pmd, __pmd(phys | prot_sect_kernel));
+			set_pmd(pmd, __pmd(phys | prot_sect));
 			/*
 			 * Check for previous table entries created during
 			 * boot (__create_page_tables) and flush them.
@@ -213,21 +226,23 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
 			if (!pmd_none(old_pmd))
 				flush_tlb_all();
 		} else {
-			alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys));
+			alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys),
+				       prot_pte);
 		}
 		phys += next - addr;
 	} while (pmd++, addr = next, addr != end);
 }
 
 static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
-				  unsigned long end, unsigned long phys)
+				  unsigned long end, unsigned long phys,
+				  int map_io)
 {
 	pud_t *pud = pud_offset(pgd, addr);
 	unsigned long next;
 
 	do {
 		next = pud_addr_end(addr, end);
-		alloc_init_pmd(pud, addr, next, phys);
+		alloc_init_pmd(pud, addr, next, phys, map_io);
 		phys += next - addr;
 	} while (pud++, addr = next, addr != end);
 }
@@ -236,30 +251,44 @@ static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
  * Create the page directory entries and any necessary page tables for the
  * mapping specified by 'md'.
  */
-static void __init create_mapping(phys_addr_t phys, unsigned long virt,
-				  phys_addr_t size)
+static void __init __create_mapping(pgd_t *pgd, phys_addr_t phys,
+				    unsigned long virt, phys_addr_t size,
+				    int map_io)
 {
 	unsigned long addr, length, end, next;
-	pgd_t *pgd;
-
-	if (virt < VMALLOC_START) {
-		pr_warning("BUG: not creating mapping for 0x%016llx at 0x%016lx - outside kernel range\n",
-			   phys, virt);
-		return;
-	}
 
 	addr = virt & PAGE_MASK;
 	length = PAGE_ALIGN(size + (virt & ~PAGE_MASK));
 
-	pgd = pgd_offset_k(addr);
 	end = addr + length;
 	do {
 		next = pgd_addr_end(addr, end);
-		alloc_init_pud(pgd, addr, next, phys);
+		alloc_init_pud(pgd, addr, next, phys, map_io);
 		phys += next - addr;
 	} while (pgd++, addr = next, addr != end);
 }
 
+static void __init create_mapping(phys_addr_t phys, unsigned long virt,
+				  phys_addr_t size)
+{
+	if (virt < VMALLOC_START) {
+		pr_warn("BUG: not creating mapping for 0x%016llx@0x%016lx - outside kernel range\n",
+			phys, virt);
+		return;
+	}
+	__create_mapping(pgd_offset_k(virt & PAGE_MASK), phys, virt, size, 0);
+}
+
+void __init create_id_mapping(phys_addr_t addr, phys_addr_t size, int map_io)
+{
+	if ((addr >> PGDIR_SHIFT) >= ARRAY_SIZE(idmap_pg_dir)) {
+		pr_warn("BUG: not creating id mapping for 0x%016llx\n", addr);
+		return;
+	}
+	__create_mapping(&idmap_pg_dir[pgd_index(addr)],
+			 addr, addr, size, map_io);
+}
+
 static void __init map_mem(void)
 {
 	struct memblock_region *reg;
-- 
1.7.10.4

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

* [PATCH v3 05/10] efi: Add shared FDT related functions for ARM/ARM64
@ 2014-04-04 18:45   ` Leif Lindholm
  0 siblings, 0 replies; 55+ messages in thread
From: Leif Lindholm @ 2014-04-04 18:45 UTC (permalink / raw)
  To: linux-arm-kernel, linux-efi
  Cc: linux-kernel, Roy Franz, Leif Lindholm, Matt Fleming

From: Roy Franz <roy.franz@linaro.org>

Both ARM and ARM64 stubs will update the device tree that they pass to
the kernel.  In both cases they primarily need to add the same UEFI
related information, so the function can be shared.  Create a new FDT
related file for this to avoid use of architecture #ifdefs in
efi-stub-helper.c.

Signed-off-by: Roy Franz <roy.franz@linaro.org>
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Acked-by: Grant Likely <grant.likely@linaro.org>
Cc: Matt Fleming <matt.fleming@intel.com>
---
 drivers/firmware/efi/fdt.c |  269 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/efi.h        |    3 +
 2 files changed, 272 insertions(+)
 create mode 100644 drivers/firmware/efi/fdt.c

diff --git a/drivers/firmware/efi/fdt.c b/drivers/firmware/efi/fdt.c
new file mode 100644
index 0000000..6f306b4
--- /dev/null
+++ b/drivers/firmware/efi/fdt.c
@@ -0,0 +1,269 @@
+/*
+ * FDT related Helper functions used by the EFI stub on multiple
+ * architectures. This should be #included by the EFI stub
+ * implementation files.
+ *
+ * Copyright 2013 Linaro Limited; author Roy Franz
+ *
+ * This file is part of the Linux kernel, and is made available
+ * under the terms of the GNU General Public License version 2.
+ *
+ */
+
+static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
+			       unsigned long orig_fdt_size,
+			       void *fdt, int new_fdt_size, char *cmdline_ptr,
+			       u64 initrd_addr, u64 initrd_size,
+			       efi_memory_desc_t *memory_map,
+			       unsigned long map_size, unsigned long desc_size,
+			       u32 desc_ver)
+{
+	int node;
+	int status;
+	u32 fdt_val32;
+	u64 fdt_val64;
+
+	/*
+	 * Copy definition of linux_banner here.  Since this code is
+	 * built as part of the decompressor for ARM v7, pulling
+	 * in version.c where linux_banner is defined for the
+	 * kernel brings other kernel dependencies with it.
+	 */
+	const char linux_banner[] =
+	    "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
+	    LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
+
+	/* Do some checks on provided FDT, if it exists*/
+	if (orig_fdt) {
+		if (fdt_check_header(orig_fdt)) {
+			pr_efi_err(sys_table, "Device Tree header not valid!\n");
+			return EFI_LOAD_ERROR;
+		}
+		/*
+		 * We don't get the size of the FDT if we get if from a
+		 * configuration table.
+		 */
+		if (orig_fdt_size && fdt_totalsize(orig_fdt) > orig_fdt_size) {
+			pr_efi_err(sys_table, "Truncated device tree! foo!\n");
+			return EFI_LOAD_ERROR;
+		}
+	}
+
+	if (orig_fdt)
+		status = fdt_open_into(orig_fdt, fdt, new_fdt_size);
+	else
+		status = fdt_create_empty_tree(fdt, new_fdt_size);
+
+	if (status != 0)
+		goto fdt_set_fail;
+
+	/* Delete any memory nodes present */
+	while ((node = fdt_subnode_offset(fdt, 0, "memory")) >= 0)
+		fdt_del_node(fdt, node);
+
+	node = fdt_subnode_offset(fdt, 0, "chosen");
+	if (node < 0) {
+		node = fdt_add_subnode(fdt, 0, "chosen");
+		if (node < 0) {
+			status = node; /* node is error code when negative */
+			goto fdt_set_fail;
+		}
+	}
+
+	if ((cmdline_ptr != NULL) && (strlen(cmdline_ptr) > 0)) {
+		status = fdt_setprop(fdt, node, "bootargs", cmdline_ptr,
+				     strlen(cmdline_ptr) + 1);
+		if (status)
+			goto fdt_set_fail;
+	}
+
+	/* Set initrd address/end in device tree, if present */
+	if (initrd_size != 0) {
+		u64 initrd_image_end;
+		u64 initrd_image_start = cpu_to_fdt64(initrd_addr);
+
+		status = fdt_setprop(fdt, node, "linux,initrd-start",
+				     &initrd_image_start, sizeof(u64));
+		if (status)
+			goto fdt_set_fail;
+		initrd_image_end = cpu_to_fdt64(initrd_addr + initrd_size);
+		status = fdt_setprop(fdt, node, "linux,initrd-end",
+				     &initrd_image_end, sizeof(u64));
+		if (status)
+			goto fdt_set_fail;
+	}
+
+	/* Add FDT entries for EFI runtime services in chosen node. */
+	node = fdt_subnode_offset(fdt, 0, "chosen");
+	fdt_val64 = cpu_to_fdt64((u64)(unsigned long)sys_table);
+	status = fdt_setprop(fdt, node, "linux,uefi-system-table",
+			     &fdt_val64, sizeof(fdt_val64));
+	if (status)
+		goto fdt_set_fail;
+
+	fdt_val64 = cpu_to_fdt64((u64)(unsigned long)memory_map);
+	status = fdt_setprop(fdt, node, "linux,uefi-mmap-start",
+			     &fdt_val64,  sizeof(fdt_val64));
+	if (status)
+		goto fdt_set_fail;
+
+	fdt_val32 = cpu_to_fdt32(map_size);
+	status = fdt_setprop(fdt, node, "linux,uefi-mmap-size",
+			     &fdt_val32,  sizeof(fdt_val32));
+	if (status)
+		goto fdt_set_fail;
+
+	fdt_val32 = cpu_to_fdt32(desc_size);
+	status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size",
+			     &fdt_val32, sizeof(fdt_val32));
+	if (status)
+		goto fdt_set_fail;
+
+	fdt_val32 = cpu_to_fdt32(desc_ver);
+	status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver",
+			     &fdt_val32, sizeof(fdt_val32));
+	if (status)
+		goto fdt_set_fail;
+
+	/*
+	 * Add kernel version banner so stub/kernel match can be
+	 * verified.
+	 */
+	status = fdt_setprop_string(fdt, node, "linux,uefi-stub-kern-ver",
+			     linux_banner);
+	if (status)
+		goto fdt_set_fail;
+
+	return EFI_SUCCESS;
+
+fdt_set_fail:
+	if (status == -FDT_ERR_NOSPACE)
+		return EFI_BUFFER_TOO_SMALL;
+
+	return EFI_LOAD_ERROR;
+}
+
+#ifndef EFI_FDT_ALIGN
+#define EFI_FDT_ALIGN EFI_PAGE_SIZE
+#endif
+
+/*
+ * Allocate memory for a new FDT, then add EFI, commandline, and
+ * initrd related fields to the FDT.  This routine increases the
+ * FDT allocation size until the allocated memory is large
+ * enough.  EFI allocations are in EFI_PAGE_SIZE granules,
+ * which are fixed at 4K bytes, so in most cases the first
+ * allocation should succeed.
+ * EFI boot services are exited at the end of this function.
+ * There must be no allocations between the get_memory_map()
+ * call and the exit_boot_services() call, so the exiting of
+ * boot services is very tightly tied to the creation of the FDT
+ * with the final memory map in it.
+ */
+
+efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
+					    void *handle,
+					    unsigned long *new_fdt_addr,
+					    unsigned long max_addr,
+					    u64 initrd_addr, u64 initrd_size,
+					    char *cmdline_ptr,
+					    unsigned long fdt_addr,
+					    unsigned long fdt_size)
+{
+	unsigned long map_size, desc_size;
+	u32 desc_ver;
+	unsigned long mmap_key;
+	efi_memory_desc_t *memory_map;
+	unsigned long new_fdt_size;
+	efi_status_t status;
+
+	/*
+	 * Estimate size of new FDT, and allocate memory for it. We
+	 * will allocate a bigger buffer if this ends up being too
+	 * small, so a rough guess is OK here.
+	 */
+	new_fdt_size = fdt_size + EFI_PAGE_SIZE;
+	while (1) {
+		status = efi_high_alloc(sys_table, new_fdt_size, EFI_FDT_ALIGN,
+					new_fdt_addr, max_addr);
+		if (status != EFI_SUCCESS) {
+			pr_efi_err(sys_table, "Unable to allocate memory for new device tree.\n");
+			goto fail;
+		}
+
+		/*
+		 * Now that we have done our final memory allocation (and free)
+		 * we can get the memory map key  needed for
+		 * exit_boot_services().
+		 */
+		status = efi_get_memory_map(sys_table, &memory_map, &map_size,
+					    &desc_size, &desc_ver, &mmap_key);
+		if (status != EFI_SUCCESS)
+			goto fail_free_new_fdt;
+
+		status = update_fdt(sys_table,
+				    (void *)fdt_addr, fdt_size,
+				    (void *)*new_fdt_addr, new_fdt_size,
+				    cmdline_ptr, initrd_addr, initrd_size,
+				    memory_map, map_size, desc_size, desc_ver);
+
+		/* Succeeding the first time is the expected case. */
+		if (status == EFI_SUCCESS)
+			break;
+
+		if (status == EFI_BUFFER_TOO_SMALL) {
+			/*
+			 * We need to allocate more space for the new
+			 * device tree, so free existing buffer that is
+			 * too small.  Also free memory map, as we will need
+			 * to get new one that reflects the free/alloc we do
+			 * on the device tree buffer.
+			 */
+			efi_free(sys_table, new_fdt_size, *new_fdt_addr);
+			efi_call_phys1(sys_table->boottime->free_pool,
+				       memory_map);
+			new_fdt_size += EFI_PAGE_SIZE;
+		} else {
+			pr_efi_err(sys_table, "Unable to constuct new device tree.\n");
+			goto fail_free_mmap;
+		}
+	}
+
+	/* Now we are ready to exit_boot_services.*/
+	status = efi_call_phys2(sys_table->boottime->exit_boot_services,
+				handle, mmap_key);
+
+
+	if (status == EFI_SUCCESS)
+		return status;
+
+	pr_efi_err(sys_table, "Exit boot services failed.\n");
+
+fail_free_mmap:
+	efi_call_phys1(sys_table->boottime->free_pool, memory_map);
+
+fail_free_new_fdt:
+	efi_free(sys_table, new_fdt_size, *new_fdt_addr);
+
+fail:
+	return EFI_LOAD_ERROR;
+}
+
+static void *get_fdt(efi_system_table_t *sys_table)
+{
+	efi_guid_t fdt_guid = DEVICE_TREE_GUID;
+	efi_config_table_t *tables;
+	void *fdt;
+	int i;
+
+	tables = (efi_config_table_t *) sys_table->tables;
+	fdt = NULL;
+
+	for (i = 0; i < sys_table->nr_tables; i++)
+		if (efi_guidcmp(tables[i].guid, fdt_guid) == 0) {
+			fdt = (void *) tables[i].table;
+			break;
+	 }
+
+	return fdt;
+}
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 4f52ac6..ae3e2b2 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -575,6 +575,9 @@ typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long si
 #define EFI_FILE_SYSTEM_GUID \
     EFI_GUID(  0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
 
+#define DEVICE_TREE_GUID \
+    EFI_GUID(  0xb1b621d5, 0xf19c, 0x41a5, 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0 )
+
 typedef struct {
 	efi_guid_t guid;
 	u64 table;
-- 
1.7.10.4


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

* [PATCH v3 05/10] efi: Add shared FDT related functions for ARM/ARM64
@ 2014-04-04 18:45   ` Leif Lindholm
  0 siblings, 0 replies; 55+ messages in thread
From: Leif Lindholm @ 2014-04-04 18:45 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Roy Franz, Leif Lindholm,
	Matt Fleming

From: Roy Franz <roy.franz-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

Both ARM and ARM64 stubs will update the device tree that they pass to
the kernel.  In both cases they primarily need to add the same UEFI
related information, so the function can be shared.  Create a new FDT
related file for this to avoid use of architecture #ifdefs in
efi-stub-helper.c.

Signed-off-by: Roy Franz <roy.franz-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Signed-off-by: Leif Lindholm <leif.lindholm-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Acked-by: Grant Likely <grant.likely-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Cc: Matt Fleming <matt.fleming-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/firmware/efi/fdt.c |  269 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/efi.h        |    3 +
 2 files changed, 272 insertions(+)
 create mode 100644 drivers/firmware/efi/fdt.c

diff --git a/drivers/firmware/efi/fdt.c b/drivers/firmware/efi/fdt.c
new file mode 100644
index 0000000..6f306b4
--- /dev/null
+++ b/drivers/firmware/efi/fdt.c
@@ -0,0 +1,269 @@
+/*
+ * FDT related Helper functions used by the EFI stub on multiple
+ * architectures. This should be #included by the EFI stub
+ * implementation files.
+ *
+ * Copyright 2013 Linaro Limited; author Roy Franz
+ *
+ * This file is part of the Linux kernel, and is made available
+ * under the terms of the GNU General Public License version 2.
+ *
+ */
+
+static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
+			       unsigned long orig_fdt_size,
+			       void *fdt, int new_fdt_size, char *cmdline_ptr,
+			       u64 initrd_addr, u64 initrd_size,
+			       efi_memory_desc_t *memory_map,
+			       unsigned long map_size, unsigned long desc_size,
+			       u32 desc_ver)
+{
+	int node;
+	int status;
+	u32 fdt_val32;
+	u64 fdt_val64;
+
+	/*
+	 * Copy definition of linux_banner here.  Since this code is
+	 * built as part of the decompressor for ARM v7, pulling
+	 * in version.c where linux_banner is defined for the
+	 * kernel brings other kernel dependencies with it.
+	 */
+	const char linux_banner[] =
+	    "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
+	    LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
+
+	/* Do some checks on provided FDT, if it exists*/
+	if (orig_fdt) {
+		if (fdt_check_header(orig_fdt)) {
+			pr_efi_err(sys_table, "Device Tree header not valid!\n");
+			return EFI_LOAD_ERROR;
+		}
+		/*
+		 * We don't get the size of the FDT if we get if from a
+		 * configuration table.
+		 */
+		if (orig_fdt_size && fdt_totalsize(orig_fdt) > orig_fdt_size) {
+			pr_efi_err(sys_table, "Truncated device tree! foo!\n");
+			return EFI_LOAD_ERROR;
+		}
+	}
+
+	if (orig_fdt)
+		status = fdt_open_into(orig_fdt, fdt, new_fdt_size);
+	else
+		status = fdt_create_empty_tree(fdt, new_fdt_size);
+
+	if (status != 0)
+		goto fdt_set_fail;
+
+	/* Delete any memory nodes present */
+	while ((node = fdt_subnode_offset(fdt, 0, "memory")) >= 0)
+		fdt_del_node(fdt, node);
+
+	node = fdt_subnode_offset(fdt, 0, "chosen");
+	if (node < 0) {
+		node = fdt_add_subnode(fdt, 0, "chosen");
+		if (node < 0) {
+			status = node; /* node is error code when negative */
+			goto fdt_set_fail;
+		}
+	}
+
+	if ((cmdline_ptr != NULL) && (strlen(cmdline_ptr) > 0)) {
+		status = fdt_setprop(fdt, node, "bootargs", cmdline_ptr,
+				     strlen(cmdline_ptr) + 1);
+		if (status)
+			goto fdt_set_fail;
+	}
+
+	/* Set initrd address/end in device tree, if present */
+	if (initrd_size != 0) {
+		u64 initrd_image_end;
+		u64 initrd_image_start = cpu_to_fdt64(initrd_addr);
+
+		status = fdt_setprop(fdt, node, "linux,initrd-start",
+				     &initrd_image_start, sizeof(u64));
+		if (status)
+			goto fdt_set_fail;
+		initrd_image_end = cpu_to_fdt64(initrd_addr + initrd_size);
+		status = fdt_setprop(fdt, node, "linux,initrd-end",
+				     &initrd_image_end, sizeof(u64));
+		if (status)
+			goto fdt_set_fail;
+	}
+
+	/* Add FDT entries for EFI runtime services in chosen node. */
+	node = fdt_subnode_offset(fdt, 0, "chosen");
+	fdt_val64 = cpu_to_fdt64((u64)(unsigned long)sys_table);
+	status = fdt_setprop(fdt, node, "linux,uefi-system-table",
+			     &fdt_val64, sizeof(fdt_val64));
+	if (status)
+		goto fdt_set_fail;
+
+	fdt_val64 = cpu_to_fdt64((u64)(unsigned long)memory_map);
+	status = fdt_setprop(fdt, node, "linux,uefi-mmap-start",
+			     &fdt_val64,  sizeof(fdt_val64));
+	if (status)
+		goto fdt_set_fail;
+
+	fdt_val32 = cpu_to_fdt32(map_size);
+	status = fdt_setprop(fdt, node, "linux,uefi-mmap-size",
+			     &fdt_val32,  sizeof(fdt_val32));
+	if (status)
+		goto fdt_set_fail;
+
+	fdt_val32 = cpu_to_fdt32(desc_size);
+	status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size",
+			     &fdt_val32, sizeof(fdt_val32));
+	if (status)
+		goto fdt_set_fail;
+
+	fdt_val32 = cpu_to_fdt32(desc_ver);
+	status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver",
+			     &fdt_val32, sizeof(fdt_val32));
+	if (status)
+		goto fdt_set_fail;
+
+	/*
+	 * Add kernel version banner so stub/kernel match can be
+	 * verified.
+	 */
+	status = fdt_setprop_string(fdt, node, "linux,uefi-stub-kern-ver",
+			     linux_banner);
+	if (status)
+		goto fdt_set_fail;
+
+	return EFI_SUCCESS;
+
+fdt_set_fail:
+	if (status == -FDT_ERR_NOSPACE)
+		return EFI_BUFFER_TOO_SMALL;
+
+	return EFI_LOAD_ERROR;
+}
+
+#ifndef EFI_FDT_ALIGN
+#define EFI_FDT_ALIGN EFI_PAGE_SIZE
+#endif
+
+/*
+ * Allocate memory for a new FDT, then add EFI, commandline, and
+ * initrd related fields to the FDT.  This routine increases the
+ * FDT allocation size until the allocated memory is large
+ * enough.  EFI allocations are in EFI_PAGE_SIZE granules,
+ * which are fixed at 4K bytes, so in most cases the first
+ * allocation should succeed.
+ * EFI boot services are exited at the end of this function.
+ * There must be no allocations between the get_memory_map()
+ * call and the exit_boot_services() call, so the exiting of
+ * boot services is very tightly tied to the creation of the FDT
+ * with the final memory map in it.
+ */
+
+efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
+					    void *handle,
+					    unsigned long *new_fdt_addr,
+					    unsigned long max_addr,
+					    u64 initrd_addr, u64 initrd_size,
+					    char *cmdline_ptr,
+					    unsigned long fdt_addr,
+					    unsigned long fdt_size)
+{
+	unsigned long map_size, desc_size;
+	u32 desc_ver;
+	unsigned long mmap_key;
+	efi_memory_desc_t *memory_map;
+	unsigned long new_fdt_size;
+	efi_status_t status;
+
+	/*
+	 * Estimate size of new FDT, and allocate memory for it. We
+	 * will allocate a bigger buffer if this ends up being too
+	 * small, so a rough guess is OK here.
+	 */
+	new_fdt_size = fdt_size + EFI_PAGE_SIZE;
+	while (1) {
+		status = efi_high_alloc(sys_table, new_fdt_size, EFI_FDT_ALIGN,
+					new_fdt_addr, max_addr);
+		if (status != EFI_SUCCESS) {
+			pr_efi_err(sys_table, "Unable to allocate memory for new device tree.\n");
+			goto fail;
+		}
+
+		/*
+		 * Now that we have done our final memory allocation (and free)
+		 * we can get the memory map key  needed for
+		 * exit_boot_services().
+		 */
+		status = efi_get_memory_map(sys_table, &memory_map, &map_size,
+					    &desc_size, &desc_ver, &mmap_key);
+		if (status != EFI_SUCCESS)
+			goto fail_free_new_fdt;
+
+		status = update_fdt(sys_table,
+				    (void *)fdt_addr, fdt_size,
+				    (void *)*new_fdt_addr, new_fdt_size,
+				    cmdline_ptr, initrd_addr, initrd_size,
+				    memory_map, map_size, desc_size, desc_ver);
+
+		/* Succeeding the first time is the expected case. */
+		if (status == EFI_SUCCESS)
+			break;
+
+		if (status == EFI_BUFFER_TOO_SMALL) {
+			/*
+			 * We need to allocate more space for the new
+			 * device tree, so free existing buffer that is
+			 * too small.  Also free memory map, as we will need
+			 * to get new one that reflects the free/alloc we do
+			 * on the device tree buffer.
+			 */
+			efi_free(sys_table, new_fdt_size, *new_fdt_addr);
+			efi_call_phys1(sys_table->boottime->free_pool,
+				       memory_map);
+			new_fdt_size += EFI_PAGE_SIZE;
+		} else {
+			pr_efi_err(sys_table, "Unable to constuct new device tree.\n");
+			goto fail_free_mmap;
+		}
+	}
+
+	/* Now we are ready to exit_boot_services.*/
+	status = efi_call_phys2(sys_table->boottime->exit_boot_services,
+				handle, mmap_key);
+
+
+	if (status == EFI_SUCCESS)
+		return status;
+
+	pr_efi_err(sys_table, "Exit boot services failed.\n");
+
+fail_free_mmap:
+	efi_call_phys1(sys_table->boottime->free_pool, memory_map);
+
+fail_free_new_fdt:
+	efi_free(sys_table, new_fdt_size, *new_fdt_addr);
+
+fail:
+	return EFI_LOAD_ERROR;
+}
+
+static void *get_fdt(efi_system_table_t *sys_table)
+{
+	efi_guid_t fdt_guid = DEVICE_TREE_GUID;
+	efi_config_table_t *tables;
+	void *fdt;
+	int i;
+
+	tables = (efi_config_table_t *) sys_table->tables;
+	fdt = NULL;
+
+	for (i = 0; i < sys_table->nr_tables; i++)
+		if (efi_guidcmp(tables[i].guid, fdt_guid) == 0) {
+			fdt = (void *) tables[i].table;
+			break;
+	 }
+
+	return fdt;
+}
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 4f52ac6..ae3e2b2 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -575,6 +575,9 @@ typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long si
 #define EFI_FILE_SYSTEM_GUID \
     EFI_GUID(  0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
 
+#define DEVICE_TREE_GUID \
+    EFI_GUID(  0xb1b621d5, 0xf19c, 0x41a5, 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0 )
+
 typedef struct {
 	efi_guid_t guid;
 	u64 table;
-- 
1.7.10.4

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

* [PATCH v3 05/10] efi: Add shared FDT related functions for ARM/ARM64
@ 2014-04-04 18:45   ` Leif Lindholm
  0 siblings, 0 replies; 55+ messages in thread
From: Leif Lindholm @ 2014-04-04 18:45 UTC (permalink / raw)
  To: linux-arm-kernel

From: Roy Franz <roy.franz@linaro.org>

Both ARM and ARM64 stubs will update the device tree that they pass to
the kernel.  In both cases they primarily need to add the same UEFI
related information, so the function can be shared.  Create a new FDT
related file for this to avoid use of architecture #ifdefs in
efi-stub-helper.c.

Signed-off-by: Roy Franz <roy.franz@linaro.org>
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Acked-by: Grant Likely <grant.likely@linaro.org>
Cc: Matt Fleming <matt.fleming@intel.com>
---
 drivers/firmware/efi/fdt.c |  269 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/efi.h        |    3 +
 2 files changed, 272 insertions(+)
 create mode 100644 drivers/firmware/efi/fdt.c

diff --git a/drivers/firmware/efi/fdt.c b/drivers/firmware/efi/fdt.c
new file mode 100644
index 0000000..6f306b4
--- /dev/null
+++ b/drivers/firmware/efi/fdt.c
@@ -0,0 +1,269 @@
+/*
+ * FDT related Helper functions used by the EFI stub on multiple
+ * architectures. This should be #included by the EFI stub
+ * implementation files.
+ *
+ * Copyright 2013 Linaro Limited; author Roy Franz
+ *
+ * This file is part of the Linux kernel, and is made available
+ * under the terms of the GNU General Public License version 2.
+ *
+ */
+
+static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
+			       unsigned long orig_fdt_size,
+			       void *fdt, int new_fdt_size, char *cmdline_ptr,
+			       u64 initrd_addr, u64 initrd_size,
+			       efi_memory_desc_t *memory_map,
+			       unsigned long map_size, unsigned long desc_size,
+			       u32 desc_ver)
+{
+	int node;
+	int status;
+	u32 fdt_val32;
+	u64 fdt_val64;
+
+	/*
+	 * Copy definition of linux_banner here.  Since this code is
+	 * built as part of the decompressor for ARM v7, pulling
+	 * in version.c where linux_banner is defined for the
+	 * kernel brings other kernel dependencies with it.
+	 */
+	const char linux_banner[] =
+	    "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
+	    LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
+
+	/* Do some checks on provided FDT, if it exists*/
+	if (orig_fdt) {
+		if (fdt_check_header(orig_fdt)) {
+			pr_efi_err(sys_table, "Device Tree header not valid!\n");
+			return EFI_LOAD_ERROR;
+		}
+		/*
+		 * We don't get the size of the FDT if we get if from a
+		 * configuration table.
+		 */
+		if (orig_fdt_size && fdt_totalsize(orig_fdt) > orig_fdt_size) {
+			pr_efi_err(sys_table, "Truncated device tree! foo!\n");
+			return EFI_LOAD_ERROR;
+		}
+	}
+
+	if (orig_fdt)
+		status = fdt_open_into(orig_fdt, fdt, new_fdt_size);
+	else
+		status = fdt_create_empty_tree(fdt, new_fdt_size);
+
+	if (status != 0)
+		goto fdt_set_fail;
+
+	/* Delete any memory nodes present */
+	while ((node = fdt_subnode_offset(fdt, 0, "memory")) >= 0)
+		fdt_del_node(fdt, node);
+
+	node = fdt_subnode_offset(fdt, 0, "chosen");
+	if (node < 0) {
+		node = fdt_add_subnode(fdt, 0, "chosen");
+		if (node < 0) {
+			status = node; /* node is error code when negative */
+			goto fdt_set_fail;
+		}
+	}
+
+	if ((cmdline_ptr != NULL) && (strlen(cmdline_ptr) > 0)) {
+		status = fdt_setprop(fdt, node, "bootargs", cmdline_ptr,
+				     strlen(cmdline_ptr) + 1);
+		if (status)
+			goto fdt_set_fail;
+	}
+
+	/* Set initrd address/end in device tree, if present */
+	if (initrd_size != 0) {
+		u64 initrd_image_end;
+		u64 initrd_image_start = cpu_to_fdt64(initrd_addr);
+
+		status = fdt_setprop(fdt, node, "linux,initrd-start",
+				     &initrd_image_start, sizeof(u64));
+		if (status)
+			goto fdt_set_fail;
+		initrd_image_end = cpu_to_fdt64(initrd_addr + initrd_size);
+		status = fdt_setprop(fdt, node, "linux,initrd-end",
+				     &initrd_image_end, sizeof(u64));
+		if (status)
+			goto fdt_set_fail;
+	}
+
+	/* Add FDT entries for EFI runtime services in chosen node. */
+	node = fdt_subnode_offset(fdt, 0, "chosen");
+	fdt_val64 = cpu_to_fdt64((u64)(unsigned long)sys_table);
+	status = fdt_setprop(fdt, node, "linux,uefi-system-table",
+			     &fdt_val64, sizeof(fdt_val64));
+	if (status)
+		goto fdt_set_fail;
+
+	fdt_val64 = cpu_to_fdt64((u64)(unsigned long)memory_map);
+	status = fdt_setprop(fdt, node, "linux,uefi-mmap-start",
+			     &fdt_val64,  sizeof(fdt_val64));
+	if (status)
+		goto fdt_set_fail;
+
+	fdt_val32 = cpu_to_fdt32(map_size);
+	status = fdt_setprop(fdt, node, "linux,uefi-mmap-size",
+			     &fdt_val32,  sizeof(fdt_val32));
+	if (status)
+		goto fdt_set_fail;
+
+	fdt_val32 = cpu_to_fdt32(desc_size);
+	status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size",
+			     &fdt_val32, sizeof(fdt_val32));
+	if (status)
+		goto fdt_set_fail;
+
+	fdt_val32 = cpu_to_fdt32(desc_ver);
+	status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver",
+			     &fdt_val32, sizeof(fdt_val32));
+	if (status)
+		goto fdt_set_fail;
+
+	/*
+	 * Add kernel version banner so stub/kernel match can be
+	 * verified.
+	 */
+	status = fdt_setprop_string(fdt, node, "linux,uefi-stub-kern-ver",
+			     linux_banner);
+	if (status)
+		goto fdt_set_fail;
+
+	return EFI_SUCCESS;
+
+fdt_set_fail:
+	if (status == -FDT_ERR_NOSPACE)
+		return EFI_BUFFER_TOO_SMALL;
+
+	return EFI_LOAD_ERROR;
+}
+
+#ifndef EFI_FDT_ALIGN
+#define EFI_FDT_ALIGN EFI_PAGE_SIZE
+#endif
+
+/*
+ * Allocate memory for a new FDT, then add EFI, commandline, and
+ * initrd related fields to the FDT.  This routine increases the
+ * FDT allocation size until the allocated memory is large
+ * enough.  EFI allocations are in EFI_PAGE_SIZE granules,
+ * which are fixed at 4K bytes, so in most cases the first
+ * allocation should succeed.
+ * EFI boot services are exited at the end of this function.
+ * There must be no allocations between the get_memory_map()
+ * call and the exit_boot_services() call, so the exiting of
+ * boot services is very tightly tied to the creation of the FDT
+ * with the final memory map in it.
+ */
+
+efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
+					    void *handle,
+					    unsigned long *new_fdt_addr,
+					    unsigned long max_addr,
+					    u64 initrd_addr, u64 initrd_size,
+					    char *cmdline_ptr,
+					    unsigned long fdt_addr,
+					    unsigned long fdt_size)
+{
+	unsigned long map_size, desc_size;
+	u32 desc_ver;
+	unsigned long mmap_key;
+	efi_memory_desc_t *memory_map;
+	unsigned long new_fdt_size;
+	efi_status_t status;
+
+	/*
+	 * Estimate size of new FDT, and allocate memory for it. We
+	 * will allocate a bigger buffer if this ends up being too
+	 * small, so a rough guess is OK here.
+	 */
+	new_fdt_size = fdt_size + EFI_PAGE_SIZE;
+	while (1) {
+		status = efi_high_alloc(sys_table, new_fdt_size, EFI_FDT_ALIGN,
+					new_fdt_addr, max_addr);
+		if (status != EFI_SUCCESS) {
+			pr_efi_err(sys_table, "Unable to allocate memory for new device tree.\n");
+			goto fail;
+		}
+
+		/*
+		 * Now that we have done our final memory allocation (and free)
+		 * we can get the memory map key  needed for
+		 * exit_boot_services().
+		 */
+		status = efi_get_memory_map(sys_table, &memory_map, &map_size,
+					    &desc_size, &desc_ver, &mmap_key);
+		if (status != EFI_SUCCESS)
+			goto fail_free_new_fdt;
+
+		status = update_fdt(sys_table,
+				    (void *)fdt_addr, fdt_size,
+				    (void *)*new_fdt_addr, new_fdt_size,
+				    cmdline_ptr, initrd_addr, initrd_size,
+				    memory_map, map_size, desc_size, desc_ver);
+
+		/* Succeeding the first time is the expected case. */
+		if (status == EFI_SUCCESS)
+			break;
+
+		if (status == EFI_BUFFER_TOO_SMALL) {
+			/*
+			 * We need to allocate more space for the new
+			 * device tree, so free existing buffer that is
+			 * too small.  Also free memory map, as we will need
+			 * to get new one that reflects the free/alloc we do
+			 * on the device tree buffer.
+			 */
+			efi_free(sys_table, new_fdt_size, *new_fdt_addr);
+			efi_call_phys1(sys_table->boottime->free_pool,
+				       memory_map);
+			new_fdt_size += EFI_PAGE_SIZE;
+		} else {
+			pr_efi_err(sys_table, "Unable to constuct new device tree.\n");
+			goto fail_free_mmap;
+		}
+	}
+
+	/* Now we are ready to exit_boot_services.*/
+	status = efi_call_phys2(sys_table->boottime->exit_boot_services,
+				handle, mmap_key);
+
+
+	if (status == EFI_SUCCESS)
+		return status;
+
+	pr_efi_err(sys_table, "Exit boot services failed.\n");
+
+fail_free_mmap:
+	efi_call_phys1(sys_table->boottime->free_pool, memory_map);
+
+fail_free_new_fdt:
+	efi_free(sys_table, new_fdt_size, *new_fdt_addr);
+
+fail:
+	return EFI_LOAD_ERROR;
+}
+
+static void *get_fdt(efi_system_table_t *sys_table)
+{
+	efi_guid_t fdt_guid = DEVICE_TREE_GUID;
+	efi_config_table_t *tables;
+	void *fdt;
+	int i;
+
+	tables = (efi_config_table_t *) sys_table->tables;
+	fdt = NULL;
+
+	for (i = 0; i < sys_table->nr_tables; i++)
+		if (efi_guidcmp(tables[i].guid, fdt_guid) == 0) {
+			fdt = (void *) tables[i].table;
+			break;
+	 }
+
+	return fdt;
+}
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 4f52ac6..ae3e2b2 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -575,6 +575,9 @@ typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long si
 #define EFI_FILE_SYSTEM_GUID \
     EFI_GUID(  0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
 
+#define DEVICE_TREE_GUID \
+    EFI_GUID(  0xb1b621d5, 0xf19c, 0x41a5, 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0 )
+
 typedef struct {
 	efi_guid_t guid;
 	u64 table;
-- 
1.7.10.4

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

* [PATCH v3 06/10] arm64: efi: add EFI stub
  2014-04-04 18:45 ` Leif Lindholm
@ 2014-04-04 18:45   ` Leif Lindholm
  -1 siblings, 0 replies; 55+ messages in thread
From: Leif Lindholm @ 2014-04-04 18:45 UTC (permalink / raw)
  To: linux-arm-kernel, linux-efi
  Cc: linux-kernel, Mark Salter, Ard Biesheuvel, Leif Lindholm,
	Catalin Marinas, Matt Fleming

From: Mark Salter <msalter@redhat.com>

This patch adds PE/COFF header fields to the start of the Image
so that it appears as an EFI application to EFI firmware. An EFI
stub is included to allow direct booting of the kernel Image.
Support in the COFF header for signed images was provided by
Ard Biesheuvel.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Mark Salter <msalter@redhat.com>
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Matt Fleming <matt.fleming@intel.com>
---
 arch/arm64/Kconfig              |   14 +++
 arch/arm64/kernel/Makefile      |    3 +
 arch/arm64/kernel/efi-entry.S   |  100 ++++++++++++++++
 arch/arm64/kernel/efi-stub.c    |   97 +++++++++++++++
 arch/arm64/kernel/head.S        |  112 ++++++++++++++++++
 drivers/firmware/efi/arm-stub.c |  248 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 574 insertions(+)
 create mode 100644 arch/arm64/kernel/efi-entry.S
 create mode 100644 arch/arm64/kernel/efi-stub.c
 create mode 100644 drivers/firmware/efi/arm-stub.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index d9f23ad..791ec61 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -280,6 +280,20 @@ config CMDLINE_FORCE
 	  This is useful if you cannot or don't want to change the
 	  command-line options your boot loader passes to the kernel.
 
+config EFI
+	bool "UEFI firmware support"
+	depends on OF
+	select LIBFDT
+	default y
+	help
+	  This option permits an Image to be loaded directly
+	  by EFI firmware without the use of a bootloader.
+	  See Documentation/efi-stub.txt for more information.
+
+	  This is only useful on systems that have UEFI firmware.
+	  However, even with this option, the resultant kernel should
+	  continue to boot on existing non-UEFI platforms.
+
 endmenu
 
 menu "Userspace binary formats"
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 7d811d9..21009b7 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -4,6 +4,8 @@
 
 CPPFLAGS_vmlinux.lds	:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
+CFLAGS_efi-stub.o 	:= -DTEXT_OFFSET=$(TEXT_OFFSET) \
+			   -I$(src)/../../../scripts/dtc/libfdt
 
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
@@ -22,6 +24,7 @@ arm64-obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND)	+= sleep.o suspend.o
 arm64-obj-$(CONFIG_JUMP_LABEL)		+= jump_label.o
 arm64-obj-$(CONFIG_KGDB)		+= kgdb.o
+arm64-obj-$(CONFIG_EFI)			+= efi-stub.o efi-entry.o
 
 obj-y					+= $(arm64-obj-y) vdso/
 obj-m					+= $(arm64-obj-m)
diff --git a/arch/arm64/kernel/efi-entry.S b/arch/arm64/kernel/efi-entry.S
new file mode 100644
index 0000000..d99a034e
--- /dev/null
+++ b/arch/arm64/kernel/efi-entry.S
@@ -0,0 +1,100 @@
+/*
+ * EFI entry point.
+ *
+ * Copyright (C) 2013, 2014 Red Hat, Inc.
+ * Author: Mark Salter <msalter@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+#include <asm/assembler.h>
+
+#define EFI_LOAD_ERROR 0x8000000000000001
+
+	__INIT
+
+	/*
+	 * We arrive here from the EFI boot manager with:
+	 *
+	 *    * MMU on with identity-mapped RAM.
+	 *    * Icache and Dcache on
+	 *
+	 * We will most likely be running from some place other than where
+	 * we want to be. The kernel image wants to be placed at TEXT_OFFSET
+	 * from start of RAM.
+	 */
+ENTRY(efi_stub_entry)
+	stp	x29, x30, [sp, #-32]!
+
+	/*
+	 * Call efi_entry to do the real work.
+	 * x0 and x1 are already set up by firmware. Current runtime
+	 * address of image is calculated and passed via *image_addr.
+	 *
+	 * unsigned long efi_entry(void *handle,
+	 *                         efi_system_table_t *sys_table,
+	 *                         unsigned long *image_addr) ;
+	 */
+	adrp	x8, _text
+	add	x8, x8, #:lo12:_text
+	add	x2, sp, 16
+	str	x8, [x2]
+	bl	efi_entry
+	cmn	x0, #1
+	b.eq	efi_load_fail
+
+	/*
+	 * efi_entry() will have relocated the kernel image if necessary
+	 * and we return here with device tree address in x0 and the kernel
+	 * entry point stored at *image_addr. Save those values in registers
+	 * which are callee preserved.
+	 */
+	mov	x20, x0		// DTB address
+	ldr	x0, [sp, #16]	// relocated _text address
+	mov	x21, x0
+
+	adrp	x1, _text
+	add	x1, x1, #:lo12:_text
+	adrp	x2, _edata
+	add	x2, x2, #:lo12:_edata
+	sub	x1, x2, x1
+
+	bl	__flush_dcache_area
+	ic	ialluis
+
+	/* Turn off Dcache and MMU */
+	mrs	x0, CurrentEL
+	cmp	x0, #PSR_MODE_EL2t
+	ccmp	x0, #PSR_MODE_EL2h, #0x4, ne
+	b.ne	1f
+	mrs	x0, sctlr_el2
+	bic	x0, x0, #1 << 0	// clear SCTLR.M
+	bic	x0, x0, #1 << 2	// clear SCTLR.C
+	msr	sctlr_el2, x0
+	isb
+	b	2f
+1:
+	mrs	x0, sctlr_el1
+	bic	x0, x0, #1 << 0	// clear SCTLR.M
+	bic	x0, x0, #1 << 2	// clear SCTLR.C
+	msr	sctlr_el1, x0
+	isb
+2:
+	/* Jump to real entry point */
+	mov	x0, x20
+	mov	x1, xzr
+	mov	x2, xzr
+	mov	x3, xzr
+	br	x21
+
+efi_load_fail:
+	mov	x0, #EFI_LOAD_ERROR
+	ldp	x29, x30, [sp], #32
+	ret
+
+ENDPROC(efi_stub_entry)
diff --git a/arch/arm64/kernel/efi-stub.c b/arch/arm64/kernel/efi-stub.c
new file mode 100644
index 0000000..c416eff
--- /dev/null
+++ b/arch/arm64/kernel/efi-stub.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2013, 2014 Linaro Ltd;  <roy.franz@linaro.org>
+ *
+ * This file implements the EFI boot stub for the arm64 kernel.
+ * Adapted from ARM version by Mark Salter <msalter@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/efi.h>
+#include <linux/libfdt.h>
+#include <asm/sections.h>
+#include <generated/compile.h>
+#include <generated/utsrelease.h>
+
+/*
+ * EFI function call wrappers. These are not required for arm/arm64, but
+ * wrappers are required for X86 to convert between ABIs. These wrappers are
+ * provided to allow code sharing between X86 and other architectures. Since
+ * these wrappers directly invoke the EFI function pointer, the function
+ * pointer type must be properly defined, which is not the case for X86. One
+ * advantage of this is it allows for type checking of arguments, which is not
+ * possible with the X86 wrappers.
+ */
+#define efi_call_phys0(f)			f()
+#define efi_call_phys1(f, a1)			f(a1)
+#define efi_call_phys2(f, a1, a2)		f(a1, a2)
+#define efi_call_phys3(f, a1, a2, a3)		f(a1, a2, a3)
+#define efi_call_phys4(f, a1, a2, a3, a4)	f(a1, a2, a3, a4)
+#define efi_call_phys5(f, a1, a2, a3, a4, a5)	f(a1, a2, a3, a4, a5)
+
+/*
+ * AArch64 requires the DTB to be 8-byte aligned in the first 512MiB from
+ * start of kernel and may not cross a 2MiB boundary. We set alignment to
+ * 2MiB so we know it won't cross a 2MiB boundary.
+ */
+#define EFI_FDT_ALIGN	SZ_2M   /* used by allocate_new_fdt_and_exit_boot() */
+#define MAX_FDT_OFFSET	SZ_512M
+
+#define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__)
+
+static void efi_char16_printk(efi_system_table_t *sys_table_arg,
+			      efi_char16_t *str);
+
+static efi_status_t efi_open_volume(efi_system_table_t *sys_table,
+				    void *__image, void **__fh);
+static efi_status_t efi_file_close(void *__fh, void *handle);
+
+static efi_status_t
+efi_file_read(void *__fh, void *handle, unsigned long *size, void *addr);
+
+static efi_status_t
+efi_file_size(efi_system_table_t *sys_table, void *__fh,
+	      efi_char16_t *filename_16, void **handle, u64 *file_sz);
+
+/* Include shared EFI stub code */
+#include "../../../drivers/firmware/efi/efi-stub-helper.c"
+#include "../../../drivers/firmware/efi/fdt.c"
+#include "../../../drivers/firmware/efi/arm-stub.c"
+
+
+static efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
+					unsigned long *image_addr,
+					unsigned long *image_size,
+					unsigned long *reserve_addr,
+					unsigned long *reserve_size,
+					unsigned long dram_base,
+					efi_loaded_image_t *image)
+{
+	efi_status_t status;
+	unsigned long kernel_size, kernel_memsize = 0;
+
+	/* Relocate the image, if required. */
+	kernel_size = _edata - _text;
+	if (*image_addr != (dram_base + TEXT_OFFSET)) {
+		kernel_memsize = kernel_size + (_end - _edata);
+		status = efi_relocate_kernel(sys_table, image_addr,
+					     kernel_size, kernel_memsize,
+					     dram_base + TEXT_OFFSET,
+					     PAGE_SIZE);
+		if (status != EFI_SUCCESS) {
+			pr_efi_err(sys_table, "Failed to relocate kernel\n");
+			return status;
+		}
+		if (*image_addr != (dram_base + TEXT_OFFSET)) {
+			pr_efi_err(sys_table, "Failed to alloc kernel memory\n");
+			efi_free(sys_table, kernel_memsize, *image_addr);
+			return EFI_ERROR;
+		}
+		*image_size = kernel_memsize;
+	}
+
+
+	return EFI_SUCCESS;
+}
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 1fe5d8d..2aee658 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -107,8 +107,18 @@
 	/*
 	 * DO NOT MODIFY. Image header expected by Linux boot-loaders.
 	 */
+#ifdef CONFIG_EFI
+	/*
+	 * Magic "MZ" signature for PE/COFF
+	 * Little Endian:  add x13, x18, #0x16
+	 */
+efi_head:
+	.long   0x91005a4d
+	b	stext
+#else
 	b	stext				// branch to kernel start, magic
 	.long	0				// reserved
+#endif
 	.quad	TEXT_OFFSET			// Image load offset from start of RAM
 	.quad	0				// reserved
 	.quad	0				// reserved
@@ -119,7 +129,109 @@
 	.byte	0x52
 	.byte	0x4d
 	.byte	0x64
+#ifdef CONFIG_EFI
+	.long	pe_header - efi_head		// Offset to the PE header.
+#else
 	.word	0				// reserved
+#endif
+
+#ifdef CONFIG_EFI
+	.align 3
+pe_header:
+	.ascii	"PE"
+	.short 	0
+coff_header:
+	.short	0xaa64				// AArch64
+	.short	2				// nr_sections
+	.long	0 				// TimeDateStamp
+	.long	0				// PointerToSymbolTable
+	.long	1				// NumberOfSymbols
+	.short	section_table - optional_header	// SizeOfOptionalHeader
+	.short	0x206				// Characteristics.
+						// IMAGE_FILE_DEBUG_STRIPPED |
+						// IMAGE_FILE_EXECUTABLE_IMAGE |
+						// IMAGE_FILE_LINE_NUMS_STRIPPED
+optional_header:
+	.short	0x20b				// PE32+ format
+	.byte	0x02				// MajorLinkerVersion
+	.byte	0x14				// MinorLinkerVersion
+	.long	_edata - stext			// SizeOfCode
+	.long	0				// SizeOfInitializedData
+	.long	0				// SizeOfUninitializedData
+	.long	efi_stub_entry - efi_head	// AddressOfEntryPoint
+	.long	stext - efi_head		// BaseOfCode
+
+extra_header_fields:
+	.quad	0				// ImageBase
+	.long	0x20				// SectionAlignment
+	.long	0x8				// FileAlignment
+	.short	0				// MajorOperatingSystemVersion
+	.short	0				// MinorOperatingSystemVersion
+	.short	0				// MajorImageVersion
+	.short	0				// MinorImageVersion
+	.short	0				// MajorSubsystemVersion
+	.short	0				// MinorSubsystemVersion
+	.long	0				// Win32VersionValue
+
+	.long	_edata - efi_head		// SizeOfImage
+
+	// Everything before the kernel image is considered part of the header
+	.long	stext - efi_head			// SizeOfHeaders
+	.long	0				// CheckSum
+	.short	0xa				// Subsystem (EFI application)
+	.short	0				// DllCharacteristics
+	.quad	0				// SizeOfStackReserve
+	.quad	0				// SizeOfStackCommit
+	.quad	0				// SizeOfHeapReserve
+	.quad	0				// SizeOfHeapCommit
+	.long	0				// LoaderFlags
+	.long	0x6				// NumberOfRvaAndSizes
+
+	.quad	0				// ExportTable
+	.quad	0				// ImportTable
+	.quad	0				// ResourceTable
+	.quad	0				// ExceptionTable
+	.quad	0				// CertificationTable
+	.quad	0				// BaseRelocationTable
+
+	// Section table
+section_table:
+
+	/*
+	 * The EFI application loader requires a relocation section
+	 * because EFI applications must be relocatable.  This is a
+	 * dummy section as far as we are concerned.
+	 */
+	.ascii	".reloc"
+	.byte	0
+	.byte	0			// end of 0 padding of section name
+	.long	0
+	.long	0
+	.long	0			// SizeOfRawData
+	.long	0			// PointerToRawData
+	.long	0			// PointerToRelocations
+	.long	0			// PointerToLineNumbers
+	.short	0			// NumberOfRelocations
+	.short	0			// NumberOfLineNumbers
+	.long	0x42100040		// Characteristics (section flags)
+
+
+	.ascii	".text"
+	.byte	0
+	.byte	0
+	.byte	0        		// end of 0 padding of section name
+	.long	_edata - stext		// VirtualSize
+	.long	stext - efi_head	// VirtualAddress
+	.long	_edata - stext		// SizeOfRawData
+	.long	stext - efi_head	// PointerToRawData
+
+	.long	0		// PointerToRelocations (0 for executables)
+	.long	0		// PointerToLineNumbers (0 for executables)
+	.short	0		// NumberOfRelocations  (0 for executables)
+	.short	0		// NumberOfLineNumbers  (0 for executables)
+	.long	0xe0500020	// Characteristics (section flags)
+	.align 5
+#endif
 
 ENTRY(stext)
 	mov	x21, x0				// x21=FDT
diff --git a/drivers/firmware/efi/arm-stub.c b/drivers/firmware/efi/arm-stub.c
new file mode 100644
index 0000000..b9b7c00
--- /dev/null
+++ b/drivers/firmware/efi/arm-stub.c
@@ -0,0 +1,248 @@
+/*
+ * EFI stub implementation that is shared by arm and arm64 architectures.
+ * This should be #included by the EFI stub implementation files.
+ *
+ * Copyright (C) 2013,2014 Linaro Limited
+ *     Roy Franz <roy.franz@linaro.org
+ * Copyright (C) 2013 Red Hat, Inc.
+ *     Mark Salter <msalter@redhat.com>
+ *
+ * This file is part of the Linux kernel, and is made available under the
+ * terms of the GNU General Public License version 2.
+ *
+ */
+
+
+static efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
+				    void *__image, void **__fh)
+{
+	efi_file_io_interface_t *io;
+	efi_loaded_image_t *image = __image;
+	efi_file_handle_t *fh;
+	efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
+	efi_status_t status;
+	void *handle = (void *)(unsigned long)image->device_handle;
+
+	status = sys_table_arg->boottime->handle_protocol(handle,
+				 &fs_proto, (void **)&io);
+	if (status != EFI_SUCCESS) {
+		efi_printk(sys_table_arg, "Failed to handle fs_proto\n");
+		return status;
+	}
+
+	status = io->open_volume(io, &fh);
+	if (status != EFI_SUCCESS)
+		efi_printk(sys_table_arg, "Failed to open volume\n");
+
+	*__fh = fh;
+	return status;
+}
+static efi_status_t efi_file_close(void *__fh, void *handle)
+{
+	efi_file_handle_t *fh = __fh;
+
+	return fh->close(handle);
+}
+
+static efi_status_t
+efi_file_read(void *__fh, void *handle, unsigned long *size, void *addr)
+{
+	efi_file_handle_t *fh = __fh;
+
+	return fh->read(handle, size, addr);
+}
+
+
+static efi_status_t
+efi_file_size(efi_system_table_t *sys_table_arg, void *__fh,
+	      efi_char16_t *filename_16, void **handle, u64 *file_sz)
+{
+	efi_file_handle_t *h, *fh = __fh;
+	efi_file_info_t *info;
+	efi_status_t status;
+	efi_guid_t info_guid = EFI_FILE_INFO_ID;
+	unsigned long info_sz;
+
+	status = fh->open(fh, &h, filename_16, EFI_FILE_MODE_READ, (u64)0);
+	if (status != EFI_SUCCESS) {
+		efi_printk(sys_table_arg, "Failed to open file: ");
+		efi_char16_printk(sys_table_arg, filename_16);
+		efi_printk(sys_table_arg, "\n");
+		return status;
+	}
+
+	*handle = h;
+
+	info_sz = 0;
+	status = h->get_info(h, &info_guid, &info_sz, NULL);
+	if (status != EFI_BUFFER_TOO_SMALL) {
+		efi_printk(sys_table_arg, "Failed to get file info size\n");
+		return status;
+	}
+
+grow:
+	status = sys_table_arg->boottime->allocate_pool(EFI_LOADER_DATA,
+				 info_sz, (void **)&info);
+	if (status != EFI_SUCCESS) {
+		efi_printk(sys_table_arg, "Failed to alloc mem for file info\n");
+		return status;
+	}
+
+	status = h->get_info(h, &info_guid, &info_sz,
+						   info);
+	if (status == EFI_BUFFER_TOO_SMALL) {
+		sys_table_arg->boottime->free_pool(info);
+		goto grow;
+	}
+
+	*file_sz = info->file_size;
+	sys_table_arg->boottime->free_pool(info);
+
+	if (status != EFI_SUCCESS)
+		efi_printk(sys_table_arg, "Failed to get initrd info\n");
+
+	return status;
+}
+
+
+
+static void efi_char16_printk(efi_system_table_t *sys_table_arg,
+			      efi_char16_t *str)
+{
+	struct efi_simple_text_output_protocol *out;
+
+	out = (struct efi_simple_text_output_protocol *)sys_table_arg->con_out;
+	efi_call_phys2(out->output_string, out, str);
+}
+
+
+/*
+ * This function handles the architcture specific differences between arm and
+ * arm64 regarding where the kernel image must be loaded and any memory that
+ * must be reserved. On failure it is required to free all
+ * all allocations it has made.
+ */
+static efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
+					unsigned long *image_addr,
+					unsigned long *image_size,
+					unsigned long *reserve_addr,
+					unsigned long *reserve_size,
+					unsigned long dram_base,
+					efi_loaded_image_t *image);
+/*
+ * EFI entry point for the arm/arm64 EFI stubs.  This is the entrypoint
+ * that is described in the PE/COFF header.  Most of the code is the same
+ * for both archictectures, with the arch-specific code provided in the
+ * handle_kernel_image() function.
+ */
+unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table,
+			       unsigned long *image_addr)
+{
+	efi_loaded_image_t *image;
+	efi_status_t status;
+	unsigned long image_size = 0;
+	unsigned long dram_base;
+	/* addr/point and size pairs for memory management*/
+	unsigned long initrd_addr;
+	u64 initrd_size = 0;
+	unsigned long fdt_addr;  /* Original DTB */
+	u64 fdt_size = 0;  /* We don't get size from configuration table */
+	char *cmdline_ptr = NULL;
+	int cmdline_size = 0;
+	unsigned long new_fdt_addr;
+	efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID;
+	unsigned long reserve_addr = 0;
+	unsigned long reserve_size = 0;
+
+	/* Check if we were booted by the EFI firmware */
+	if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
+		goto fail;
+
+	pr_efi(sys_table, "Booting Linux Kernel...\n");
+
+	/*
+	 * Get a handle to the loaded image protocol.  This is used to get
+	 * information about the running image, such as size and the command
+	 * line.
+	 */
+	status = efi_call_phys3(sys_table->boottime->handle_protocol,
+				handle, &loaded_image_proto, (void *)&image);
+	if (status != EFI_SUCCESS) {
+		pr_efi_err(sys_table, "Failed to get loaded image protocol\n");
+		goto fail;
+	}
+
+	dram_base = get_dram_base(sys_table);
+	if (dram_base == EFI_ERROR) {
+		pr_efi_err(sys_table, "Failed to find DRAM base\n");
+		goto fail;
+	}
+	status = handle_kernel_image(sys_table, image_addr, &image_size,
+				     &reserve_addr,
+				     &reserve_size,
+				     dram_base, image);
+	if (status != EFI_SUCCESS) {
+		pr_efi_err(sys_table, "Failed to relocate kernel\n");
+		goto fail;
+	}
+
+	/*
+	 * Get the command line from EFI, using the LOADED_IMAGE
+	 * protocol. We are going to copy the command line into the
+	 * device tree, so this can be allocated anywhere.
+	 */
+	cmdline_ptr = efi_convert_cmdline(sys_table, image, &cmdline_size);
+	if (!cmdline_ptr) {
+		pr_efi_err(sys_table, "getting command line via LOADED_IMAGE_PROTOCOL\n");
+		goto fail_free_image;
+	}
+
+	/* Load a device tree from the configuration table, if present. */
+	fdt_addr = (uintptr_t)get_fdt(sys_table);
+	if (!fdt_addr) {
+		status = handle_cmdline_files(sys_table, image, cmdline_ptr,
+					      "dtb=",
+					      ~0UL, (unsigned long *)&fdt_addr,
+					      (unsigned long *)&fdt_size);
+
+		if (status != EFI_SUCCESS) {
+			pr_efi_err(sys_table, "Failed to load device tree!\n");
+			goto fail_free_cmdline;
+		}
+	}
+
+	status = handle_cmdline_files(sys_table, image, cmdline_ptr,
+				      "initrd=", dram_base + SZ_512M,
+				      (unsigned long *)&initrd_addr,
+				      (unsigned long *)&initrd_size);
+	if (status != EFI_SUCCESS)
+		pr_efi_err(sys_table, "Failed initrd from command line!\n");
+
+	new_fdt_addr = fdt_addr;
+	status = allocate_new_fdt_and_exit_boot(sys_table, handle,
+				&new_fdt_addr, dram_base + MAX_FDT_OFFSET,
+				initrd_addr, initrd_size, cmdline_ptr,
+				fdt_addr, fdt_size);
+
+	/*
+	 * If all went well, we need to return the FDT address to the
+	 * calling function so it can be passed to kernel as part of
+	 * the kernel boot protocol.
+	 */
+	if (status == EFI_SUCCESS)
+		return new_fdt_addr;
+
+	pr_efi_err(sys_table, "Failed to update FDT and exit boot services\n");
+
+	efi_free(sys_table, initrd_size, initrd_addr);
+	efi_free(sys_table, fdt_size, fdt_addr);
+
+fail_free_cmdline:
+	efi_free(sys_table, cmdline_size, (unsigned long)cmdline_ptr);
+
+fail_free_image:
+	efi_free(sys_table, image_size, *image_addr);
+	efi_free(sys_table, reserve_size, reserve_addr);
+fail:
+	return EFI_ERROR;
+}
-- 
1.7.10.4


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

* [PATCH v3 06/10] arm64: efi: add EFI stub
@ 2014-04-04 18:45   ` Leif Lindholm
  0 siblings, 0 replies; 55+ messages in thread
From: Leif Lindholm @ 2014-04-04 18:45 UTC (permalink / raw)
  To: linux-arm-kernel

From: Mark Salter <msalter@redhat.com>

This patch adds PE/COFF header fields to the start of the Image
so that it appears as an EFI application to EFI firmware. An EFI
stub is included to allow direct booting of the kernel Image.
Support in the COFF header for signed images was provided by
Ard Biesheuvel.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Mark Salter <msalter@redhat.com>
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Matt Fleming <matt.fleming@intel.com>
---
 arch/arm64/Kconfig              |   14 +++
 arch/arm64/kernel/Makefile      |    3 +
 arch/arm64/kernel/efi-entry.S   |  100 ++++++++++++++++
 arch/arm64/kernel/efi-stub.c    |   97 +++++++++++++++
 arch/arm64/kernel/head.S        |  112 ++++++++++++++++++
 drivers/firmware/efi/arm-stub.c |  248 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 574 insertions(+)
 create mode 100644 arch/arm64/kernel/efi-entry.S
 create mode 100644 arch/arm64/kernel/efi-stub.c
 create mode 100644 drivers/firmware/efi/arm-stub.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index d9f23ad..791ec61 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -280,6 +280,20 @@ config CMDLINE_FORCE
 	  This is useful if you cannot or don't want to change the
 	  command-line options your boot loader passes to the kernel.
 
+config EFI
+	bool "UEFI firmware support"
+	depends on OF
+	select LIBFDT
+	default y
+	help
+	  This option permits an Image to be loaded directly
+	  by EFI firmware without the use of a bootloader.
+	  See Documentation/efi-stub.txt for more information.
+
+	  This is only useful on systems that have UEFI firmware.
+	  However, even with this option, the resultant kernel should
+	  continue to boot on existing non-UEFI platforms.
+
 endmenu
 
 menu "Userspace binary formats"
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 7d811d9..21009b7 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -4,6 +4,8 @@
 
 CPPFLAGS_vmlinux.lds	:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
+CFLAGS_efi-stub.o 	:= -DTEXT_OFFSET=$(TEXT_OFFSET) \
+			   -I$(src)/../../../scripts/dtc/libfdt
 
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
@@ -22,6 +24,7 @@ arm64-obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND)	+= sleep.o suspend.o
 arm64-obj-$(CONFIG_JUMP_LABEL)		+= jump_label.o
 arm64-obj-$(CONFIG_KGDB)		+= kgdb.o
+arm64-obj-$(CONFIG_EFI)			+= efi-stub.o efi-entry.o
 
 obj-y					+= $(arm64-obj-y) vdso/
 obj-m					+= $(arm64-obj-m)
diff --git a/arch/arm64/kernel/efi-entry.S b/arch/arm64/kernel/efi-entry.S
new file mode 100644
index 0000000..d99a034e
--- /dev/null
+++ b/arch/arm64/kernel/efi-entry.S
@@ -0,0 +1,100 @@
+/*
+ * EFI entry point.
+ *
+ * Copyright (C) 2013, 2014 Red Hat, Inc.
+ * Author: Mark Salter <msalter@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+#include <asm/assembler.h>
+
+#define EFI_LOAD_ERROR 0x8000000000000001
+
+	__INIT
+
+	/*
+	 * We arrive here from the EFI boot manager with:
+	 *
+	 *    * MMU on with identity-mapped RAM.
+	 *    * Icache and Dcache on
+	 *
+	 * We will most likely be running from some place other than where
+	 * we want to be. The kernel image wants to be placed at TEXT_OFFSET
+	 * from start of RAM.
+	 */
+ENTRY(efi_stub_entry)
+	stp	x29, x30, [sp, #-32]!
+
+	/*
+	 * Call efi_entry to do the real work.
+	 * x0 and x1 are already set up by firmware. Current runtime
+	 * address of image is calculated and passed via *image_addr.
+	 *
+	 * unsigned long efi_entry(void *handle,
+	 *                         efi_system_table_t *sys_table,
+	 *                         unsigned long *image_addr) ;
+	 */
+	adrp	x8, _text
+	add	x8, x8, #:lo12:_text
+	add	x2, sp, 16
+	str	x8, [x2]
+	bl	efi_entry
+	cmn	x0, #1
+	b.eq	efi_load_fail
+
+	/*
+	 * efi_entry() will have relocated the kernel image if necessary
+	 * and we return here with device tree address in x0 and the kernel
+	 * entry point stored at *image_addr. Save those values in registers
+	 * which are callee preserved.
+	 */
+	mov	x20, x0		// DTB address
+	ldr	x0, [sp, #16]	// relocated _text address
+	mov	x21, x0
+
+	adrp	x1, _text
+	add	x1, x1, #:lo12:_text
+	adrp	x2, _edata
+	add	x2, x2, #:lo12:_edata
+	sub	x1, x2, x1
+
+	bl	__flush_dcache_area
+	ic	ialluis
+
+	/* Turn off Dcache and MMU */
+	mrs	x0, CurrentEL
+	cmp	x0, #PSR_MODE_EL2t
+	ccmp	x0, #PSR_MODE_EL2h, #0x4, ne
+	b.ne	1f
+	mrs	x0, sctlr_el2
+	bic	x0, x0, #1 << 0	// clear SCTLR.M
+	bic	x0, x0, #1 << 2	// clear SCTLR.C
+	msr	sctlr_el2, x0
+	isb
+	b	2f
+1:
+	mrs	x0, sctlr_el1
+	bic	x0, x0, #1 << 0	// clear SCTLR.M
+	bic	x0, x0, #1 << 2	// clear SCTLR.C
+	msr	sctlr_el1, x0
+	isb
+2:
+	/* Jump to real entry point */
+	mov	x0, x20
+	mov	x1, xzr
+	mov	x2, xzr
+	mov	x3, xzr
+	br	x21
+
+efi_load_fail:
+	mov	x0, #EFI_LOAD_ERROR
+	ldp	x29, x30, [sp], #32
+	ret
+
+ENDPROC(efi_stub_entry)
diff --git a/arch/arm64/kernel/efi-stub.c b/arch/arm64/kernel/efi-stub.c
new file mode 100644
index 0000000..c416eff
--- /dev/null
+++ b/arch/arm64/kernel/efi-stub.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2013, 2014 Linaro Ltd;  <roy.franz@linaro.org>
+ *
+ * This file implements the EFI boot stub for the arm64 kernel.
+ * Adapted from ARM version by Mark Salter <msalter@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/efi.h>
+#include <linux/libfdt.h>
+#include <asm/sections.h>
+#include <generated/compile.h>
+#include <generated/utsrelease.h>
+
+/*
+ * EFI function call wrappers. These are not required for arm/arm64, but
+ * wrappers are required for X86 to convert between ABIs. These wrappers are
+ * provided to allow code sharing between X86 and other architectures. Since
+ * these wrappers directly invoke the EFI function pointer, the function
+ * pointer type must be properly defined, which is not the case for X86. One
+ * advantage of this is it allows for type checking of arguments, which is not
+ * possible with the X86 wrappers.
+ */
+#define efi_call_phys0(f)			f()
+#define efi_call_phys1(f, a1)			f(a1)
+#define efi_call_phys2(f, a1, a2)		f(a1, a2)
+#define efi_call_phys3(f, a1, a2, a3)		f(a1, a2, a3)
+#define efi_call_phys4(f, a1, a2, a3, a4)	f(a1, a2, a3, a4)
+#define efi_call_phys5(f, a1, a2, a3, a4, a5)	f(a1, a2, a3, a4, a5)
+
+/*
+ * AArch64 requires the DTB to be 8-byte aligned in the first 512MiB from
+ * start of kernel and may not cross a 2MiB boundary. We set alignment to
+ * 2MiB so we know it won't cross a 2MiB boundary.
+ */
+#define EFI_FDT_ALIGN	SZ_2M   /* used by allocate_new_fdt_and_exit_boot() */
+#define MAX_FDT_OFFSET	SZ_512M
+
+#define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__)
+
+static void efi_char16_printk(efi_system_table_t *sys_table_arg,
+			      efi_char16_t *str);
+
+static efi_status_t efi_open_volume(efi_system_table_t *sys_table,
+				    void *__image, void **__fh);
+static efi_status_t efi_file_close(void *__fh, void *handle);
+
+static efi_status_t
+efi_file_read(void *__fh, void *handle, unsigned long *size, void *addr);
+
+static efi_status_t
+efi_file_size(efi_system_table_t *sys_table, void *__fh,
+	      efi_char16_t *filename_16, void **handle, u64 *file_sz);
+
+/* Include shared EFI stub code */
+#include "../../../drivers/firmware/efi/efi-stub-helper.c"
+#include "../../../drivers/firmware/efi/fdt.c"
+#include "../../../drivers/firmware/efi/arm-stub.c"
+
+
+static efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
+					unsigned long *image_addr,
+					unsigned long *image_size,
+					unsigned long *reserve_addr,
+					unsigned long *reserve_size,
+					unsigned long dram_base,
+					efi_loaded_image_t *image)
+{
+	efi_status_t status;
+	unsigned long kernel_size, kernel_memsize = 0;
+
+	/* Relocate the image, if required. */
+	kernel_size = _edata - _text;
+	if (*image_addr != (dram_base + TEXT_OFFSET)) {
+		kernel_memsize = kernel_size + (_end - _edata);
+		status = efi_relocate_kernel(sys_table, image_addr,
+					     kernel_size, kernel_memsize,
+					     dram_base + TEXT_OFFSET,
+					     PAGE_SIZE);
+		if (status != EFI_SUCCESS) {
+			pr_efi_err(sys_table, "Failed to relocate kernel\n");
+			return status;
+		}
+		if (*image_addr != (dram_base + TEXT_OFFSET)) {
+			pr_efi_err(sys_table, "Failed to alloc kernel memory\n");
+			efi_free(sys_table, kernel_memsize, *image_addr);
+			return EFI_ERROR;
+		}
+		*image_size = kernel_memsize;
+	}
+
+
+	return EFI_SUCCESS;
+}
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 1fe5d8d..2aee658 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -107,8 +107,18 @@
 	/*
 	 * DO NOT MODIFY. Image header expected by Linux boot-loaders.
 	 */
+#ifdef CONFIG_EFI
+	/*
+	 * Magic "MZ" signature for PE/COFF
+	 * Little Endian:  add x13, x18, #0x16
+	 */
+efi_head:
+	.long   0x91005a4d
+	b	stext
+#else
 	b	stext				// branch to kernel start, magic
 	.long	0				// reserved
+#endif
 	.quad	TEXT_OFFSET			// Image load offset from start of RAM
 	.quad	0				// reserved
 	.quad	0				// reserved
@@ -119,7 +129,109 @@
 	.byte	0x52
 	.byte	0x4d
 	.byte	0x64
+#ifdef CONFIG_EFI
+	.long	pe_header - efi_head		// Offset to the PE header.
+#else
 	.word	0				// reserved
+#endif
+
+#ifdef CONFIG_EFI
+	.align 3
+pe_header:
+	.ascii	"PE"
+	.short 	0
+coff_header:
+	.short	0xaa64				// AArch64
+	.short	2				// nr_sections
+	.long	0 				// TimeDateStamp
+	.long	0				// PointerToSymbolTable
+	.long	1				// NumberOfSymbols
+	.short	section_table - optional_header	// SizeOfOptionalHeader
+	.short	0x206				// Characteristics.
+						// IMAGE_FILE_DEBUG_STRIPPED |
+						// IMAGE_FILE_EXECUTABLE_IMAGE |
+						// IMAGE_FILE_LINE_NUMS_STRIPPED
+optional_header:
+	.short	0x20b				// PE32+ format
+	.byte	0x02				// MajorLinkerVersion
+	.byte	0x14				// MinorLinkerVersion
+	.long	_edata - stext			// SizeOfCode
+	.long	0				// SizeOfInitializedData
+	.long	0				// SizeOfUninitializedData
+	.long	efi_stub_entry - efi_head	// AddressOfEntryPoint
+	.long	stext - efi_head		// BaseOfCode
+
+extra_header_fields:
+	.quad	0				// ImageBase
+	.long	0x20				// SectionAlignment
+	.long	0x8				// FileAlignment
+	.short	0				// MajorOperatingSystemVersion
+	.short	0				// MinorOperatingSystemVersion
+	.short	0				// MajorImageVersion
+	.short	0				// MinorImageVersion
+	.short	0				// MajorSubsystemVersion
+	.short	0				// MinorSubsystemVersion
+	.long	0				// Win32VersionValue
+
+	.long	_edata - efi_head		// SizeOfImage
+
+	// Everything before the kernel image is considered part of the header
+	.long	stext - efi_head			// SizeOfHeaders
+	.long	0				// CheckSum
+	.short	0xa				// Subsystem (EFI application)
+	.short	0				// DllCharacteristics
+	.quad	0				// SizeOfStackReserve
+	.quad	0				// SizeOfStackCommit
+	.quad	0				// SizeOfHeapReserve
+	.quad	0				// SizeOfHeapCommit
+	.long	0				// LoaderFlags
+	.long	0x6				// NumberOfRvaAndSizes
+
+	.quad	0				// ExportTable
+	.quad	0				// ImportTable
+	.quad	0				// ResourceTable
+	.quad	0				// ExceptionTable
+	.quad	0				// CertificationTable
+	.quad	0				// BaseRelocationTable
+
+	// Section table
+section_table:
+
+	/*
+	 * The EFI application loader requires a relocation section
+	 * because EFI applications must be relocatable.  This is a
+	 * dummy section as far as we are concerned.
+	 */
+	.ascii	".reloc"
+	.byte	0
+	.byte	0			// end of 0 padding of section name
+	.long	0
+	.long	0
+	.long	0			// SizeOfRawData
+	.long	0			// PointerToRawData
+	.long	0			// PointerToRelocations
+	.long	0			// PointerToLineNumbers
+	.short	0			// NumberOfRelocations
+	.short	0			// NumberOfLineNumbers
+	.long	0x42100040		// Characteristics (section flags)
+
+
+	.ascii	".text"
+	.byte	0
+	.byte	0
+	.byte	0        		// end of 0 padding of section name
+	.long	_edata - stext		// VirtualSize
+	.long	stext - efi_head	// VirtualAddress
+	.long	_edata - stext		// SizeOfRawData
+	.long	stext - efi_head	// PointerToRawData
+
+	.long	0		// PointerToRelocations (0 for executables)
+	.long	0		// PointerToLineNumbers (0 for executables)
+	.short	0		// NumberOfRelocations  (0 for executables)
+	.short	0		// NumberOfLineNumbers  (0 for executables)
+	.long	0xe0500020	// Characteristics (section flags)
+	.align 5
+#endif
 
 ENTRY(stext)
 	mov	x21, x0				// x21=FDT
diff --git a/drivers/firmware/efi/arm-stub.c b/drivers/firmware/efi/arm-stub.c
new file mode 100644
index 0000000..b9b7c00
--- /dev/null
+++ b/drivers/firmware/efi/arm-stub.c
@@ -0,0 +1,248 @@
+/*
+ * EFI stub implementation that is shared by arm and arm64 architectures.
+ * This should be #included by the EFI stub implementation files.
+ *
+ * Copyright (C) 2013,2014 Linaro Limited
+ *     Roy Franz <roy.franz at linaro.org
+ * Copyright (C) 2013 Red Hat, Inc.
+ *     Mark Salter <msalter@redhat.com>
+ *
+ * This file is part of the Linux kernel, and is made available under the
+ * terms of the GNU General Public License version 2.
+ *
+ */
+
+
+static efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
+				    void *__image, void **__fh)
+{
+	efi_file_io_interface_t *io;
+	efi_loaded_image_t *image = __image;
+	efi_file_handle_t *fh;
+	efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
+	efi_status_t status;
+	void *handle = (void *)(unsigned long)image->device_handle;
+
+	status = sys_table_arg->boottime->handle_protocol(handle,
+				 &fs_proto, (void **)&io);
+	if (status != EFI_SUCCESS) {
+		efi_printk(sys_table_arg, "Failed to handle fs_proto\n");
+		return status;
+	}
+
+	status = io->open_volume(io, &fh);
+	if (status != EFI_SUCCESS)
+		efi_printk(sys_table_arg, "Failed to open volume\n");
+
+	*__fh = fh;
+	return status;
+}
+static efi_status_t efi_file_close(void *__fh, void *handle)
+{
+	efi_file_handle_t *fh = __fh;
+
+	return fh->close(handle);
+}
+
+static efi_status_t
+efi_file_read(void *__fh, void *handle, unsigned long *size, void *addr)
+{
+	efi_file_handle_t *fh = __fh;
+
+	return fh->read(handle, size, addr);
+}
+
+
+static efi_status_t
+efi_file_size(efi_system_table_t *sys_table_arg, void *__fh,
+	      efi_char16_t *filename_16, void **handle, u64 *file_sz)
+{
+	efi_file_handle_t *h, *fh = __fh;
+	efi_file_info_t *info;
+	efi_status_t status;
+	efi_guid_t info_guid = EFI_FILE_INFO_ID;
+	unsigned long info_sz;
+
+	status = fh->open(fh, &h, filename_16, EFI_FILE_MODE_READ, (u64)0);
+	if (status != EFI_SUCCESS) {
+		efi_printk(sys_table_arg, "Failed to open file: ");
+		efi_char16_printk(sys_table_arg, filename_16);
+		efi_printk(sys_table_arg, "\n");
+		return status;
+	}
+
+	*handle = h;
+
+	info_sz = 0;
+	status = h->get_info(h, &info_guid, &info_sz, NULL);
+	if (status != EFI_BUFFER_TOO_SMALL) {
+		efi_printk(sys_table_arg, "Failed to get file info size\n");
+		return status;
+	}
+
+grow:
+	status = sys_table_arg->boottime->allocate_pool(EFI_LOADER_DATA,
+				 info_sz, (void **)&info);
+	if (status != EFI_SUCCESS) {
+		efi_printk(sys_table_arg, "Failed to alloc mem for file info\n");
+		return status;
+	}
+
+	status = h->get_info(h, &info_guid, &info_sz,
+						   info);
+	if (status == EFI_BUFFER_TOO_SMALL) {
+		sys_table_arg->boottime->free_pool(info);
+		goto grow;
+	}
+
+	*file_sz = info->file_size;
+	sys_table_arg->boottime->free_pool(info);
+
+	if (status != EFI_SUCCESS)
+		efi_printk(sys_table_arg, "Failed to get initrd info\n");
+
+	return status;
+}
+
+
+
+static void efi_char16_printk(efi_system_table_t *sys_table_arg,
+			      efi_char16_t *str)
+{
+	struct efi_simple_text_output_protocol *out;
+
+	out = (struct efi_simple_text_output_protocol *)sys_table_arg->con_out;
+	efi_call_phys2(out->output_string, out, str);
+}
+
+
+/*
+ * This function handles the architcture specific differences between arm and
+ * arm64 regarding where the kernel image must be loaded and any memory that
+ * must be reserved. On failure it is required to free all
+ * all allocations it has made.
+ */
+static efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
+					unsigned long *image_addr,
+					unsigned long *image_size,
+					unsigned long *reserve_addr,
+					unsigned long *reserve_size,
+					unsigned long dram_base,
+					efi_loaded_image_t *image);
+/*
+ * EFI entry point for the arm/arm64 EFI stubs.  This is the entrypoint
+ * that is described in the PE/COFF header.  Most of the code is the same
+ * for both archictectures, with the arch-specific code provided in the
+ * handle_kernel_image() function.
+ */
+unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table,
+			       unsigned long *image_addr)
+{
+	efi_loaded_image_t *image;
+	efi_status_t status;
+	unsigned long image_size = 0;
+	unsigned long dram_base;
+	/* addr/point and size pairs for memory management*/
+	unsigned long initrd_addr;
+	u64 initrd_size = 0;
+	unsigned long fdt_addr;  /* Original DTB */
+	u64 fdt_size = 0;  /* We don't get size from configuration table */
+	char *cmdline_ptr = NULL;
+	int cmdline_size = 0;
+	unsigned long new_fdt_addr;
+	efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID;
+	unsigned long reserve_addr = 0;
+	unsigned long reserve_size = 0;
+
+	/* Check if we were booted by the EFI firmware */
+	if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
+		goto fail;
+
+	pr_efi(sys_table, "Booting Linux Kernel...\n");
+
+	/*
+	 * Get a handle to the loaded image protocol.  This is used to get
+	 * information about the running image, such as size and the command
+	 * line.
+	 */
+	status = efi_call_phys3(sys_table->boottime->handle_protocol,
+				handle, &loaded_image_proto, (void *)&image);
+	if (status != EFI_SUCCESS) {
+		pr_efi_err(sys_table, "Failed to get loaded image protocol\n");
+		goto fail;
+	}
+
+	dram_base = get_dram_base(sys_table);
+	if (dram_base == EFI_ERROR) {
+		pr_efi_err(sys_table, "Failed to find DRAM base\n");
+		goto fail;
+	}
+	status = handle_kernel_image(sys_table, image_addr, &image_size,
+				     &reserve_addr,
+				     &reserve_size,
+				     dram_base, image);
+	if (status != EFI_SUCCESS) {
+		pr_efi_err(sys_table, "Failed to relocate kernel\n");
+		goto fail;
+	}
+
+	/*
+	 * Get the command line from EFI, using the LOADED_IMAGE
+	 * protocol. We are going to copy the command line into the
+	 * device tree, so this can be allocated anywhere.
+	 */
+	cmdline_ptr = efi_convert_cmdline(sys_table, image, &cmdline_size);
+	if (!cmdline_ptr) {
+		pr_efi_err(sys_table, "getting command line via LOADED_IMAGE_PROTOCOL\n");
+		goto fail_free_image;
+	}
+
+	/* Load a device tree from the configuration table, if present. */
+	fdt_addr = (uintptr_t)get_fdt(sys_table);
+	if (!fdt_addr) {
+		status = handle_cmdline_files(sys_table, image, cmdline_ptr,
+					      "dtb=",
+					      ~0UL, (unsigned long *)&fdt_addr,
+					      (unsigned long *)&fdt_size);
+
+		if (status != EFI_SUCCESS) {
+			pr_efi_err(sys_table, "Failed to load device tree!\n");
+			goto fail_free_cmdline;
+		}
+	}
+
+	status = handle_cmdline_files(sys_table, image, cmdline_ptr,
+				      "initrd=", dram_base + SZ_512M,
+				      (unsigned long *)&initrd_addr,
+				      (unsigned long *)&initrd_size);
+	if (status != EFI_SUCCESS)
+		pr_efi_err(sys_table, "Failed initrd from command line!\n");
+
+	new_fdt_addr = fdt_addr;
+	status = allocate_new_fdt_and_exit_boot(sys_table, handle,
+				&new_fdt_addr, dram_base + MAX_FDT_OFFSET,
+				initrd_addr, initrd_size, cmdline_ptr,
+				fdt_addr, fdt_size);
+
+	/*
+	 * If all went well, we need to return the FDT address to the
+	 * calling function so it can be passed to kernel as part of
+	 * the kernel boot protocol.
+	 */
+	if (status == EFI_SUCCESS)
+		return new_fdt_addr;
+
+	pr_efi_err(sys_table, "Failed to update FDT and exit boot services\n");
+
+	efi_free(sys_table, initrd_size, initrd_addr);
+	efi_free(sys_table, fdt_size, fdt_addr);
+
+fail_free_cmdline:
+	efi_free(sys_table, cmdline_size, (unsigned long)cmdline_ptr);
+
+fail_free_image:
+	efi_free(sys_table, image_size, *image_addr);
+	efi_free(sys_table, reserve_size, reserve_addr);
+fail:
+	return EFI_ERROR;
+}
-- 
1.7.10.4

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

* [PATCH v3 07/10] doc: arm64: add description of EFI stub support
  2014-04-04 18:45 ` Leif Lindholm
@ 2014-04-04 18:45   ` Leif Lindholm
  -1 siblings, 0 replies; 55+ messages in thread
From: Leif Lindholm @ 2014-04-04 18:45 UTC (permalink / raw)
  To: linux-arm-kernel, linux-efi
  Cc: linux-kernel, Mark Salter, Leif Lindholm, linux-doc, Rob Landley

From: Mark Salter <msalter@redhat.com>

Add explanation of arm64 EFI stub and kernel image header changes
needed to masquerade as a PE/COFF application.

Signed-off-by: Mark Salter <msalter@redhat.com>
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Acked-by: Grant Likely <grant.likely@linaro.org>
CC: linux-doc@vger.kernel.org
CC: Rob Landley <rob@landley.net>
---
 Documentation/arm64/booting.txt |    4 ++++
 Documentation/efi-stub.txt      |   12 +++++++++---
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/Documentation/arm64/booting.txt b/Documentation/arm64/booting.txt
index a9691cc..aa95d38c 100644
--- a/Documentation/arm64/booting.txt
+++ b/Documentation/arm64/booting.txt
@@ -85,6 +85,10 @@ The decompressed kernel image contains a 64-byte header as follows:
 Header notes:
 
 - code0/code1 are responsible for branching to stext.
+- when booting through EFI, code0/code1 are initially skipped.
+  res5 is an offset to the PE header and the PE header has the EFI
+  entry point (efi_stub_entry). When the stub has done its work, it
+  jumps to code0 to resume the normal boot process.
 
 The image must be placed at the specified offset (currently 0x80000)
 from the start of the system RAM and called there. The start of the
diff --git a/Documentation/efi-stub.txt b/Documentation/efi-stub.txt
index 26be7b0..7747024 100644
--- a/Documentation/efi-stub.txt
+++ b/Documentation/efi-stub.txt
@@ -12,6 +12,11 @@ arch/arm/boot/compressed/efi-header.S and
 arch/arm/boot/compressed/efi-stub.c. EFI stub code that is shared
 between architectures is in drivers/firmware/efi/efi-stub-helper.c.
 
+For arm64, there is no compressed kernel support, so the Image itself
+masquerades as a PE/COFF image and the EFI stub is linked into the
+kernel. The arm64 EFI stub lives in arch/arm64/kernel/efi-entry.S
+and arch/arm64/kernel/efi-stub.c.
+
 By using the EFI boot stub it's possible to boot a Linux kernel
 without the use of a conventional EFI boot loader, such as grub or
 elilo. Since the EFI boot stub performs the jobs of a boot loader, in
@@ -28,7 +33,8 @@ the extension the EFI firmware loader will refuse to execute it. It's
 not possible to execute bzImage.efi from the usual Linux file systems
 because EFI firmware doesn't have support for them. For ARM the
 arch/arm/boot/zImage should be copied to the system partition, and it
-may not need to be renamed.
+may not need to be renamed. Similarly for arm64, arch/arm64/boot/Image
+should be copied but not necessarily renamed.
 
 
 **** Passing kernel parameters from the EFI shell
@@ -72,7 +78,7 @@ is passed to bzImage.efi.
 
 **** The "dtb=" option
 
-For the ARM architecture, we also need to be able to provide a device
-tree to the kernel. This is done with the "dtb=" command line option,
+For the ARM and arm64 architectures, we also need to be able to provide a
+device tree to the kernel. This is done with the "dtb=" command line option,
 and is processed in the same manner as the "initrd=" option that is
 described above.
-- 
1.7.10.4


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

* [PATCH v3 07/10] doc: arm64: add description of EFI stub support
@ 2014-04-04 18:45   ` Leif Lindholm
  0 siblings, 0 replies; 55+ messages in thread
From: Leif Lindholm @ 2014-04-04 18:45 UTC (permalink / raw)
  To: linux-arm-kernel

From: Mark Salter <msalter@redhat.com>

Add explanation of arm64 EFI stub and kernel image header changes
needed to masquerade as a PE/COFF application.

Signed-off-by: Mark Salter <msalter@redhat.com>
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Acked-by: Grant Likely <grant.likely@linaro.org>
CC: linux-doc at vger.kernel.org
CC: Rob Landley <rob@landley.net>
---
 Documentation/arm64/booting.txt |    4 ++++
 Documentation/efi-stub.txt      |   12 +++++++++---
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/Documentation/arm64/booting.txt b/Documentation/arm64/booting.txt
index a9691cc..aa95d38c 100644
--- a/Documentation/arm64/booting.txt
+++ b/Documentation/arm64/booting.txt
@@ -85,6 +85,10 @@ The decompressed kernel image contains a 64-byte header as follows:
 Header notes:
 
 - code0/code1 are responsible for branching to stext.
+- when booting through EFI, code0/code1 are initially skipped.
+  res5 is an offset to the PE header and the PE header has the EFI
+  entry point (efi_stub_entry). When the stub has done its work, it
+  jumps to code0 to resume the normal boot process.
 
 The image must be placed at the specified offset (currently 0x80000)
 from the start of the system RAM and called there. The start of the
diff --git a/Documentation/efi-stub.txt b/Documentation/efi-stub.txt
index 26be7b0..7747024 100644
--- a/Documentation/efi-stub.txt
+++ b/Documentation/efi-stub.txt
@@ -12,6 +12,11 @@ arch/arm/boot/compressed/efi-header.S and
 arch/arm/boot/compressed/efi-stub.c. EFI stub code that is shared
 between architectures is in drivers/firmware/efi/efi-stub-helper.c.
 
+For arm64, there is no compressed kernel support, so the Image itself
+masquerades as a PE/COFF image and the EFI stub is linked into the
+kernel. The arm64 EFI stub lives in arch/arm64/kernel/efi-entry.S
+and arch/arm64/kernel/efi-stub.c.
+
 By using the EFI boot stub it's possible to boot a Linux kernel
 without the use of a conventional EFI boot loader, such as grub or
 elilo. Since the EFI boot stub performs the jobs of a boot loader, in
@@ -28,7 +33,8 @@ the extension the EFI firmware loader will refuse to execute it. It's
 not possible to execute bzImage.efi from the usual Linux file systems
 because EFI firmware doesn't have support for them. For ARM the
 arch/arm/boot/zImage should be copied to the system partition, and it
-may not need to be renamed.
+may not need to be renamed. Similarly for arm64, arch/arm64/boot/Image
+should be copied but not necessarily renamed.
 
 
 **** Passing kernel parameters from the EFI shell
@@ -72,7 +78,7 @@ is passed to bzImage.efi.
 
 **** The "dtb=" option
 
-For the ARM architecture, we also need to be able to provide a device
-tree to the kernel. This is done with the "dtb=" command line option,
+For the ARM and arm64 architectures, we also need to be able to provide a
+device tree to the kernel. This is done with the "dtb=" command line option,
 and is processed in the same manner as the "initrd=" option that is
 described above.
-- 
1.7.10.4

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

* [PATCH v3 08/10] arm64: add EFI runtime services
  2014-04-04 18:45 ` Leif Lindholm
@ 2014-04-04 18:45   ` Leif Lindholm
  -1 siblings, 0 replies; 55+ messages in thread
From: Leif Lindholm @ 2014-04-04 18:45 UTC (permalink / raw)
  To: linux-arm-kernel, linux-efi
  Cc: linux-kernel, Mark Salter, Leif Lindholm, Catalin Marinas

From: Mark Salter <msalter@redhat.com>

This patch adds EFI runtime support for arm64. The runtime support allows
the kernel to access various EFI runtime services provided by EFI firmware.
Things like reboot, real time clock, EFI boot variables, and others.

Signed-off-by: Mark Salter <msalter@redhat.com>
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
---
 arch/arm64/Kconfig           |    7 +
 arch/arm64/include/asm/efi.h |   14 ++
 arch/arm64/kernel/Makefile   |    2 +-
 arch/arm64/kernel/efi.c      |  469 ++++++++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/setup.c    |    5 +
 5 files changed, 496 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/include/asm/efi.h
 create mode 100644 arch/arm64/kernel/efi.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 791ec61..a7ee734 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -284,12 +284,17 @@ config EFI
 	bool "UEFI firmware support"
 	depends on OF
 	select LIBFDT
+	select UCS2_STRING
+	select UEFI_PARAMS_FROM_FDT
 	default y
 	help
 	  This option permits an Image to be loaded directly
 	  by EFI firmware without the use of a bootloader.
 	  See Documentation/efi-stub.txt for more information.
 
+	  It also enables the kernel to use available UEFI runtime
+	  services (such as the UEFI variable services).
+
 	  This is only useful on systems that have UEFI firmware.
 	  However, even with this option, the resultant kernel should
 	  continue to boot on existing non-UEFI platforms.
@@ -353,6 +358,8 @@ source "net/Kconfig"
 
 source "drivers/Kconfig"
 
+source "drivers/firmware/Kconfig"
+
 source "fs/Kconfig"
 
 source "arch/arm64/kvm/Kconfig"
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
new file mode 100644
index 0000000..5a46c4e
--- /dev/null
+++ b/arch/arm64/include/asm/efi.h
@@ -0,0 +1,14 @@
+#ifndef _ASM_EFI_H
+#define _ASM_EFI_H
+
+#include <asm/io.h>
+
+#ifdef CONFIG_EFI
+extern void efi_init(void);
+extern void efi_idmap_init(void);
+#else
+#define efi_init()
+#define efi_idmap_init()
+#endif
+
+#endif /* _ASM_EFI_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 21009b7..3a2815b 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -24,7 +24,7 @@ arm64-obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND)	+= sleep.o suspend.o
 arm64-obj-$(CONFIG_JUMP_LABEL)		+= jump_label.o
 arm64-obj-$(CONFIG_KGDB)		+= kgdb.o
-arm64-obj-$(CONFIG_EFI)			+= efi-stub.o efi-entry.o
+arm64-obj-$(CONFIG_EFI)			+= efi-stub.o efi-entry.o efi.o
 
 obj-y					+= $(arm64-obj-y) vdso/
 obj-m					+= $(arm64-obj-m)
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
new file mode 100644
index 0000000..45f4784
--- /dev/null
+++ b/arch/arm64/kernel/efi.c
@@ -0,0 +1,469 @@
+/*
+ * Extensible Firmware Interface
+ *
+ * Based on Extensible Firmware Interface Specification version 2.4
+ *
+ * Copyright (C) 2013, 2014 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/efi.h>
+#include <linux/export.h>
+#include <linux/memblock.h>
+#include <linux/bootmem.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include <asm/cacheflush.h>
+#include <asm/efi.h>
+#include <asm/tlbflush.h>
+#include <asm/mmu_context.h>
+
+struct efi_memory_map memmap;
+
+static efi_runtime_services_t *runtime;
+
+static u64 efi_system_table;
+
+static int uefi_debug __initdata;
+static int __init uefi_debug_setup(char *str)
+{
+	uefi_debug = 1;
+
+	return 0;
+}
+early_param("uefi_debug", uefi_debug_setup);
+
+static int __init is_normal_ram(efi_memory_desc_t *md)
+{
+	if (md->attribute & EFI_MEMORY_WB)
+		return 1;
+	return 0;
+}
+
+static void __init efi_setup_idmap(void)
+{
+	struct memblock_region *r;
+	efi_memory_desc_t *md;
+	u64 paddr, npages, size;
+
+	for_each_memblock(memory, r)
+		create_id_mapping(r->base, r->size, 0);
+
+	/* map runtime io spaces */
+	for_each_efi_memory_desc(&memmap, md) {
+		if (!(md->attribute & EFI_MEMORY_RUNTIME) || is_normal_ram(md))
+			continue;
+		paddr = md->phys_addr;
+		npages = md->num_pages;
+		memrange_efi_to_native(&paddr, &npages);
+		size = npages << PAGE_SHIFT;
+		create_id_mapping(paddr, size, 1);
+	}
+}
+
+static int __init uefi_init(void)
+{
+	efi_char16_t *c16;
+	char vendor[100] = "unknown";
+	int i, retval;
+
+	efi.systab = early_memremap(efi_system_table,
+				    sizeof(efi_system_table_t));
+	if (efi.systab == NULL) {
+		pr_warn("Unable to map EFI system table.\n");
+		return -ENOMEM;
+	}
+
+	set_bit(EFI_BOOT, &efi.flags);
+	set_bit(EFI_64BIT, &efi.flags);
+
+	/*
+	 * Verify the EFI Table
+	 */
+	if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) {
+		pr_err("System table signature incorrect\n");
+		return -EINVAL;
+	}
+	if ((efi.systab->hdr.revision >> 16) < 2)
+		pr_warn("Warning: EFI system table version %d.%02d, expected 2.00 or greater\n",
+			efi.systab->hdr.revision >> 16,
+			efi.systab->hdr.revision & 0xffff);
+
+	/* Show what we know for posterity */
+	c16 = early_memremap(efi.systab->fw_vendor,
+			     sizeof(vendor));
+	if (c16) {
+		for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
+			vendor[i] = c16[i];
+		vendor[i] = '\0';
+	}
+
+	pr_info("EFI v%u.%.02u by %s\n",
+		efi.systab->hdr.revision >> 16,
+		efi.systab->hdr.revision & 0xffff, vendor);
+
+	retval = efi_config_init(NULL);
+	if (retval == 0)
+		set_bit(EFI_CONFIG_TABLES, &efi.flags);
+
+	early_memunmap(c16, sizeof(vendor));
+	early_memunmap(efi.systab,  sizeof(efi_system_table_t));
+
+	return retval;
+}
+
+static __initdata char memory_type_name[][32] = {
+	{"Reserved"},
+	{"Loader Code"},
+	{"Loader Data"},
+	{"Boot Code"},
+	{"Boot Data"},
+	{"Runtime Code"},
+	{"Runtime Data"},
+	{"Conventional Memory"},
+	{"Unusable Memory"},
+	{"ACPI Reclaim Memory"},
+	{"ACPI Memory NVS"},
+	{"Memory Mapped I/O"},
+	{"MMIO Port Space"},
+	{"PAL Code"},
+};
+
+/*
+ * Return true for RAM regions we want to permanently reserve.
+ */
+static __init int is_reserve_region(efi_memory_desc_t *md)
+{
+	if (!is_normal_ram(md))
+		return 0;
+
+	if (md->attribute & EFI_MEMORY_RUNTIME)
+		return 1;
+
+	if (md->type == EFI_ACPI_RECLAIM_MEMORY ||
+	    md->type == EFI_RESERVED_TYPE)
+		return 1;
+
+	return 0;
+}
+
+static __init void reserve_regions(void)
+{
+	efi_memory_desc_t *md;
+	u64 paddr, npages, size;
+
+	if (uefi_debug)
+		pr_info("Processing EFI memory map:\n");
+
+	for_each_efi_memory_desc(&memmap, md) {
+		paddr = md->phys_addr;
+		npages = md->num_pages;
+
+		if (uefi_debug)
+			pr_info("  0x%012llx-0x%012llx [%s]",
+				paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
+				memory_type_name[md->type]);
+
+		memrange_efi_to_native(&paddr, &npages);
+		size = npages << PAGE_SHIFT;
+
+		if (is_normal_ram(md))
+			early_init_dt_add_memory_arch(paddr, size);
+
+		if (is_reserve_region(md) ||
+		    md->type == EFI_BOOT_SERVICES_CODE ||
+		    md->type == EFI_BOOT_SERVICES_DATA) {
+			memblock_reserve(paddr, size);
+			if (uefi_debug)
+				pr_cont("*");
+		}
+
+		if (uefi_debug)
+			pr_cont("\n");
+	}
+}
+
+
+static u64 __init free_one_region(u64 start, u64 end)
+{
+	u64 size = end - start;
+
+	if (uefi_debug)
+		pr_info("  EFI freeing: 0x%012llx-0x%012llx\n",	start, end - 1);
+
+	free_bootmem_late(start, size);
+	return size;
+}
+
+static u64 __init free_region(u64 start, u64 end)
+{
+	u64 map_start, map_end, total = 0;
+
+	if (end <= start)
+		return total;
+
+	map_start = (u64)memmap.phys_map;
+	map_end = PAGE_ALIGN(map_start + (memmap.map_end - memmap.map));
+	map_start &= PAGE_MASK;
+
+	if (start < map_end && end > map_start) {
+		/* region overlaps UEFI memmap */
+		if (start < map_start)
+			total += free_one_region(start, map_start);
+
+		if (map_end < end)
+			total += free_one_region(map_end, end);
+	} else
+		total += free_one_region(start, end);
+
+	return total;
+}
+
+static void __init free_boot_services(void)
+{
+	u64 total_freed = 0;
+	u64 keep_end, free_start, free_end;
+	efi_memory_desc_t *md;
+
+	/*
+	 * If kernel uses larger pages than UEFI, we have to be careful
+	 * not to inadvertantly free memory we want to keep if there is
+	 * overlap at the kernel page size alignment. We do not want to
+	 * free is_reserve_region() memory nor the UEFI memmap itself.
+	 *
+	 * The memory map is sorted, so we keep track of the end of
+	 * any previous region we want to keep, remember any region
+	 * we want to free and defer freeing it until we encounter
+	 * the next region we want to keep. This way, before freeing
+	 * it, we can clip it as needed to avoid freeing memory we
+	 * want to keep for UEFI.
+	 */
+
+	keep_end = 0;
+	free_start = 0;
+
+	for_each_efi_memory_desc(&memmap, md) {
+		u64 paddr, npages, size;
+
+		if (is_reserve_region(md)) {
+			/*
+			 * We don't want to free any memory from this region.
+			 */
+			if (free_start) {
+				/* adjust free_end then free region */
+				if (free_end > md->phys_addr)
+					free_end -= PAGE_SIZE;
+				total_freed += free_region(free_start, free_end);
+				free_start = 0;
+			}
+			keep_end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
+			continue;
+		}
+
+		if (md->type != EFI_BOOT_SERVICES_CODE &&
+		    md->type != EFI_BOOT_SERVICES_DATA) {
+			/* no need to free this region */
+			continue;
+		}
+
+		/*
+		 * We want to free memory from this region.
+		 */
+		paddr = md->phys_addr;
+		npages = md->num_pages;
+		memrange_efi_to_native(&paddr, &npages);
+		size = npages << PAGE_SHIFT;
+
+		if (free_start) {
+			if (paddr <= free_end)
+				free_end = paddr + size;
+			else {
+				total_freed += free_region(free_start, free_end);
+				free_start = paddr;
+				free_end = paddr + size;
+			}
+		} else {
+			free_start = paddr;
+			free_end = paddr + size;
+		}
+		if (free_start < keep_end) {
+			free_start += PAGE_SIZE;
+			if (free_start >= free_end)
+				free_start = 0;
+		}
+	}
+	if (free_start)
+		total_freed += free_region(free_start, free_end);
+
+	if (total_freed)
+		pr_info("Freed 0x%llx bytes of EFI boot services memory",
+			total_freed);
+}
+
+void __init efi_init(void)
+{
+	struct efi_fdt_params params;
+
+	/* Grab UEFI information placed in FDT by stub */
+	if (!efi_get_fdt_params(&params, uefi_debug))
+		return;
+
+	efi_system_table = params.system_table;
+
+	memblock_reserve(params.mmap & PAGE_MASK,
+			 PAGE_ALIGN(params.mmap_size + (params.mmap & ~PAGE_MASK)));
+	memmap.phys_map = (void *)params.mmap;
+	memmap.map = early_memremap(params.mmap, params.mmap_size);
+	memmap.map_end = memmap.map + params.mmap_size;
+	memmap.desc_size = params.desc_size;
+	memmap.desc_version = params.desc_ver;
+
+	if (uefi_init() < 0)
+		return;
+
+	reserve_regions();
+}
+
+void __init efi_idmap_init(void)
+{
+	/* boot time idmap_pg_dir is incomplete, so fill in missing parts */
+	efi_setup_idmap();
+}
+
+static int __init remap_region(efi_memory_desc_t *md, void **new)
+{
+	u64 paddr, vaddr, npages, size;
+
+	paddr = md->phys_addr;
+	npages = md->num_pages;
+	memrange_efi_to_native(&paddr, &npages);
+	size = npages << PAGE_SHIFT;
+
+	if (is_normal_ram(md))
+		vaddr = (__force u64)ioremap_cache(paddr, size);
+	else
+		vaddr = (__force u64)ioremap(paddr, size);
+
+	if (!vaddr) {
+		pr_err("Unable to remap 0x%llx pages @ %p\n",
+		       npages, (void *)paddr);
+		return 0;
+	}
+
+	/* adjust for any rounding when EFI and system pagesize differs */
+	md->virt_addr = vaddr + (md->phys_addr - paddr);
+
+	if (uefi_debug)
+		pr_info("  EFI remap 0x%012llx => %p\n",
+			md->phys_addr, (void *)md->virt_addr);
+
+	memcpy(*new, md, memmap.desc_size);
+	*new += memmap.desc_size;
+
+	return 1;
+}
+
+/*
+ * Switch UEFI from an identity map to a kernel virtual map
+ */
+static int __init arm64_enter_virtual_mode(void)
+{
+	efi_memory_desc_t *md;
+	phys_addr_t virtmap_phys;
+	void *virtmap, *virt_md;
+	efi_status_t status;
+	u64 mapsize;
+	int count = 0;
+	unsigned long flags;
+
+	if (!efi_enabled(EFI_BOOT)) {
+		pr_info("EFI services will not be available.\n");
+		return -1;
+	}
+
+	pr_info("Remapping and enabling EFI services.\n");
+
+	/* replace early memmap mapping with permanent mapping */
+	mapsize = memmap.map_end - memmap.map;
+	early_memunmap(memmap.map, mapsize);
+	memmap.map = (__force void *)ioremap_cache((phys_addr_t)memmap.phys_map,
+						   mapsize);
+	memmap.map_end = memmap.map + mapsize;
+
+	efi.memmap = &memmap;
+
+	/* Map the runtime regions */
+	virtmap = kmalloc(mapsize, GFP_KERNEL);
+	if (!virtmap) {
+		pr_err("Failed to allocate EFI virtual memmap\n");
+		return -1;
+	}
+	virtmap_phys = virt_to_phys(virtmap);
+	virt_md = virtmap;
+
+	for_each_efi_memory_desc(&memmap, md) {
+		if (!(md->attribute & EFI_MEMORY_RUNTIME))
+			continue;
+		if (remap_region(md, &virt_md))
+			++count;
+	}
+
+	efi.systab = (__force void *)efi_lookup_mapped_addr(efi_system_table);
+	if (efi.systab)
+		set_bit(EFI_SYSTEM_TABLES, &efi.flags);
+
+	local_irq_save(flags);
+	cpu_switch_mm(idmap_pg_dir, &init_mm);
+	flush_tlb_all();
+	flush_cache_all();
+
+	/* Call SetVirtualAddressMap with the physical address of the map */
+	runtime = efi.systab->runtime;
+	efi.set_virtual_address_map = runtime->set_virtual_address_map;
+
+	status = efi.set_virtual_address_map(count * memmap.desc_size,
+					     memmap.desc_size,
+					     memmap.desc_version,
+					     (efi_memory_desc_t *)virtmap_phys);
+	cpu_set_reserved_ttbr0();
+	flush_tlb_all();
+	flush_cache_all();
+	local_irq_restore(flags);
+
+	kfree(virtmap);
+
+	free_boot_services();
+
+	if (status != EFI_SUCCESS) {
+		pr_err("Failed to set EFI virtual address map! [%lx]\n",
+			status);
+		return -1;
+	}
+
+	/* Set up runtime services function pointers */
+	runtime = efi.systab->runtime;
+	efi.get_time = runtime->get_time;
+	efi.set_time = runtime->set_time;
+	efi.get_wakeup_time = runtime->get_wakeup_time;
+	efi.set_wakeup_time = runtime->set_wakeup_time;
+	efi.get_variable = runtime->get_variable;
+	efi.get_next_variable = runtime->get_next_variable;
+	efi.set_variable = runtime->set_variable;
+	efi.query_variable_info = runtime->query_variable_info;
+	efi.update_capsule = runtime->update_capsule;
+	efi.query_capsule_caps = runtime->query_capsule_caps;
+	efi.get_next_high_mono_count = runtime->get_next_high_mono_count;
+	efi.reset_system = runtime->reset_system;
+
+	set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
+
+	return 0;
+}
+early_initcall(arm64_enter_virtual_mode);
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 720853f..0a14aaf 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -41,6 +41,7 @@
 #include <linux/memblock.h>
 #include <linux/of_fdt.h>
 #include <linux/of_platform.h>
+#include <linux/efi.h>
 
 #include <asm/fixmap.h>
 #include <asm/cputype.h>
@@ -55,6 +56,7 @@
 #include <asm/traps.h>
 #include <asm/memblock.h>
 #include <asm/psci.h>
+#include <asm/efi.h>
 
 unsigned int processor_id;
 EXPORT_SYMBOL(processor_id);
@@ -366,11 +368,14 @@ void __init setup_arch(char **cmdline_p)
 
 	parse_early_param();
 
+	efi_init();
 	arm64_memblock_init();
 
 	paging_init();
 	request_standard_resources();
 
+	efi_idmap_init();
+
 	unflatten_device_tree();
 
 	psci_init();
-- 
1.7.10.4


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

* [PATCH v3 08/10] arm64: add EFI runtime services
@ 2014-04-04 18:45   ` Leif Lindholm
  0 siblings, 0 replies; 55+ messages in thread
From: Leif Lindholm @ 2014-04-04 18:45 UTC (permalink / raw)
  To: linux-arm-kernel

From: Mark Salter <msalter@redhat.com>

This patch adds EFI runtime support for arm64. The runtime support allows
the kernel to access various EFI runtime services provided by EFI firmware.
Things like reboot, real time clock, EFI boot variables, and others.

Signed-off-by: Mark Salter <msalter@redhat.com>
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
---
 arch/arm64/Kconfig           |    7 +
 arch/arm64/include/asm/efi.h |   14 ++
 arch/arm64/kernel/Makefile   |    2 +-
 arch/arm64/kernel/efi.c      |  469 ++++++++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/setup.c    |    5 +
 5 files changed, 496 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/include/asm/efi.h
 create mode 100644 arch/arm64/kernel/efi.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 791ec61..a7ee734 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -284,12 +284,17 @@ config EFI
 	bool "UEFI firmware support"
 	depends on OF
 	select LIBFDT
+	select UCS2_STRING
+	select UEFI_PARAMS_FROM_FDT
 	default y
 	help
 	  This option permits an Image to be loaded directly
 	  by EFI firmware without the use of a bootloader.
 	  See Documentation/efi-stub.txt for more information.
 
+	  It also enables the kernel to use available UEFI runtime
+	  services (such as the UEFI variable services).
+
 	  This is only useful on systems that have UEFI firmware.
 	  However, even with this option, the resultant kernel should
 	  continue to boot on existing non-UEFI platforms.
@@ -353,6 +358,8 @@ source "net/Kconfig"
 
 source "drivers/Kconfig"
 
+source "drivers/firmware/Kconfig"
+
 source "fs/Kconfig"
 
 source "arch/arm64/kvm/Kconfig"
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
new file mode 100644
index 0000000..5a46c4e
--- /dev/null
+++ b/arch/arm64/include/asm/efi.h
@@ -0,0 +1,14 @@
+#ifndef _ASM_EFI_H
+#define _ASM_EFI_H
+
+#include <asm/io.h>
+
+#ifdef CONFIG_EFI
+extern void efi_init(void);
+extern void efi_idmap_init(void);
+#else
+#define efi_init()
+#define efi_idmap_init()
+#endif
+
+#endif /* _ASM_EFI_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 21009b7..3a2815b 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -24,7 +24,7 @@ arm64-obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND)	+= sleep.o suspend.o
 arm64-obj-$(CONFIG_JUMP_LABEL)		+= jump_label.o
 arm64-obj-$(CONFIG_KGDB)		+= kgdb.o
-arm64-obj-$(CONFIG_EFI)			+= efi-stub.o efi-entry.o
+arm64-obj-$(CONFIG_EFI)			+= efi-stub.o efi-entry.o efi.o
 
 obj-y					+= $(arm64-obj-y) vdso/
 obj-m					+= $(arm64-obj-m)
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
new file mode 100644
index 0000000..45f4784
--- /dev/null
+++ b/arch/arm64/kernel/efi.c
@@ -0,0 +1,469 @@
+/*
+ * Extensible Firmware Interface
+ *
+ * Based on Extensible Firmware Interface Specification version 2.4
+ *
+ * Copyright (C) 2013, 2014 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/efi.h>
+#include <linux/export.h>
+#include <linux/memblock.h>
+#include <linux/bootmem.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include <asm/cacheflush.h>
+#include <asm/efi.h>
+#include <asm/tlbflush.h>
+#include <asm/mmu_context.h>
+
+struct efi_memory_map memmap;
+
+static efi_runtime_services_t *runtime;
+
+static u64 efi_system_table;
+
+static int uefi_debug __initdata;
+static int __init uefi_debug_setup(char *str)
+{
+	uefi_debug = 1;
+
+	return 0;
+}
+early_param("uefi_debug", uefi_debug_setup);
+
+static int __init is_normal_ram(efi_memory_desc_t *md)
+{
+	if (md->attribute & EFI_MEMORY_WB)
+		return 1;
+	return 0;
+}
+
+static void __init efi_setup_idmap(void)
+{
+	struct memblock_region *r;
+	efi_memory_desc_t *md;
+	u64 paddr, npages, size;
+
+	for_each_memblock(memory, r)
+		create_id_mapping(r->base, r->size, 0);
+
+	/* map runtime io spaces */
+	for_each_efi_memory_desc(&memmap, md) {
+		if (!(md->attribute & EFI_MEMORY_RUNTIME) || is_normal_ram(md))
+			continue;
+		paddr = md->phys_addr;
+		npages = md->num_pages;
+		memrange_efi_to_native(&paddr, &npages);
+		size = npages << PAGE_SHIFT;
+		create_id_mapping(paddr, size, 1);
+	}
+}
+
+static int __init uefi_init(void)
+{
+	efi_char16_t *c16;
+	char vendor[100] = "unknown";
+	int i, retval;
+
+	efi.systab = early_memremap(efi_system_table,
+				    sizeof(efi_system_table_t));
+	if (efi.systab == NULL) {
+		pr_warn("Unable to map EFI system table.\n");
+		return -ENOMEM;
+	}
+
+	set_bit(EFI_BOOT, &efi.flags);
+	set_bit(EFI_64BIT, &efi.flags);
+
+	/*
+	 * Verify the EFI Table
+	 */
+	if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) {
+		pr_err("System table signature incorrect\n");
+		return -EINVAL;
+	}
+	if ((efi.systab->hdr.revision >> 16) < 2)
+		pr_warn("Warning: EFI system table version %d.%02d, expected 2.00 or greater\n",
+			efi.systab->hdr.revision >> 16,
+			efi.systab->hdr.revision & 0xffff);
+
+	/* Show what we know for posterity */
+	c16 = early_memremap(efi.systab->fw_vendor,
+			     sizeof(vendor));
+	if (c16) {
+		for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
+			vendor[i] = c16[i];
+		vendor[i] = '\0';
+	}
+
+	pr_info("EFI v%u.%.02u by %s\n",
+		efi.systab->hdr.revision >> 16,
+		efi.systab->hdr.revision & 0xffff, vendor);
+
+	retval = efi_config_init(NULL);
+	if (retval == 0)
+		set_bit(EFI_CONFIG_TABLES, &efi.flags);
+
+	early_memunmap(c16, sizeof(vendor));
+	early_memunmap(efi.systab,  sizeof(efi_system_table_t));
+
+	return retval;
+}
+
+static __initdata char memory_type_name[][32] = {
+	{"Reserved"},
+	{"Loader Code"},
+	{"Loader Data"},
+	{"Boot Code"},
+	{"Boot Data"},
+	{"Runtime Code"},
+	{"Runtime Data"},
+	{"Conventional Memory"},
+	{"Unusable Memory"},
+	{"ACPI Reclaim Memory"},
+	{"ACPI Memory NVS"},
+	{"Memory Mapped I/O"},
+	{"MMIO Port Space"},
+	{"PAL Code"},
+};
+
+/*
+ * Return true for RAM regions we want to permanently reserve.
+ */
+static __init int is_reserve_region(efi_memory_desc_t *md)
+{
+	if (!is_normal_ram(md))
+		return 0;
+
+	if (md->attribute & EFI_MEMORY_RUNTIME)
+		return 1;
+
+	if (md->type == EFI_ACPI_RECLAIM_MEMORY ||
+	    md->type == EFI_RESERVED_TYPE)
+		return 1;
+
+	return 0;
+}
+
+static __init void reserve_regions(void)
+{
+	efi_memory_desc_t *md;
+	u64 paddr, npages, size;
+
+	if (uefi_debug)
+		pr_info("Processing EFI memory map:\n");
+
+	for_each_efi_memory_desc(&memmap, md) {
+		paddr = md->phys_addr;
+		npages = md->num_pages;
+
+		if (uefi_debug)
+			pr_info("  0x%012llx-0x%012llx [%s]",
+				paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
+				memory_type_name[md->type]);
+
+		memrange_efi_to_native(&paddr, &npages);
+		size = npages << PAGE_SHIFT;
+
+		if (is_normal_ram(md))
+			early_init_dt_add_memory_arch(paddr, size);
+
+		if (is_reserve_region(md) ||
+		    md->type == EFI_BOOT_SERVICES_CODE ||
+		    md->type == EFI_BOOT_SERVICES_DATA) {
+			memblock_reserve(paddr, size);
+			if (uefi_debug)
+				pr_cont("*");
+		}
+
+		if (uefi_debug)
+			pr_cont("\n");
+	}
+}
+
+
+static u64 __init free_one_region(u64 start, u64 end)
+{
+	u64 size = end - start;
+
+	if (uefi_debug)
+		pr_info("  EFI freeing: 0x%012llx-0x%012llx\n",	start, end - 1);
+
+	free_bootmem_late(start, size);
+	return size;
+}
+
+static u64 __init free_region(u64 start, u64 end)
+{
+	u64 map_start, map_end, total = 0;
+
+	if (end <= start)
+		return total;
+
+	map_start = (u64)memmap.phys_map;
+	map_end = PAGE_ALIGN(map_start + (memmap.map_end - memmap.map));
+	map_start &= PAGE_MASK;
+
+	if (start < map_end && end > map_start) {
+		/* region overlaps UEFI memmap */
+		if (start < map_start)
+			total += free_one_region(start, map_start);
+
+		if (map_end < end)
+			total += free_one_region(map_end, end);
+	} else
+		total += free_one_region(start, end);
+
+	return total;
+}
+
+static void __init free_boot_services(void)
+{
+	u64 total_freed = 0;
+	u64 keep_end, free_start, free_end;
+	efi_memory_desc_t *md;
+
+	/*
+	 * If kernel uses larger pages than UEFI, we have to be careful
+	 * not to inadvertantly free memory we want to keep if there is
+	 * overlap@the kernel page size alignment. We do not want to
+	 * free is_reserve_region() memory nor the UEFI memmap itself.
+	 *
+	 * The memory map is sorted, so we keep track of the end of
+	 * any previous region we want to keep, remember any region
+	 * we want to free and defer freeing it until we encounter
+	 * the next region we want to keep. This way, before freeing
+	 * it, we can clip it as needed to avoid freeing memory we
+	 * want to keep for UEFI.
+	 */
+
+	keep_end = 0;
+	free_start = 0;
+
+	for_each_efi_memory_desc(&memmap, md) {
+		u64 paddr, npages, size;
+
+		if (is_reserve_region(md)) {
+			/*
+			 * We don't want to free any memory from this region.
+			 */
+			if (free_start) {
+				/* adjust free_end then free region */
+				if (free_end > md->phys_addr)
+					free_end -= PAGE_SIZE;
+				total_freed += free_region(free_start, free_end);
+				free_start = 0;
+			}
+			keep_end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
+			continue;
+		}
+
+		if (md->type != EFI_BOOT_SERVICES_CODE &&
+		    md->type != EFI_BOOT_SERVICES_DATA) {
+			/* no need to free this region */
+			continue;
+		}
+
+		/*
+		 * We want to free memory from this region.
+		 */
+		paddr = md->phys_addr;
+		npages = md->num_pages;
+		memrange_efi_to_native(&paddr, &npages);
+		size = npages << PAGE_SHIFT;
+
+		if (free_start) {
+			if (paddr <= free_end)
+				free_end = paddr + size;
+			else {
+				total_freed += free_region(free_start, free_end);
+				free_start = paddr;
+				free_end = paddr + size;
+			}
+		} else {
+			free_start = paddr;
+			free_end = paddr + size;
+		}
+		if (free_start < keep_end) {
+			free_start += PAGE_SIZE;
+			if (free_start >= free_end)
+				free_start = 0;
+		}
+	}
+	if (free_start)
+		total_freed += free_region(free_start, free_end);
+
+	if (total_freed)
+		pr_info("Freed 0x%llx bytes of EFI boot services memory",
+			total_freed);
+}
+
+void __init efi_init(void)
+{
+	struct efi_fdt_params params;
+
+	/* Grab UEFI information placed in FDT by stub */
+	if (!efi_get_fdt_params(&params, uefi_debug))
+		return;
+
+	efi_system_table = params.system_table;
+
+	memblock_reserve(params.mmap & PAGE_MASK,
+			 PAGE_ALIGN(params.mmap_size + (params.mmap & ~PAGE_MASK)));
+	memmap.phys_map = (void *)params.mmap;
+	memmap.map = early_memremap(params.mmap, params.mmap_size);
+	memmap.map_end = memmap.map + params.mmap_size;
+	memmap.desc_size = params.desc_size;
+	memmap.desc_version = params.desc_ver;
+
+	if (uefi_init() < 0)
+		return;
+
+	reserve_regions();
+}
+
+void __init efi_idmap_init(void)
+{
+	/* boot time idmap_pg_dir is incomplete, so fill in missing parts */
+	efi_setup_idmap();
+}
+
+static int __init remap_region(efi_memory_desc_t *md, void **new)
+{
+	u64 paddr, vaddr, npages, size;
+
+	paddr = md->phys_addr;
+	npages = md->num_pages;
+	memrange_efi_to_native(&paddr, &npages);
+	size = npages << PAGE_SHIFT;
+
+	if (is_normal_ram(md))
+		vaddr = (__force u64)ioremap_cache(paddr, size);
+	else
+		vaddr = (__force u64)ioremap(paddr, size);
+
+	if (!vaddr) {
+		pr_err("Unable to remap 0x%llx pages @ %p\n",
+		       npages, (void *)paddr);
+		return 0;
+	}
+
+	/* adjust for any rounding when EFI and system pagesize differs */
+	md->virt_addr = vaddr + (md->phys_addr - paddr);
+
+	if (uefi_debug)
+		pr_info("  EFI remap 0x%012llx => %p\n",
+			md->phys_addr, (void *)md->virt_addr);
+
+	memcpy(*new, md, memmap.desc_size);
+	*new += memmap.desc_size;
+
+	return 1;
+}
+
+/*
+ * Switch UEFI from an identity map to a kernel virtual map
+ */
+static int __init arm64_enter_virtual_mode(void)
+{
+	efi_memory_desc_t *md;
+	phys_addr_t virtmap_phys;
+	void *virtmap, *virt_md;
+	efi_status_t status;
+	u64 mapsize;
+	int count = 0;
+	unsigned long flags;
+
+	if (!efi_enabled(EFI_BOOT)) {
+		pr_info("EFI services will not be available.\n");
+		return -1;
+	}
+
+	pr_info("Remapping and enabling EFI services.\n");
+
+	/* replace early memmap mapping with permanent mapping */
+	mapsize = memmap.map_end - memmap.map;
+	early_memunmap(memmap.map, mapsize);
+	memmap.map = (__force void *)ioremap_cache((phys_addr_t)memmap.phys_map,
+						   mapsize);
+	memmap.map_end = memmap.map + mapsize;
+
+	efi.memmap = &memmap;
+
+	/* Map the runtime regions */
+	virtmap = kmalloc(mapsize, GFP_KERNEL);
+	if (!virtmap) {
+		pr_err("Failed to allocate EFI virtual memmap\n");
+		return -1;
+	}
+	virtmap_phys = virt_to_phys(virtmap);
+	virt_md = virtmap;
+
+	for_each_efi_memory_desc(&memmap, md) {
+		if (!(md->attribute & EFI_MEMORY_RUNTIME))
+			continue;
+		if (remap_region(md, &virt_md))
+			++count;
+	}
+
+	efi.systab = (__force void *)efi_lookup_mapped_addr(efi_system_table);
+	if (efi.systab)
+		set_bit(EFI_SYSTEM_TABLES, &efi.flags);
+
+	local_irq_save(flags);
+	cpu_switch_mm(idmap_pg_dir, &init_mm);
+	flush_tlb_all();
+	flush_cache_all();
+
+	/* Call SetVirtualAddressMap with the physical address of the map */
+	runtime = efi.systab->runtime;
+	efi.set_virtual_address_map = runtime->set_virtual_address_map;
+
+	status = efi.set_virtual_address_map(count * memmap.desc_size,
+					     memmap.desc_size,
+					     memmap.desc_version,
+					     (efi_memory_desc_t *)virtmap_phys);
+	cpu_set_reserved_ttbr0();
+	flush_tlb_all();
+	flush_cache_all();
+	local_irq_restore(flags);
+
+	kfree(virtmap);
+
+	free_boot_services();
+
+	if (status != EFI_SUCCESS) {
+		pr_err("Failed to set EFI virtual address map! [%lx]\n",
+			status);
+		return -1;
+	}
+
+	/* Set up runtime services function pointers */
+	runtime = efi.systab->runtime;
+	efi.get_time = runtime->get_time;
+	efi.set_time = runtime->set_time;
+	efi.get_wakeup_time = runtime->get_wakeup_time;
+	efi.set_wakeup_time = runtime->set_wakeup_time;
+	efi.get_variable = runtime->get_variable;
+	efi.get_next_variable = runtime->get_next_variable;
+	efi.set_variable = runtime->set_variable;
+	efi.query_variable_info = runtime->query_variable_info;
+	efi.update_capsule = runtime->update_capsule;
+	efi.query_capsule_caps = runtime->query_capsule_caps;
+	efi.get_next_high_mono_count = runtime->get_next_high_mono_count;
+	efi.reset_system = runtime->reset_system;
+
+	set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
+
+	return 0;
+}
+early_initcall(arm64_enter_virtual_mode);
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 720853f..0a14aaf 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -41,6 +41,7 @@
 #include <linux/memblock.h>
 #include <linux/of_fdt.h>
 #include <linux/of_platform.h>
+#include <linux/efi.h>
 
 #include <asm/fixmap.h>
 #include <asm/cputype.h>
@@ -55,6 +56,7 @@
 #include <asm/traps.h>
 #include <asm/memblock.h>
 #include <asm/psci.h>
+#include <asm/efi.h>
 
 unsigned int processor_id;
 EXPORT_SYMBOL(processor_id);
@@ -366,11 +368,14 @@ void __init setup_arch(char **cmdline_p)
 
 	parse_early_param();
 
+	efi_init();
 	arm64_memblock_init();
 
 	paging_init();
 	request_standard_resources();
 
+	efi_idmap_init();
+
 	unflatten_device_tree();
 
 	psci_init();
-- 
1.7.10.4

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

* [PATCH v3 09/10] doc: arm: add UEFI support documentation
  2014-04-04 18:45 ` Leif Lindholm
@ 2014-04-04 18:45   ` Leif Lindholm
  -1 siblings, 0 replies; 55+ messages in thread
From: Leif Lindholm @ 2014-04-04 18:45 UTC (permalink / raw)
  To: linux-arm-kernel, linux-efi
  Cc: linux-kernel, Leif Lindholm, Rob Landley, linux-doc

This patch provides documentation of the [U]EFI runtime service and
configuration features for the arm architecture.

Cc: Rob Landley <rob@landley.net>
Cc: linux-doc@vger.kernel.org

Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Acked-by: Grant Likely <grant.likely@linaro.org>
---
 Documentation/arm/00-INDEX |    2 ++
 Documentation/arm/uefi.txt |   64 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 66 insertions(+)
 create mode 100644 Documentation/arm/uefi.txt

diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX
index a94090c..3b08bc2 100644
--- a/Documentation/arm/00-INDEX
+++ b/Documentation/arm/00-INDEX
@@ -46,5 +46,7 @@ swp_emulation
 	- SWP/SWPB emulation handler/logging description
 tcm.txt
 	- ARM Tightly Coupled Memory
+uefi.txt
+	- [U]EFI configuration and runtime services documentation
 vlocks.txt
 	- Voting locks, low-level mechanism relying on memory system atomic writes.
diff --git a/Documentation/arm/uefi.txt b/Documentation/arm/uefi.txt
new file mode 100644
index 0000000..d60030a
--- /dev/null
+++ b/Documentation/arm/uefi.txt
@@ -0,0 +1,64 @@
+UEFI, the Unified Extensible Firmware Interface, is a specification
+governing the behaviours of compatible firmware interfaces. It is
+maintained by the UEFI Forum - http://www.uefi.org/.
+
+UEFI is an evolution of its predecessor 'EFI', so the terms EFI and
+UEFI are used somewhat interchangeably in this document and associated
+source code. As a rule, anything new uses 'UEFI', whereas 'EFI' refers
+to legacy code or specifications.
+
+UEFI support in Linux
+=====================
+Booting on a platform with firmware compliant with the UEFI specification
+makes it possible for the kernel to support additional features:
+- UEFI Runtime Services
+- Retrieving various configuration information through the standardised
+  interface of UEFI configuration tables. (ACPI, SMBIOS, ...)
+
+For actually enabling [U]EFI support, enable:
+- CONFIG_EFI=y
+- CONFIG_EFI_VARS=y or m
+
+The implementation depends on receiving information about the UEFI environment
+in a Flattened Device Tree (FDT) - so is only available with CONFIG_OF.
+
+UEFI stub
+=========
+The "stub" is a feature that extends the Image/zImage into a valid UEFI
+PE/COFF executable, including a loader application that makes it possible to
+load the kernel directly from the UEFI shell, boot menu, or one of the
+lightweight bootloaders like Gummiboot or rEFInd.
+
+The kernel image built with stub support remains a valid kernel image for
+booting in non-UEFI environments.
+
+UEFI kernel support on ARM
+==========================
+UEFI kernel support on the ARM architectures (arm and arm64) is only available
+when boot is performed through the stub.
+
+When booting in UEFI mode, the stub deletes any memory nodes from a provided DT.
+Instead, the kernel reads the UEFI memory map.
+
+The stub populates the FDT /chosen node with (and the kernel scans for) the
+following parameters:
+________________________________________________________________________________
+Name                      | Size   | Description
+================================================================================
+linux,uefi-system-table   | 64-bit | Physical address of the UEFI System Table.
+--------------------------------------------------------------------------------
+linux,uefi-mmap-start     | 64-bit | Physical address of the UEFI memory map,
+                          |        | populated by the UEFI GetMemoryMap() call.
+--------------------------------------------------------------------------------
+linux,uefi-mmap-size      | 32-bit | Size in bytes of the UEFI memory map
+                          |        | pointed to in previous entry.
+--------------------------------------------------------------------------------
+linux,uefi-mmap-desc-size | 32-bit | Size in bytes of each entry in the UEFI
+                          |        | memory map.
+--------------------------------------------------------------------------------
+linux,uefi-mmap-desc-ver  | 32-bit | Version of the mmap descriptor format.
+--------------------------------------------------------------------------------
+linux,uefi-stub-kern-ver  | string | Copy of linux_banner from build.
+--------------------------------------------------------------------------------
+
+For verbose debug messages, specify 'uefi_debug' on the kernel command line.
-- 
1.7.10.4


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

* [PATCH v3 09/10] doc: arm: add UEFI support documentation
@ 2014-04-04 18:45   ` Leif Lindholm
  0 siblings, 0 replies; 55+ messages in thread
From: Leif Lindholm @ 2014-04-04 18:45 UTC (permalink / raw)
  To: linux-arm-kernel

This patch provides documentation of the [U]EFI runtime service and
configuration features for the arm architecture.

Cc: Rob Landley <rob@landley.net>
Cc: linux-doc at vger.kernel.org

Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Acked-by: Grant Likely <grant.likely@linaro.org>
---
 Documentation/arm/00-INDEX |    2 ++
 Documentation/arm/uefi.txt |   64 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 66 insertions(+)
 create mode 100644 Documentation/arm/uefi.txt

diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX
index a94090c..3b08bc2 100644
--- a/Documentation/arm/00-INDEX
+++ b/Documentation/arm/00-INDEX
@@ -46,5 +46,7 @@ swp_emulation
 	- SWP/SWPB emulation handler/logging description
 tcm.txt
 	- ARM Tightly Coupled Memory
+uefi.txt
+	- [U]EFI configuration and runtime services documentation
 vlocks.txt
 	- Voting locks, low-level mechanism relying on memory system atomic writes.
diff --git a/Documentation/arm/uefi.txt b/Documentation/arm/uefi.txt
new file mode 100644
index 0000000..d60030a
--- /dev/null
+++ b/Documentation/arm/uefi.txt
@@ -0,0 +1,64 @@
+UEFI, the Unified Extensible Firmware Interface, is a specification
+governing the behaviours of compatible firmware interfaces. It is
+maintained by the UEFI Forum - http://www.uefi.org/.
+
+UEFI is an evolution of its predecessor 'EFI', so the terms EFI and
+UEFI are used somewhat interchangeably in this document and associated
+source code. As a rule, anything new uses 'UEFI', whereas 'EFI' refers
+to legacy code or specifications.
+
+UEFI support in Linux
+=====================
+Booting on a platform with firmware compliant with the UEFI specification
+makes it possible for the kernel to support additional features:
+- UEFI Runtime Services
+- Retrieving various configuration information through the standardised
+  interface of UEFI configuration tables. (ACPI, SMBIOS, ...)
+
+For actually enabling [U]EFI support, enable:
+- CONFIG_EFI=y
+- CONFIG_EFI_VARS=y or m
+
+The implementation depends on receiving information about the UEFI environment
+in a Flattened Device Tree (FDT) - so is only available with CONFIG_OF.
+
+UEFI stub
+=========
+The "stub" is a feature that extends the Image/zImage into a valid UEFI
+PE/COFF executable, including a loader application that makes it possible to
+load the kernel directly from the UEFI shell, boot menu, or one of the
+lightweight bootloaders like Gummiboot or rEFInd.
+
+The kernel image built with stub support remains a valid kernel image for
+booting in non-UEFI environments.
+
+UEFI kernel support on ARM
+==========================
+UEFI kernel support on the ARM architectures (arm and arm64) is only available
+when boot is performed through the stub.
+
+When booting in UEFI mode, the stub deletes any memory nodes from a provided DT.
+Instead, the kernel reads the UEFI memory map.
+
+The stub populates the FDT /chosen node with (and the kernel scans for) the
+following parameters:
+________________________________________________________________________________
+Name                      | Size   | Description
+================================================================================
+linux,uefi-system-table   | 64-bit | Physical address of the UEFI System Table.
+--------------------------------------------------------------------------------
+linux,uefi-mmap-start     | 64-bit | Physical address of the UEFI memory map,
+                          |        | populated by the UEFI GetMemoryMap() call.
+--------------------------------------------------------------------------------
+linux,uefi-mmap-size      | 32-bit | Size in bytes of the UEFI memory map
+                          |        | pointed to in previous entry.
+--------------------------------------------------------------------------------
+linux,uefi-mmap-desc-size | 32-bit | Size in bytes of each entry in the UEFI
+                          |        | memory map.
+--------------------------------------------------------------------------------
+linux,uefi-mmap-desc-ver  | 32-bit | Version of the mmap descriptor format.
+--------------------------------------------------------------------------------
+linux,uefi-stub-kern-ver  | string | Copy of linux_banner from build.
+--------------------------------------------------------------------------------
+
+For verbose debug messages, specify 'uefi_debug' on the kernel command line.
-- 
1.7.10.4

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

* [PATCH v3 10/10] efi/arm64: ignore dtb= when UEFI SecureBoot is enabled
  2014-04-04 18:45 ` Leif Lindholm
@ 2014-04-04 18:45   ` Leif Lindholm
  -1 siblings, 0 replies; 55+ messages in thread
From: Leif Lindholm @ 2014-04-04 18:45 UTC (permalink / raw)
  To: linux-arm-kernel, linux-efi
  Cc: linux-kernel, Ard Biesheuvel, Leif Lindholm, Catalin Marinas,
	Matt Fleming

From: Ard Biesheuvel <ard.biesheuvel@linaro.org>

Loading unauthenticated FDT blobs directly from storage is a security hazard,
so this should only be allowed when running with UEFI Secure Boot disabled.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Matt Fleming <matt.fleming@intel.com>
---
 drivers/firmware/efi/arm-stub.c        |   15 +++++++++++----
 drivers/firmware/efi/efi-stub-helper.c |   24 ++++++++++++++++++++++++
 2 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/drivers/firmware/efi/arm-stub.c b/drivers/firmware/efi/arm-stub.c
index b9b7c00..c8988b2 100644
--- a/drivers/firmware/efi/arm-stub.c
+++ b/drivers/firmware/efi/arm-stub.c
@@ -145,7 +145,7 @@ unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table,
 	/* addr/point and size pairs for memory management*/
 	unsigned long initrd_addr;
 	u64 initrd_size = 0;
-	unsigned long fdt_addr;  /* Original DTB */
+	unsigned long fdt_addr = 0;  /* Original DTB */
 	u64 fdt_size = 0;  /* We don't get size from configuration table */
 	char *cmdline_ptr = NULL;
 	int cmdline_size = 0;
@@ -197,9 +197,13 @@ unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table,
 		goto fail_free_image;
 	}
 
-	/* Load a device tree from the configuration table, if present. */
-	fdt_addr = (uintptr_t)get_fdt(sys_table);
-	if (!fdt_addr) {
+	/*
+	 * Unauthenticated device tree data is a security hazard, so
+	 * ignore 'dtb=' unless UEFI Secure Boot is disabled.
+	 */
+	if (efi_secureboot_enabled(sys_table)) {
+		pr_efi(sys_table, "UEFI Secure Boot is enabled.\n");
+	} else {
 		status = handle_cmdline_files(sys_table, image, cmdline_ptr,
 					      "dtb=",
 					      ~0UL, (unsigned long *)&fdt_addr,
@@ -210,6 +214,9 @@ unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table,
 			goto fail_free_cmdline;
 		}
 	}
+	if (!fdt_addr)
+		/* Look for a device tree configuration table entry. */
+		fdt_addr = (uintptr_t)get_fdt(sys_table);
 
 	status = handle_cmdline_files(sys_table, image, cmdline_ptr,
 				      "initrd=", dram_base + SZ_512M,
diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/efi-stub-helper.c
index 998b884..8f8b538 100644
--- a/drivers/firmware/efi/efi-stub-helper.c
+++ b/drivers/firmware/efi/efi-stub-helper.c
@@ -632,3 +632,27 @@ static char *efi_convert_cmdline(efi_system_table_t *sys_table_arg,
 	*cmd_line_len = options_bytes;
 	return (char *)cmdline_addr;
 }
+
+static int __init efi_secureboot_enabled(efi_system_table_t *sys_table_arg)
+{
+	static efi_guid_t const var_guid __initconst = EFI_GLOBAL_VARIABLE_GUID;
+	static efi_char16_t const var_name[] __initconst = {
+		'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 };
+
+	efi_get_variable_t *f_getvar = sys_table_arg->runtime->get_variable;
+	unsigned long size = sizeof(u8);
+	efi_status_t status;
+	u8 val;
+
+	status = efi_call_phys5(f_getvar, (efi_char16_t *)var_name,
+				(efi_guid_t *)&var_guid, NULL, &size, &val);
+
+	switch (status) {
+	case EFI_SUCCESS:
+		return val;
+	case EFI_NOT_FOUND:
+		return 0;
+	default:
+		return 1;
+	}
+}
-- 
1.7.10.4


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

* [PATCH v3 10/10] efi/arm64: ignore dtb= when UEFI SecureBoot is enabled
@ 2014-04-04 18:45   ` Leif Lindholm
  0 siblings, 0 replies; 55+ messages in thread
From: Leif Lindholm @ 2014-04-04 18:45 UTC (permalink / raw)
  To: linux-arm-kernel

From: Ard Biesheuvel <ard.biesheuvel@linaro.org>

Loading unauthenticated FDT blobs directly from storage is a security hazard,
so this should only be allowed when running with UEFI Secure Boot disabled.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Matt Fleming <matt.fleming@intel.com>
---
 drivers/firmware/efi/arm-stub.c        |   15 +++++++++++----
 drivers/firmware/efi/efi-stub-helper.c |   24 ++++++++++++++++++++++++
 2 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/drivers/firmware/efi/arm-stub.c b/drivers/firmware/efi/arm-stub.c
index b9b7c00..c8988b2 100644
--- a/drivers/firmware/efi/arm-stub.c
+++ b/drivers/firmware/efi/arm-stub.c
@@ -145,7 +145,7 @@ unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table,
 	/* addr/point and size pairs for memory management*/
 	unsigned long initrd_addr;
 	u64 initrd_size = 0;
-	unsigned long fdt_addr;  /* Original DTB */
+	unsigned long fdt_addr = 0;  /* Original DTB */
 	u64 fdt_size = 0;  /* We don't get size from configuration table */
 	char *cmdline_ptr = NULL;
 	int cmdline_size = 0;
@@ -197,9 +197,13 @@ unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table,
 		goto fail_free_image;
 	}
 
-	/* Load a device tree from the configuration table, if present. */
-	fdt_addr = (uintptr_t)get_fdt(sys_table);
-	if (!fdt_addr) {
+	/*
+	 * Unauthenticated device tree data is a security hazard, so
+	 * ignore 'dtb=' unless UEFI Secure Boot is disabled.
+	 */
+	if (efi_secureboot_enabled(sys_table)) {
+		pr_efi(sys_table, "UEFI Secure Boot is enabled.\n");
+	} else {
 		status = handle_cmdline_files(sys_table, image, cmdline_ptr,
 					      "dtb=",
 					      ~0UL, (unsigned long *)&fdt_addr,
@@ -210,6 +214,9 @@ unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table,
 			goto fail_free_cmdline;
 		}
 	}
+	if (!fdt_addr)
+		/* Look for a device tree configuration table entry. */
+		fdt_addr = (uintptr_t)get_fdt(sys_table);
 
 	status = handle_cmdline_files(sys_table, image, cmdline_ptr,
 				      "initrd=", dram_base + SZ_512M,
diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/efi-stub-helper.c
index 998b884..8f8b538 100644
--- a/drivers/firmware/efi/efi-stub-helper.c
+++ b/drivers/firmware/efi/efi-stub-helper.c
@@ -632,3 +632,27 @@ static char *efi_convert_cmdline(efi_system_table_t *sys_table_arg,
 	*cmd_line_len = options_bytes;
 	return (char *)cmdline_addr;
 }
+
+static int __init efi_secureboot_enabled(efi_system_table_t *sys_table_arg)
+{
+	static efi_guid_t const var_guid __initconst = EFI_GLOBAL_VARIABLE_GUID;
+	static efi_char16_t const var_name[] __initconst = {
+		'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 };
+
+	efi_get_variable_t *f_getvar = sys_table_arg->runtime->get_variable;
+	unsigned long size = sizeof(u8);
+	efi_status_t status;
+	u8 val;
+
+	status = efi_call_phys5(f_getvar, (efi_char16_t *)var_name,
+				(efi_guid_t *)&var_guid, NULL, &size, &val);
+
+	switch (status) {
+	case EFI_SUCCESS:
+		return val;
+	case EFI_NOT_FOUND:
+		return 0;
+	default:
+		return 1;
+	}
+}
-- 
1.7.10.4

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

* Re: [PATCH v3 06/10] arm64: efi: add EFI stub
  2014-04-04 18:45   ` Leif Lindholm
  (?)
@ 2014-04-09 14:20     ` Mark Rutland
  -1 siblings, 0 replies; 55+ messages in thread
From: Mark Rutland @ 2014-04-09 14:20 UTC (permalink / raw)
  To: Leif Lindholm
  Cc: linux-arm-kernel, linux-efi, linux-kernel, msalter,
	Ard Biesheuvel, Catalin Marinas, Matt Fleming

Hi Leif,

On Fri, Apr 04, 2014 at 07:45:09PM +0100, Leif Lindholm wrote:
> From: Mark Salter <msalter@redhat.com>
>
> This patch adds PE/COFF header fields to the start of the Image
> so that it appears as an EFI application to EFI firmware. An EFI
> stub is included to allow direct booting of the kernel Image.
> Support in the COFF header for signed images was provided by
> Ard Biesheuvel.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Signed-off-by: Mark Salter <msalter@redhat.com>
> Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Matt Fleming <matt.fleming@intel.com>
> ---
>  arch/arm64/Kconfig              |   14 +++
>  arch/arm64/kernel/Makefile      |    3 +
>  arch/arm64/kernel/efi-entry.S   |  100 ++++++++++++++++
>  arch/arm64/kernel/efi-stub.c    |   97 +++++++++++++++
>  arch/arm64/kernel/head.S        |  112 ++++++++++++++++++
>  drivers/firmware/efi/arm-stub.c |  248 +++++++++++++++++++++++++++++++++++++++
>  6 files changed, 574 insertions(+)
>  create mode 100644 arch/arm64/kernel/efi-entry.S
>  create mode 100644 arch/arm64/kernel/efi-stub.c
>  create mode 100644 drivers/firmware/efi/arm-stub.c
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index d9f23ad..791ec61 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -280,6 +280,20 @@ config CMDLINE_FORCE
>           This is useful if you cannot or don't want to change the
>           command-line options your boot loader passes to the kernel.
>
> +config EFI
> +       bool "UEFI firmware support"
> +       depends on OF

I note we're not depending on !CPU_BIG_ENDIAN here, and it looks like
the implementation is not endian-clean (I've pointed out a few issues
below).

We need to fix that up for CPU_BIG_ENDIAN. For the moment we could
depend on !CPU_BIG_ENDIAN which would at least to make it clear we don't
support EFI && CPU_BIG_ENDIAN yet. The commit message should be updated
to mention that.

[...]

> diff --git a/arch/arm64/kernel/efi-entry.S b/arch/arm64/kernel/efi-entry.S
> new file mode 100644
> index 0000000..d99a034e
> --- /dev/null
> +++ b/arch/arm64/kernel/efi-entry.S
> @@ -0,0 +1,100 @@
> +/*
> + * EFI entry point.
> + *
> + * Copyright (C) 2013, 2014 Red Hat, Inc.
> + * Author: Mark Salter <msalter@redhat.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + */
> +#include <linux/linkage.h>
> +#include <linux/init.h>
> +
> +#include <asm/assembler.h>
> +
> +#define EFI_LOAD_ERROR 0x8000000000000001
> +
> +       __INIT
> +
> +       /*
> +        * We arrive here from the EFI boot manager with:
> +        *
> +        *    * MMU on with identity-mapped RAM.
> +        *    * Icache and Dcache on

I assume we always enter with the CPU in little-endian mode? It would be
nice to note that here if so, or otherwise if not

> +        *
> +        * We will most likely be running from some place other than where
> +        * we want to be. The kernel image wants to be placed at TEXT_OFFSET
> +        * from start of RAM.
> +        */
> +ENTRY(efi_stub_entry)
> +       stp     x29, x30, [sp, #-32]!

A comment as to what the additional space is for would be nice. It seems
to be the relocated kernel address and padding for the required
alignment?

[...]

> +/*
> + * AArch64 requires the DTB to be 8-byte aligned in the first 512MiB from
> + * start of kernel and may not cross a 2MiB boundary. We set alignment to
> + * 2MiB so we know it won't cross a 2MiB boundary.
> + */

Nit: the booting documentation is poor here, but the actual requirement
is slightly different than that described. We currently need the DTB to
be within the same naturally-aligned 512 MiB region as the kernel,
though that restriction could be lifted with some rework of the initial
page tables.

[...]

>From here on in, all comments are regarding endianness issues and how we
can fix them. If you do not care about BE, stop reading here. ;)

> diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
> index 1fe5d8d..2aee658 100644
> --- a/arch/arm64/kernel/head.S
> +++ b/arch/arm64/kernel/head.S
> @@ -107,8 +107,18 @@
>         /*
>          * DO NOT MODIFY. Image header expected by Linux boot-loaders.
>          */
> +#ifdef CONFIG_EFI
> +       /*
> +        * Magic "MZ" signature for PE/COFF
> +        * Little Endian:  add x13, x18, #0x16
> +        */
> +efi_head:
> +       .long   0x91005a4d

As .long will emit the value in native endianness, this will only work
for LE kernels. In BE this will be backwards (which looks to be an
undefined instruction).

> +       b       stext
> +#else
>         b       stext                           // branch to kernel start, magic
>         .long   0                               // reserved
> +#endif
>         .quad   TEXT_OFFSET                     // Image load offset from start of RAM

This also needs to be fixed up endianness wise; I have a series for that
which I'll post shortly.

>         .quad   0                               // reserved
>         .quad   0                               // reserved
> @@ -119,7 +129,109 @@
>         .byte   0x52
>         .byte   0x4d
>         .byte   0x64
> +#ifdef CONFIG_EFI
> +       .long   pe_header - efi_head            // Offset to the PE header.

Likewise this will be backwards. Unfortunately values derived from
calculations involving symbols can't be endian-swapped here due to lack
of a suitable relocation -- we'll have to get the linker to do the
endianness swap for us.

I have a patch enabling the linker to endian-swap such values for us for
64-bit values, but it looks like we'll need other sizes too (for the
shorts below). To prevent vast swathes of symbols appearing in the main
linker script we could have a header to gather those into a
FIXED_ENDIAN_SYMBOLS macro or similar.

> +#else
>         .word   0                               // reserved
> +#endif
> +
> +#ifdef CONFIG_EFI
> +       .align 3
> +pe_header:
> +       .ascii  "PE"
> +       .short  0
> +coff_header:
> +       .short  0xaa64                          // AArch64
> +       .short  2                               // nr_sections
> +       .long   0                               // TimeDateStamp
> +       .long   0                               // PointerToSymbolTable
> +       .long   1                               // NumberOfSymbols

Everything here but the string will be the wrong way around on BE.

We could add .{short,int,long}_le macros to do the endianness swapping
of these values for us (which would also help to document the
endianness).

All other uses of {short,int,long} for non-zero values will need
endianness correction.

> +       .short  section_table - optional_header // SizeOfOptionalHeader

This might need the linker's help to swap unless the assembler resolves
the difference at assemble time.

> +       .long   efi_stub_entry - efi_head       // AddressOfEntryPoint
> +       .long   stext - efi_head                // BaseOfCode

Likewise.

> +       .long   _edata - efi_head               // SizeOfImage

This will definitely require the help of the linker for endianness
swapping.

> +       // Everything before the kernel image is considered part of the header
> +       .long   stext - efi_head                        // SizeOfHeaders

And this.

[...]

> +       .long   _edata - stext          // VirtualSize
> +       .long   stext - efi_head        // VirtualAddress
> +       .long   _edata - stext          // SizeOfRawData
> +       .long   stext - efi_head        // PointerToRawData

And these.

Cheers,
Mark.

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

* Re: [PATCH v3 06/10] arm64: efi: add EFI stub
@ 2014-04-09 14:20     ` Mark Rutland
  0 siblings, 0 replies; 55+ messages in thread
From: Mark Rutland @ 2014-04-09 14:20 UTC (permalink / raw)
  To: Leif Lindholm
  Cc: linux-efi, Ard Biesheuvel, Catalin Marinas, linux-kernel,
	Matt Fleming, msalter, linux-arm-kernel

Hi Leif,

On Fri, Apr 04, 2014 at 07:45:09PM +0100, Leif Lindholm wrote:
> From: Mark Salter <msalter@redhat.com>
>
> This patch adds PE/COFF header fields to the start of the Image
> so that it appears as an EFI application to EFI firmware. An EFI
> stub is included to allow direct booting of the kernel Image.
> Support in the COFF header for signed images was provided by
> Ard Biesheuvel.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Signed-off-by: Mark Salter <msalter@redhat.com>
> Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Matt Fleming <matt.fleming@intel.com>
> ---
>  arch/arm64/Kconfig              |   14 +++
>  arch/arm64/kernel/Makefile      |    3 +
>  arch/arm64/kernel/efi-entry.S   |  100 ++++++++++++++++
>  arch/arm64/kernel/efi-stub.c    |   97 +++++++++++++++
>  arch/arm64/kernel/head.S        |  112 ++++++++++++++++++
>  drivers/firmware/efi/arm-stub.c |  248 +++++++++++++++++++++++++++++++++++++++
>  6 files changed, 574 insertions(+)
>  create mode 100644 arch/arm64/kernel/efi-entry.S
>  create mode 100644 arch/arm64/kernel/efi-stub.c
>  create mode 100644 drivers/firmware/efi/arm-stub.c
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index d9f23ad..791ec61 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -280,6 +280,20 @@ config CMDLINE_FORCE
>           This is useful if you cannot or don't want to change the
>           command-line options your boot loader passes to the kernel.
>
> +config EFI
> +       bool "UEFI firmware support"
> +       depends on OF

I note we're not depending on !CPU_BIG_ENDIAN here, and it looks like
the implementation is not endian-clean (I've pointed out a few issues
below).

We need to fix that up for CPU_BIG_ENDIAN. For the moment we could
depend on !CPU_BIG_ENDIAN which would at least to make it clear we don't
support EFI && CPU_BIG_ENDIAN yet. The commit message should be updated
to mention that.

[...]

> diff --git a/arch/arm64/kernel/efi-entry.S b/arch/arm64/kernel/efi-entry.S
> new file mode 100644
> index 0000000..d99a034e
> --- /dev/null
> +++ b/arch/arm64/kernel/efi-entry.S
> @@ -0,0 +1,100 @@
> +/*
> + * EFI entry point.
> + *
> + * Copyright (C) 2013, 2014 Red Hat, Inc.
> + * Author: Mark Salter <msalter@redhat.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + */
> +#include <linux/linkage.h>
> +#include <linux/init.h>
> +
> +#include <asm/assembler.h>
> +
> +#define EFI_LOAD_ERROR 0x8000000000000001
> +
> +       __INIT
> +
> +       /*
> +        * We arrive here from the EFI boot manager with:
> +        *
> +        *    * MMU on with identity-mapped RAM.
> +        *    * Icache and Dcache on

I assume we always enter with the CPU in little-endian mode? It would be
nice to note that here if so, or otherwise if not

> +        *
> +        * We will most likely be running from some place other than where
> +        * we want to be. The kernel image wants to be placed at TEXT_OFFSET
> +        * from start of RAM.
> +        */
> +ENTRY(efi_stub_entry)
> +       stp     x29, x30, [sp, #-32]!

A comment as to what the additional space is for would be nice. It seems
to be the relocated kernel address and padding for the required
alignment?

[...]

> +/*
> + * AArch64 requires the DTB to be 8-byte aligned in the first 512MiB from
> + * start of kernel and may not cross a 2MiB boundary. We set alignment to
> + * 2MiB so we know it won't cross a 2MiB boundary.
> + */

Nit: the booting documentation is poor here, but the actual requirement
is slightly different than that described. We currently need the DTB to
be within the same naturally-aligned 512 MiB region as the kernel,
though that restriction could be lifted with some rework of the initial
page tables.

[...]

>From here on in, all comments are regarding endianness issues and how we
can fix them. If you do not care about BE, stop reading here. ;)

> diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
> index 1fe5d8d..2aee658 100644
> --- a/arch/arm64/kernel/head.S
> +++ b/arch/arm64/kernel/head.S
> @@ -107,8 +107,18 @@
>         /*
>          * DO NOT MODIFY. Image header expected by Linux boot-loaders.
>          */
> +#ifdef CONFIG_EFI
> +       /*
> +        * Magic "MZ" signature for PE/COFF
> +        * Little Endian:  add x13, x18, #0x16
> +        */
> +efi_head:
> +       .long   0x91005a4d

As .long will emit the value in native endianness, this will only work
for LE kernels. In BE this will be backwards (which looks to be an
undefined instruction).

> +       b       stext
> +#else
>         b       stext                           // branch to kernel start, magic
>         .long   0                               // reserved
> +#endif
>         .quad   TEXT_OFFSET                     // Image load offset from start of RAM

This also needs to be fixed up endianness wise; I have a series for that
which I'll post shortly.

>         .quad   0                               // reserved
>         .quad   0                               // reserved
> @@ -119,7 +129,109 @@
>         .byte   0x52
>         .byte   0x4d
>         .byte   0x64
> +#ifdef CONFIG_EFI
> +       .long   pe_header - efi_head            // Offset to the PE header.

Likewise this will be backwards. Unfortunately values derived from
calculations involving symbols can't be endian-swapped here due to lack
of a suitable relocation -- we'll have to get the linker to do the
endianness swap for us.

I have a patch enabling the linker to endian-swap such values for us for
64-bit values, but it looks like we'll need other sizes too (for the
shorts below). To prevent vast swathes of symbols appearing in the main
linker script we could have a header to gather those into a
FIXED_ENDIAN_SYMBOLS macro or similar.

> +#else
>         .word   0                               // reserved
> +#endif
> +
> +#ifdef CONFIG_EFI
> +       .align 3
> +pe_header:
> +       .ascii  "PE"
> +       .short  0
> +coff_header:
> +       .short  0xaa64                          // AArch64
> +       .short  2                               // nr_sections
> +       .long   0                               // TimeDateStamp
> +       .long   0                               // PointerToSymbolTable
> +       .long   1                               // NumberOfSymbols

Everything here but the string will be the wrong way around on BE.

We could add .{short,int,long}_le macros to do the endianness swapping
of these values for us (which would also help to document the
endianness).

All other uses of {short,int,long} for non-zero values will need
endianness correction.

> +       .short  section_table - optional_header // SizeOfOptionalHeader

This might need the linker's help to swap unless the assembler resolves
the difference at assemble time.

> +       .long   efi_stub_entry - efi_head       // AddressOfEntryPoint
> +       .long   stext - efi_head                // BaseOfCode

Likewise.

> +       .long   _edata - efi_head               // SizeOfImage

This will definitely require the help of the linker for endianness
swapping.

> +       // Everything before the kernel image is considered part of the header
> +       .long   stext - efi_head                        // SizeOfHeaders

And this.

[...]

> +       .long   _edata - stext          // VirtualSize
> +       .long   stext - efi_head        // VirtualAddress
> +       .long   _edata - stext          // SizeOfRawData
> +       .long   stext - efi_head        // PointerToRawData

And these.

Cheers,
Mark.

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

* [PATCH v3 06/10] arm64: efi: add EFI stub
@ 2014-04-09 14:20     ` Mark Rutland
  0 siblings, 0 replies; 55+ messages in thread
From: Mark Rutland @ 2014-04-09 14:20 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Leif,

On Fri, Apr 04, 2014 at 07:45:09PM +0100, Leif Lindholm wrote:
> From: Mark Salter <msalter@redhat.com>
>
> This patch adds PE/COFF header fields to the start of the Image
> so that it appears as an EFI application to EFI firmware. An EFI
> stub is included to allow direct booting of the kernel Image.
> Support in the COFF header for signed images was provided by
> Ard Biesheuvel.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Signed-off-by: Mark Salter <msalter@redhat.com>
> Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Matt Fleming <matt.fleming@intel.com>
> ---
>  arch/arm64/Kconfig              |   14 +++
>  arch/arm64/kernel/Makefile      |    3 +
>  arch/arm64/kernel/efi-entry.S   |  100 ++++++++++++++++
>  arch/arm64/kernel/efi-stub.c    |   97 +++++++++++++++
>  arch/arm64/kernel/head.S        |  112 ++++++++++++++++++
>  drivers/firmware/efi/arm-stub.c |  248 +++++++++++++++++++++++++++++++++++++++
>  6 files changed, 574 insertions(+)
>  create mode 100644 arch/arm64/kernel/efi-entry.S
>  create mode 100644 arch/arm64/kernel/efi-stub.c
>  create mode 100644 drivers/firmware/efi/arm-stub.c
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index d9f23ad..791ec61 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -280,6 +280,20 @@ config CMDLINE_FORCE
>           This is useful if you cannot or don't want to change the
>           command-line options your boot loader passes to the kernel.
>
> +config EFI
> +       bool "UEFI firmware support"
> +       depends on OF

I note we're not depending on !CPU_BIG_ENDIAN here, and it looks like
the implementation is not endian-clean (I've pointed out a few issues
below).

We need to fix that up for CPU_BIG_ENDIAN. For the moment we could
depend on !CPU_BIG_ENDIAN which would at least to make it clear we don't
support EFI && CPU_BIG_ENDIAN yet. The commit message should be updated
to mention that.

[...]

> diff --git a/arch/arm64/kernel/efi-entry.S b/arch/arm64/kernel/efi-entry.S
> new file mode 100644
> index 0000000..d99a034e
> --- /dev/null
> +++ b/arch/arm64/kernel/efi-entry.S
> @@ -0,0 +1,100 @@
> +/*
> + * EFI entry point.
> + *
> + * Copyright (C) 2013, 2014 Red Hat, Inc.
> + * Author: Mark Salter <msalter@redhat.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + */
> +#include <linux/linkage.h>
> +#include <linux/init.h>
> +
> +#include <asm/assembler.h>
> +
> +#define EFI_LOAD_ERROR 0x8000000000000001
> +
> +       __INIT
> +
> +       /*
> +        * We arrive here from the EFI boot manager with:
> +        *
> +        *    * MMU on with identity-mapped RAM.
> +        *    * Icache and Dcache on

I assume we always enter with the CPU in little-endian mode? It would be
nice to note that here if so, or otherwise if not

> +        *
> +        * We will most likely be running from some place other than where
> +        * we want to be. The kernel image wants to be placed at TEXT_OFFSET
> +        * from start of RAM.
> +        */
> +ENTRY(efi_stub_entry)
> +       stp     x29, x30, [sp, #-32]!

A comment as to what the additional space is for would be nice. It seems
to be the relocated kernel address and padding for the required
alignment?

[...]

> +/*
> + * AArch64 requires the DTB to be 8-byte aligned in the first 512MiB from
> + * start of kernel and may not cross a 2MiB boundary. We set alignment to
> + * 2MiB so we know it won't cross a 2MiB boundary.
> + */

Nit: the booting documentation is poor here, but the actual requirement
is slightly different than that described. We currently need the DTB to
be within the same naturally-aligned 512 MiB region as the kernel,
though that restriction could be lifted with some rework of the initial
page tables.

[...]

>From here on in, all comments are regarding endianness issues and how we
can fix them. If you do not care about BE, stop reading here. ;)

> diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
> index 1fe5d8d..2aee658 100644
> --- a/arch/arm64/kernel/head.S
> +++ b/arch/arm64/kernel/head.S
> @@ -107,8 +107,18 @@
>         /*
>          * DO NOT MODIFY. Image header expected by Linux boot-loaders.
>          */
> +#ifdef CONFIG_EFI
> +       /*
> +        * Magic "MZ" signature for PE/COFF
> +        * Little Endian:  add x13, x18, #0x16
> +        */
> +efi_head:
> +       .long   0x91005a4d

As .long will emit the value in native endianness, this will only work
for LE kernels. In BE this will be backwards (which looks to be an
undefined instruction).

> +       b       stext
> +#else
>         b       stext                           // branch to kernel start, magic
>         .long   0                               // reserved
> +#endif
>         .quad   TEXT_OFFSET                     // Image load offset from start of RAM

This also needs to be fixed up endianness wise; I have a series for that
which I'll post shortly.

>         .quad   0                               // reserved
>         .quad   0                               // reserved
> @@ -119,7 +129,109 @@
>         .byte   0x52
>         .byte   0x4d
>         .byte   0x64
> +#ifdef CONFIG_EFI
> +       .long   pe_header - efi_head            // Offset to the PE header.

Likewise this will be backwards. Unfortunately values derived from
calculations involving symbols can't be endian-swapped here due to lack
of a suitable relocation -- we'll have to get the linker to do the
endianness swap for us.

I have a patch enabling the linker to endian-swap such values for us for
64-bit values, but it looks like we'll need other sizes too (for the
shorts below). To prevent vast swathes of symbols appearing in the main
linker script we could have a header to gather those into a
FIXED_ENDIAN_SYMBOLS macro or similar.

> +#else
>         .word   0                               // reserved
> +#endif
> +
> +#ifdef CONFIG_EFI
> +       .align 3
> +pe_header:
> +       .ascii  "PE"
> +       .short  0
> +coff_header:
> +       .short  0xaa64                          // AArch64
> +       .short  2                               // nr_sections
> +       .long   0                               // TimeDateStamp
> +       .long   0                               // PointerToSymbolTable
> +       .long   1                               // NumberOfSymbols

Everything here but the string will be the wrong way around on BE.

We could add .{short,int,long}_le macros to do the endianness swapping
of these values for us (which would also help to document the
endianness).

All other uses of {short,int,long} for non-zero values will need
endianness correction.

> +       .short  section_table - optional_header // SizeOfOptionalHeader

This might need the linker's help to swap unless the assembler resolves
the difference at assemble time.

> +       .long   efi_stub_entry - efi_head       // AddressOfEntryPoint
> +       .long   stext - efi_head                // BaseOfCode

Likewise.

> +       .long   _edata - efi_head               // SizeOfImage

This will definitely require the help of the linker for endianness
swapping.

> +       // Everything before the kernel image is considered part of the header
> +       .long   stext - efi_head                        // SizeOfHeaders

And this.

[...]

> +       .long   _edata - stext          // VirtualSize
> +       .long   stext - efi_head        // VirtualAddress
> +       .long   _edata - stext          // SizeOfRawData
> +       .long   stext - efi_head        // PointerToRawData

And these.

Cheers,
Mark.

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

* Re: [PATCH v3 06/10] arm64: efi: add EFI stub
@ 2014-04-10 12:54       ` Mark Salter
  0 siblings, 0 replies; 55+ messages in thread
From: Mark Salter @ 2014-04-10 12:54 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Leif Lindholm, linux-arm-kernel, linux-efi, linux-kernel,
	Ard Biesheuvel, Catalin Marinas, Matt Fleming

On Wed, 2014-04-09 at 15:20 +0100, Mark Rutland wrote:
> >
> > +config EFI
> > +       bool "UEFI firmware support"
> > +       depends on OF
> 
> I note we're not depending on !CPU_BIG_ENDIAN here, and it looks like
> the implementation is not endian-clean (I've pointed out a few issues
> below).
> 
> We need to fix that up for CPU_BIG_ENDIAN. For the moment we could
> depend on !CPU_BIG_ENDIAN which would at least to make it clear we don't
> support EFI && CPU_BIG_ENDIAN yet. The commit message should be updated
> to mention that.
> 

Yes, the !CPU_BIG_ENDIAN was there at one point but got lost along
the way. It may be best to put it back for now, but I'll take a
stab at getting the stub part sorted out based on your comments.
Full runtime services will be trickier and need a followup patch in
the future after the initial patch series goes in.



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

* Re: [PATCH v3 06/10] arm64: efi: add EFI stub
@ 2014-04-10 12:54       ` Mark Salter
  0 siblings, 0 replies; 55+ messages in thread
From: Mark Salter @ 2014-04-10 12:54 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Leif Lindholm, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Ard Biesheuvel,
	Catalin Marinas, Matt Fleming

On Wed, 2014-04-09 at 15:20 +0100, Mark Rutland wrote:
> >
> > +config EFI
> > +       bool "UEFI firmware support"
> > +       depends on OF
> 
> I note we're not depending on !CPU_BIG_ENDIAN here, and it looks like
> the implementation is not endian-clean (I've pointed out a few issues
> below).
> 
> We need to fix that up for CPU_BIG_ENDIAN. For the moment we could
> depend on !CPU_BIG_ENDIAN which would at least to make it clear we don't
> support EFI && CPU_BIG_ENDIAN yet. The commit message should be updated
> to mention that.
> 

Yes, the !CPU_BIG_ENDIAN was there at one point but got lost along
the way. It may be best to put it back for now, but I'll take a
stab at getting the stub part sorted out based on your comments.
Full runtime services will be trickier and need a followup patch in
the future after the initial patch series goes in.

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

* [PATCH v3 06/10] arm64: efi: add EFI stub
@ 2014-04-10 12:54       ` Mark Salter
  0 siblings, 0 replies; 55+ messages in thread
From: Mark Salter @ 2014-04-10 12:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 2014-04-09 at 15:20 +0100, Mark Rutland wrote:
> >
> > +config EFI
> > +       bool "UEFI firmware support"
> > +       depends on OF
> 
> I note we're not depending on !CPU_BIG_ENDIAN here, and it looks like
> the implementation is not endian-clean (I've pointed out a few issues
> below).
> 
> We need to fix that up for CPU_BIG_ENDIAN. For the moment we could
> depend on !CPU_BIG_ENDIAN which would at least to make it clear we don't
> support EFI && CPU_BIG_ENDIAN yet. The commit message should be updated
> to mention that.
> 

Yes, the !CPU_BIG_ENDIAN was there at one point but got lost along
the way. It may be best to put it back for now, but I'll take a
stab at getting the stub part sorted out based on your comments.
Full runtime services will be trickier and need a followup patch in
the future after the initial patch series goes in.

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

* Re: [PATCH v3 06/10] arm64: efi: add EFI stub
  2014-04-04 18:45   ` Leif Lindholm
  (?)
@ 2017-02-08 16:28     ` Timur Tabi
  -1 siblings, 0 replies; 55+ messages in thread
From: Timur Tabi @ 2017-02-08 16:28 UTC (permalink / raw)
  To: Leif Lindholm
  Cc: linux-arm-kernel, linux-efi, lkml, Mark Salter, Ard Biesheuvel,
	Catalin Marinas, Matt Fleming

On Fri, Apr 4, 2014 at 1:45 PM, Leif Lindholm <leif.lindholm@linaro.org> wrote:
>
> +/*
> + * EFI entry point for the arm/arm64 EFI stubs.  This is the entrypoint
> + * that is described in the PE/COFF header.  Most of the code is the same
> + * for both archictectures, with the arch-specific code provided in the
> + * handle_kernel_image() function.
> + */
> +unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table,
> +                              unsigned long *image_addr)
> +{

...

> +
> +       status = handle_cmdline_files(sys_table, image, cmdline_ptr,
> +                                     "initrd=", dram_base + SZ_512M,
> +                                     (unsigned long *)&initrd_addr,
> +                                     (unsigned long *)&initrd_size);

So I know this patch is almost three years old, but why is there a
512M limit on the initrd size?

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.

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

* Re: [PATCH v3 06/10] arm64: efi: add EFI stub
@ 2017-02-08 16:28     ` Timur Tabi
  0 siblings, 0 replies; 55+ messages in thread
From: Timur Tabi @ 2017-02-08 16:28 UTC (permalink / raw)
  To: Leif Lindholm
  Cc: linux-efi, Ard Biesheuvel, Catalin Marinas, lkml, Matt Fleming,
	Mark Salter, linux-arm-kernel

On Fri, Apr 4, 2014 at 1:45 PM, Leif Lindholm <leif.lindholm@linaro.org> wrote:
>
> +/*
> + * EFI entry point for the arm/arm64 EFI stubs.  This is the entrypoint
> + * that is described in the PE/COFF header.  Most of the code is the same
> + * for both archictectures, with the arch-specific code provided in the
> + * handle_kernel_image() function.
> + */
> +unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table,
> +                              unsigned long *image_addr)
> +{

...

> +
> +       status = handle_cmdline_files(sys_table, image, cmdline_ptr,
> +                                     "initrd=", dram_base + SZ_512M,
> +                                     (unsigned long *)&initrd_addr,
> +                                     (unsigned long *)&initrd_size);

So I know this patch is almost three years old, but why is there a
512M limit on the initrd size?

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.

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

* [PATCH v3 06/10] arm64: efi: add EFI stub
@ 2017-02-08 16:28     ` Timur Tabi
  0 siblings, 0 replies; 55+ messages in thread
From: Timur Tabi @ 2017-02-08 16:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 4, 2014 at 1:45 PM, Leif Lindholm <leif.lindholm@linaro.org> wrote:
>
> +/*
> + * EFI entry point for the arm/arm64 EFI stubs.  This is the entrypoint
> + * that is described in the PE/COFF header.  Most of the code is the same
> + * for both archictectures, with the arch-specific code provided in the
> + * handle_kernel_image() function.
> + */
> +unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table,
> +                              unsigned long *image_addr)
> +{

...

> +
> +       status = handle_cmdline_files(sys_table, image, cmdline_ptr,
> +                                     "initrd=", dram_base + SZ_512M,
> +                                     (unsigned long *)&initrd_addr,
> +                                     (unsigned long *)&initrd_size);

So I know this patch is almost three years old, but why is there a
512M limit on the initrd size?

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.

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

* Re: [PATCH v3 06/10] arm64: efi: add EFI stub
  2017-02-08 16:28     ` Timur Tabi
  (?)
@ 2017-02-08 16:29       ` Ard Biesheuvel
  -1 siblings, 0 replies; 55+ messages in thread
From: Ard Biesheuvel @ 2017-02-08 16:29 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Leif Lindholm, linux-arm-kernel, linux-efi, lkml, Mark Salter,
	Catalin Marinas, Matt Fleming



> On 8 Feb 2017, at 16:28, Timur Tabi <timur@codeaurora.org> wrote:
> 
>> On Fri, Apr 4, 2014 at 1:45 PM, Leif Lindholm <leif.lindholm@linaro.org> wrote:
>> 
>> +/*
>> + * EFI entry point for the arm/arm64 EFI stubs.  This is the entrypoint
>> + * that is described in the PE/COFF header.  Most of the code is the same
>> + * for both archictectures, with the arch-specific code provided in the
>> + * handle_kernel_image() function.
>> + */
>> +unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table,
>> +                              unsigned long *image_addr)
>> +{
> 
> ...
> 
>> +
>> +       status = handle_cmdline_files(sys_table, image, cmdline_ptr,
>> +                                     "initrd=", dram_base + SZ_512M,
>> +                                     (unsigned long *)&initrd_addr,
>> +                                     (unsigned long *)&initrd_size);
> 
> So I know this patch is almost three years old, but why is there a
> 512M limit on the initrd size?
> 

How do you reckon this constitutes a limit?

> -- 
> Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project.

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

* Re: [PATCH v3 06/10] arm64: efi: add EFI stub
@ 2017-02-08 16:29       ` Ard Biesheuvel
  0 siblings, 0 replies; 55+ messages in thread
From: Ard Biesheuvel @ 2017-02-08 16:29 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Leif Lindholm, linux-arm-kernel, linux-efi, lkml, Mark Salter,
	Catalin Marinas, Matt Fleming



> On 8 Feb 2017, at 16:28, Timur Tabi <timur@codeaurora.org> wrote:
> 
>> On Fri, Apr 4, 2014 at 1:45 PM, Leif Lindholm <leif.lindholm@linaro.org> wrote:
>> 
>> +/*
>> + * EFI entry point for the arm/arm64 EFI stubs.  This is the entrypoint
>> + * that is described in the PE/COFF header.  Most of the code is the same
>> + * for both archictectures, with the arch-specific code provided in the
>> + * handle_kernel_image() function.
>> + */
>> +unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table,
>> +                              unsigned long *image_addr)
>> +{
> 
> ...
> 
>> +
>> +       status = handle_cmdline_files(sys_table, image, cmdline_ptr,
>> +                                     "initrd=", dram_base + SZ_512M,
>> +                                     (unsigned long *)&initrd_addr,
>> +                                     (unsigned long *)&initrd_size);
> 
> So I know this patch is almost three years old, but why is there a
> 512M limit on the initrd size?
> 

How do you reckon this constitutes a limit?

> -- 
> Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project.

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

* [PATCH v3 06/10] arm64: efi: add EFI stub
@ 2017-02-08 16:29       ` Ard Biesheuvel
  0 siblings, 0 replies; 55+ messages in thread
From: Ard Biesheuvel @ 2017-02-08 16:29 UTC (permalink / raw)
  To: linux-arm-kernel



> On 8 Feb 2017, at 16:28, Timur Tabi <timur@codeaurora.org> wrote:
> 
>> On Fri, Apr 4, 2014 at 1:45 PM, Leif Lindholm <leif.lindholm@linaro.org> wrote:
>> 
>> +/*
>> + * EFI entry point for the arm/arm64 EFI stubs.  This is the entrypoint
>> + * that is described in the PE/COFF header.  Most of the code is the same
>> + * for both archictectures, with the arch-specific code provided in the
>> + * handle_kernel_image() function.
>> + */
>> +unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table,
>> +                              unsigned long *image_addr)
>> +{
> 
> ...
> 
>> +
>> +       status = handle_cmdline_files(sys_table, image, cmdline_ptr,
>> +                                     "initrd=", dram_base + SZ_512M,
>> +                                     (unsigned long *)&initrd_addr,
>> +                                     (unsigned long *)&initrd_size);
> 
> So I know this patch is almost three years old, but why is there a
> 512M limit on the initrd size?
> 

How do you reckon this constitutes a limit?

> -- 
> Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project.

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

* Re: [PATCH v3 06/10] arm64: efi: add EFI stub
  2017-02-08 16:29       ` Ard Biesheuvel
  (?)
@ 2017-02-08 16:35         ` Timur Tabi
  -1 siblings, 0 replies; 55+ messages in thread
From: Timur Tabi @ 2017-02-08 16:35 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Leif Lindholm, linux-arm-kernel, linux-efi, lkml, Mark Salter,
	Catalin Marinas

On 02/08/2017 10:29 AM, Ard Biesheuvel wrote:
>>> >> +       status = handle_cmdline_files(sys_table, image, cmdline_ptr,
>>> >> +                                     "initrd=", dram_base + SZ_512M,
>>> >> +                                     (unsigned long *)&initrd_addr,
>>> >> +                                     (unsigned long *)&initrd_size);
>> >
>> > So I know this patch is almost three years old, but why is there a
>> > 512M limit on the initrd size?
>> >
> How do you reckon this constitutes a limit?

handle_cmdline_files() calls efi_high_alloc() with that limit.  I'm still 
trying to understand all the details myself, but apparently our firmware and 
initrd need to fit within the first 512MB because of dram_base + SZ_512M. 
When we change "dram_base + SZ_512M" to "~0", everything works.

-- 
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm
Technologies, Inc.  Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

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

* Re: [PATCH v3 06/10] arm64: efi: add EFI stub
@ 2017-02-08 16:35         ` Timur Tabi
  0 siblings, 0 replies; 55+ messages in thread
From: Timur Tabi @ 2017-02-08 16:35 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-efi, Catalin Marinas, lkml, Leif Lindholm, Mark Salter,
	linux-arm-kernel

On 02/08/2017 10:29 AM, Ard Biesheuvel wrote:
>>> >> +       status = handle_cmdline_files(sys_table, image, cmdline_ptr,
>>> >> +                                     "initrd=", dram_base + SZ_512M,
>>> >> +                                     (unsigned long *)&initrd_addr,
>>> >> +                                     (unsigned long *)&initrd_size);
>> >
>> > So I know this patch is almost three years old, but why is there a
>> > 512M limit on the initrd size?
>> >
> How do you reckon this constitutes a limit?

handle_cmdline_files() calls efi_high_alloc() with that limit.  I'm still 
trying to understand all the details myself, but apparently our firmware and 
initrd need to fit within the first 512MB because of dram_base + SZ_512M. 
When we change "dram_base + SZ_512M" to "~0", everything works.

-- 
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm
Technologies, Inc.  Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

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

* [PATCH v3 06/10] arm64: efi: add EFI stub
@ 2017-02-08 16:35         ` Timur Tabi
  0 siblings, 0 replies; 55+ messages in thread
From: Timur Tabi @ 2017-02-08 16:35 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/08/2017 10:29 AM, Ard Biesheuvel wrote:
>>> >> +       status = handle_cmdline_files(sys_table, image, cmdline_ptr,
>>> >> +                                     "initrd=", dram_base + SZ_512M,
>>> >> +                                     (unsigned long *)&initrd_addr,
>>> >> +                                     (unsigned long *)&initrd_size);
>> >
>> > So I know this patch is almost three years old, but why is there a
>> > 512M limit on the initrd size?
>> >
> How do you reckon this constitutes a limit?

handle_cmdline_files() calls efi_high_alloc() with that limit.  I'm still 
trying to understand all the details myself, but apparently our firmware and 
initrd need to fit within the first 512MB because of dram_base + SZ_512M. 
When we change "dram_base + SZ_512M" to "~0", everything works.

-- 
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm
Technologies, Inc.  Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

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

* Re: [PATCH v3 06/10] arm64: efi: add EFI stub
  2017-02-08 16:35         ` Timur Tabi
  (?)
@ 2017-02-08 17:03           ` Mark Rutland
  -1 siblings, 0 replies; 55+ messages in thread
From: Mark Rutland @ 2017-02-08 17:03 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Ard Biesheuvel, linux-efi, Catalin Marinas, lkml, Leif Lindholm,
	Mark Salter, linux-arm-kernel

On Wed, Feb 08, 2017 at 10:35:02AM -0600, Timur Tabi wrote:
> On 02/08/2017 10:29 AM, Ard Biesheuvel wrote:
> >>>>> +       status = handle_cmdline_files(sys_table, image, cmdline_ptr,
> >>>>> +                                     "initrd=", dram_base + SZ_512M,
> >>>>> +                                     (unsigned long *)&initrd_addr,
> >>>>> +                                     (unsigned long *)&initrd_size);
> >>>
> >>> So I know this patch is almost three years old, but why is there a
> >>> 512M limit on the initrd size?
> >>>
> >How do you reckon this constitutes a limit?
> 
> handle_cmdline_files() calls efi_high_alloc() with that limit.  I'm
> still trying to understand all the details myself, but apparently
> our firmware and initrd need to fit within the first 512MB because
> of dram_base + SZ_512M. When we change "dram_base + SZ_512M" to
> "~0", everything works.

Just to check, how big is that initrd?

I guess it's possible that there simply isn't sufficient contiguous free
memory in that range, even if the initrd isn't that large. Can you share
the EFI memory map dump from booting with efi=debug?

We originally needed to restrict this to ensure that the kernel could
map the initrd (and I think the 512M restriction specifically was
inherited from the DTB mapping restriction). Since then, we have relaxed
things in the kernel, and today Documentation/arm64/booting.txt says:

	If an initrd/initramfs is passed to the kernel at boot, it must
	reside entirely within a 1 GB aligned physical memory window of
	up to 32 GB in size that fully covers the kernel Image as well.

... so I think the EFI stub should be able to take advantage of that
relaxation.

Ard?

Thanks,
Mark.

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

* Re: [PATCH v3 06/10] arm64: efi: add EFI stub
@ 2017-02-08 17:03           ` Mark Rutland
  0 siblings, 0 replies; 55+ messages in thread
From: Mark Rutland @ 2017-02-08 17:03 UTC (permalink / raw)
  To: Timur Tabi
  Cc: linux-efi, Ard Biesheuvel, Catalin Marinas, lkml, Leif Lindholm,
	Mark Salter, linux-arm-kernel

On Wed, Feb 08, 2017 at 10:35:02AM -0600, Timur Tabi wrote:
> On 02/08/2017 10:29 AM, Ard Biesheuvel wrote:
> >>>>> +       status = handle_cmdline_files(sys_table, image, cmdline_ptr,
> >>>>> +                                     "initrd=", dram_base + SZ_512M,
> >>>>> +                                     (unsigned long *)&initrd_addr,
> >>>>> +                                     (unsigned long *)&initrd_size);
> >>>
> >>> So I know this patch is almost three years old, but why is there a
> >>> 512M limit on the initrd size?
> >>>
> >How do you reckon this constitutes a limit?
> 
> handle_cmdline_files() calls efi_high_alloc() with that limit.  I'm
> still trying to understand all the details myself, but apparently
> our firmware and initrd need to fit within the first 512MB because
> of dram_base + SZ_512M. When we change "dram_base + SZ_512M" to
> "~0", everything works.

Just to check, how big is that initrd?

I guess it's possible that there simply isn't sufficient contiguous free
memory in that range, even if the initrd isn't that large. Can you share
the EFI memory map dump from booting with efi=debug?

We originally needed to restrict this to ensure that the kernel could
map the initrd (and I think the 512M restriction specifically was
inherited from the DTB mapping restriction). Since then, we have relaxed
things in the kernel, and today Documentation/arm64/booting.txt says:

	If an initrd/initramfs is passed to the kernel at boot, it must
	reside entirely within a 1 GB aligned physical memory window of
	up to 32 GB in size that fully covers the kernel Image as well.

... so I think the EFI stub should be able to take advantage of that
relaxation.

Ard?

Thanks,
Mark.

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

* [PATCH v3 06/10] arm64: efi: add EFI stub
@ 2017-02-08 17:03           ` Mark Rutland
  0 siblings, 0 replies; 55+ messages in thread
From: Mark Rutland @ 2017-02-08 17:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Feb 08, 2017 at 10:35:02AM -0600, Timur Tabi wrote:
> On 02/08/2017 10:29 AM, Ard Biesheuvel wrote:
> >>>>> +       status = handle_cmdline_files(sys_table, image, cmdline_ptr,
> >>>>> +                                     "initrd=", dram_base + SZ_512M,
> >>>>> +                                     (unsigned long *)&initrd_addr,
> >>>>> +                                     (unsigned long *)&initrd_size);
> >>>
> >>> So I know this patch is almost three years old, but why is there a
> >>> 512M limit on the initrd size?
> >>>
> >How do you reckon this constitutes a limit?
> 
> handle_cmdline_files() calls efi_high_alloc() with that limit.  I'm
> still trying to understand all the details myself, but apparently
> our firmware and initrd need to fit within the first 512MB because
> of dram_base + SZ_512M. When we change "dram_base + SZ_512M" to
> "~0", everything works.

Just to check, how big is that initrd?

I guess it's possible that there simply isn't sufficient contiguous free
memory in that range, even if the initrd isn't that large. Can you share
the EFI memory map dump from booting with efi=debug?

We originally needed to restrict this to ensure that the kernel could
map the initrd (and I think the 512M restriction specifically was
inherited from the DTB mapping restriction). Since then, we have relaxed
things in the kernel, and today Documentation/arm64/booting.txt says:

	If an initrd/initramfs is passed to the kernel at boot, it must
	reside entirely within a 1 GB aligned physical memory window of
	up to 32 GB in size that fully covers the kernel Image as well.

... so I think the EFI stub should be able to take advantage of that
relaxation.

Ard?

Thanks,
Mark.

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

* Re: [PATCH v3 06/10] arm64: efi: add EFI stub
  2017-02-08 17:03           ` Mark Rutland
  (?)
@ 2017-02-08 17:22             ` Jeffrey Hugo
  -1 siblings, 0 replies; 55+ messages in thread
From: Jeffrey Hugo @ 2017-02-08 17:22 UTC (permalink / raw)
  To: Mark Rutland, Timur Tabi
  Cc: Ard Biesheuvel, linux-efi, Catalin Marinas, lkml, Leif Lindholm,
	Mark Salter, linux-arm-kernel

On 2/8/2017 10:03 AM, Mark Rutland wrote:
> On Wed, Feb 08, 2017 at 10:35:02AM -0600, Timur Tabi wrote:
>> On 02/08/2017 10:29 AM, Ard Biesheuvel wrote:
>>>>>>> +       status = handle_cmdline_files(sys_table, image, cmdline_ptr,
>>>>>>> +                                     "initrd=", dram_base + SZ_512M,
>>>>>>> +                                     (unsigned long *)&initrd_addr,
>>>>>>> +                                     (unsigned long *)&initrd_size);
>>>>>
>>>>> So I know this patch is almost three years old, but why is there a
>>>>> 512M limit on the initrd size?
>>>>>
>>> How do you reckon this constitutes a limit?
>>
>> handle_cmdline_files() calls efi_high_alloc() with that limit.  I'm
>> still trying to understand all the details myself, but apparently
>> our firmware and initrd need to fit within the first 512MB because
>> of dram_base + SZ_512M. When we change "dram_base + SZ_512M" to
>> "~0", everything works.
>
> Just to check, how big is that initrd?

120MB right now.  Probably could be optimized, but I don't think that's 
really the issue here.

The big problem is we don't have much memory free as the platform 
requires that all of firmware exists in the first 512MB.  On systems 
with a lot of devices (ie 16+ STAT drives), UEFI ends up doing a lot of 
allocations, which pushes the platform over the edge due to the limited 
memory and fragmentation of what is available.

>
> I guess it's possible that there simply isn't sufficient contiguous free
> memory in that range, even if the initrd isn't that large. Can you share
> the EFI memory map dump from booting with efi=debug?
>
> We originally needed to restrict this to ensure that the kernel could
> map the initrd (and I think the 512M restriction specifically was
> inherited from the DTB mapping restriction). Since then, we have relaxed
> things in the kernel, and today Documentation/arm64/booting.txt says:
>
> 	If an initrd/initramfs is passed to the kernel at boot, it must
> 	reside entirely within a 1 GB aligned physical memory window of
> 	up to 32 GB in size that fully covers the kernel Image as well.
>
> ... so I think the EFI stub should be able to take advantage of that
> relaxation.
>
> Ard?
>
> Thanks,
> Mark.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-efi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Jeffrey Hugo
Qualcomm Datacenter Technologies as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

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

* Re: [PATCH v3 06/10] arm64: efi: add EFI stub
@ 2017-02-08 17:22             ` Jeffrey Hugo
  0 siblings, 0 replies; 55+ messages in thread
From: Jeffrey Hugo @ 2017-02-08 17:22 UTC (permalink / raw)
  To: Mark Rutland, Timur Tabi
  Cc: linux-efi, Ard Biesheuvel, Catalin Marinas, lkml, Leif Lindholm,
	Mark Salter, linux-arm-kernel

On 2/8/2017 10:03 AM, Mark Rutland wrote:
> On Wed, Feb 08, 2017 at 10:35:02AM -0600, Timur Tabi wrote:
>> On 02/08/2017 10:29 AM, Ard Biesheuvel wrote:
>>>>>>> +       status = handle_cmdline_files(sys_table, image, cmdline_ptr,
>>>>>>> +                                     "initrd=", dram_base + SZ_512M,
>>>>>>> +                                     (unsigned long *)&initrd_addr,
>>>>>>> +                                     (unsigned long *)&initrd_size);
>>>>>
>>>>> So I know this patch is almost three years old, but why is there a
>>>>> 512M limit on the initrd size?
>>>>>
>>> How do you reckon this constitutes a limit?
>>
>> handle_cmdline_files() calls efi_high_alloc() with that limit.  I'm
>> still trying to understand all the details myself, but apparently
>> our firmware and initrd need to fit within the first 512MB because
>> of dram_base + SZ_512M. When we change "dram_base + SZ_512M" to
>> "~0", everything works.
>
> Just to check, how big is that initrd?

120MB right now.  Probably could be optimized, but I don't think that's 
really the issue here.

The big problem is we don't have much memory free as the platform 
requires that all of firmware exists in the first 512MB.  On systems 
with a lot of devices (ie 16+ STAT drives), UEFI ends up doing a lot of 
allocations, which pushes the platform over the edge due to the limited 
memory and fragmentation of what is available.

>
> I guess it's possible that there simply isn't sufficient contiguous free
> memory in that range, even if the initrd isn't that large. Can you share
> the EFI memory map dump from booting with efi=debug?
>
> We originally needed to restrict this to ensure that the kernel could
> map the initrd (and I think the 512M restriction specifically was
> inherited from the DTB mapping restriction). Since then, we have relaxed
> things in the kernel, and today Documentation/arm64/booting.txt says:
>
> 	If an initrd/initramfs is passed to the kernel at boot, it must
> 	reside entirely within a 1 GB aligned physical memory window of
> 	up to 32 GB in size that fully covers the kernel Image as well.
>
> ... so I think the EFI stub should be able to take advantage of that
> relaxation.
>
> Ard?
>
> Thanks,
> Mark.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-efi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Jeffrey Hugo
Qualcomm Datacenter Technologies as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

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

* [PATCH v3 06/10] arm64: efi: add EFI stub
@ 2017-02-08 17:22             ` Jeffrey Hugo
  0 siblings, 0 replies; 55+ messages in thread
From: Jeffrey Hugo @ 2017-02-08 17:22 UTC (permalink / raw)
  To: linux-arm-kernel

On 2/8/2017 10:03 AM, Mark Rutland wrote:
> On Wed, Feb 08, 2017 at 10:35:02AM -0600, Timur Tabi wrote:
>> On 02/08/2017 10:29 AM, Ard Biesheuvel wrote:
>>>>>>> +       status = handle_cmdline_files(sys_table, image, cmdline_ptr,
>>>>>>> +                                     "initrd=", dram_base + SZ_512M,
>>>>>>> +                                     (unsigned long *)&initrd_addr,
>>>>>>> +                                     (unsigned long *)&initrd_size);
>>>>>
>>>>> So I know this patch is almost three years old, but why is there a
>>>>> 512M limit on the initrd size?
>>>>>
>>> How do you reckon this constitutes a limit?
>>
>> handle_cmdline_files() calls efi_high_alloc() with that limit.  I'm
>> still trying to understand all the details myself, but apparently
>> our firmware and initrd need to fit within the first 512MB because
>> of dram_base + SZ_512M. When we change "dram_base + SZ_512M" to
>> "~0", everything works.
>
> Just to check, how big is that initrd?

120MB right now.  Probably could be optimized, but I don't think that's 
really the issue here.

The big problem is we don't have much memory free as the platform 
requires that all of firmware exists in the first 512MB.  On systems 
with a lot of devices (ie 16+ STAT drives), UEFI ends up doing a lot of 
allocations, which pushes the platform over the edge due to the limited 
memory and fragmentation of what is available.

>
> I guess it's possible that there simply isn't sufficient contiguous free
> memory in that range, even if the initrd isn't that large. Can you share
> the EFI memory map dump from booting with efi=debug?
>
> We originally needed to restrict this to ensure that the kernel could
> map the initrd (and I think the 512M restriction specifically was
> inherited from the DTB mapping restriction). Since then, we have relaxed
> things in the kernel, and today Documentation/arm64/booting.txt says:
>
> 	If an initrd/initramfs is passed to the kernel at boot, it must
> 	reside entirely within a 1 GB aligned physical memory window of
> 	up to 32 GB in size that fully covers the kernel Image as well.
>
> ... so I think the EFI stub should be able to take advantage of that
> relaxation.
>
> Ard?
>
> Thanks,
> Mark.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-efi" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Jeffrey Hugo
Qualcomm Datacenter Technologies as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

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

* Re: [PATCH v3 06/10] arm64: efi: add EFI stub
  2017-02-08 17:03           ` Mark Rutland
  (?)
@ 2017-02-08 17:30             ` Jeffrey Hugo
  -1 siblings, 0 replies; 55+ messages in thread
From: Jeffrey Hugo @ 2017-02-08 17:30 UTC (permalink / raw)
  To: Mark Rutland, Timur Tabi
  Cc: Ard Biesheuvel, linux-efi, Catalin Marinas, lkml, Leif Lindholm,
	Mark Salter, linux-arm-kernel

On 2/8/2017 10:03 AM, Mark Rutland wrote:
> On Wed, Feb 08, 2017 at 10:35:02AM -0600, Timur Tabi wrote:
>> On 02/08/2017 10:29 AM, Ard Biesheuvel wrote:
>>>>>>> +       status = handle_cmdline_files(sys_table, image, cmdline_ptr,
>>>>>>> +                                     "initrd=", dram_base + SZ_512M,
>>>>>>> +                                     (unsigned long *)&initrd_addr,
>>>>>>> +                                     (unsigned long *)&initrd_size);
>>>>>
>>>>> So I know this patch is almost three years old, but why is there a
>>>>> 512M limit on the initrd size?
>>>>>
>>> How do you reckon this constitutes a limit?
>>
>> handle_cmdline_files() calls efi_high_alloc() with that limit.  I'm
>> still trying to understand all the details myself, but apparently
>> our firmware and initrd need to fit within the first 512MB because
>> of dram_base + SZ_512M. When we change "dram_base + SZ_512M" to
>> "~0", everything works.
>
> Just to check, how big is that initrd?
>
> I guess it's possible that there simply isn't sufficient contiguous free
> memory in that range, even if the initrd isn't that large. Can you share
> the EFI memory map dump from booting with efi=debug?
>
> We originally needed to restrict this to ensure that the kernel could
> map the initrd (and I think the 512M restriction specifically was
> inherited from the DTB mapping restriction). Since then, we have relaxed
> things in the kernel, and today Documentation/arm64/booting.txt says:
>
> 	If an initrd/initramfs is passed to the kernel at boot, it must
> 	reside entirely within a 1 GB aligned physical memory window of
> 	up to 32 GB in size that fully covers the kernel Image as well.
>
> ... so I think the EFI stub should be able to take advantage of that
> relaxation.

I agree.  The wrinkle I can see in this is it looks like KASLR can put 
the kernel anywhere in RAM.  How do we ensure initrd is within 32GB of 
the kernel on a system with 256 GB of RAM?

>
> Ard?
>
> Thanks,
> Mark.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-efi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Jeffrey Hugo
Qualcomm Datacenter Technologies as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

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

* Re: [PATCH v3 06/10] arm64: efi: add EFI stub
@ 2017-02-08 17:30             ` Jeffrey Hugo
  0 siblings, 0 replies; 55+ messages in thread
From: Jeffrey Hugo @ 2017-02-08 17:30 UTC (permalink / raw)
  To: Mark Rutland, Timur Tabi
  Cc: linux-efi, Ard Biesheuvel, Catalin Marinas, lkml, Leif Lindholm,
	Mark Salter, linux-arm-kernel

On 2/8/2017 10:03 AM, Mark Rutland wrote:
> On Wed, Feb 08, 2017 at 10:35:02AM -0600, Timur Tabi wrote:
>> On 02/08/2017 10:29 AM, Ard Biesheuvel wrote:
>>>>>>> +       status = handle_cmdline_files(sys_table, image, cmdline_ptr,
>>>>>>> +                                     "initrd=", dram_base + SZ_512M,
>>>>>>> +                                     (unsigned long *)&initrd_addr,
>>>>>>> +                                     (unsigned long *)&initrd_size);
>>>>>
>>>>> So I know this patch is almost three years old, but why is there a
>>>>> 512M limit on the initrd size?
>>>>>
>>> How do you reckon this constitutes a limit?
>>
>> handle_cmdline_files() calls efi_high_alloc() with that limit.  I'm
>> still trying to understand all the details myself, but apparently
>> our firmware and initrd need to fit within the first 512MB because
>> of dram_base + SZ_512M. When we change "dram_base + SZ_512M" to
>> "~0", everything works.
>
> Just to check, how big is that initrd?
>
> I guess it's possible that there simply isn't sufficient contiguous free
> memory in that range, even if the initrd isn't that large. Can you share
> the EFI memory map dump from booting with efi=debug?
>
> We originally needed to restrict this to ensure that the kernel could
> map the initrd (and I think the 512M restriction specifically was
> inherited from the DTB mapping restriction). Since then, we have relaxed
> things in the kernel, and today Documentation/arm64/booting.txt says:
>
> 	If an initrd/initramfs is passed to the kernel at boot, it must
> 	reside entirely within a 1 GB aligned physical memory window of
> 	up to 32 GB in size that fully covers the kernel Image as well.
>
> ... so I think the EFI stub should be able to take advantage of that
> relaxation.

I agree.  The wrinkle I can see in this is it looks like KASLR can put 
the kernel anywhere in RAM.  How do we ensure initrd is within 32GB of 
the kernel on a system with 256 GB of RAM?

>
> Ard?
>
> Thanks,
> Mark.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-efi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Jeffrey Hugo
Qualcomm Datacenter Technologies as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

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

* [PATCH v3 06/10] arm64: efi: add EFI stub
@ 2017-02-08 17:30             ` Jeffrey Hugo
  0 siblings, 0 replies; 55+ messages in thread
From: Jeffrey Hugo @ 2017-02-08 17:30 UTC (permalink / raw)
  To: linux-arm-kernel

On 2/8/2017 10:03 AM, Mark Rutland wrote:
> On Wed, Feb 08, 2017 at 10:35:02AM -0600, Timur Tabi wrote:
>> On 02/08/2017 10:29 AM, Ard Biesheuvel wrote:
>>>>>>> +       status = handle_cmdline_files(sys_table, image, cmdline_ptr,
>>>>>>> +                                     "initrd=", dram_base + SZ_512M,
>>>>>>> +                                     (unsigned long *)&initrd_addr,
>>>>>>> +                                     (unsigned long *)&initrd_size);
>>>>>
>>>>> So I know this patch is almost three years old, but why is there a
>>>>> 512M limit on the initrd size?
>>>>>
>>> How do you reckon this constitutes a limit?
>>
>> handle_cmdline_files() calls efi_high_alloc() with that limit.  I'm
>> still trying to understand all the details myself, but apparently
>> our firmware and initrd need to fit within the first 512MB because
>> of dram_base + SZ_512M. When we change "dram_base + SZ_512M" to
>> "~0", everything works.
>
> Just to check, how big is that initrd?
>
> I guess it's possible that there simply isn't sufficient contiguous free
> memory in that range, even if the initrd isn't that large. Can you share
> the EFI memory map dump from booting with efi=debug?
>
> We originally needed to restrict this to ensure that the kernel could
> map the initrd (and I think the 512M restriction specifically was
> inherited from the DTB mapping restriction). Since then, we have relaxed
> things in the kernel, and today Documentation/arm64/booting.txt says:
>
> 	If an initrd/initramfs is passed to the kernel at boot, it must
> 	reside entirely within a 1 GB aligned physical memory window of
> 	up to 32 GB in size that fully covers the kernel Image as well.
>
> ... so I think the EFI stub should be able to take advantage of that
> relaxation.

I agree.  The wrinkle I can see in this is it looks like KASLR can put 
the kernel anywhere in RAM.  How do we ensure initrd is within 32GB of 
the kernel on a system with 256 GB of RAM?

>
> Ard?
>
> Thanks,
> Mark.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-efi" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Jeffrey Hugo
Qualcomm Datacenter Technologies as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

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

* Re: [PATCH v3 06/10] arm64: efi: add EFI stub
  2017-02-08 17:30             ` Jeffrey Hugo
  (?)
@ 2017-02-08 17:34               ` Mark Rutland
  -1 siblings, 0 replies; 55+ messages in thread
From: Mark Rutland @ 2017-02-08 17:34 UTC (permalink / raw)
  To: Jeffrey Hugo
  Cc: Timur Tabi, Ard Biesheuvel, linux-efi, Catalin Marinas, lkml,
	Leif Lindholm, Mark Salter, linux-arm-kernel

On Wed, Feb 08, 2017 at 10:30:37AM -0700, Jeffrey Hugo wrote:
> On 2/8/2017 10:03 AM, Mark Rutland wrote:
> >On Wed, Feb 08, 2017 at 10:35:02AM -0600, Timur Tabi wrote:
> >>On 02/08/2017 10:29 AM, Ard Biesheuvel wrote:
> >>>>>>>+       status = handle_cmdline_files(sys_table, image, cmdline_ptr,
> >>>>>>>+                                     "initrd=", dram_base + SZ_512M,
> >>>>>>>+                                     (unsigned long *)&initrd_addr,
> >>>>>>>+                                     (unsigned long *)&initrd_size);
> >>>>>
> >>>>>So I know this patch is almost three years old, but why is there a
> >>>>>512M limit on the initrd size?
> >>>>>
> >>>How do you reckon this constitutes a limit?
> >>
> >>handle_cmdline_files() calls efi_high_alloc() with that limit.  I'm
> >>still trying to understand all the details myself, but apparently
> >>our firmware and initrd need to fit within the first 512MB because
> >>of dram_base + SZ_512M. When we change "dram_base + SZ_512M" to
> >>"~0", everything works.
> >
> >Just to check, how big is that initrd?
> >
> >I guess it's possible that there simply isn't sufficient contiguous free
> >memory in that range, even if the initrd isn't that large. Can you share
> >the EFI memory map dump from booting with efi=debug?
> >
> >We originally needed to restrict this to ensure that the kernel could
> >map the initrd (and I think the 512M restriction specifically was
> >inherited from the DTB mapping restriction). Since then, we have relaxed
> >things in the kernel, and today Documentation/arm64/booting.txt says:
> >
> >	If an initrd/initramfs is passed to the kernel at boot, it must
> >	reside entirely within a 1 GB aligned physical memory window of
> >	up to 32 GB in size that fully covers the kernel Image as well.
> >
> >... so I think the EFI stub should be able to take advantage of that
> >relaxation.
> 
> I agree.  The wrinkle I can see in this is it looks like KASLR can
> put the kernel anywhere in RAM.  How do we ensure initrd is within
> 32GB of the kernel on a system with 256 GB of RAM?

The EFI stub chose the physical location of the kernel, and should know
where it put it. The virtual location of the kernel shouldn't matter.

At some point though, this does become best-effort, unless we want a SAT
solver in the stub.

Thanks,
Mark.

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

* Re: [PATCH v3 06/10] arm64: efi: add EFI stub
@ 2017-02-08 17:34               ` Mark Rutland
  0 siblings, 0 replies; 55+ messages in thread
From: Mark Rutland @ 2017-02-08 17:34 UTC (permalink / raw)
  To: Jeffrey Hugo
  Cc: linux-efi, Ard Biesheuvel, Catalin Marinas, Timur Tabi, lkml,
	Leif Lindholm, Mark Salter, linux-arm-kernel

On Wed, Feb 08, 2017 at 10:30:37AM -0700, Jeffrey Hugo wrote:
> On 2/8/2017 10:03 AM, Mark Rutland wrote:
> >On Wed, Feb 08, 2017 at 10:35:02AM -0600, Timur Tabi wrote:
> >>On 02/08/2017 10:29 AM, Ard Biesheuvel wrote:
> >>>>>>>+       status = handle_cmdline_files(sys_table, image, cmdline_ptr,
> >>>>>>>+                                     "initrd=", dram_base + SZ_512M,
> >>>>>>>+                                     (unsigned long *)&initrd_addr,
> >>>>>>>+                                     (unsigned long *)&initrd_size);
> >>>>>
> >>>>>So I know this patch is almost three years old, but why is there a
> >>>>>512M limit on the initrd size?
> >>>>>
> >>>How do you reckon this constitutes a limit?
> >>
> >>handle_cmdline_files() calls efi_high_alloc() with that limit.  I'm
> >>still trying to understand all the details myself, but apparently
> >>our firmware and initrd need to fit within the first 512MB because
> >>of dram_base + SZ_512M. When we change "dram_base + SZ_512M" to
> >>"~0", everything works.
> >
> >Just to check, how big is that initrd?
> >
> >I guess it's possible that there simply isn't sufficient contiguous free
> >memory in that range, even if the initrd isn't that large. Can you share
> >the EFI memory map dump from booting with efi=debug?
> >
> >We originally needed to restrict this to ensure that the kernel could
> >map the initrd (and I think the 512M restriction specifically was
> >inherited from the DTB mapping restriction). Since then, we have relaxed
> >things in the kernel, and today Documentation/arm64/booting.txt says:
> >
> >	If an initrd/initramfs is passed to the kernel at boot, it must
> >	reside entirely within a 1 GB aligned physical memory window of
> >	up to 32 GB in size that fully covers the kernel Image as well.
> >
> >... so I think the EFI stub should be able to take advantage of that
> >relaxation.
> 
> I agree.  The wrinkle I can see in this is it looks like KASLR can
> put the kernel anywhere in RAM.  How do we ensure initrd is within
> 32GB of the kernel on a system with 256 GB of RAM?

The EFI stub chose the physical location of the kernel, and should know
where it put it. The virtual location of the kernel shouldn't matter.

At some point though, this does become best-effort, unless we want a SAT
solver in the stub.

Thanks,
Mark.

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

* [PATCH v3 06/10] arm64: efi: add EFI stub
@ 2017-02-08 17:34               ` Mark Rutland
  0 siblings, 0 replies; 55+ messages in thread
From: Mark Rutland @ 2017-02-08 17:34 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Feb 08, 2017 at 10:30:37AM -0700, Jeffrey Hugo wrote:
> On 2/8/2017 10:03 AM, Mark Rutland wrote:
> >On Wed, Feb 08, 2017 at 10:35:02AM -0600, Timur Tabi wrote:
> >>On 02/08/2017 10:29 AM, Ard Biesheuvel wrote:
> >>>>>>>+       status = handle_cmdline_files(sys_table, image, cmdline_ptr,
> >>>>>>>+                                     "initrd=", dram_base + SZ_512M,
> >>>>>>>+                                     (unsigned long *)&initrd_addr,
> >>>>>>>+                                     (unsigned long *)&initrd_size);
> >>>>>
> >>>>>So I know this patch is almost three years old, but why is there a
> >>>>>512M limit on the initrd size?
> >>>>>
> >>>How do you reckon this constitutes a limit?
> >>
> >>handle_cmdline_files() calls efi_high_alloc() with that limit.  I'm
> >>still trying to understand all the details myself, but apparently
> >>our firmware and initrd need to fit within the first 512MB because
> >>of dram_base + SZ_512M. When we change "dram_base + SZ_512M" to
> >>"~0", everything works.
> >
> >Just to check, how big is that initrd?
> >
> >I guess it's possible that there simply isn't sufficient contiguous free
> >memory in that range, even if the initrd isn't that large. Can you share
> >the EFI memory map dump from booting with efi=debug?
> >
> >We originally needed to restrict this to ensure that the kernel could
> >map the initrd (and I think the 512M restriction specifically was
> >inherited from the DTB mapping restriction). Since then, we have relaxed
> >things in the kernel, and today Documentation/arm64/booting.txt says:
> >
> >	If an initrd/initramfs is passed to the kernel at boot, it must
> >	reside entirely within a 1 GB aligned physical memory window of
> >	up to 32 GB in size that fully covers the kernel Image as well.
> >
> >... so I think the EFI stub should be able to take advantage of that
> >relaxation.
> 
> I agree.  The wrinkle I can see in this is it looks like KASLR can
> put the kernel anywhere in RAM.  How do we ensure initrd is within
> 32GB of the kernel on a system with 256 GB of RAM?

The EFI stub chose the physical location of the kernel, and should know
where it put it. The virtual location of the kernel shouldn't matter.

At some point though, this does become best-effort, unless we want a SAT
solver in the stub.

Thanks,
Mark.

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

* Re: [PATCH v3 06/10] arm64: efi: add EFI stub
  2017-02-08 17:03           ` Mark Rutland
  (?)
@ 2017-02-08 17:40             ` Ard Biesheuvel
  -1 siblings, 0 replies; 55+ messages in thread
From: Ard Biesheuvel @ 2017-02-08 17:40 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Timur Tabi, linux-efi, Catalin Marinas, lkml, Leif Lindholm,
	Mark Salter, linux-arm-kernel


> On 8 Feb 2017, at 17:03, Mark Rutland <mark.rutland@arm.com> wrote:
> 
>> On Wed, Feb 08, 2017 at 10:35:02AM -0600, Timur Tabi wrote:
>> On 02/08/2017 10:29 AM, Ard Biesheuvel wrote:
>>>>>>> +       status = handle_cmdline_files(sys_table, image, cmdline_ptr,
>>>>>>> +                                     "initrd=", dram_base + SZ_512M,
>>>>>>> +                                     (unsigned long *)&initrd_addr,
>>>>>>> +                                     (unsigned long *)&initrd_size);
>>>>> 
>>>>> So I know this patch is almost three years old, but why is there a
>>>>> 512M limit on the initrd size?
>>>>> 
>>> How do you reckon this constitutes a limit?
>> 
>> handle_cmdline_files() calls efi_high_alloc() with that limit.  I'm
>> still trying to understand all the details myself, but apparently
>> our firmware and initrd need to fit within the first 512MB because
>> of dram_base + SZ_512M. When we change "dram_base + SZ_512M" to
>> "~0", everything works.
> 
> Just to check, how big is that initrd?
> 
> I guess it's possible that there simply isn't sufficient contiguous free
> memory in that range, even if the initrd isn't that large. Can you share
> the EFI memory map dump from booting with efi=debug?
> 
> We originally needed to restrict this to ensure that the kernel could
> map the initrd (and I think the 512M restriction specifically was
> inherited from the DTB mapping restriction). Since then, we have relaxed
> things in the kernel, and today Documentation/arm64/booting.txt says:
> 
>    If an initrd/initramfs is passed to the kernel at boot, it must
>    reside entirely within a 1 GB aligned physical memory window of
>    up to 32 GB in size that fully covers the kernel Image as well.
> 
> ... so I think the EFI stub should be able to take advantage of that
> relaxation.
> 
> Ard?
> 

Interestingly enough, this code originates on 32-bit ARM, where the linear mapping is only 800 MB so I suspect that may have something to do with it.

I agree the stub should simply follow the rules laid out in booting.txt. I think nobody hit this because it is usually GRUB that loads the initrd not the EFI stub

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

* Re: [PATCH v3 06/10] arm64: efi: add EFI stub
@ 2017-02-08 17:40             ` Ard Biesheuvel
  0 siblings, 0 replies; 55+ messages in thread
From: Ard Biesheuvel @ 2017-02-08 17:40 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Timur Tabi, linux-efi-u79uwXL29TY76Z2rM5mHXA, Catalin Marinas,
	lkml, Leif Lindholm, Mark Salter,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r


> On 8 Feb 2017, at 17:03, Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org> wrote:
> 
>> On Wed, Feb 08, 2017 at 10:35:02AM -0600, Timur Tabi wrote:
>> On 02/08/2017 10:29 AM, Ard Biesheuvel wrote:
>>>>>>> +       status = handle_cmdline_files(sys_table, image, cmdline_ptr,
>>>>>>> +                                     "initrd=", dram_base + SZ_512M,
>>>>>>> +                                     (unsigned long *)&initrd_addr,
>>>>>>> +                                     (unsigned long *)&initrd_size);
>>>>> 
>>>>> So I know this patch is almost three years old, but why is there a
>>>>> 512M limit on the initrd size?
>>>>> 
>>> How do you reckon this constitutes a limit?
>> 
>> handle_cmdline_files() calls efi_high_alloc() with that limit.  I'm
>> still trying to understand all the details myself, but apparently
>> our firmware and initrd need to fit within the first 512MB because
>> of dram_base + SZ_512M. When we change "dram_base + SZ_512M" to
>> "~0", everything works.
> 
> Just to check, how big is that initrd?
> 
> I guess it's possible that there simply isn't sufficient contiguous free
> memory in that range, even if the initrd isn't that large. Can you share
> the EFI memory map dump from booting with efi=debug?
> 
> We originally needed to restrict this to ensure that the kernel could
> map the initrd (and I think the 512M restriction specifically was
> inherited from the DTB mapping restriction). Since then, we have relaxed
> things in the kernel, and today Documentation/arm64/booting.txt says:
> 
>    If an initrd/initramfs is passed to the kernel at boot, it must
>    reside entirely within a 1 GB aligned physical memory window of
>    up to 32 GB in size that fully covers the kernel Image as well.
> 
> ... so I think the EFI stub should be able to take advantage of that
> relaxation.
> 
> Ard?
> 

Interestingly enough, this code originates on 32-bit ARM, where the linear mapping is only 800 MB so I suspect that may have something to do with it.

I agree the stub should simply follow the rules laid out in booting.txt. I think nobody hit this because it is usually GRUB that loads the initrd not the EFI stub

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

* [PATCH v3 06/10] arm64: efi: add EFI stub
@ 2017-02-08 17:40             ` Ard Biesheuvel
  0 siblings, 0 replies; 55+ messages in thread
From: Ard Biesheuvel @ 2017-02-08 17:40 UTC (permalink / raw)
  To: linux-arm-kernel


> On 8 Feb 2017, at 17:03, Mark Rutland <mark.rutland@arm.com> wrote:
> 
>> On Wed, Feb 08, 2017 at 10:35:02AM -0600, Timur Tabi wrote:
>> On 02/08/2017 10:29 AM, Ard Biesheuvel wrote:
>>>>>>> +       status = handle_cmdline_files(sys_table, image, cmdline_ptr,
>>>>>>> +                                     "initrd=", dram_base + SZ_512M,
>>>>>>> +                                     (unsigned long *)&initrd_addr,
>>>>>>> +                                     (unsigned long *)&initrd_size);
>>>>> 
>>>>> So I know this patch is almost three years old, but why is there a
>>>>> 512M limit on the initrd size?
>>>>> 
>>> How do you reckon this constitutes a limit?
>> 
>> handle_cmdline_files() calls efi_high_alloc() with that limit.  I'm
>> still trying to understand all the details myself, but apparently
>> our firmware and initrd need to fit within the first 512MB because
>> of dram_base + SZ_512M. When we change "dram_base + SZ_512M" to
>> "~0", everything works.
> 
> Just to check, how big is that initrd?
> 
> I guess it's possible that there simply isn't sufficient contiguous free
> memory in that range, even if the initrd isn't that large. Can you share
> the EFI memory map dump from booting with efi=debug?
> 
> We originally needed to restrict this to ensure that the kernel could
> map the initrd (and I think the 512M restriction specifically was
> inherited from the DTB mapping restriction). Since then, we have relaxed
> things in the kernel, and today Documentation/arm64/booting.txt says:
> 
>    If an initrd/initramfs is passed to the kernel at boot, it must
>    reside entirely within a 1 GB aligned physical memory window of
>    up to 32 GB in size that fully covers the kernel Image as well.
> 
> ... so I think the EFI stub should be able to take advantage of that
> relaxation.
> 
> Ard?
> 

Interestingly enough, this code originates on 32-bit ARM, where the linear mapping is only 800 MB so I suspect that may have something to do with it.

I agree the stub should simply follow the rules laid out in booting.txt. I think nobody hit this because it is usually GRUB that loads the initrd not the EFI stub

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

end of thread, other threads:[~2017-02-08 17:41 UTC | newest]

Thread overview: 55+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-04 18:45 [PATCH v3 00/10] arm64: UEFI support Leif Lindholm
2014-04-04 18:45 ` Leif Lindholm
2014-04-04 18:45 ` Leif Lindholm
2014-04-04 18:45 ` [PATCH v3 01/10] lib: add fdt_empty_tree.c Leif Lindholm
2014-04-04 18:45   ` Leif Lindholm
2014-04-04 18:45 ` [PATCH v3 02/10] doc: efi-stub.txt updates for ARM Leif Lindholm
2014-04-04 18:45   ` Leif Lindholm
2014-04-04 18:45   ` Leif Lindholm
2014-04-04 18:45 ` [PATCH v3 03/10] efi: add helper function to get UEFI params from FDT Leif Lindholm
2014-04-04 18:45   ` Leif Lindholm
2014-04-04 18:45 ` [PATCH v3 04/10] arm64: Add function to create identity mappings Leif Lindholm
2014-04-04 18:45   ` Leif Lindholm
2014-04-04 18:45 ` [PATCH v3 05/10] efi: Add shared FDT related functions for ARM/ARM64 Leif Lindholm
2014-04-04 18:45   ` Leif Lindholm
2014-04-04 18:45   ` Leif Lindholm
2014-04-04 18:45 ` [PATCH v3 06/10] arm64: efi: add EFI stub Leif Lindholm
2014-04-04 18:45   ` Leif Lindholm
2014-04-09 14:20   ` Mark Rutland
2014-04-09 14:20     ` Mark Rutland
2014-04-09 14:20     ` Mark Rutland
2014-04-10 12:54     ` Mark Salter
2014-04-10 12:54       ` Mark Salter
2014-04-10 12:54       ` Mark Salter
2017-02-08 16:28   ` Timur Tabi
2017-02-08 16:28     ` Timur Tabi
2017-02-08 16:28     ` Timur Tabi
2017-02-08 16:29     ` Ard Biesheuvel
2017-02-08 16:29       ` Ard Biesheuvel
2017-02-08 16:29       ` Ard Biesheuvel
2017-02-08 16:35       ` Timur Tabi
2017-02-08 16:35         ` Timur Tabi
2017-02-08 16:35         ` Timur Tabi
2017-02-08 17:03         ` Mark Rutland
2017-02-08 17:03           ` Mark Rutland
2017-02-08 17:03           ` Mark Rutland
2017-02-08 17:22           ` Jeffrey Hugo
2017-02-08 17:22             ` Jeffrey Hugo
2017-02-08 17:22             ` Jeffrey Hugo
2017-02-08 17:30           ` Jeffrey Hugo
2017-02-08 17:30             ` Jeffrey Hugo
2017-02-08 17:30             ` Jeffrey Hugo
2017-02-08 17:34             ` Mark Rutland
2017-02-08 17:34               ` Mark Rutland
2017-02-08 17:34               ` Mark Rutland
2017-02-08 17:40           ` Ard Biesheuvel
2017-02-08 17:40             ` Ard Biesheuvel
2017-02-08 17:40             ` Ard Biesheuvel
2014-04-04 18:45 ` [PATCH v3 07/10] doc: arm64: add description of EFI stub support Leif Lindholm
2014-04-04 18:45   ` Leif Lindholm
2014-04-04 18:45 ` [PATCH v3 08/10] arm64: add EFI runtime services Leif Lindholm
2014-04-04 18:45   ` Leif Lindholm
2014-04-04 18:45 ` [PATCH v3 09/10] doc: arm: add UEFI support documentation Leif Lindholm
2014-04-04 18:45   ` Leif Lindholm
2014-04-04 18:45 ` [PATCH v3 10/10] efi/arm64: ignore dtb= when UEFI SecureBoot is enabled Leif Lindholm
2014-04-04 18:45   ` 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.