linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [v4 PATCH 0/3] Add UEFI support for RISC-V
@ 2020-04-21  3:33 Atish Patra
  2020-04-21  3:33 ` [v4 PATCH 1/3] RISC-V: Define fixmap bindings for generic early ioremap support Atish Patra
                   ` (3 more replies)
  0 siblings, 4 replies; 16+ messages in thread
From: Atish Patra @ 2020-04-21  3:33 UTC (permalink / raw)
  To: linux-kernel
  Cc: Atish Patra, Ard Biesheuvel, linux-efi, linux-riscv,
	Masahiro Yamada, Palmer Dabbelt, Heinrich Schuchardt

This series adds UEFI support for RISC-V. Currently, only boot time
services have been added. Runtime services will be added in a separate
series. This series depends on some core EFI patches
present in current in efi-next and following other patches.

U-Boot: Adds the boot hartid under chosen node.
https://lists.denx.de/pipermail/u-boot/2020-April/405726.html

Linux kernel: 5.7-rc1

OpenSBI: master

Patch 1 just moves arm-stub code to a generic code so that it can be used
across different architecture.

Patch 3 adds fixmap bindings so that CONFIG_EFI can be compiled and we do not
have create separate config to enable boot time services. 
As runtime services are not enabled at this time, full generic early ioremap
support is also not added in this series.

Patch 4 and 5 adds the PE/COFF header and EFI stub code support for RISC-V
respectively.

The patches can also be found in following git repo.

https://github.com/atishp04/linux/tree/wip_uefi_riscv_v4

The patches have been verified on Qemu using bootefi command in U-Boot.

Changes from v3->v4:
1. Rebased on top of efi-next.
2. Dropped patch 1 & 2 from this series as it is already queued in efi-next.
Changes from v2->v3:
3. Improved handle_kernel_image() for RISC-V.

Changes from v1->v2:
1. Rebased on 5.7-rc1.
2. Fixed minor typos and removed redundant macros/comments.

Changes from previous version:
1. Renamed to the generic efi stub macro.
2. Address all redundant comments.
3. Supported EFI kernel image with normal booti command.
4. Removed runtime service related macro defines.

Atish Patra (3):
RISC-V: Define fixmap bindings for generic early ioremap support
RISC-V: Add PE/COFF header for EFI stub
RISC-V: Add EFI stub support.

arch/riscv/Kconfig                        |  21 +++++
arch/riscv/Makefile                       |   1 +
arch/riscv/configs/defconfig              |   1 +
arch/riscv/include/asm/Kbuild             |   1 +
arch/riscv/include/asm/efi.h              |  44 +++++++++
arch/riscv/include/asm/fixmap.h           |  18 ++++
arch/riscv/include/asm/io.h               |   1 +
arch/riscv/include/asm/sections.h         |  13 +++
arch/riscv/kernel/Makefile                |   4 +
arch/riscv/kernel/efi-header.S            |  99 ++++++++++++++++++++
arch/riscv/kernel/head.S                  |  16 ++++
arch/riscv/kernel/image-vars.h            |  53 +++++++++++
arch/riscv/kernel/vmlinux.lds.S           |  20 +++-
drivers/firmware/efi/Kconfig              |   2 +-
drivers/firmware/efi/libstub/Makefile     |  10 ++
drivers/firmware/efi/libstub/riscv-stub.c | 106 ++++++++++++++++++++++
16 files changed, 407 insertions(+), 3 deletions(-)
create mode 100644 arch/riscv/include/asm/efi.h
create mode 100644 arch/riscv/include/asm/sections.h
create mode 100644 arch/riscv/kernel/efi-header.S
create mode 100644 arch/riscv/kernel/image-vars.h
create mode 100644 drivers/firmware/efi/libstub/riscv-stub.c

--
2.24.0


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

* [v4 PATCH 1/3] RISC-V: Define fixmap bindings for generic early ioremap support
  2020-04-21  3:33 [v4 PATCH 0/3] Add UEFI support for RISC-V Atish Patra
@ 2020-04-21  3:33 ` Atish Patra
  2020-04-21 19:52   ` Palmer Dabbelt
  2020-04-21  3:33 ` [v4 PATCH 2/3] RISC-V: Add PE/COFF header for EFI stub Atish Patra
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 16+ messages in thread
From: Atish Patra @ 2020-04-21  3:33 UTC (permalink / raw)
  To: linux-kernel
  Cc: Atish Patra, Ard Biesheuvel, linux-efi, linux-riscv,
	Masahiro Yamada, Palmer Dabbelt, Heinrich Schuchardt

UEFI uses early IO or memory mappings for runtime services before
normal ioremap() is usable. This patch only adds minimum necessary
fixmap bindings and headers for generic ioremap support to work.

Signed-off-by: Atish Patra <atish.patra@wdc.com>
Acked-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/riscv/Kconfig              |  1 +
 arch/riscv/include/asm/Kbuild   |  1 +
 arch/riscv/include/asm/fixmap.h | 18 ++++++++++++++++++
 arch/riscv/include/asm/io.h     |  1 +
 4 files changed, 21 insertions(+)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index a197258595ef..f39e326a7a42 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -68,6 +68,7 @@ config RISCV
 	select ARCH_HAS_GCOV_PROFILE_ALL
 	select HAVE_COPY_THREAD_TLS
 	select HAVE_ARCH_KASAN if MMU && 64BIT
+	select GENERIC_EARLY_IOREMAP
 
 config ARCH_MMAP_RND_BITS_MIN
 	default 18 if 64BIT
diff --git a/arch/riscv/include/asm/Kbuild b/arch/riscv/include/asm/Kbuild
index 3d9410bb4de0..59dd7be55005 100644
--- a/arch/riscv/include/asm/Kbuild
+++ b/arch/riscv/include/asm/Kbuild
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
+generic-y += early_ioremap.h
 generic-y += extable.h
 generic-y += flat.h
 generic-y += kvm_para.h
diff --git a/arch/riscv/include/asm/fixmap.h b/arch/riscv/include/asm/fixmap.h
index 2368d49eb4ef..ba5096d65fb0 100644
--- a/arch/riscv/include/asm/fixmap.h
+++ b/arch/riscv/include/asm/fixmap.h
@@ -30,6 +30,24 @@ enum fixed_addresses {
 	FIX_TEXT_POKE1,
 	FIX_TEXT_POKE0,
 	FIX_EARLYCON_MEM_BASE,
+	/*
+	 * Make sure that it is 2MB aligned.
+	 */
+#define NR_FIX_SZ_2M	(SZ_2M / PAGE_SIZE)
+	FIX_THOLE = NR_FIX_SZ_2M - FIX_PMD - 1,
+
+	__end_of_permanent_fixed_addresses,
+	/*
+	 * Temporary boot-time mappings, used by early_ioremap(),
+	 * before ioremap() is functional.
+	 */
+#define NR_FIX_BTMAPS		(SZ_256K / PAGE_SIZE)
+#define FIX_BTMAPS_SLOTS	7
+#define TOTAL_FIX_BTMAPS	(NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS)
+
+	FIX_BTMAP_END = __end_of_permanent_fixed_addresses,
+	FIX_BTMAP_BEGIN = FIX_BTMAP_END + TOTAL_FIX_BTMAPS - 1,
+
 	__end_of_fixed_addresses
 };
 
diff --git a/arch/riscv/include/asm/io.h b/arch/riscv/include/asm/io.h
index 0f477206a4ed..047f414b6948 100644
--- a/arch/riscv/include/asm/io.h
+++ b/arch/riscv/include/asm/io.h
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 #include <asm/mmiowb.h>
 #include <asm/pgtable.h>
+#include <asm/early_ioremap.h>
 
 /*
  * MMIO access functions are separated out to break dependency cycles
-- 
2.24.0


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

* [v4 PATCH 2/3] RISC-V: Add PE/COFF header for EFI stub
  2020-04-21  3:33 [v4 PATCH 0/3] Add UEFI support for RISC-V Atish Patra
  2020-04-21  3:33 ` [v4 PATCH 1/3] RISC-V: Define fixmap bindings for generic early ioremap support Atish Patra
@ 2020-04-21  3:33 ` Atish Patra
  2020-04-21 17:51   ` Ard Biesheuvel
  2020-04-21 20:02   ` Palmer Dabbelt
  2020-04-21  3:33 ` [v4 PATCH 3/3] RISC-V: Add EFI stub support Atish Patra
  2020-04-21  7:24 ` [v4 PATCH 0/3] Add UEFI support for RISC-V Ard Biesheuvel
  3 siblings, 2 replies; 16+ messages in thread
From: Atish Patra @ 2020-04-21  3:33 UTC (permalink / raw)
  To: linux-kernel
  Cc: Atish Patra, Ard Biesheuvel, linux-efi, linux-riscv,
	Masahiro Yamada, Palmer Dabbelt, Heinrich Schuchardt

Linux kernel Image can appear as an EFI application With appropriate
PE/COFF header fields in the beginning of the Image header. An EFI
application loader can directly load a Linux kernel Image and an EFI
stub residing in kernel can boot Linux kernel directly.

Add the necessary PE/COFF header.

Signed-off-by: Atish Patra <atish.patra@wdc.com>
---
 arch/riscv/include/asm/sections.h | 13 ++++
 arch/riscv/kernel/Makefile        |  4 ++
 arch/riscv/kernel/efi-header.S    | 99 +++++++++++++++++++++++++++++++
 arch/riscv/kernel/head.S          | 16 +++++
 arch/riscv/kernel/image-vars.h    | 53 +++++++++++++++++
 arch/riscv/kernel/vmlinux.lds.S   | 20 ++++++-
 6 files changed, 203 insertions(+), 2 deletions(-)
 create mode 100644 arch/riscv/include/asm/sections.h
 create mode 100644 arch/riscv/kernel/efi-header.S
 create mode 100644 arch/riscv/kernel/image-vars.h

diff --git a/arch/riscv/include/asm/sections.h b/arch/riscv/include/asm/sections.h
new file mode 100644
index 000000000000..3a9971b1210f
--- /dev/null
+++ b/arch/riscv/include/asm/sections.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2020 Western Digital Corporation or its affiliates.
+ */
+#ifndef __ASM_SECTIONS_H
+#define __ASM_SECTIONS_H
+
+#include <asm-generic/sections.h>
+
+extern char _start[];
+extern char _start_kernel[];
+
+#endif /* __ASM_SECTIONS_H */
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index 86c83081044f..86ca755f8a9f 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -32,6 +32,10 @@ obj-y	+= patch.o
 obj-$(CONFIG_MMU) += vdso.o vdso/
 
 obj-$(CONFIG_RISCV_M_MODE)	+= clint.o traps_misaligned.o
+OBJCOPYFLAGS := --prefix-symbols=__efistub_
+$(obj)/%.stub.o: $(obj)/%.o FORCE
+	$(call if_changed,objcopy)
+
 obj-$(CONFIG_FPU)		+= fpu.o
 obj-$(CONFIG_SMP)		+= smpboot.o
 obj-$(CONFIG_SMP)		+= smp.o
diff --git a/arch/riscv/kernel/efi-header.S b/arch/riscv/kernel/efi-header.S
new file mode 100644
index 000000000000..69dde8268527
--- /dev/null
+++ b/arch/riscv/kernel/efi-header.S
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2020 Western Digital Corporation or its affiliates.
+ * Adapted from arch/arm64/kernel/efi-header.S
+ */
+
+#include <linux/pe.h>
+#include <linux/sizes.h>
+
+	.macro	__EFI_PE_HEADER
+	.long	PE_MAGIC
+coff_header:
+	.short	IMAGE_FILE_MACHINE_RISCV64		// Machine
+	.short	section_count				// NumberOfSections
+	.long	0 					// TimeDateStamp
+	.long	0					// PointerToSymbolTable
+	.long	0					// NumberOfSymbols
+	.short	section_table - optional_header		// SizeOfOptionalHeader
+	.short	IMAGE_FILE_DEBUG_STRIPPED | \
+		IMAGE_FILE_EXECUTABLE_IMAGE | \
+		IMAGE_FILE_LINE_NUMS_STRIPPED		// Characteristics
+
+optional_header:
+	.short	PE_OPT_MAGIC_PE32PLUS			// PE32+ format
+	.byte	0x02					// MajorLinkerVersion
+	.byte	0x14					// MinorLinkerVersion
+	.long	__text_end - efi_header_end		// SizeOfCode
+	.long	_end - __text_end			// SizeOfInitializedData
+	.long	0					// SizeOfUninitializedData
+	.long	__efistub_efi_entry - _start		// AddressOfEntryPoint
+	.long	efi_header_end - _start			// BaseOfCode
+
+extra_header_fields:
+	.quad	0					// ImageBase
+	.long	SZ_4K					// SectionAlignment
+	.long	PECOFF_FILE_ALIGNMENT			// FileAlignment
+	.short	0					// MajorOperatingSystemVersion
+	.short	0					// MinorOperatingSystemVersion
+	.short	LINUX_EFISTUB_MAJOR_VERSION		// MajorImageVersion
+	.short	LINUX_EFISTUB_MINOR_VERSION		// MinorImageVersion
+	.short	0					// MajorSubsystemVersion
+	.short	0					// MinorSubsystemVersion
+	.long	0					// Win32VersionValue
+
+	.long	_end - _start				// SizeOfImage
+
+	// Everything before the kernel image is considered part of the header
+	.long	efi_header_end - _start			// SizeOfHeaders
+	.long	0					// CheckSum
+	.short	IMAGE_SUBSYSTEM_EFI_APPLICATION		// Subsystem
+	.short	0					// DllCharacteristics
+	.quad	0					// SizeOfStackReserve
+	.quad	0					// SizeOfStackCommit
+	.quad	0					// SizeOfHeapReserve
+	.quad	0					// SizeOfHeapCommit
+	.long	0					// LoaderFlags
+	.long	(section_table - .) / 8			// NumberOfRvaAndSizes
+
+	.quad	0					// ExportTable
+	.quad	0					// ImportTable
+	.quad	0					// ResourceTable
+	.quad	0					// ExceptionTable
+	.quad	0					// CertificationTable
+	.quad	0					// BaseRelocationTable
+
+	// Section table
+section_table:
+	.ascii	".text\0\0\0"
+	.long	__text_end - efi_header_end		// VirtualSize
+	.long	efi_header_end - _start			// VirtualAddress
+	.long	__text_end - efi_header_end		// SizeOfRawData
+	.long	efi_header_end - _start			// PointerToRawData
+
+	.long	0					// PointerToRelocations
+	.long	0					// PointerToLineNumbers
+	.short	0					// NumberOfRelocations
+	.short	0					// NumberOfLineNumbers
+	.long	IMAGE_SCN_CNT_CODE | \
+		IMAGE_SCN_MEM_READ | \
+		IMAGE_SCN_MEM_EXECUTE			// Characteristics
+
+	.ascii	".data\0\0\0"
+	.long	__data_virt_size			// VirtualSize
+	.long	__text_end - _start			// VirtualAddress
+	.long	__data_raw_size				// SizeOfRawData
+	.long	__text_end - _start			// PointerToRawData
+
+	.long	0					// PointerToRelocations
+	.long	0					// PointerToLineNumbers
+	.short	0					// NumberOfRelocations
+	.short	0					// NumberOfLineNumbers
+	.long	IMAGE_SCN_CNT_INITIALIZED_DATA | \
+		IMAGE_SCN_MEM_READ | \
+		IMAGE_SCN_MEM_WRITE			// Characteristics
+
+	.set	section_count, (. - section_table) / 40
+
+efi_header_end:
+	.endm
diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S
index 98a406474e7d..ddd613dac9d6 100644
--- a/arch/riscv/kernel/head.S
+++ b/arch/riscv/kernel/head.S
@@ -13,6 +13,7 @@
 #include <asm/csr.h>
 #include <asm/hwcap.h>
 #include <asm/image.h>
+#include "efi-header.S"
 
 __HEAD
 ENTRY(_start)
@@ -22,10 +23,18 @@ ENTRY(_start)
 	 * Do not modify it without modifying the structure and all bootloaders
 	 * that expects this header format!!
 	 */
+#ifdef CONFIG_EFI
+	/*
+	 * This instruction decodes to "MZ" ASCII required by UEFI.
+	 */
+	li s4,-13
+	j _start_kernel
+#else
 	/* jump to start kernel */
 	j _start_kernel
 	/* reserved */
 	.word 0
+#endif
 	.balign 8
 #if __riscv_xlen == 64
 	/* Image load offset(2MB) from start of RAM */
@@ -43,7 +52,14 @@ ENTRY(_start)
 	.ascii RISCV_IMAGE_MAGIC
 	.balign 4
 	.ascii RISCV_IMAGE_MAGIC2
+#ifdef CONFIG_EFI
+	.word pe_head_start - _start
+pe_head_start:
+
+	__EFI_PE_HEADER
+#else
 	.word 0
+#endif
 
 .align 2
 #ifdef CONFIG_MMU
diff --git a/arch/riscv/kernel/image-vars.h b/arch/riscv/kernel/image-vars.h
new file mode 100644
index 000000000000..bd8b764f0ad9
--- /dev/null
+++ b/arch/riscv/kernel/image-vars.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2020 Western Digital Corporation or its affiliates.
+ * Linker script variables to be set after section resolution, as
+ * ld.lld does not like variables assigned before SECTIONS is processed.
+ * Based on arch/arm64/kerne/image-vars.h
+ */
+#ifndef __RISCV_KERNEL_IMAGE_VARS_H
+#define __RISCV_KERNEL_IMAGE_VARS_H
+
+#ifndef LINKER_SCRIPT
+#error This file should only be included in vmlinux.lds.S
+#endif
+
+#ifdef CONFIG_EFI
+
+__efistub_stext_offset = _start_kernel - _start;
+
+/*
+ * The EFI stub has its own symbol namespace prefixed by __efistub_, to
+ * isolate it from the kernel proper. The following symbols are legally
+ * accessed by the stub, so provide some aliases to make them accessible.
+ * Only include data symbols here, or text symbols of functions that are
+ * guaranteed to be safe when executed at another offset than they were
+ * linked at. The routines below are all implemented in assembler in a
+ * position independent manner
+ */
+__efistub_memcmp		= memcmp;
+__efistub_memchr		= memchr;
+__efistub_memcpy		= memcpy;
+__efistub_memmove		= memmove;
+__efistub_memset		= memset;
+__efistub_strlen		= strlen;
+__efistub_strnlen		= strnlen;
+__efistub_strcmp		= strcmp;
+__efistub_strncmp		= strncmp;
+__efistub_strrchr		= strrchr;
+
+#ifdef CONFIG_KASAN
+__efistub___memcpy		= memcpy;
+__efistub___memmove		= memmove;
+__efistub___memset		= memset;
+#endif
+
+__efistub__start		= _start;
+__efistub__start_kernel		= _start_kernel;
+__efistub__end			= _end;
+__efistub__edata		= _edata;
+__efistub_screen_info		= screen_info;
+
+#endif
+
+#endif /* __RISCV_KERNEL_IMAGE_VARS_H */
diff --git a/arch/riscv/kernel/vmlinux.lds.S b/arch/riscv/kernel/vmlinux.lds.S
index 0339b6bbe11a..20ebf7e8c215 100644
--- a/arch/riscv/kernel/vmlinux.lds.S
+++ b/arch/riscv/kernel/vmlinux.lds.S
@@ -10,6 +10,7 @@
 #include <asm/cache.h>
 #include <asm/thread_info.h>
 #include <asm/set_memory.h>
+#include "image-vars.h"
 
 #include <linux/sizes.h>
 OUTPUT_ARCH(riscv)
@@ -17,6 +18,14 @@ ENTRY(_start)
 
 jiffies = jiffies_64;
 
+PECOFF_FILE_ALIGNMENT = 0x200;
+#ifdef CONFIG_EFI
+#define PECOFF_EDATA_PADDING	\
+	.pecoff_edata_padding : { BYTE(0); . = ALIGN(PECOFF_FILE_ALIGNMENT); }
+#else
+#define PECOFF_EDATA_PADDING
+#endif
+
 SECTIONS
 {
 	/* Beginning of code and text segment */
@@ -62,6 +71,8 @@ SECTIONS
 		_etext = .;
 	}
 
+	__text_end = .;
+
 	/* Start of data section */
 	_sdata = .;
 	RO_DATA(SECTION_ALIGN)
@@ -78,9 +89,12 @@ SECTIONS
 	.sdata : {
 		__global_pointer$ = . + 0x800;
 		*(.sdata*)
-		/* End of data section */
-		_edata = .;
 	}
+	PECOFF_EDATA_PADDING
+	__data_raw_size = ABSOLUTE(. - __text_end);
+
+	/* End of data section */
+	_edata = .;
 
 	BSS_SECTION(PAGE_SIZE, PAGE_SIZE, 0)
 
@@ -88,6 +102,8 @@ SECTIONS
 		*(.rel.dyn*)
 	}
 
+	__data_virt_size = ABSOLUTE(. - __text_end);
+
 	_end = .;
 
 	STABS_DEBUG
-- 
2.24.0


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

* [v4 PATCH 3/3] RISC-V: Add EFI stub support.
  2020-04-21  3:33 [v4 PATCH 0/3] Add UEFI support for RISC-V Atish Patra
  2020-04-21  3:33 ` [v4 PATCH 1/3] RISC-V: Define fixmap bindings for generic early ioremap support Atish Patra
  2020-04-21  3:33 ` [v4 PATCH 2/3] RISC-V: Add PE/COFF header for EFI stub Atish Patra
@ 2020-04-21  3:33 ` Atish Patra
  2020-04-21 20:08   ` Palmer Dabbelt
  2020-04-21  7:24 ` [v4 PATCH 0/3] Add UEFI support for RISC-V Ard Biesheuvel
  3 siblings, 1 reply; 16+ messages in thread
From: Atish Patra @ 2020-04-21  3:33 UTC (permalink / raw)
  To: linux-kernel
  Cc: Atish Patra, Ard Biesheuvel, linux-efi, linux-riscv,
	Masahiro Yamada, Palmer Dabbelt, Heinrich Schuchardt

Add a RISC-V architecture specific stub code that actually copies the
actual kernel image to a valid address and jump to it after boot services
are terminated. Enable UEFI related kernel configs as well for RISC-V.

Signed-off-by: Atish Patra <atish.patra@wdc.com>
---
 arch/riscv/Kconfig                        |  20 ++++
 arch/riscv/Makefile                       |   1 +
 arch/riscv/configs/defconfig              |   1 +
 arch/riscv/include/asm/efi.h              |  44 +++++++++
 drivers/firmware/efi/Kconfig              |   2 +-
 drivers/firmware/efi/libstub/Makefile     |  10 ++
 drivers/firmware/efi/libstub/riscv-stub.c | 106 ++++++++++++++++++++++
 7 files changed, 183 insertions(+), 1 deletion(-)
 create mode 100644 arch/riscv/include/asm/efi.h
 create mode 100644 drivers/firmware/efi/libstub/riscv-stub.c

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index f39e326a7a42..eb4f41c8f3ce 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -379,10 +379,30 @@ config CMDLINE_FORCE
 
 endchoice
 
+config EFI_STUB
+	bool
+
+config EFI
+	bool "UEFI runtime support"
+	depends on OF
+	select LIBFDT
+	select UCS2_STRING
+	select EFI_PARAMS_FROM_FDT
+	select EFI_STUB
+	select EFI_GENERIC_STUB
+	default y
+	help
+	  This option provides support for runtime services provided
+	  by UEFI firmware (such as non-volatile variables, realtime
+          clock, and platform reset). A UEFI stub is also provided to
+	  allow the kernel to be booted as an EFI application. This
+	  is only useful on systems that have UEFI firmware.
+
 endmenu
 
 menu "Power management options"
 
 source "kernel/power/Kconfig"
+source "drivers/firmware/Kconfig"
 
 endmenu
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index fb6e37db836d..079435804d6d 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -80,6 +80,7 @@ head-y := arch/riscv/kernel/head.o
 core-y += arch/riscv/
 
 libs-y += arch/riscv/lib/
+core-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
 
 PHONY += vdso_install
 vdso_install:
diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig
index 4da4886246a4..ae69e12d306a 100644
--- a/arch/riscv/configs/defconfig
+++ b/arch/riscv/configs/defconfig
@@ -129,3 +129,4 @@ CONFIG_DEBUG_BLOCK_EXT_DEVT=y
 # CONFIG_RUNTIME_TESTING_MENU is not set
 CONFIG_MEMTEST=y
 # CONFIG_SYSFS_SYSCALL is not set
+CONFIG_EFI=y
diff --git a/arch/riscv/include/asm/efi.h b/arch/riscv/include/asm/efi.h
new file mode 100644
index 000000000000..62d7d5eafed8
--- /dev/null
+++ b/arch/riscv/include/asm/efi.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020 Western Digital Corporation or its affiliates.
+ * Based on arch/arm64/include/asm/efi.h
+ */
+#ifndef _ASM_EFI_H
+#define _ASM_EFI_H
+
+#include <asm/io.h>
+#include <asm/mmu_context.h>
+#include <asm/ptrace.h>
+#include <asm/tlbflush.h>
+
+#define VA_BITS_MIN 39
+
+/* on RISC-V, the FDT may be located anywhere in system RAM */
+static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base)
+{
+	return ULONG_MAX;
+}
+
+/* Load initrd at enough distance from DRAM start */
+static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
+						    unsigned long image_addr)
+{
+	return dram_base + SZ_256M;
+}
+
+#define efi_bs_call(func, ...)	efi_system_table()->boottime->func(__VA_ARGS__)
+#define efi_rt_call(func, ...)	efi_system_table()->runtime->func(__VA_ARGS__)
+#define efi_is_native()		(true)
+
+#define efi_table_attr(inst, attr)	(inst->attr)
+
+#define efi_call_proto(inst, func, ...) inst->func(inst, ##__VA_ARGS__)
+
+#define alloc_screen_info(x...)		(&screen_info)
+extern char stext_offset[];
+
+static inline void free_screen_info(struct screen_info *si)
+{
+}
+
+#endif /* _ASM_EFI_H */
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 2a2b2b96a1dc..fcdc789d3f87 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -111,7 +111,7 @@ config EFI_GENERIC_STUB
 
 config EFI_ARMSTUB_DTB_LOADER
 	bool "Enable the DTB loader"
-	depends on EFI_GENERIC_STUB
+	depends on EFI_GENERIC_STUB && !RISCV
 	default y
 	help
 	  Select this config option to add support for the dtb= command
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index 0f57293d777e..eb365c55c0fe 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -22,6 +22,8 @@ cflags-$(CONFIG_ARM64)		:= $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \
 cflags-$(CONFIG_ARM)		:= $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \
 				   -fno-builtin -fpic \
 				   $(call cc-option,-mno-single-pic-base)
+cflags-$(CONFIG_RISCV)		:= $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \
+				   -fpic
 
 cflags-$(CONFIG_EFI_GENERIC_STUB) += -I$(srctree)/scripts/dtc/libfdt
 
@@ -57,6 +59,7 @@ lib-$(CONFIG_EFI_GENERIC_STUB)	+= efi-stub.o fdt.o string.o \
 lib-$(CONFIG_ARM)		+= arm32-stub.o
 lib-$(CONFIG_ARM64)		+= arm64-stub.o
 lib-$(CONFIG_X86)		+= x86-stub.o
+lib-$(CONFIG_RISCV)		+= riscv-stub.o
 CFLAGS_arm32-stub.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 CFLAGS_arm64-stub.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
@@ -100,6 +103,13 @@ STUBCOPY_FLAGS-$(CONFIG_X86)	+= --rename-section .bss=.bss.efistub,load,alloc
 STUBCOPY_RELOC-$(CONFIG_X86_32)	:= R_386_32
 STUBCOPY_RELOC-$(CONFIG_X86_64)	:= R_X86_64_64
 
+# For RISC-V, we don't need anything special other than arm64. Keep all the
+# symbols in .init section and make sure that no absolute symbols references
+# doesn't exist.
+STUBCOPY_FLAGS-$(CONFIG_RISCV)	+= --prefix-alloc-sections=.init \
+				   --prefix-symbols=__efistub_
+STUBCOPY_RELOC-$(CONFIG_RISCV)	:= R_RISCV_HI20
+
 $(obj)/%.stub.o: $(obj)/%.o FORCE
 	$(call if_changed,stubcopy)
 
diff --git a/drivers/firmware/efi/libstub/riscv-stub.c b/drivers/firmware/efi/libstub/riscv-stub.c
new file mode 100644
index 000000000000..bd1d6fed8754
--- /dev/null
+++ b/drivers/firmware/efi/libstub/riscv-stub.c
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2013, 2014 Linaro Ltd;  <roy.franz@linaro.org>
+ * Copyright (C) 2020 Western Digital Corporation or its affiliates.
+ *
+ * This file implements the EFI boot stub for the RISC-V kernel.
+ * Adapted from ARM64 version at drivers/firmware/efi/libstub/arm64-stub.c.
+ */
+
+#include <linux/efi.h>
+#include <linux/libfdt.h>
+#include <linux/libfdt_env.h>
+#include <asm/efi.h>
+#include <asm/sections.h>
+
+#include "efistub.h"
+/*
+ * RISC-V requires the kernel image to placed 2 MB aligned base for 64 bit and
+ * 4MB for 32 bit.
+ */
+#ifdef CONFIG_64BIT
+#define MIN_KIMG_ALIGN	SZ_2M
+#else
+#define MIN_KIMG_ALIGN	SZ_4M
+#endif
+
+typedef __attribute__((noreturn)) void (*jump_kernel_func)(unsigned int,
+							   unsigned long);
+efi_status_t check_platform_features(void)
+{
+	return EFI_SUCCESS;
+}
+
+static u32 get_boot_hartid_from_fdt(unsigned long fdt)
+{
+	int chosen_node, len;
+	const fdt32_t *prop;
+
+	chosen_node = fdt_path_offset((void *)fdt, "/chosen");
+	if (chosen_node < 0)
+		return U32_MAX;
+	prop = fdt_getprop((void *)fdt, chosen_node, "boot-hartid", &len);
+	if (!prop || len != sizeof(u32))
+		return U32_MAX;
+
+	return fdt32_to_cpu(*prop);
+}
+
+/*
+ * Jump to real kernel here with following constraints.
+ * 1. MMU should be disabled.
+ * 2. a0 should contain hartid
+ * 3. a1 should DT address
+ */
+void __noreturn efi_enter_kernel(unsigned long entrypoint, unsigned long fdt,
+				 unsigned long fdt_size)
+{
+	unsigned long kernel_entry = entrypoint + (unsigned long)stext_offset;
+	jump_kernel_func jump_kernel = (jump_kernel_func) kernel_entry;
+	u32 hartid = get_boot_hartid_from_fdt(fdt);
+
+	if (hartid == U32_MAX)
+		/* We can not use panic or BUG at this point */
+		__asm__ __volatile__ ("ebreak");
+	/* Disable MMU */
+	csr_write(CSR_SATP, 0);
+	jump_kernel(hartid, fdt);
+}
+
+efi_status_t handle_kernel_image(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 = 0;
+	unsigned long preferred_addr;
+
+	kernel_size = _edata - _start;
+	*reserve_size = kernel_size + (_end - _edata);
+	*image_addr = (unsigned long)_start;
+
+	/*
+	 * RISC-V kernel maps PAGE_OFFSET virtual address to the same physical
+	 * address where kernel is booted. That's why kernel should boot from
+	 * as low as possible to avoid wastage of memory. Currently, dram_base
+	 * is occupied by the firmware. So the preferred address for kernel to
+	 * boot is next aligned address. If preferred address is not available,
+	 * relocate_kernel will fall back to efi_low_alloc_above to allocate
+	 * lowest possible memory region as long as the address and size meets
+	 * the alignment constraints.
+	 */
+	preferred_addr = round_up(dram_base, MIN_KIMG_ALIGN) + MIN_KIMG_ALIGN;
+	status = efi_relocate_kernel(image_addr, kernel_size, *reserve_size,
+				     preferred_addr, MIN_KIMG_ALIGN, dram_base);
+
+	if (status != EFI_SUCCESS) {
+		pr_efi_err("Failed to relocate kernel\n");
+		*reserve_size = 0;
+		return status;
+	}
+
+	return EFI_SUCCESS;
+}
-- 
2.24.0


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

* Re: [v4 PATCH 0/3] Add UEFI support for RISC-V
  2020-04-21  3:33 [v4 PATCH 0/3] Add UEFI support for RISC-V Atish Patra
                   ` (2 preceding siblings ...)
  2020-04-21  3:33 ` [v4 PATCH 3/3] RISC-V: Add EFI stub support Atish Patra
@ 2020-04-21  7:24 ` Ard Biesheuvel
  2020-04-21 17:29   ` Atish Patra
  2020-04-21 20:59   ` Palmer Dabbelt
  3 siblings, 2 replies; 16+ messages in thread
From: Ard Biesheuvel @ 2020-04-21  7:24 UTC (permalink / raw)
  To: Atish Patra
  Cc: Linux Kernel Mailing List, linux-efi, linux-riscv,
	Masahiro Yamada, Palmer Dabbelt, Heinrich Schuchardt

On Tue, 21 Apr 2020 at 05:34, Atish Patra <atish.patra@wdc.com> wrote:
>
> This series adds UEFI support for RISC-V. Currently, only boot time
> services have been added. Runtime services will be added in a separate
> series. This series depends on some core EFI patches
> present in current in efi-next and following other patches.
>
> U-Boot: Adds the boot hartid under chosen node.
> https://lists.denx.de/pipermail/u-boot/2020-April/405726.html
>
> Linux kernel: 5.7-rc1
>
> OpenSBI: master
>
> Patch 1 just moves arm-stub code to a generic code so that it can be used
> across different architecture.
>
> Patch 3 adds fixmap bindings so that CONFIG_EFI can be compiled and we do not
> have create separate config to enable boot time services.
> As runtime services are not enabled at this time, full generic early ioremap
> support is also not added in this series.
>
> Patch 4 and 5 adds the PE/COFF header and EFI stub code support for RISC-V
> respectively.
>
> The patches can also be found in following git repo.
>
> https://github.com/atishp04/linux/tree/wip_uefi_riscv_v4
>
> The patches have been verified on Qemu using bootefi command in U-Boot.
>
> Changes from v3->v4:
> 1. Rebased on top of efi-next.
> 2. Dropped patch 1 & 2 from this series as it is already queued in efi-next.
> Changes from v2->v3:
> 3. Improved handle_kernel_image() for RISC-V.
>

Thanks Atish. This looks nice and simple now.

I will need an ack from the RISC-V maintainers on these, and it is up
to them to consider whether the changes to core kconfigs and makefiles
are likely to cause trouble or not. If so, I am happy to work out a
way to merge this via a shared stable branch.



> Changes from v1->v2:
> 1. Rebased on 5.7-rc1.
> 2. Fixed minor typos and removed redundant macros/comments.
>
> Changes from previous version:
> 1. Renamed to the generic efi stub macro.
> 2. Address all redundant comments.
> 3. Supported EFI kernel image with normal booti command.
> 4. Removed runtime service related macro defines.
>
> Atish Patra (3):
> RISC-V: Define fixmap bindings for generic early ioremap support
> RISC-V: Add PE/COFF header for EFI stub
> RISC-V: Add EFI stub support.
>
> arch/riscv/Kconfig                        |  21 +++++
> arch/riscv/Makefile                       |   1 +
> arch/riscv/configs/defconfig              |   1 +
> arch/riscv/include/asm/Kbuild             |   1 +
> arch/riscv/include/asm/efi.h              |  44 +++++++++
> arch/riscv/include/asm/fixmap.h           |  18 ++++
> arch/riscv/include/asm/io.h               |   1 +
> arch/riscv/include/asm/sections.h         |  13 +++
> arch/riscv/kernel/Makefile                |   4 +
> arch/riscv/kernel/efi-header.S            |  99 ++++++++++++++++++++
> arch/riscv/kernel/head.S                  |  16 ++++
> arch/riscv/kernel/image-vars.h            |  53 +++++++++++
> arch/riscv/kernel/vmlinux.lds.S           |  20 +++-
> drivers/firmware/efi/Kconfig              |   2 +-
> drivers/firmware/efi/libstub/Makefile     |  10 ++
> drivers/firmware/efi/libstub/riscv-stub.c | 106 ++++++++++++++++++++++
> 16 files changed, 407 insertions(+), 3 deletions(-)
> create mode 100644 arch/riscv/include/asm/efi.h
> create mode 100644 arch/riscv/include/asm/sections.h
> create mode 100644 arch/riscv/kernel/efi-header.S
> create mode 100644 arch/riscv/kernel/image-vars.h
> create mode 100644 drivers/firmware/efi/libstub/riscv-stub.c
>
> --
> 2.24.0
>

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

* Re: [v4 PATCH 0/3] Add UEFI support for RISC-V
  2020-04-21  7:24 ` [v4 PATCH 0/3] Add UEFI support for RISC-V Ard Biesheuvel
@ 2020-04-21 17:29   ` Atish Patra
  2020-04-21 20:59   ` Palmer Dabbelt
  1 sibling, 0 replies; 16+ messages in thread
From: Atish Patra @ 2020-04-21 17:29 UTC (permalink / raw)
  To: Ard Biesheuvel, Palmer Dabbelt
  Cc: Atish Patra, Linux Kernel Mailing List, linux-efi, linux-riscv,
	Masahiro Yamada, Heinrich Schuchardt

On Tue, Apr 21, 2020 at 12:24 AM Ard Biesheuvel <ardb@kernel.org> wrote:
>
> On Tue, 21 Apr 2020 at 05:34, Atish Patra <atish.patra@wdc.com> wrote:
> >
> > This series adds UEFI support for RISC-V. Currently, only boot time
> > services have been added. Runtime services will be added in a separate
> > series. This series depends on some core EFI patches
> > present in current in efi-next and following other patches.
> >
> > U-Boot: Adds the boot hartid under chosen node.
> > https://lists.denx.de/pipermail/u-boot/2020-April/405726.html
> >
> > Linux kernel: 5.7-rc1
> >
> > OpenSBI: master
> >
> > Patch 1 just moves arm-stub code to a generic code so that it can be used
> > across different architecture.
> >
> > Patch 3 adds fixmap bindings so that CONFIG_EFI can be compiled and we do not
> > have create separate config to enable boot time services.
> > As runtime services are not enabled at this time, full generic early ioremap
> > support is also not added in this series.
> >
> > Patch 4 and 5 adds the PE/COFF header and EFI stub code support for RISC-V
> > respectively.
> >
> > The patches can also be found in following git repo.
> >
> > https://github.com/atishp04/linux/tree/wip_uefi_riscv_v4
> >
> > The patches have been verified on Qemu using bootefi command in U-Boot.
> >
> > Changes from v3->v4:
> > 1. Rebased on top of efi-next.
> > 2. Dropped patch 1 & 2 from this series as it is already queued in efi-next.
> > Changes from v2->v3:
> > 3. Improved handle_kernel_image() for RISC-V.
> >
>
> Thanks Atish. This looks nice and simple now.
>
> I will need an ack from the RISC-V maintainers on these, and it is up
> to them to consider whether the changes to core kconfigs and makefiles
> are likely to cause trouble or not. If so, I am happy to work out a
> way to merge this via a shared stable branch.
>
@Palmer Dabbelt : Can you take a look at the series whenever you have
some free cycles ?
We would like to merge the series sooner than later.

>
>
> > Changes from v1->v2:
> > 1. Rebased on 5.7-rc1.
> > 2. Fixed minor typos and removed redundant macros/comments.
> >
> > Changes from previous version:
> > 1. Renamed to the generic efi stub macro.
> > 2. Address all redundant comments.
> > 3. Supported EFI kernel image with normal booti command.
> > 4. Removed runtime service related macro defines.
> >
> > Atish Patra (3):
> > RISC-V: Define fixmap bindings for generic early ioremap support
> > RISC-V: Add PE/COFF header for EFI stub
> > RISC-V: Add EFI stub support.
> >
> > arch/riscv/Kconfig                        |  21 +++++
> > arch/riscv/Makefile                       |   1 +
> > arch/riscv/configs/defconfig              |   1 +
> > arch/riscv/include/asm/Kbuild             |   1 +
> > arch/riscv/include/asm/efi.h              |  44 +++++++++
> > arch/riscv/include/asm/fixmap.h           |  18 ++++
> > arch/riscv/include/asm/io.h               |   1 +
> > arch/riscv/include/asm/sections.h         |  13 +++
> > arch/riscv/kernel/Makefile                |   4 +
> > arch/riscv/kernel/efi-header.S            |  99 ++++++++++++++++++++
> > arch/riscv/kernel/head.S                  |  16 ++++
> > arch/riscv/kernel/image-vars.h            |  53 +++++++++++
> > arch/riscv/kernel/vmlinux.lds.S           |  20 +++-
> > drivers/firmware/efi/Kconfig              |   2 +-
> > drivers/firmware/efi/libstub/Makefile     |  10 ++
> > drivers/firmware/efi/libstub/riscv-stub.c | 106 ++++++++++++++++++++++
> > 16 files changed, 407 insertions(+), 3 deletions(-)
> > create mode 100644 arch/riscv/include/asm/efi.h
> > create mode 100644 arch/riscv/include/asm/sections.h
> > create mode 100644 arch/riscv/kernel/efi-header.S
> > create mode 100644 arch/riscv/kernel/image-vars.h
> > create mode 100644 drivers/firmware/efi/libstub/riscv-stub.c
> >
> > --
> > 2.24.0
> >



-- 
Regards,
Atish

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

* Re: [v4 PATCH 2/3] RISC-V: Add PE/COFF header for EFI stub
  2020-04-21  3:33 ` [v4 PATCH 2/3] RISC-V: Add PE/COFF header for EFI stub Atish Patra
@ 2020-04-21 17:51   ` Ard Biesheuvel
  2020-04-22 17:44     ` Atish Patra
  2020-04-21 20:02   ` Palmer Dabbelt
  1 sibling, 1 reply; 16+ messages in thread
From: Ard Biesheuvel @ 2020-04-21 17:51 UTC (permalink / raw)
  To: Atish Patra
  Cc: Linux Kernel Mailing List, linux-efi, linux-riscv,
	Masahiro Yamada, Palmer Dabbelt, Heinrich Schuchardt

Hi Atish,

One thing I forgot to check, below:

On Tue, 21 Apr 2020 at 05:34, Atish Patra <atish.patra@wdc.com> wrote:
>
> Linux kernel Image can appear as an EFI application With appropriate
> PE/COFF header fields in the beginning of the Image header. An EFI
> application loader can directly load a Linux kernel Image and an EFI
> stub residing in kernel can boot Linux kernel directly.
>
> Add the necessary PE/COFF header.
>
> Signed-off-by: Atish Patra <atish.patra@wdc.com>
> ---
>  arch/riscv/include/asm/sections.h | 13 ++++
>  arch/riscv/kernel/Makefile        |  4 ++
>  arch/riscv/kernel/efi-header.S    | 99 +++++++++++++++++++++++++++++++
>  arch/riscv/kernel/head.S          | 16 +++++
>  arch/riscv/kernel/image-vars.h    | 53 +++++++++++++++++
>  arch/riscv/kernel/vmlinux.lds.S   | 20 ++++++-
>  6 files changed, 203 insertions(+), 2 deletions(-)
>  create mode 100644 arch/riscv/include/asm/sections.h
>  create mode 100644 arch/riscv/kernel/efi-header.S
>  create mode 100644 arch/riscv/kernel/image-vars.h
>
> diff --git a/arch/riscv/include/asm/sections.h b/arch/riscv/include/asm/sections.h
> new file mode 100644
> index 000000000000..3a9971b1210f
> --- /dev/null
> +++ b/arch/riscv/include/asm/sections.h
> @@ -0,0 +1,13 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) 2020 Western Digital Corporation or its affiliates.
> + */
> +#ifndef __ASM_SECTIONS_H
> +#define __ASM_SECTIONS_H
> +
> +#include <asm-generic/sections.h>
> +
> +extern char _start[];
> +extern char _start_kernel[];
> +
> +#endif /* __ASM_SECTIONS_H */
> diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
> index 86c83081044f..86ca755f8a9f 100644
> --- a/arch/riscv/kernel/Makefile
> +++ b/arch/riscv/kernel/Makefile
> @@ -32,6 +32,10 @@ obj-y        += patch.o
>  obj-$(CONFIG_MMU) += vdso.o vdso/
>
>  obj-$(CONFIG_RISCV_M_MODE)     += clint.o traps_misaligned.o
> +OBJCOPYFLAGS := --prefix-symbols=__efistub_
> +$(obj)/%.stub.o: $(obj)/%.o FORCE
> +       $(call if_changed,objcopy)
> +
>  obj-$(CONFIG_FPU)              += fpu.o
>  obj-$(CONFIG_SMP)              += smpboot.o
>  obj-$(CONFIG_SMP)              += smp.o
> diff --git a/arch/riscv/kernel/efi-header.S b/arch/riscv/kernel/efi-header.S
> new file mode 100644
> index 000000000000..69dde8268527
> --- /dev/null
> +++ b/arch/riscv/kernel/efi-header.S
> @@ -0,0 +1,99 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) 2020 Western Digital Corporation or its affiliates.
> + * Adapted from arch/arm64/kernel/efi-header.S
> + */
> +
> +#include <linux/pe.h>
> +#include <linux/sizes.h>
> +
> +       .macro  __EFI_PE_HEADER
> +       .long   PE_MAGIC
> +coff_header:
> +       .short  IMAGE_FILE_MACHINE_RISCV64              // Machine
> +       .short  section_count                           // NumberOfSections
> +       .long   0                                       // TimeDateStamp
> +       .long   0                                       // PointerToSymbolTable
> +       .long   0                                       // NumberOfSymbols
> +       .short  section_table - optional_header         // SizeOfOptionalHeader
> +       .short  IMAGE_FILE_DEBUG_STRIPPED | \
> +               IMAGE_FILE_EXECUTABLE_IMAGE | \
> +               IMAGE_FILE_LINE_NUMS_STRIPPED           // Characteristics
> +
> +optional_header:
> +       .short  PE_OPT_MAGIC_PE32PLUS                   // PE32+ format
> +       .byte   0x02                                    // MajorLinkerVersion
> +       .byte   0x14                                    // MinorLinkerVersion
> +       .long   __text_end - efi_header_end             // SizeOfCode
> +       .long   _end - __text_end                       // SizeOfInitializedData
> +       .long   0                                       // SizeOfUninitializedData
> +       .long   __efistub_efi_entry - _start            // AddressOfEntryPoint
> +       .long   efi_header_end - _start                 // BaseOfCode
> +
> +extra_header_fields:
> +       .quad   0                                       // ImageBase
> +       .long   SZ_4K                                   // SectionAlignment

Here you set the section alignment to 4 KB ...

> +       .long   PECOFF_FILE_ALIGNMENT                   // FileAlignment
> +       .short  0                                       // MajorOperatingSystemVersion
> +       .short  0                                       // MinorOperatingSystemVersion
> +       .short  LINUX_EFISTUB_MAJOR_VERSION             // MajorImageVersion
> +       .short  LINUX_EFISTUB_MINOR_VERSION             // MinorImageVersion
> +       .short  0                                       // MajorSubsystemVersion
> +       .short  0                                       // MinorSubsystemVersion
> +       .long   0                                       // Win32VersionValue
> +
> +       .long   _end - _start                           // SizeOfImage
> +
> +       // Everything before the kernel image is considered part of the header
> +       .long   efi_header_end - _start                 // SizeOfHeaders
> +       .long   0                                       // CheckSum
> +       .short  IMAGE_SUBSYSTEM_EFI_APPLICATION         // Subsystem
> +       .short  0                                       // DllCharacteristics
> +       .quad   0                                       // SizeOfStackReserve
> +       .quad   0                                       // SizeOfStackCommit
> +       .quad   0                                       // SizeOfHeapReserve
> +       .quad   0                                       // SizeOfHeapCommit
> +       .long   0                                       // LoaderFlags
> +       .long   (section_table - .) / 8                 // NumberOfRvaAndSizes
> +
> +       .quad   0                                       // ExportTable
> +       .quad   0                                       // ImportTable
> +       .quad   0                                       // ResourceTable
> +       .quad   0                                       // ExceptionTable
> +       .quad   0                                       // CertificationTable
> +       .quad   0                                       // BaseRelocationTable
> +
> +       // Section table
> +section_table:
> +       .ascii  ".text\0\0\0"
> +       .long   __text_end - efi_header_end             // VirtualSize
> +       .long   efi_header_end - _start                 // VirtualAddress

... and here you define the address of the first section, which should
be aligned to section alignment of 4 KB

> +       .long   __text_end - efi_header_end             // SizeOfRawData
> +       .long   efi_header_end - _start                 // PointerToRawData
> +
> +       .long   0                                       // PointerToRelocations
> +       .long   0                                       // PointerToLineNumbers
> +       .short  0                                       // NumberOfRelocations
> +       .short  0                                       // NumberOfLineNumbers
> +       .long   IMAGE_SCN_CNT_CODE | \
> +               IMAGE_SCN_MEM_READ | \
> +               IMAGE_SCN_MEM_EXECUTE                   // Characteristics
> +
> +       .ascii  ".data\0\0\0"
> +       .long   __data_virt_size                        // VirtualSize
> +       .long   __text_end - _start                     // VirtualAddress
> +       .long   __data_raw_size                         // SizeOfRawData
> +       .long   __text_end - _start                     // PointerToRawData
> +
> +       .long   0                                       // PointerToRelocations
> +       .long   0                                       // PointerToLineNumbers
> +       .short  0                                       // NumberOfRelocations
> +       .short  0                                       // NumberOfLineNumbers
> +       .long   IMAGE_SCN_CNT_INITIALIZED_DATA | \
> +               IMAGE_SCN_MEM_READ | \
> +               IMAGE_SCN_MEM_WRITE                     // Characteristics
> +
> +       .set    section_count, (. - section_table) / 40
> +
> +efi_header_end:

... so you will need to put an .p2align 12 here to ensure that
efi_header_end appears at 4 KB boundary.

Similarly, you will have to align the symbols __text_end and
__data_virt_size in the linker scripts to make them round multiples of
4 KB.



> +       .endm
> diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S
> index 98a406474e7d..ddd613dac9d6 100644
> --- a/arch/riscv/kernel/head.S
> +++ b/arch/riscv/kernel/head.S
> @@ -13,6 +13,7 @@
>  #include <asm/csr.h>
>  #include <asm/hwcap.h>
>  #include <asm/image.h>
> +#include "efi-header.S"
>
>  __HEAD
>  ENTRY(_start)
> @@ -22,10 +23,18 @@ ENTRY(_start)
>          * Do not modify it without modifying the structure and all bootloaders
>          * that expects this header format!!
>          */
> +#ifdef CONFIG_EFI
> +       /*
> +        * This instruction decodes to "MZ" ASCII required by UEFI.
> +        */
> +       li s4,-13
> +       j _start_kernel
> +#else
>         /* jump to start kernel */
>         j _start_kernel
>         /* reserved */
>         .word 0
> +#endif
>         .balign 8
>  #if __riscv_xlen == 64
>         /* Image load offset(2MB) from start of RAM */
> @@ -43,7 +52,14 @@ ENTRY(_start)
>         .ascii RISCV_IMAGE_MAGIC
>         .balign 4
>         .ascii RISCV_IMAGE_MAGIC2
> +#ifdef CONFIG_EFI
> +       .word pe_head_start - _start
> +pe_head_start:
> +
> +       __EFI_PE_HEADER
> +#else
>         .word 0
> +#endif
>
>  .align 2
>  #ifdef CONFIG_MMU
> diff --git a/arch/riscv/kernel/image-vars.h b/arch/riscv/kernel/image-vars.h
> new file mode 100644
> index 000000000000..bd8b764f0ad9
> --- /dev/null
> +++ b/arch/riscv/kernel/image-vars.h
> @@ -0,0 +1,53 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) 2020 Western Digital Corporation or its affiliates.
> + * Linker script variables to be set after section resolution, as
> + * ld.lld does not like variables assigned before SECTIONS is processed.
> + * Based on arch/arm64/kerne/image-vars.h
> + */
> +#ifndef __RISCV_KERNEL_IMAGE_VARS_H
> +#define __RISCV_KERNEL_IMAGE_VARS_H
> +
> +#ifndef LINKER_SCRIPT
> +#error This file should only be included in vmlinux.lds.S
> +#endif
> +
> +#ifdef CONFIG_EFI
> +
> +__efistub_stext_offset = _start_kernel - _start;
> +
> +/*
> + * The EFI stub has its own symbol namespace prefixed by __efistub_, to
> + * isolate it from the kernel proper. The following symbols are legally
> + * accessed by the stub, so provide some aliases to make them accessible.
> + * Only include data symbols here, or text symbols of functions that are
> + * guaranteed to be safe when executed at another offset than they were
> + * linked at. The routines below are all implemented in assembler in a
> + * position independent manner
> + */
> +__efistub_memcmp               = memcmp;
> +__efistub_memchr               = memchr;
> +__efistub_memcpy               = memcpy;
> +__efistub_memmove              = memmove;
> +__efistub_memset               = memset;
> +__efistub_strlen               = strlen;
> +__efistub_strnlen              = strnlen;
> +__efistub_strcmp               = strcmp;
> +__efistub_strncmp              = strncmp;
> +__efistub_strrchr              = strrchr;
> +
> +#ifdef CONFIG_KASAN
> +__efistub___memcpy             = memcpy;
> +__efistub___memmove            = memmove;
> +__efistub___memset             = memset;
> +#endif
> +
> +__efistub__start               = _start;
> +__efistub__start_kernel                = _start_kernel;
> +__efistub__end                 = _end;
> +__efistub__edata               = _edata;
> +__efistub_screen_info          = screen_info;
> +
> +#endif
> +
> +#endif /* __RISCV_KERNEL_IMAGE_VARS_H */
> diff --git a/arch/riscv/kernel/vmlinux.lds.S b/arch/riscv/kernel/vmlinux.lds.S
> index 0339b6bbe11a..20ebf7e8c215 100644
> --- a/arch/riscv/kernel/vmlinux.lds.S
> +++ b/arch/riscv/kernel/vmlinux.lds.S
> @@ -10,6 +10,7 @@
>  #include <asm/cache.h>
>  #include <asm/thread_info.h>
>  #include <asm/set_memory.h>
> +#include "image-vars.h"
>
>  #include <linux/sizes.h>
>  OUTPUT_ARCH(riscv)
> @@ -17,6 +18,14 @@ ENTRY(_start)
>
>  jiffies = jiffies_64;
>
> +PECOFF_FILE_ALIGNMENT = 0x200;
> +#ifdef CONFIG_EFI
> +#define PECOFF_EDATA_PADDING   \
> +       .pecoff_edata_padding : { BYTE(0); . = ALIGN(PECOFF_FILE_ALIGNMENT); }
> +#else
> +#define PECOFF_EDATA_PADDING
> +#endif
> +
>  SECTIONS
>  {
>         /* Beginning of code and text segment */
> @@ -62,6 +71,8 @@ SECTIONS
>                 _etext = .;
>         }
>
> +       __text_end = .;
> +
>         /* Start of data section */
>         _sdata = .;
>         RO_DATA(SECTION_ALIGN)
> @@ -78,9 +89,12 @@ SECTIONS
>         .sdata : {
>                 __global_pointer$ = . + 0x800;
>                 *(.sdata*)
> -               /* End of data section */
> -               _edata = .;
>         }
> +       PECOFF_EDATA_PADDING
> +       __data_raw_size = ABSOLUTE(. - __text_end);
> +
> +       /* End of data section */
> +       _edata = .;
>
>         BSS_SECTION(PAGE_SIZE, PAGE_SIZE, 0)
>
> @@ -88,6 +102,8 @@ SECTIONS
>                 *(.rel.dyn*)
>         }
>
> +       __data_virt_size = ABSOLUTE(. - __text_end);
> +
>         _end = .;
>
>         STABS_DEBUG
> --
> 2.24.0
>

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

* Re: [v4 PATCH 1/3] RISC-V: Define fixmap bindings for generic early ioremap support
  2020-04-21  3:33 ` [v4 PATCH 1/3] RISC-V: Define fixmap bindings for generic early ioremap support Atish Patra
@ 2020-04-21 19:52   ` Palmer Dabbelt
  2020-04-21 19:56     ` Atish Patra
  0 siblings, 1 reply; 16+ messages in thread
From: Palmer Dabbelt @ 2020-04-21 19:52 UTC (permalink / raw)
  To: Atish Patra
  Cc: linux-kernel, Atish Patra, ardb, linux-efi, linux-riscv,
	masahiroy, xypron.glpk

I missed that there's a v4 now, so I'm jumping over here

On Mon, 20 Apr 2020 20:33:34 PDT (-0700), Atish Patra wrote:
> UEFI uses early IO or memory mappings for runtime services before
> normal ioremap() is usable. This patch only adds minimum necessary
> fixmap bindings and headers for generic ioremap support to work.
>
> Signed-off-by: Atish Patra <atish.patra@wdc.com>
> Acked-by: Ard Biesheuvel <ardb@kernel.org>
> ---
>  arch/riscv/Kconfig              |  1 +
>  arch/riscv/include/asm/Kbuild   |  1 +
>  arch/riscv/include/asm/fixmap.h | 18 ++++++++++++++++++
>  arch/riscv/include/asm/io.h     |  1 +
>  4 files changed, 21 insertions(+)
>
> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> index a197258595ef..f39e326a7a42 100644
> --- a/arch/riscv/Kconfig
> +++ b/arch/riscv/Kconfig
> @@ -68,6 +68,7 @@ config RISCV
>  	select ARCH_HAS_GCOV_PROFILE_ALL
>  	select HAVE_COPY_THREAD_TLS
>  	select HAVE_ARCH_KASAN if MMU && 64BIT
> +	select GENERIC_EARLY_IOREMAP
>
>  config ARCH_MMAP_RND_BITS_MIN
>  	default 18 if 64BIT
> diff --git a/arch/riscv/include/asm/Kbuild b/arch/riscv/include/asm/Kbuild
> index 3d9410bb4de0..59dd7be55005 100644
> --- a/arch/riscv/include/asm/Kbuild
> +++ b/arch/riscv/include/asm/Kbuild
> @@ -1,4 +1,5 @@
>  # SPDX-License-Identifier: GPL-2.0
> +generic-y += early_ioremap.h
>  generic-y += extable.h
>  generic-y += flat.h
>  generic-y += kvm_para.h
> diff --git a/arch/riscv/include/asm/fixmap.h b/arch/riscv/include/asm/fixmap.h
> index 2368d49eb4ef..ba5096d65fb0 100644
> --- a/arch/riscv/include/asm/fixmap.h
> +++ b/arch/riscv/include/asm/fixmap.h
> @@ -30,6 +30,24 @@ enum fixed_addresses {
>  	FIX_TEXT_POKE1,
>  	FIX_TEXT_POKE0,
>  	FIX_EARLYCON_MEM_BASE,
> +	/*
> +	 * Make sure that it is 2MB aligned.
> +	 */
> +#define NR_FIX_SZ_2M	(SZ_2M / PAGE_SIZE)
> +	FIX_THOLE = NR_FIX_SZ_2M - FIX_PMD - 1,
> +
> +	__end_of_permanent_fixed_addresses,
> +	/*
> +	 * Temporary boot-time mappings, used by early_ioremap(),
> +	 * before ioremap() is functional.
> +	 */
> +#define NR_FIX_BTMAPS		(SZ_256K / PAGE_SIZE)
> +#define FIX_BTMAPS_SLOTS	7
> +#define TOTAL_FIX_BTMAPS	(NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS)
> +
> +	FIX_BTMAP_END = __end_of_permanent_fixed_addresses,
> +	FIX_BTMAP_BEGIN = FIX_BTMAP_END + TOTAL_FIX_BTMAPS - 1,
> +
>  	__end_of_fixed_addresses
>  };
>
> diff --git a/arch/riscv/include/asm/io.h b/arch/riscv/include/asm/io.h
> index 0f477206a4ed..047f414b6948 100644
> --- a/arch/riscv/include/asm/io.h
> +++ b/arch/riscv/include/asm/io.h
> @@ -14,6 +14,7 @@
>  #include <linux/types.h>
>  #include <asm/mmiowb.h>
>  #include <asm/pgtable.h>
> +#include <asm/early_ioremap.h>
>
>  /*
>   * MMIO access functions are separated out to break dependency cycles

Just so it doesn't get lost (the patch is the same)

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>

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

* Re: [v4 PATCH 1/3] RISC-V: Define fixmap bindings for generic early ioremap support
  2020-04-21 19:52   ` Palmer Dabbelt
@ 2020-04-21 19:56     ` Atish Patra
  0 siblings, 0 replies; 16+ messages in thread
From: Atish Patra @ 2020-04-21 19:56 UTC (permalink / raw)
  To: Palmer Dabbelt
  Cc: Atish Patra, linux-kernel@vger.kernel.org List, Ard Biesheuvel,
	linux-efi, linux-riscv, Heinrich Schuchardt

On Tue, Apr 21, 2020 at 12:52 PM Palmer Dabbelt <palmer@dabbelt.com> wrote:
>
> I missed that there's a v4 now, so I'm jumping over here
>

Thanks. Just FYI: Ard has already pulled the patches 1 & 2 into efi-next.
So the v4 will only have 3 patches, mostly riscv specific stuff.

> On Mon, 20 Apr 2020 20:33:34 PDT (-0700), Atish Patra wrote:
> > UEFI uses early IO or memory mappings for runtime services before
> > normal ioremap() is usable. This patch only adds minimum necessary
> > fixmap bindings and headers for generic ioremap support to work.
> >
> > Signed-off-by: Atish Patra <atish.patra@wdc.com>
> > Acked-by: Ard Biesheuvel <ardb@kernel.org>
> > ---
> >  arch/riscv/Kconfig              |  1 +
> >  arch/riscv/include/asm/Kbuild   |  1 +
> >  arch/riscv/include/asm/fixmap.h | 18 ++++++++++++++++++
> >  arch/riscv/include/asm/io.h     |  1 +
> >  4 files changed, 21 insertions(+)
> >
> > diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> > index a197258595ef..f39e326a7a42 100644
> > --- a/arch/riscv/Kconfig
> > +++ b/arch/riscv/Kconfig
> > @@ -68,6 +68,7 @@ config RISCV
> >       select ARCH_HAS_GCOV_PROFILE_ALL
> >       select HAVE_COPY_THREAD_TLS
> >       select HAVE_ARCH_KASAN if MMU && 64BIT
> > +     select GENERIC_EARLY_IOREMAP
> >
> >  config ARCH_MMAP_RND_BITS_MIN
> >       default 18 if 64BIT
> > diff --git a/arch/riscv/include/asm/Kbuild b/arch/riscv/include/asm/Kbuild
> > index 3d9410bb4de0..59dd7be55005 100644
> > --- a/arch/riscv/include/asm/Kbuild
> > +++ b/arch/riscv/include/asm/Kbuild
> > @@ -1,4 +1,5 @@
> >  # SPDX-License-Identifier: GPL-2.0
> > +generic-y += early_ioremap.h
> >  generic-y += extable.h
> >  generic-y += flat.h
> >  generic-y += kvm_para.h
> > diff --git a/arch/riscv/include/asm/fixmap.h b/arch/riscv/include/asm/fixmap.h
> > index 2368d49eb4ef..ba5096d65fb0 100644
> > --- a/arch/riscv/include/asm/fixmap.h
> > +++ b/arch/riscv/include/asm/fixmap.h
> > @@ -30,6 +30,24 @@ enum fixed_addresses {
> >       FIX_TEXT_POKE1,
> >       FIX_TEXT_POKE0,
> >       FIX_EARLYCON_MEM_BASE,
> > +     /*
> > +      * Make sure that it is 2MB aligned.
> > +      */
> > +#define NR_FIX_SZ_2M (SZ_2M / PAGE_SIZE)
> > +     FIX_THOLE = NR_FIX_SZ_2M - FIX_PMD - 1,
> > +
> > +     __end_of_permanent_fixed_addresses,
> > +     /*
> > +      * Temporary boot-time mappings, used by early_ioremap(),
> > +      * before ioremap() is functional.
> > +      */
> > +#define NR_FIX_BTMAPS                (SZ_256K / PAGE_SIZE)
> > +#define FIX_BTMAPS_SLOTS     7
> > +#define TOTAL_FIX_BTMAPS     (NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS)
> > +
> > +     FIX_BTMAP_END = __end_of_permanent_fixed_addresses,
> > +     FIX_BTMAP_BEGIN = FIX_BTMAP_END + TOTAL_FIX_BTMAPS - 1,
> > +
> >       __end_of_fixed_addresses
> >  };
> >
> > diff --git a/arch/riscv/include/asm/io.h b/arch/riscv/include/asm/io.h
> > index 0f477206a4ed..047f414b6948 100644
> > --- a/arch/riscv/include/asm/io.h
> > +++ b/arch/riscv/include/asm/io.h
> > @@ -14,6 +14,7 @@
> >  #include <linux/types.h>
> >  #include <asm/mmiowb.h>
> >  #include <asm/pgtable.h>
> > +#include <asm/early_ioremap.h>
> >
> >  /*
> >   * MMIO access functions are separated out to break dependency cycles
>
> Just so it doesn't get lost (the patch is the same)
>
> Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>



-- 
Regards,
Atish

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

* Re: [v4 PATCH 2/3] RISC-V: Add PE/COFF header for EFI stub
  2020-04-21  3:33 ` [v4 PATCH 2/3] RISC-V: Add PE/COFF header for EFI stub Atish Patra
  2020-04-21 17:51   ` Ard Biesheuvel
@ 2020-04-21 20:02   ` Palmer Dabbelt
  2020-04-22 17:43     ` Atish Patra
  1 sibling, 1 reply; 16+ messages in thread
From: Palmer Dabbelt @ 2020-04-21 20:02 UTC (permalink / raw)
  To: Atish Patra
  Cc: linux-kernel, Atish Patra, ardb, linux-efi, linux-riscv,
	masahiroy, xypron.glpk

[I just saw there's a v4, so I'm moving over here]

On Mon, 20 Apr 2020 20:33:35 PDT (-0700), Atish Patra wrote:
> Linux kernel Image can appear as an EFI application With appropriate
> PE/COFF header fields in the beginning of the Image header. An EFI
> application loader can directly load a Linux kernel Image and an EFI
> stub residing in kernel can boot Linux kernel directly.
>
> Add the necessary PE/COFF header.
>
> Signed-off-by: Atish Patra <atish.patra@wdc.com>
> ---
>  arch/riscv/include/asm/sections.h | 13 ++++
>  arch/riscv/kernel/Makefile        |  4 ++
>  arch/riscv/kernel/efi-header.S    | 99 +++++++++++++++++++++++++++++++
>  arch/riscv/kernel/head.S          | 16 +++++
>  arch/riscv/kernel/image-vars.h    | 53 +++++++++++++++++
>  arch/riscv/kernel/vmlinux.lds.S   | 20 ++++++-
>  6 files changed, 203 insertions(+), 2 deletions(-)
>  create mode 100644 arch/riscv/include/asm/sections.h
>  create mode 100644 arch/riscv/kernel/efi-header.S
>  create mode 100644 arch/riscv/kernel/image-vars.h
>
> diff --git a/arch/riscv/include/asm/sections.h b/arch/riscv/include/asm/sections.h
> new file mode 100644
> index 000000000000..3a9971b1210f
> --- /dev/null
> +++ b/arch/riscv/include/asm/sections.h
> @@ -0,0 +1,13 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) 2020 Western Digital Corporation or its affiliates.
> + */
> +#ifndef __ASM_SECTIONS_H
> +#define __ASM_SECTIONS_H
> +
> +#include <asm-generic/sections.h>
> +
> +extern char _start[];
> +extern char _start_kernel[];
> +
> +#endif /* __ASM_SECTIONS_H */
> diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
> index 86c83081044f..86ca755f8a9f 100644
> --- a/arch/riscv/kernel/Makefile
> +++ b/arch/riscv/kernel/Makefile
> @@ -32,6 +32,10 @@ obj-y	+= patch.o
>  obj-$(CONFIG_MMU) += vdso.o vdso/
>
>  obj-$(CONFIG_RISCV_M_MODE)	+= clint.o traps_misaligned.o
> +OBJCOPYFLAGS := --prefix-symbols=__efistub_
> +$(obj)/%.stub.o: $(obj)/%.o FORCE
> +	$(call if_changed,objcopy)
> +
>  obj-$(CONFIG_FPU)		+= fpu.o
>  obj-$(CONFIG_SMP)		+= smpboot.o
>  obj-$(CONFIG_SMP)		+= smp.o
> diff --git a/arch/riscv/kernel/efi-header.S b/arch/riscv/kernel/efi-header.S
> new file mode 100644
> index 000000000000..69dde8268527
> --- /dev/null
> +++ b/arch/riscv/kernel/efi-header.S
> @@ -0,0 +1,99 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) 2020 Western Digital Corporation or its affiliates.
> + * Adapted from arch/arm64/kernel/efi-header.S
> + */
> +
> +#include <linux/pe.h>
> +#include <linux/sizes.h>
> +
> +	.macro	__EFI_PE_HEADER
> +	.long	PE_MAGIC
> +coff_header:
> +	.short	IMAGE_FILE_MACHINE_RISCV64		// Machine
> +	.short	section_count				// NumberOfSections
> +	.long	0 					// TimeDateStamp
> +	.long	0					// PointerToSymbolTable
> +	.long	0					// NumberOfSymbols
> +	.short	section_table - optional_header		// SizeOfOptionalHeader
> +	.short	IMAGE_FILE_DEBUG_STRIPPED | \
> +		IMAGE_FILE_EXECUTABLE_IMAGE | \
> +		IMAGE_FILE_LINE_NUMS_STRIPPED		// Characteristics
> +
> +optional_header:
> +	.short	PE_OPT_MAGIC_PE32PLUS			// PE32+ format
> +	.byte	0x02					// MajorLinkerVersion
> +	.byte	0x14					// MinorLinkerVersion
> +	.long	__text_end - efi_header_end		// SizeOfCode
> +	.long	_end - __text_end			// SizeOfInitializedData
> +	.long	0					// SizeOfUninitializedData
> +	.long	__efistub_efi_entry - _start		// AddressOfEntryPoint
> +	.long	efi_header_end - _start			// BaseOfCode
> +
> +extra_header_fields:
> +	.quad	0					// ImageBase
> +	.long	SZ_4K					// SectionAlignment
> +	.long	PECOFF_FILE_ALIGNMENT			// FileAlignment
> +	.short	0					// MajorOperatingSystemVersion
> +	.short	0					// MinorOperatingSystemVersion
> +	.short	LINUX_EFISTUB_MAJOR_VERSION		// MajorImageVersion
> +	.short	LINUX_EFISTUB_MINOR_VERSION		// MinorImageVersion
> +	.short	0					// MajorSubsystemVersion
> +	.short	0					// MinorSubsystemVersion
> +	.long	0					// Win32VersionValue
> +
> +	.long	_end - _start				// SizeOfImage
> +
> +	// Everything before the kernel image is considered part of the header
> +	.long	efi_header_end - _start			// SizeOfHeaders
> +	.long	0					// CheckSum
> +	.short	IMAGE_SUBSYSTEM_EFI_APPLICATION		// Subsystem
> +	.short	0					// DllCharacteristics
> +	.quad	0					// SizeOfStackReserve
> +	.quad	0					// SizeOfStackCommit
> +	.quad	0					// SizeOfHeapReserve
> +	.quad	0					// SizeOfHeapCommit
> +	.long	0					// LoaderFlags
> +	.long	(section_table - .) / 8			// NumberOfRvaAndSizes
> +
> +	.quad	0					// ExportTable
> +	.quad	0					// ImportTable
> +	.quad	0					// ResourceTable
> +	.quad	0					// ExceptionTable
> +	.quad	0					// CertificationTable
> +	.quad	0					// BaseRelocationTable
> +
> +	// Section table
> +section_table:
> +	.ascii	".text\0\0\0"
> +	.long	__text_end - efi_header_end		// VirtualSize
> +	.long	efi_header_end - _start			// VirtualAddress
> +	.long	__text_end - efi_header_end		// SizeOfRawData
> +	.long	efi_header_end - _start			// PointerToRawData
> +
> +	.long	0					// PointerToRelocations
> +	.long	0					// PointerToLineNumbers
> +	.short	0					// NumberOfRelocations
> +	.short	0					// NumberOfLineNumbers
> +	.long	IMAGE_SCN_CNT_CODE | \
> +		IMAGE_SCN_MEM_READ | \
> +		IMAGE_SCN_MEM_EXECUTE			// Characteristics
> +
> +	.ascii	".data\0\0\0"
> +	.long	__data_virt_size			// VirtualSize
> +	.long	__text_end - _start			// VirtualAddress
> +	.long	__data_raw_size				// SizeOfRawData
> +	.long	__text_end - _start			// PointerToRawData
> +
> +	.long	0					// PointerToRelocations
> +	.long	0					// PointerToLineNumbers
> +	.short	0					// NumberOfRelocations
> +	.short	0					// NumberOfLineNumbers
> +	.long	IMAGE_SCN_CNT_INITIALIZED_DATA | \
> +		IMAGE_SCN_MEM_READ | \
> +		IMAGE_SCN_MEM_WRITE			// Characteristics
> +
> +	.set	section_count, (. - section_table) / 40
> +
> +efi_header_end:
> +	.endm
> diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S
> index 98a406474e7d..ddd613dac9d6 100644
> --- a/arch/riscv/kernel/head.S
> +++ b/arch/riscv/kernel/head.S
> @@ -13,6 +13,7 @@
>  #include <asm/csr.h>
>  #include <asm/hwcap.h>
>  #include <asm/image.h>
> +#include "efi-header.S"
>
>  __HEAD
>  ENTRY(_start)
> @@ -22,10 +23,18 @@ ENTRY(_start)
>  	 * Do not modify it without modifying the structure and all bootloaders
>  	 * that expects this header format!!
>  	 */
> +#ifdef CONFIG_EFI
> +	/*
> +	 * This instruction decodes to "MZ" ASCII required by UEFI.
> +	 */
> +	li s4,-13

This needs to be a c.li in order to encode as "MZ".  It'd be cleaner to
explicitly write it that way rather that having the assembler transparently
compress it, but we definately need to have Kconfig make EFI select ISA_C.

> +	j _start_kernel
> +#else
>  	/* jump to start kernel */
>  	j _start_kernel
>  	/* reserved */
>  	.word 0
> +#endif
>  	.balign 8
>  #if __riscv_xlen == 64
>  	/* Image load offset(2MB) from start of RAM */
> @@ -43,7 +52,14 @@ ENTRY(_start)
>  	.ascii RISCV_IMAGE_MAGIC
>  	.balign 4
>  	.ascii RISCV_IMAGE_MAGIC2
> +#ifdef CONFIG_EFI
> +	.word pe_head_start - _start
> +pe_head_start:
> +
> +	__EFI_PE_HEADER
> +#else
>  	.word 0
> +#endif
>
>  .align 2
>  #ifdef CONFIG_MMU
> diff --git a/arch/riscv/kernel/image-vars.h b/arch/riscv/kernel/image-vars.h
> new file mode 100644
> index 000000000000..bd8b764f0ad9
> --- /dev/null
> +++ b/arch/riscv/kernel/image-vars.h
> @@ -0,0 +1,53 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) 2020 Western Digital Corporation or its affiliates.
> + * Linker script variables to be set after section resolution, as
> + * ld.lld does not like variables assigned before SECTIONS is processed.
> + * Based on arch/arm64/kerne/image-vars.h
> + */
> +#ifndef __RISCV_KERNEL_IMAGE_VARS_H
> +#define __RISCV_KERNEL_IMAGE_VARS_H
> +
> +#ifndef LINKER_SCRIPT
> +#error This file should only be included in vmlinux.lds.S
> +#endif
> +
> +#ifdef CONFIG_EFI
> +
> +__efistub_stext_offset = _start_kernel - _start;
> +
> +/*
> + * The EFI stub has its own symbol namespace prefixed by __efistub_, to
> + * isolate it from the kernel proper. The following symbols are legally
> + * accessed by the stub, so provide some aliases to make them accessible.
> + * Only include data symbols here, or text symbols of functions that are
> + * guaranteed to be safe when executed at another offset than they were
> + * linked at. The routines below are all implemented in assembler in a
> + * position independent manner
> + */
> +__efistub_memcmp		= memcmp;
> +__efistub_memchr		= memchr;
> +__efistub_memcpy		= memcpy;
> +__efistub_memmove		= memmove;
> +__efistub_memset		= memset;
> +__efistub_strlen		= strlen;
> +__efistub_strnlen		= strnlen;
> +__efistub_strcmp		= strcmp;
> +__efistub_strncmp		= strncmp;
> +__efistub_strrchr		= strrchr;
> +
> +#ifdef CONFIG_KASAN
> +__efistub___memcpy		= memcpy;
> +__efistub___memmove		= memmove;
> +__efistub___memset		= memset;
> +#endif
> +
> +__efistub__start		= _start;
> +__efistub__start_kernel		= _start_kernel;
> +__efistub__end			= _end;
> +__efistub__edata		= _edata;
> +__efistub_screen_info		= screen_info;
> +
> +#endif
> +
> +#endif /* __RISCV_KERNEL_IMAGE_VARS_H */
> diff --git a/arch/riscv/kernel/vmlinux.lds.S b/arch/riscv/kernel/vmlinux.lds.S
> index 0339b6bbe11a..20ebf7e8c215 100644
> --- a/arch/riscv/kernel/vmlinux.lds.S
> +++ b/arch/riscv/kernel/vmlinux.lds.S
> @@ -10,6 +10,7 @@
>  #include <asm/cache.h>
>  #include <asm/thread_info.h>
>  #include <asm/set_memory.h>
> +#include "image-vars.h"
>
>  #include <linux/sizes.h>
>  OUTPUT_ARCH(riscv)
> @@ -17,6 +18,14 @@ ENTRY(_start)
>
>  jiffies = jiffies_64;
>
> +PECOFF_FILE_ALIGNMENT = 0x200;
> +#ifdef CONFIG_EFI
> +#define PECOFF_EDATA_PADDING	\
> +	.pecoff_edata_padding : { BYTE(0); . = ALIGN(PECOFF_FILE_ALIGNMENT); }
> +#else
> +#define PECOFF_EDATA_PADDING
> +#endif
> +
>  SECTIONS
>  {
>  	/* Beginning of code and text segment */
> @@ -62,6 +71,8 @@ SECTIONS
>  		_etext = .;
>  	}
>
> +	__text_end = .;
> +
>  	/* Start of data section */
>  	_sdata = .;
>  	RO_DATA(SECTION_ALIGN)
> @@ -78,9 +89,12 @@ SECTIONS
>  	.sdata : {
>  		__global_pointer$ = . + 0x800;
>  		*(.sdata*)
> -		/* End of data section */
> -		_edata = .;
>  	}
> +	PECOFF_EDATA_PADDING
> +	__data_raw_size = ABSOLUTE(. - __text_end);
> +
> +	/* End of data section */
> +	_edata = .;
>
>  	BSS_SECTION(PAGE_SIZE, PAGE_SIZE, 0)
>
> @@ -88,6 +102,8 @@ SECTIONS
>  		*(.rel.dyn*)
>  	}
>
> +	__data_virt_size = ABSOLUTE(. - __text_end);
> +
>  	_end = .;
>
>  	STABS_DEBUG

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

* Re: [v4 PATCH 3/3] RISC-V: Add EFI stub support.
  2020-04-21  3:33 ` [v4 PATCH 3/3] RISC-V: Add EFI stub support Atish Patra
@ 2020-04-21 20:08   ` Palmer Dabbelt
  2020-04-22 17:45     ` Atish Patra
  0 siblings, 1 reply; 16+ messages in thread
From: Palmer Dabbelt @ 2020-04-21 20:08 UTC (permalink / raw)
  To: Atish Patra
  Cc: linux-kernel, Atish Patra, ardb, linux-efi, linux-riscv,
	masahiroy, xypron.glpk

On Mon, 20 Apr 2020 20:33:36 PDT (-0700), Atish Patra wrote:
> Add a RISC-V architecture specific stub code that actually copies the
> actual kernel image to a valid address and jump to it after boot services
> are terminated. Enable UEFI related kernel configs as well for RISC-V.
>
> Signed-off-by: Atish Patra <atish.patra@wdc.com>
> ---
>  arch/riscv/Kconfig                        |  20 ++++
>  arch/riscv/Makefile                       |   1 +
>  arch/riscv/configs/defconfig              |   1 +
>  arch/riscv/include/asm/efi.h              |  44 +++++++++
>  drivers/firmware/efi/Kconfig              |   2 +-
>  drivers/firmware/efi/libstub/Makefile     |  10 ++
>  drivers/firmware/efi/libstub/riscv-stub.c | 106 ++++++++++++++++++++++
>  7 files changed, 183 insertions(+), 1 deletion(-)
>  create mode 100644 arch/riscv/include/asm/efi.h
>  create mode 100644 drivers/firmware/efi/libstub/riscv-stub.c
>
> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> index f39e326a7a42..eb4f41c8f3ce 100644
> --- a/arch/riscv/Kconfig
> +++ b/arch/riscv/Kconfig
> @@ -379,10 +379,30 @@ config CMDLINE_FORCE
>
>  endchoice
>
> +config EFI_STUB
> +	bool
> +
> +config EFI
> +	bool "UEFI runtime support"
> +	depends on OF
> +	select LIBFDT
> +	select UCS2_STRING
> +	select EFI_PARAMS_FROM_FDT
> +	select EFI_STUB
> +	select EFI_GENERIC_STUB

So I guess just "select RISCV_ISA_C" would be sufficient to make this work, but
I still feel flike an explicit "c.li" is saner.

> +	default y
> +	help
> +	  This option provides support for runtime services provided
> +	  by UEFI firmware (such as non-volatile variables, realtime
> +          clock, and platform reset). A UEFI stub is also provided to
> +	  allow the kernel to be booted as an EFI application. This
> +	  is only useful on systems that have UEFI firmware.
> +
>  endmenu
>
>  menu "Power management options"
>
>  source "kernel/power/Kconfig"
> +source "drivers/firmware/Kconfig"
>
>  endmenu
> diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
> index fb6e37db836d..079435804d6d 100644
> --- a/arch/riscv/Makefile
> +++ b/arch/riscv/Makefile
> @@ -80,6 +80,7 @@ head-y := arch/riscv/kernel/head.o
>  core-y += arch/riscv/
>
>  libs-y += arch/riscv/lib/
> +core-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
>
>  PHONY += vdso_install
>  vdso_install:
> diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig
> index 4da4886246a4..ae69e12d306a 100644
> --- a/arch/riscv/configs/defconfig
> +++ b/arch/riscv/configs/defconfig
> @@ -129,3 +129,4 @@ CONFIG_DEBUG_BLOCK_EXT_DEVT=y
>  # CONFIG_RUNTIME_TESTING_MENU is not set
>  CONFIG_MEMTEST=y
>  # CONFIG_SYSFS_SYSCALL is not set
> +CONFIG_EFI=y
> diff --git a/arch/riscv/include/asm/efi.h b/arch/riscv/include/asm/efi.h
> new file mode 100644
> index 000000000000..62d7d5eafed8
> --- /dev/null
> +++ b/arch/riscv/include/asm/efi.h
> @@ -0,0 +1,44 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2020 Western Digital Corporation or its affiliates.
> + * Based on arch/arm64/include/asm/efi.h
> + */
> +#ifndef _ASM_EFI_H
> +#define _ASM_EFI_H
> +
> +#include <asm/io.h>
> +#include <asm/mmu_context.h>
> +#include <asm/ptrace.h>
> +#include <asm/tlbflush.h>
> +
> +#define VA_BITS_MIN 39

I don't see this actually being used, but if it's releant to some macro that
I'm missing then EFI support should depend on rv64.

> +
> +/* on RISC-V, the FDT may be located anywhere in system RAM */
> +static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base)
> +{
> +	return ULONG_MAX;
> +}
> +
> +/* Load initrd at enough distance from DRAM start */
> +static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
> +						    unsigned long image_addr)
> +{
> +	return dram_base + SZ_256M;
> +}
> +
> +#define efi_bs_call(func, ...)	efi_system_table()->boottime->func(__VA_ARGS__)
> +#define efi_rt_call(func, ...)	efi_system_table()->runtime->func(__VA_ARGS__)
> +#define efi_is_native()		(true)
> +
> +#define efi_table_attr(inst, attr)	(inst->attr)
> +
> +#define efi_call_proto(inst, func, ...) inst->func(inst, ##__VA_ARGS__)
> +
> +#define alloc_screen_info(x...)		(&screen_info)
> +extern char stext_offset[];
> +
> +static inline void free_screen_info(struct screen_info *si)
> +{
> +}
> +
> +#endif /* _ASM_EFI_H */
> diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
> index 2a2b2b96a1dc..fcdc789d3f87 100644
> --- a/drivers/firmware/efi/Kconfig
> +++ b/drivers/firmware/efi/Kconfig
> @@ -111,7 +111,7 @@ config EFI_GENERIC_STUB
>
>  config EFI_ARMSTUB_DTB_LOADER
>  	bool "Enable the DTB loader"
> -	depends on EFI_GENERIC_STUB
> +	depends on EFI_GENERIC_STUB && !RISCV
>  	default y
>  	help
>  	  Select this config option to add support for the dtb= command
> diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
> index 0f57293d777e..eb365c55c0fe 100644
> --- a/drivers/firmware/efi/libstub/Makefile
> +++ b/drivers/firmware/efi/libstub/Makefile
> @@ -22,6 +22,8 @@ cflags-$(CONFIG_ARM64)		:= $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \
>  cflags-$(CONFIG_ARM)		:= $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \
>  				   -fno-builtin -fpic \
>  				   $(call cc-option,-mno-single-pic-base)
> +cflags-$(CONFIG_RISCV)		:= $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \
> +				   -fpic
>
>  cflags-$(CONFIG_EFI_GENERIC_STUB) += -I$(srctree)/scripts/dtc/libfdt
>
> @@ -57,6 +59,7 @@ lib-$(CONFIG_EFI_GENERIC_STUB)	+= efi-stub.o fdt.o string.o \
>  lib-$(CONFIG_ARM)		+= arm32-stub.o
>  lib-$(CONFIG_ARM64)		+= arm64-stub.o
>  lib-$(CONFIG_X86)		+= x86-stub.o
> +lib-$(CONFIG_RISCV)		+= riscv-stub.o
>  CFLAGS_arm32-stub.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
>  CFLAGS_arm64-stub.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
>
> @@ -100,6 +103,13 @@ STUBCOPY_FLAGS-$(CONFIG_X86)	+= --rename-section .bss=.bss.efistub,load,alloc
>  STUBCOPY_RELOC-$(CONFIG_X86_32)	:= R_386_32
>  STUBCOPY_RELOC-$(CONFIG_X86_64)	:= R_X86_64_64
>
> +# For RISC-V, we don't need anything special other than arm64. Keep all the
> +# symbols in .init section and make sure that no absolute symbols references
> +# doesn't exist.
> +STUBCOPY_FLAGS-$(CONFIG_RISCV)	+= --prefix-alloc-sections=.init \
> +				   --prefix-symbols=__efistub_
> +STUBCOPY_RELOC-$(CONFIG_RISCV)	:= R_RISCV_HI20
> +
>  $(obj)/%.stub.o: $(obj)/%.o FORCE
>  	$(call if_changed,stubcopy)
>
> diff --git a/drivers/firmware/efi/libstub/riscv-stub.c b/drivers/firmware/efi/libstub/riscv-stub.c
> new file mode 100644
> index 000000000000..bd1d6fed8754
> --- /dev/null
> +++ b/drivers/firmware/efi/libstub/riscv-stub.c
> @@ -0,0 +1,106 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2013, 2014 Linaro Ltd;  <roy.franz@linaro.org>
> + * Copyright (C) 2020 Western Digital Corporation or its affiliates.
> + *
> + * This file implements the EFI boot stub for the RISC-V kernel.
> + * Adapted from ARM64 version at drivers/firmware/efi/libstub/arm64-stub.c.
> + */
> +
> +#include <linux/efi.h>
> +#include <linux/libfdt.h>
> +#include <linux/libfdt_env.h>
> +#include <asm/efi.h>
> +#include <asm/sections.h>
> +
> +#include "efistub.h"
> +/*
> + * RISC-V requires the kernel image to placed 2 MB aligned base for 64 bit and
> + * 4MB for 32 bit.
> + */
> +#ifdef CONFIG_64BIT
> +#define MIN_KIMG_ALIGN	SZ_2M
> +#else
> +#define MIN_KIMG_ALIGN	SZ_4M
> +#endif
> +
> +typedef __attribute__((noreturn)) void (*jump_kernel_func)(unsigned int,
> +							   unsigned long);
> +efi_status_t check_platform_features(void)
> +{
> +	return EFI_SUCCESS;
> +}
> +
> +static u32 get_boot_hartid_from_fdt(unsigned long fdt)
> +{
> +	int chosen_node, len;
> +	const fdt32_t *prop;
> +
> +	chosen_node = fdt_path_offset((void *)fdt, "/chosen");
> +	if (chosen_node < 0)
> +		return U32_MAX;
> +	prop = fdt_getprop((void *)fdt, chosen_node, "boot-hartid", &len);
> +	if (!prop || len != sizeof(u32))
> +		return U32_MAX;
> +
> +	return fdt32_to_cpu(*prop);
> +}
> +
> +/*
> + * Jump to real kernel here with following constraints.
> + * 1. MMU should be disabled.
> + * 2. a0 should contain hartid
> + * 3. a1 should DT address
> + */
> +void __noreturn efi_enter_kernel(unsigned long entrypoint, unsigned long fdt,
> +				 unsigned long fdt_size)
> +{
> +	unsigned long kernel_entry = entrypoint + (unsigned long)stext_offset;
> +	jump_kernel_func jump_kernel = (jump_kernel_func) kernel_entry;
> +	u32 hartid = get_boot_hartid_from_fdt(fdt);
> +
> +	if (hartid == U32_MAX)
> +		/* We can not use panic or BUG at this point */
> +		__asm__ __volatile__ ("ebreak");
> +	/* Disable MMU */
> +	csr_write(CSR_SATP, 0);
> +	jump_kernel(hartid, fdt);
> +}
> +
> +efi_status_t handle_kernel_image(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 = 0;
> +	unsigned long preferred_addr;
> +
> +	kernel_size = _edata - _start;
> +	*reserve_size = kernel_size + (_end - _edata);
> +	*image_addr = (unsigned long)_start;
> +
> +	/*
> +	 * RISC-V kernel maps PAGE_OFFSET virtual address to the same physical
> +	 * address where kernel is booted. That's why kernel should boot from
> +	 * as low as possible to avoid wastage of memory. Currently, dram_base
> +	 * is occupied by the firmware. So the preferred address for kernel to
> +	 * boot is next aligned address. If preferred address is not available,
> +	 * relocate_kernel will fall back to efi_low_alloc_above to allocate
> +	 * lowest possible memory region as long as the address and size meets
> +	 * the alignment constraints.
> +	 */
> +	preferred_addr = round_up(dram_base, MIN_KIMG_ALIGN) + MIN_KIMG_ALIGN;
> +	status = efi_relocate_kernel(image_addr, kernel_size, *reserve_size,
> +				     preferred_addr, MIN_KIMG_ALIGN, dram_base);
> +
> +	if (status != EFI_SUCCESS) {
> +		pr_efi_err("Failed to relocate kernel\n");
> +		*reserve_size = 0;
> +		return status;
> +	}
> +
> +	return EFI_SUCCESS;
> +}

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

* Re: [v4 PATCH 0/3] Add UEFI support for RISC-V
  2020-04-21  7:24 ` [v4 PATCH 0/3] Add UEFI support for RISC-V Ard Biesheuvel
  2020-04-21 17:29   ` Atish Patra
@ 2020-04-21 20:59   ` Palmer Dabbelt
  2020-04-22 16:39     ` Ard Biesheuvel
  1 sibling, 1 reply; 16+ messages in thread
From: Palmer Dabbelt @ 2020-04-21 20:59 UTC (permalink / raw)
  To: ardb
  Cc: Atish Patra, linux-kernel, linux-efi, linux-riscv, masahiroy,
	xypron.glpk

On Tue, 21 Apr 2020 00:24:04 PDT (-0700), ardb@kernel.org wrote:
> On Tue, 21 Apr 2020 at 05:34, Atish Patra <atish.patra@wdc.com> wrote:
>>
>> This series adds UEFI support for RISC-V. Currently, only boot time
>> services have been added. Runtime services will be added in a separate
>> series. This series depends on some core EFI patches
>> present in current in efi-next and following other patches.
>>
>> U-Boot: Adds the boot hartid under chosen node.
>> https://lists.denx.de/pipermail/u-boot/2020-April/405726.html
>>
>> Linux kernel: 5.7-rc1
>>
>> OpenSBI: master
>>
>> Patch 1 just moves arm-stub code to a generic code so that it can be used
>> across different architecture.
>>
>> Patch 3 adds fixmap bindings so that CONFIG_EFI can be compiled and we do not
>> have create separate config to enable boot time services.
>> As runtime services are not enabled at this time, full generic early ioremap
>> support is also not added in this series.
>>
>> Patch 4 and 5 adds the PE/COFF header and EFI stub code support for RISC-V
>> respectively.
>>
>> The patches can also be found in following git repo.
>>
>> https://github.com/atishp04/linux/tree/wip_uefi_riscv_v4
>>
>> The patches have been verified on Qemu using bootefi command in U-Boot.
>>
>> Changes from v3->v4:
>> 1. Rebased on top of efi-next.
>> 2. Dropped patch 1 & 2 from this series as it is already queued in efi-next.
>> Changes from v2->v3:
>> 3. Improved handle_kernel_image() for RISC-V.
>>
>
> Thanks Atish. This looks nice and simple now.
>
> I will need an ack from the RISC-V maintainers on these, and it is up
> to them to consider whether the changes to core kconfigs and makefiles
> are likely to cause trouble or not. If so, I am happy to work out a
> way to merge this via a shared stable branch.

Sorry it took me a while to get around to these, but they're essentially good
with me.  There's some comments about needing ISA_C/c.li, but that's pretty
trivial.  In terms of mechanics: I don't really ever understand how to do these
multi-tree merges.  In an ideal world I'd like to have the arch/riscv/ stuff
stay in riscv/for-next, both because I don't want to deal with merge conflicts
and because that's where the RISC-V autobuilders look.

The best I can come up with is to split #3 up such that drivers/firmware/efi/
is its own patch and then send that up along with the PE header definitions
into an RC.  It'd be unused code at that point, but at least it'd break the
dependency between the trees and it'll be getting tested in riscv/for-next so
it won't rot.  We can ARMSTUB->GENERIC_STUB by just having the RISC-V support
select woth ARMSTUB and GENERIC_STUB, with a cleanup going in after everything
is merged.

That said, I'm happy if there's a better way to do this...

>> Changes from v1->v2:
>> 1. Rebased on 5.7-rc1.
>> 2. Fixed minor typos and removed redundant macros/comments.
>>
>> Changes from previous version:
>> 1. Renamed to the generic efi stub macro.
>> 2. Address all redundant comments.
>> 3. Supported EFI kernel image with normal booti command.
>> 4. Removed runtime service related macro defines.
>>
>> Atish Patra (3):
>> RISC-V: Define fixmap bindings for generic early ioremap support
>> RISC-V: Add PE/COFF header for EFI stub
>> RISC-V: Add EFI stub support.
>>
>> arch/riscv/Kconfig                        |  21 +++++
>> arch/riscv/Makefile                       |   1 +
>> arch/riscv/configs/defconfig              |   1 +
>> arch/riscv/include/asm/Kbuild             |   1 +
>> arch/riscv/include/asm/efi.h              |  44 +++++++++
>> arch/riscv/include/asm/fixmap.h           |  18 ++++
>> arch/riscv/include/asm/io.h               |   1 +
>> arch/riscv/include/asm/sections.h         |  13 +++
>> arch/riscv/kernel/Makefile                |   4 +
>> arch/riscv/kernel/efi-header.S            |  99 ++++++++++++++++++++
>> arch/riscv/kernel/head.S                  |  16 ++++
>> arch/riscv/kernel/image-vars.h            |  53 +++++++++++
>> arch/riscv/kernel/vmlinux.lds.S           |  20 +++-
>> drivers/firmware/efi/Kconfig              |   2 +-
>> drivers/firmware/efi/libstub/Makefile     |  10 ++
>> drivers/firmware/efi/libstub/riscv-stub.c | 106 ++++++++++++++++++++++
>> 16 files changed, 407 insertions(+), 3 deletions(-)
>> create mode 100644 arch/riscv/include/asm/efi.h
>> create mode 100644 arch/riscv/include/asm/sections.h
>> create mode 100644 arch/riscv/kernel/efi-header.S
>> create mode 100644 arch/riscv/kernel/image-vars.h
>> create mode 100644 drivers/firmware/efi/libstub/riscv-stub.c
>>
>> --
>> 2.24.0
>>

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

* Re: [v4 PATCH 0/3] Add UEFI support for RISC-V
  2020-04-21 20:59   ` Palmer Dabbelt
@ 2020-04-22 16:39     ` Ard Biesheuvel
  0 siblings, 0 replies; 16+ messages in thread
From: Ard Biesheuvel @ 2020-04-22 16:39 UTC (permalink / raw)
  To: Palmer Dabbelt
  Cc: Atish Patra, Linux Kernel Mailing List, linux-efi, linux-riscv,
	Masahiro Yamada, Heinrich Schuchardt

On Tue, 21 Apr 2020 at 22:59, Palmer Dabbelt <palmer@dabbelt.com> wrote:
>
> On Tue, 21 Apr 2020 00:24:04 PDT (-0700), ardb@kernel.org wrote:
> > On Tue, 21 Apr 2020 at 05:34, Atish Patra <atish.patra@wdc.com> wrote:
> >>
> >> This series adds UEFI support for RISC-V. Currently, only boot time
> >> services have been added. Runtime services will be added in a separate
> >> series. This series depends on some core EFI patches
> >> present in current in efi-next and following other patches.
> >>
> >> U-Boot: Adds the boot hartid under chosen node.
> >> https://lists.denx.de/pipermail/u-boot/2020-April/405726.html
> >>
> >> Linux kernel: 5.7-rc1
> >>
> >> OpenSBI: master
> >>
> >> Patch 1 just moves arm-stub code to a generic code so that it can be used
> >> across different architecture.
> >>
> >> Patch 3 adds fixmap bindings so that CONFIG_EFI can be compiled and we do not
> >> have create separate config to enable boot time services.
> >> As runtime services are not enabled at this time, full generic early ioremap
> >> support is also not added in this series.
> >>
> >> Patch 4 and 5 adds the PE/COFF header and EFI stub code support for RISC-V
> >> respectively.
> >>
> >> The patches can also be found in following git repo.
> >>
> >> https://github.com/atishp04/linux/tree/wip_uefi_riscv_v4
> >>
> >> The patches have been verified on Qemu using bootefi command in U-Boot.
> >>
> >> Changes from v3->v4:
> >> 1. Rebased on top of efi-next.
> >> 2. Dropped patch 1 & 2 from this series as it is already queued in efi-next.
> >> Changes from v2->v3:
> >> 3. Improved handle_kernel_image() for RISC-V.
> >>
> >
> > Thanks Atish. This looks nice and simple now.
> >
> > I will need an ack from the RISC-V maintainers on these, and it is up
> > to them to consider whether the changes to core kconfigs and makefiles
> > are likely to cause trouble or not. If so, I am happy to work out a
> > way to merge this via a shared stable branch.
>
> Sorry it took me a while to get around to these, but they're essentially good
> with me.  There's some comments about needing ISA_C/c.li, but that's pretty
> trivial.  In terms of mechanics: I don't really ever understand how to do these
> multi-tree merges.  In an ideal world I'd like to have the arch/riscv/ stuff
> stay in riscv/for-next, both because I don't want to deal with merge conflicts
> and because that's where the RISC-V autobuilders look.
>
> The best I can come up with is to split #3 up such that drivers/firmware/efi/
> is its own patch and then send that up along with the PE header definitions
> into an RC.  It'd be unused code at that point, but at least it'd break the
> dependency between the trees and it'll be getting tested in riscv/for-next so
> it won't rot.  We can ARMSTUB->GENERIC_STUB by just having the RISC-V support
> select woth ARMSTUB and GENERIC_STUB, with a cleanup going in after everything
> is merged.
>
> That said, I'm happy if there's a better way to do this...
>

I'll reshuffle the code a bit, and send out an updated series. If we
are all happy with that, I will stick the first 2 patches on a shared
tag that you can pull into your branch, and you can apply the
remaining 4 patches on top of that. Are you ok with a tag based on
v5.7-rc2?

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

* Re: [v4 PATCH 2/3] RISC-V: Add PE/COFF header for EFI stub
  2020-04-21 20:02   ` Palmer Dabbelt
@ 2020-04-22 17:43     ` Atish Patra
  0 siblings, 0 replies; 16+ messages in thread
From: Atish Patra @ 2020-04-22 17:43 UTC (permalink / raw)
  To: palmer; +Cc: linux-efi, linux-riscv, xypron.glpk, masahiroy, linux-kernel, ardb

On Tue, 2020-04-21 at 13:02 -0700, Palmer Dabbelt wrote:
> [I just saw there's a v4, so I'm moving over here]
> 
> On Mon, 20 Apr 2020 20:33:35 PDT (-0700), Atish Patra wrote:
> > Linux kernel Image can appear as an EFI application With
> > appropriate
> > PE/COFF header fields in the beginning of the Image header. An EFI
> > application loader can directly load a Linux kernel Image and an
> > EFI
> > stub residing in kernel can boot Linux kernel directly.
> > 
> > Add the necessary PE/COFF header.
> > 
> > Signed-off-by: Atish Patra <atish.patra@wdc.com>
> > ---
> >  arch/riscv/include/asm/sections.h | 13 ++++
> >  arch/riscv/kernel/Makefile        |  4 ++
> >  arch/riscv/kernel/efi-header.S    | 99
> > +++++++++++++++++++++++++++++++
> >  arch/riscv/kernel/head.S          | 16 +++++
> >  arch/riscv/kernel/image-vars.h    | 53 +++++++++++++++++
> >  arch/riscv/kernel/vmlinux.lds.S   | 20 ++++++-
> >  6 files changed, 203 insertions(+), 2 deletions(-)
> >  create mode 100644 arch/riscv/include/asm/sections.h
> >  create mode 100644 arch/riscv/kernel/efi-header.S
> >  create mode 100644 arch/riscv/kernel/image-vars.h
> > 
> > diff --git a/arch/riscv/include/asm/sections.h
> > b/arch/riscv/include/asm/sections.h
> > new file mode 100644
> > index 000000000000..3a9971b1210f
> > --- /dev/null
> > +++ b/arch/riscv/include/asm/sections.h
> > @@ -0,0 +1,13 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/*
> > + * Copyright (C) 2020 Western Digital Corporation or its
> > affiliates.
> > + */
> > +#ifndef __ASM_SECTIONS_H
> > +#define __ASM_SECTIONS_H
> > +
> > +#include <asm-generic/sections.h>
> > +
> > +extern char _start[];
> > +extern char _start_kernel[];
> > +
> > +#endif /* __ASM_SECTIONS_H */
> > diff --git a/arch/riscv/kernel/Makefile
> > b/arch/riscv/kernel/Makefile
> > index 86c83081044f..86ca755f8a9f 100644
> > --- a/arch/riscv/kernel/Makefile
> > +++ b/arch/riscv/kernel/Makefile
> > @@ -32,6 +32,10 @@ obj-y	+= patch.o
> >  obj-$(CONFIG_MMU) += vdso.o vdso/
> > 
> >  obj-$(CONFIG_RISCV_M_MODE)	+= clint.o traps_misaligned.o
> > +OBJCOPYFLAGS := --prefix-symbols=__efistub_
> > +$(obj)/%.stub.o: $(obj)/%.o FORCE
> > +	$(call if_changed,objcopy)
> > +
> >  obj-$(CONFIG_FPU)		+= fpu.o
> >  obj-$(CONFIG_SMP)		+= smpboot.o
> >  obj-$(CONFIG_SMP)		+= smp.o
> > diff --git a/arch/riscv/kernel/efi-header.S
> > b/arch/riscv/kernel/efi-header.S
> > new file mode 100644
> > index 000000000000..69dde8268527
> > --- /dev/null
> > +++ b/arch/riscv/kernel/efi-header.S
> > @@ -0,0 +1,99 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/*
> > + * Copyright (C) 2020 Western Digital Corporation or its
> > affiliates.
> > + * Adapted from arch/arm64/kernel/efi-header.S
> > + */
> > +
> > +#include <linux/pe.h>
> > +#include <linux/sizes.h>
> > +
> > +	.macro	__EFI_PE_HEADER
> > +	.long	PE_MAGIC
> > +coff_header:
> > +	.short	IMAGE_FILE_MACHINE_RISCV64		// Machine
> > +	.short	section_count				//
> > NumberOfSections
> > +	.long	0 					//
> > TimeDateStamp
> > +	.long	0					//
> > PointerToSymbolTable
> > +	.long	0					//
> > NumberOfSymbols
> > +	.short	section_table - optional_header		//
> > SizeOfOptionalHeader
> > +	.short	IMAGE_FILE_DEBUG_STRIPPED | \
> > +		IMAGE_FILE_EXECUTABLE_IMAGE | \
> > +		IMAGE_FILE_LINE_NUMS_STRIPPED		//
> > Characteristics
> > +
> > +optional_header:
> > +	.short	PE_OPT_MAGIC_PE32PLUS			// PE32+
> > format
> > +	.byte	0x02					//
> > MajorLinkerVersion
> > +	.byte	0x14					//
> > MinorLinkerVersion
> > +	.long	__text_end - efi_header_end		//
> > SizeOfCode
> > +	.long	_end - __text_end			//
> > SizeOfInitializedData
> > +	.long	0					//
> > SizeOfUninitializedData
> > +	.long	__efistub_efi_entry - _start		//
> > AddressOfEntryPoint
> > +	.long	efi_header_end - _start			//
> > BaseOfCode
> > +
> > +extra_header_fields:
> > +	.quad	0					//
> > ImageBase
> > +	.long	SZ_4K					//
> > SectionAlignment
> > +	.long	PECOFF_FILE_ALIGNMENT			//
> > FileAlignment
> > +	.short	0					//
> > MajorOperatingSystemVersion
> > +	.short	0					//
> > MinorOperatingSystemVersion
> > +	.short	LINUX_EFISTUB_MAJOR_VERSION		//
> > MajorImageVersion
> > +	.short	LINUX_EFISTUB_MINOR_VERSION		//
> > MinorImageVersion
> > +	.short	0					//
> > MajorSubsystemVersion
> > +	.short	0					//
> > MinorSubsystemVersion
> > +	.long	0					//
> > Win32VersionValue
> > +
> > +	.long	_end - _start				//
> > SizeOfImage
> > +
> > +	// Everything before the kernel image is considered part of the
> > header
> > +	.long	efi_header_end - _start			//
> > SizeOfHeaders
> > +	.long	0					// CheckSum
> > +	.short	IMAGE_SUBSYSTEM_EFI_APPLICATION		//
> > Subsystem
> > +	.short	0					//
> > DllCharacteristics
> > +	.quad	0					//
> > SizeOfStackReserve
> > +	.quad	0					//
> > SizeOfStackCommit
> > +	.quad	0					//
> > SizeOfHeapReserve
> > +	.quad	0					//
> > SizeOfHeapCommit
> > +	.long	0					//
> > LoaderFlags
> > +	.long	(section_table - .) / 8			//
> > NumberOfRvaAndSizes
> > +
> > +	.quad	0					//
> > ExportTable
> > +	.quad	0					//
> > ImportTable
> > +	.quad	0					//
> > ResourceTable
> > +	.quad	0					//
> > ExceptionTable
> > +	.quad	0					//
> > CertificationTable
> > +	.quad	0					//
> > BaseRelocationTable
> > +
> > +	// Section table
> > +section_table:
> > +	.ascii	".text\0\0\0"
> > +	.long	__text_end - efi_header_end		//
> > VirtualSize
> > +	.long	efi_header_end - _start			//
> > VirtualAddress
> > +	.long	__text_end - efi_header_end		//
> > SizeOfRawData
> > +	.long	efi_header_end - _start			//
> > PointerToRawData
> > +
> > +	.long	0					//
> > PointerToRelocations
> > +	.long	0					//
> > PointerToLineNumbers
> > +	.short	0					//
> > NumberOfRelocations
> > +	.short	0					//
> > NumberOfLineNumbers
> > +	.long	IMAGE_SCN_CNT_CODE | \
> > +		IMAGE_SCN_MEM_READ | \
> > +		IMAGE_SCN_MEM_EXECUTE			//
> > Characteristics
> > +
> > +	.ascii	".data\0\0\0"
> > +	.long	__data_virt_size			//
> > VirtualSize
> > +	.long	__text_end - _start			//
> > VirtualAddress
> > +	.long	__data_raw_size				//
> > SizeOfRawData
> > +	.long	__text_end - _start			//
> > PointerToRawData
> > +
> > +	.long	0					//
> > PointerToRelocations
> > +	.long	0					//
> > PointerToLineNumbers
> > +	.short	0					//
> > NumberOfRelocations
> > +	.short	0					//
> > NumberOfLineNumbers
> > +	.long	IMAGE_SCN_CNT_INITIALIZED_DATA | \
> > +		IMAGE_SCN_MEM_READ | \
> > +		IMAGE_SCN_MEM_WRITE			// Characteristics
> > +
> > +	.set	section_count, (. - section_table) / 40
> > +
> > +efi_header_end:
> > +	.endm
> > diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S
> > index 98a406474e7d..ddd613dac9d6 100644
> > --- a/arch/riscv/kernel/head.S
> > +++ b/arch/riscv/kernel/head.S
> > @@ -13,6 +13,7 @@
> >  #include <asm/csr.h>
> >  #include <asm/hwcap.h>
> >  #include <asm/image.h>
> > +#include "efi-header.S"
> > 
> >  __HEAD
> >  ENTRY(_start)
> > @@ -22,10 +23,18 @@ ENTRY(_start)
> >  	 * Do not modify it without modifying the structure and all
> > bootloaders
> >  	 * that expects this header format!!
> >  	 */
> > +#ifdef CONFIG_EFI
> > +	/*
> > +	 * This instruction decodes to "MZ" ASCII required by UEFI.
> > +	 */
> > +	li s4,-13
> 
> This needs to be a c.li in order to encode as "MZ".  It'd be cleaner
> to
> explicitly write it that way rather that having the assembler
> transparently
> compress it, but we definately need to have Kconfig make EFI select
> ISA_C.
> 

Sure. I will add that.

> > +	j _start_kernel
> > +#else
> >  	/* jump to start kernel */
> >  	j _start_kernel
> >  	/* reserved */
> >  	.word 0
> > +#endif
> >  	.balign 8
> >  #if __riscv_xlen == 64
> >  	/* Image load offset(2MB) from start of RAM */
> > @@ -43,7 +52,14 @@ ENTRY(_start)
> >  	.ascii RISCV_IMAGE_MAGIC
> >  	.balign 4
> >  	.ascii RISCV_IMAGE_MAGIC2
> > +#ifdef CONFIG_EFI
> > +	.word pe_head_start - _start
> > +pe_head_start:
> > +
> > +	__EFI_PE_HEADER
> > +#else
> >  	.word 0
> > +#endif
> > 
> >  .align 2
> >  #ifdef CONFIG_MMU
> > diff --git a/arch/riscv/kernel/image-vars.h
> > b/arch/riscv/kernel/image-vars.h
> > new file mode 100644
> > index 000000000000..bd8b764f0ad9
> > --- /dev/null
> > +++ b/arch/riscv/kernel/image-vars.h
> > @@ -0,0 +1,53 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/*
> > + * Copyright (C) 2020 Western Digital Corporation or its
> > affiliates.
> > + * Linker script variables to be set after section resolution, as
> > + * ld.lld does not like variables assigned before SECTIONS is
> > processed.
> > + * Based on arch/arm64/kerne/image-vars.h
> > + */
> > +#ifndef __RISCV_KERNEL_IMAGE_VARS_H
> > +#define __RISCV_KERNEL_IMAGE_VARS_H
> > +
> > +#ifndef LINKER_SCRIPT
> > +#error This file should only be included in vmlinux.lds.S
> > +#endif
> > +
> > +#ifdef CONFIG_EFI
> > +
> > +__efistub_stext_offset = _start_kernel - _start;
> > +
> > +/*
> > + * The EFI stub has its own symbol namespace prefixed by
> > __efistub_, to
> > + * isolate it from the kernel proper. The following symbols are
> > legally
> > + * accessed by the stub, so provide some aliases to make them
> > accessible.
> > + * Only include data symbols here, or text symbols of functions
> > that are
> > + * guaranteed to be safe when executed at another offset than they
> > were
> > + * linked at. The routines below are all implemented in assembler
> > in a
> > + * position independent manner
> > + */
> > +__efistub_memcmp		= memcmp;
> > +__efistub_memchr		= memchr;
> > +__efistub_memcpy		= memcpy;
> > +__efistub_memmove		= memmove;
> > +__efistub_memset		= memset;
> > +__efistub_strlen		= strlen;
> > +__efistub_strnlen		= strnlen;
> > +__efistub_strcmp		= strcmp;
> > +__efistub_strncmp		= strncmp;
> > +__efistub_strrchr		= strrchr;
> > +
> > +#ifdef CONFIG_KASAN
> > +__efistub___memcpy		= memcpy;
> > +__efistub___memmove		= memmove;
> > +__efistub___memset		= memset;
> > +#endif
> > +
> > +__efistub__start		= _start;
> > +__efistub__start_kernel		= _start_kernel;
> > +__efistub__end			= _end;
> > +__efistub__edata		= _edata;
> > +__efistub_screen_info		= screen_info;
> > +
> > +#endif
> > +
> > +#endif /* __RISCV_KERNEL_IMAGE_VARS_H */
> > diff --git a/arch/riscv/kernel/vmlinux.lds.S
> > b/arch/riscv/kernel/vmlinux.lds.S
> > index 0339b6bbe11a..20ebf7e8c215 100644
> > --- a/arch/riscv/kernel/vmlinux.lds.S
> > +++ b/arch/riscv/kernel/vmlinux.lds.S
> > @@ -10,6 +10,7 @@
> >  #include <asm/cache.h>
> >  #include <asm/thread_info.h>
> >  #include <asm/set_memory.h>
> > +#include "image-vars.h"
> > 
> >  #include <linux/sizes.h>
> >  OUTPUT_ARCH(riscv)
> > @@ -17,6 +18,14 @@ ENTRY(_start)
> > 
> >  jiffies = jiffies_64;
> > 
> > +PECOFF_FILE_ALIGNMENT = 0x200;
> > +#ifdef CONFIG_EFI
> > +#define PECOFF_EDATA_PADDING	\
> > +	.pecoff_edata_padding : { BYTE(0); . =
> > ALIGN(PECOFF_FILE_ALIGNMENT); }
> > +#else
> > +#define PECOFF_EDATA_PADDING
> > +#endif
> > +
> >  SECTIONS
> >  {
> >  	/* Beginning of code and text segment */
> > @@ -62,6 +71,8 @@ SECTIONS
> >  		_etext = .;
> >  	}
> > 
> > +	__text_end = .;
> > +
> >  	/* Start of data section */
> >  	_sdata = .;
> >  	RO_DATA(SECTION_ALIGN)
> > @@ -78,9 +89,12 @@ SECTIONS
> >  	.sdata : {
> >  		__global_pointer$ = . + 0x800;
> >  		*(.sdata*)
> > -		/* End of data section */
> > -		_edata = .;
> >  	}
> > +	PECOFF_EDATA_PADDING
> > +	__data_raw_size = ABSOLUTE(. - __text_end);
> > +
> > +	/* End of data section */
> > +	_edata = .;
> > 
> >  	BSS_SECTION(PAGE_SIZE, PAGE_SIZE, 0)
> > 
> > @@ -88,6 +102,8 @@ SECTIONS
> >  		*(.rel.dyn*)
> >  	}
> > 
> > +	__data_virt_size = ABSOLUTE(. - __text_end);
> > +
> >  	_end = .;
> > 
> >  	STABS_DEBUG

-- 
Regards,
Atish

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

* Re: [v4 PATCH 2/3] RISC-V: Add PE/COFF header for EFI stub
  2020-04-21 17:51   ` Ard Biesheuvel
@ 2020-04-22 17:44     ` Atish Patra
  0 siblings, 0 replies; 16+ messages in thread
From: Atish Patra @ 2020-04-22 17:44 UTC (permalink / raw)
  To: ardb; +Cc: linux-efi, linux-riscv, palmer, masahiroy, linux-kernel, xypron.glpk

On Tue, 2020-04-21 at 19:51 +0200, Ard Biesheuvel wrote:
> Hi Atish,
> 
> One thing I forgot to check, below:
> 
> On Tue, 21 Apr 2020 at 05:34, Atish Patra <atish.patra@wdc.com>
> wrote:
> > Linux kernel Image can appear as an EFI application With
> > appropriate
> > PE/COFF header fields in the beginning of the Image header. An EFI
> > application loader can directly load a Linux kernel Image and an
> > EFI
> > stub residing in kernel can boot Linux kernel directly.
> > 
> > Add the necessary PE/COFF header.
> > 
> > Signed-off-by: Atish Patra <atish.patra@wdc.com>
> > ---
> >  arch/riscv/include/asm/sections.h | 13 ++++
> >  arch/riscv/kernel/Makefile        |  4 ++
> >  arch/riscv/kernel/efi-header.S    | 99
> > +++++++++++++++++++++++++++++++
> >  arch/riscv/kernel/head.S          | 16 +++++
> >  arch/riscv/kernel/image-vars.h    | 53 +++++++++++++++++
> >  arch/riscv/kernel/vmlinux.lds.S   | 20 ++++++-
> >  6 files changed, 203 insertions(+), 2 deletions(-)
> >  create mode 100644 arch/riscv/include/asm/sections.h
> >  create mode 100644 arch/riscv/kernel/efi-header.S
> >  create mode 100644 arch/riscv/kernel/image-vars.h
> > 
> > diff --git a/arch/riscv/include/asm/sections.h
> > b/arch/riscv/include/asm/sections.h
> > new file mode 100644
> > index 000000000000..3a9971b1210f
> > --- /dev/null
> > +++ b/arch/riscv/include/asm/sections.h
> > @@ -0,0 +1,13 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/*
> > + * Copyright (C) 2020 Western Digital Corporation or its
> > affiliates.
> > + */
> > +#ifndef __ASM_SECTIONS_H
> > +#define __ASM_SECTIONS_H
> > +
> > +#include <asm-generic/sections.h>
> > +
> > +extern char _start[];
> > +extern char _start_kernel[];
> > +
> > +#endif /* __ASM_SECTIONS_H */
> > diff --git a/arch/riscv/kernel/Makefile
> > b/arch/riscv/kernel/Makefile
> > index 86c83081044f..86ca755f8a9f 100644
> > --- a/arch/riscv/kernel/Makefile
> > +++ b/arch/riscv/kernel/Makefile
> > @@ -32,6 +32,10 @@ obj-y        += patch.o
> >  obj-$(CONFIG_MMU) += vdso.o vdso/
> > 
> >  obj-$(CONFIG_RISCV_M_MODE)     += clint.o traps_misaligned.o
> > +OBJCOPYFLAGS := --prefix-symbols=__efistub_
> > +$(obj)/%.stub.o: $(obj)/%.o FORCE
> > +       $(call if_changed,objcopy)
> > +
> >  obj-$(CONFIG_FPU)              += fpu.o
> >  obj-$(CONFIG_SMP)              += smpboot.o
> >  obj-$(CONFIG_SMP)              += smp.o
> > diff --git a/arch/riscv/kernel/efi-header.S
> > b/arch/riscv/kernel/efi-header.S
> > new file mode 100644
> > index 000000000000..69dde8268527
> > --- /dev/null
> > +++ b/arch/riscv/kernel/efi-header.S
> > @@ -0,0 +1,99 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/*
> > + * Copyright (C) 2020 Western Digital Corporation or its
> > affiliates.
> > + * Adapted from arch/arm64/kernel/efi-header.S
> > + */
> > +
> > +#include <linux/pe.h>
> > +#include <linux/sizes.h>
> > +
> > +       .macro  __EFI_PE_HEADER
> > +       .long   PE_MAGIC
> > +coff_header:
> > +       .short  IMAGE_FILE_MACHINE_RISCV64              // Machine
> > +       .short  section_count                           //
> > NumberOfSections
> > +       .long   0                                       //
> > TimeDateStamp
> > +       .long   0                                       //
> > PointerToSymbolTable
> > +       .long   0                                       //
> > NumberOfSymbols
> > +       .short  section_table - optional_header         //
> > SizeOfOptionalHeader
> > +       .short  IMAGE_FILE_DEBUG_STRIPPED | \
> > +               IMAGE_FILE_EXECUTABLE_IMAGE | \
> > +               IMAGE_FILE_LINE_NUMS_STRIPPED           //
> > Characteristics
> > +
> > +optional_header:
> > +       .short  PE_OPT_MAGIC_PE32PLUS                   // PE32+
> > format
> > +       .byte   0x02                                    //
> > MajorLinkerVersion
> > +       .byte   0x14                                    //
> > MinorLinkerVersion
> > +       .long   __text_end - efi_header_end             //
> > SizeOfCode
> > +       .long   _end - __text_end                       //
> > SizeOfInitializedData
> > +       .long   0                                       //
> > SizeOfUninitializedData
> > +       .long   __efistub_efi_entry - _start            //
> > AddressOfEntryPoint
> > +       .long   efi_header_end - _start                 //
> > BaseOfCode
> > +
> > +extra_header_fields:
> > +       .quad   0                                       //
> > ImageBase
> > +       .long   SZ_4K                                   //
> > SectionAlignment
> 
> Here you set the section alignment to 4 KB ...
> 
> > +       .long   PECOFF_FILE_ALIGNMENT                   //
> > FileAlignment
> > +       .short  0                                       //
> > MajorOperatingSystemVersion
> > +       .short  0                                       //
> > MinorOperatingSystemVersion
> > +       .short  LINUX_EFISTUB_MAJOR_VERSION             //
> > MajorImageVersion
> > +       .short  LINUX_EFISTUB_MINOR_VERSION             //
> > MinorImageVersion
> > +       .short  0                                       //
> > MajorSubsystemVersion
> > +       .short  0                                       //
> > MinorSubsystemVersion
> > +       .long   0                                       //
> > Win32VersionValue
> > +
> > +       .long   _end - _start                           //
> > SizeOfImage
> > +
> > +       // Everything before the kernel image is considered part of
> > the header
> > +       .long   efi_header_end - _start                 //
> > SizeOfHeaders
> > +       .long   0                                       // CheckSum
> > +       .short  IMAGE_SUBSYSTEM_EFI_APPLICATION         //
> > Subsystem
> > +       .short  0                                       //
> > DllCharacteristics
> > +       .quad   0                                       //
> > SizeOfStackReserve
> > +       .quad   0                                       //
> > SizeOfStackCommit
> > +       .quad   0                                       //
> > SizeOfHeapReserve
> > +       .quad   0                                       //
> > SizeOfHeapCommit
> > +       .long   0                                       //
> > LoaderFlags
> > +       .long   (section_table - .) / 8                 //
> > NumberOfRvaAndSizes
> > +
> > +       .quad   0                                       //
> > ExportTable
> > +       .quad   0                                       //
> > ImportTable
> > +       .quad   0                                       //
> > ResourceTable
> > +       .quad   0                                       //
> > ExceptionTable
> > +       .quad   0                                       //
> > CertificationTable
> > +       .quad   0                                       //
> > BaseRelocationTable
> > +
> > +       // Section table
> > +section_table:
> > +       .ascii  ".text\0\0\0"
> > +       .long   __text_end - efi_header_end             //
> > VirtualSize
> > +       .long   efi_header_end - _start                 //
> > VirtualAddress
> 
> ... and here you define the address of the first section, which
> should
> be aligned to section alignment of 4 KB
> 
> > +       .long   __text_end - efi_header_end             //
> > SizeOfRawData
> > +       .long   efi_header_end - _start                 //
> > PointerToRawData
> > +
> > +       .long   0                                       //
> > PointerToRelocations
> > +       .long   0                                       //
> > PointerToLineNumbers
> > +       .short  0                                       //
> > NumberOfRelocations
> > +       .short  0                                       //
> > NumberOfLineNumbers
> > +       .long   IMAGE_SCN_CNT_CODE | \
> > +               IMAGE_SCN_MEM_READ | \
> > +               IMAGE_SCN_MEM_EXECUTE                   //
> > Characteristics
> > +
> > +       .ascii  ".data\0\0\0"
> > +       .long   __data_virt_size                        //
> > VirtualSize
> > +       .long   __text_end - _start                     //
> > VirtualAddress
> > +       .long   __data_raw_size                         //
> > SizeOfRawData
> > +       .long   __text_end - _start                     //
> > PointerToRawData
> > +
> > +       .long   0                                       //
> > PointerToRelocations
> > +       .long   0                                       //
> > PointerToLineNumbers
> > +       .short  0                                       //
> > NumberOfRelocations
> > +       .short  0                                       //
> > NumberOfLineNumbers
> > +       .long   IMAGE_SCN_CNT_INITIALIZED_DATA | \
> > +               IMAGE_SCN_MEM_READ | \
> > +               IMAGE_SCN_MEM_WRITE                     //
> > Characteristics
> > +
> > +       .set    section_count, (. - section_table) / 40
> > +
> > +efi_header_end:
> 
> ... so you will need to put an .p2align 12 here to ensure that
> efi_header_end appears at 4 KB boundary.
> 
> Similarly, you will have to align the symbols __text_end and
> __data_virt_size in the linker scripts to make them round multiples
> of
> 4 KB.
> 
> 

Sure. I will fix the alignment.

> 
> > +       .endm
> > diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S
> > index 98a406474e7d..ddd613dac9d6 100644
> > --- a/arch/riscv/kernel/head.S
> > +++ b/arch/riscv/kernel/head.S
> > @@ -13,6 +13,7 @@
> >  #include <asm/csr.h>
> >  #include <asm/hwcap.h>
> >  #include <asm/image.h>
> > +#include "efi-header.S"
> > 
> >  __HEAD
> >  ENTRY(_start)
> > @@ -22,10 +23,18 @@ ENTRY(_start)
> >          * Do not modify it without modifying the structure and all
> > bootloaders
> >          * that expects this header format!!
> >          */
> > +#ifdef CONFIG_EFI
> > +       /*
> > +        * This instruction decodes to "MZ" ASCII required by UEFI.
> > +        */
> > +       li s4,-13
> > +       j _start_kernel
> > +#else
> >         /* jump to start kernel */
> >         j _start_kernel
> >         /* reserved */
> >         .word 0
> > +#endif
> >         .balign 8
> >  #if __riscv_xlen == 64
> >         /* Image load offset(2MB) from start of RAM */
> > @@ -43,7 +52,14 @@ ENTRY(_start)
> >         .ascii RISCV_IMAGE_MAGIC
> >         .balign 4
> >         .ascii RISCV_IMAGE_MAGIC2
> > +#ifdef CONFIG_EFI
> > +       .word pe_head_start - _start
> > +pe_head_start:
> > +
> > +       __EFI_PE_HEADER
> > +#else
> >         .word 0
> > +#endif
> > 
> >  .align 2
> >  #ifdef CONFIG_MMU
> > diff --git a/arch/riscv/kernel/image-vars.h
> > b/arch/riscv/kernel/image-vars.h
> > new file mode 100644
> > index 000000000000..bd8b764f0ad9
> > --- /dev/null
> > +++ b/arch/riscv/kernel/image-vars.h
> > @@ -0,0 +1,53 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/*
> > + * Copyright (C) 2020 Western Digital Corporation or its
> > affiliates.
> > + * Linker script variables to be set after section resolution, as
> > + * ld.lld does not like variables assigned before SECTIONS is
> > processed.
> > + * Based on arch/arm64/kerne/image-vars.h
> > + */
> > +#ifndef __RISCV_KERNEL_IMAGE_VARS_H
> > +#define __RISCV_KERNEL_IMAGE_VARS_H
> > +
> > +#ifndef LINKER_SCRIPT
> > +#error This file should only be included in vmlinux.lds.S
> > +#endif
> > +
> > +#ifdef CONFIG_EFI
> > +
> > +__efistub_stext_offset = _start_kernel - _start;
> > +
> > +/*
> > + * The EFI stub has its own symbol namespace prefixed by
> > __efistub_, to
> > + * isolate it from the kernel proper. The following symbols are
> > legally
> > + * accessed by the stub, so provide some aliases to make them
> > accessible.
> > + * Only include data symbols here, or text symbols of functions
> > that are
> > + * guaranteed to be safe when executed at another offset than they
> > were
> > + * linked at. The routines below are all implemented in assembler
> > in a
> > + * position independent manner
> > + */
> > +__efistub_memcmp               = memcmp;
> > +__efistub_memchr               = memchr;
> > +__efistub_memcpy               = memcpy;
> > +__efistub_memmove              = memmove;
> > +__efistub_memset               = memset;
> > +__efistub_strlen               = strlen;
> > +__efistub_strnlen              = strnlen;
> > +__efistub_strcmp               = strcmp;
> > +__efistub_strncmp              = strncmp;
> > +__efistub_strrchr              = strrchr;
> > +
> > +#ifdef CONFIG_KASAN
> > +__efistub___memcpy             = memcpy;
> > +__efistub___memmove            = memmove;
> > +__efistub___memset             = memset;
> > +#endif
> > +
> > +__efistub__start               = _start;
> > +__efistub__start_kernel                = _start_kernel;
> > +__efistub__end                 = _end;
> > +__efistub__edata               = _edata;
> > +__efistub_screen_info          = screen_info;
> > +
> > +#endif
> > +
> > +#endif /* __RISCV_KERNEL_IMAGE_VARS_H */
> > diff --git a/arch/riscv/kernel/vmlinux.lds.S
> > b/arch/riscv/kernel/vmlinux.lds.S
> > index 0339b6bbe11a..20ebf7e8c215 100644
> > --- a/arch/riscv/kernel/vmlinux.lds.S
> > +++ b/arch/riscv/kernel/vmlinux.lds.S
> > @@ -10,6 +10,7 @@
> >  #include <asm/cache.h>
> >  #include <asm/thread_info.h>
> >  #include <asm/set_memory.h>
> > +#include "image-vars.h"
> > 
> >  #include <linux/sizes.h>
> >  OUTPUT_ARCH(riscv)
> > @@ -17,6 +18,14 @@ ENTRY(_start)
> > 
> >  jiffies = jiffies_64;
> > 
> > +PECOFF_FILE_ALIGNMENT = 0x200;
> > +#ifdef CONFIG_EFI
> > +#define PECOFF_EDATA_PADDING   \
> > +       .pecoff_edata_padding : { BYTE(0); . =
> > ALIGN(PECOFF_FILE_ALIGNMENT); }
> > +#else
> > +#define PECOFF_EDATA_PADDING
> > +#endif
> > +
> >  SECTIONS
> >  {
> >         /* Beginning of code and text segment */
> > @@ -62,6 +71,8 @@ SECTIONS
> >                 _etext = .;
> >         }
> > 
> > +       __text_end = .;
> > +
> >         /* Start of data section */
> >         _sdata = .;
> >         RO_DATA(SECTION_ALIGN)
> > @@ -78,9 +89,12 @@ SECTIONS
> >         .sdata : {
> >                 __global_pointer$ = . + 0x800;
> >                 *(.sdata*)
> > -               /* End of data section */
> > -               _edata = .;
> >         }
> > +       PECOFF_EDATA_PADDING
> > +       __data_raw_size = ABSOLUTE(. - __text_end);
> > +
> > +       /* End of data section */
> > +       _edata = .;
> > 
> >         BSS_SECTION(PAGE_SIZE, PAGE_SIZE, 0)
> > 
> > @@ -88,6 +102,8 @@ SECTIONS
> >                 *(.rel.dyn*)
> >         }
> > 
> > +       __data_virt_size = ABSOLUTE(. - __text_end);
> > +
> >         _end = .;
> > 
> >         STABS_DEBUG
> > --
> > 2.24.0
> > 

-- 
Regards,
Atish

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

* Re: [v4 PATCH 3/3] RISC-V: Add EFI stub support.
  2020-04-21 20:08   ` Palmer Dabbelt
@ 2020-04-22 17:45     ` Atish Patra
  0 siblings, 0 replies; 16+ messages in thread
From: Atish Patra @ 2020-04-22 17:45 UTC (permalink / raw)
  To: palmer; +Cc: linux-efi, linux-riscv, xypron.glpk, masahiroy, linux-kernel, ardb

On Tue, 2020-04-21 at 13:08 -0700, Palmer Dabbelt wrote:
> On Mon, 20 Apr 2020 20:33:36 PDT (-0700), Atish Patra wrote:
> > Add a RISC-V architecture specific stub code that actually copies
> > the
> > actual kernel image to a valid address and jump to it after boot
> > services
> > are terminated. Enable UEFI related kernel configs as well for
> > RISC-V.
> > 
> > Signed-off-by: Atish Patra <atish.patra@wdc.com>
> > ---
> >  arch/riscv/Kconfig                        |  20 ++++
> >  arch/riscv/Makefile                       |   1 +
> >  arch/riscv/configs/defconfig              |   1 +
> >  arch/riscv/include/asm/efi.h              |  44 +++++++++
> >  drivers/firmware/efi/Kconfig              |   2 +-
> >  drivers/firmware/efi/libstub/Makefile     |  10 ++
> >  drivers/firmware/efi/libstub/riscv-stub.c | 106
> > ++++++++++++++++++++++
> >  7 files changed, 183 insertions(+), 1 deletion(-)
> >  create mode 100644 arch/riscv/include/asm/efi.h
> >  create mode 100644 drivers/firmware/efi/libstub/riscv-stub.c
> > 
> > diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> > index f39e326a7a42..eb4f41c8f3ce 100644
> > --- a/arch/riscv/Kconfig
> > +++ b/arch/riscv/Kconfig
> > @@ -379,10 +379,30 @@ config CMDLINE_FORCE
> > 
> >  endchoice
> > 
> > +config EFI_STUB
> > +	bool
> > +
> > +config EFI
> > +	bool "UEFI runtime support"
> > +	depends on OF
> > +	select LIBFDT
> > +	select UCS2_STRING
> > +	select EFI_PARAMS_FROM_FDT
> > +	select EFI_STUB
> > +	select EFI_GENERIC_STUB
> 
> So I guess just "select RISCV_ISA_C" would be sufficient to make this
> work, but
> I still feel flike an explicit "c.li" is saner.
> 

will fix it.

> > +	default y
> > +	help
> > +	  This option provides support for runtime services provided
> > +	  by UEFI firmware (such as non-volatile variables, realtime
> > +          clock, and platform reset). A UEFI stub is also provided
> > to
> > +	  allow the kernel to be booted as an EFI application. This
> > +	  is only useful on systems that have UEFI firmware.
> > +
> >  endmenu
> > 
> >  menu "Power management options"
> > 
> >  source "kernel/power/Kconfig"
> > +source "drivers/firmware/Kconfig"
> > 
> >  endmenu
> > diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
> > index fb6e37db836d..079435804d6d 100644
> > --- a/arch/riscv/Makefile
> > +++ b/arch/riscv/Makefile
> > @@ -80,6 +80,7 @@ head-y := arch/riscv/kernel/head.o
> >  core-y += arch/riscv/
> > 
> >  libs-y += arch/riscv/lib/
> > +core-$(CONFIG_EFI_STUB) +=
> > $(objtree)/drivers/firmware/efi/libstub/lib.a
> > 
> >  PHONY += vdso_install
> >  vdso_install:
> > diff --git a/arch/riscv/configs/defconfig
> > b/arch/riscv/configs/defconfig
> > index 4da4886246a4..ae69e12d306a 100644
> > --- a/arch/riscv/configs/defconfig
> > +++ b/arch/riscv/configs/defconfig
> > @@ -129,3 +129,4 @@ CONFIG_DEBUG_BLOCK_EXT_DEVT=y
> >  # CONFIG_RUNTIME_TESTING_MENU is not set
> >  CONFIG_MEMTEST=y
> >  # CONFIG_SYSFS_SYSCALL is not set
> > +CONFIG_EFI=y
> > diff --git a/arch/riscv/include/asm/efi.h
> > b/arch/riscv/include/asm/efi.h
> > new file mode 100644
> > index 000000000000..62d7d5eafed8
> > --- /dev/null
> > +++ b/arch/riscv/include/asm/efi.h
> > @@ -0,0 +1,44 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright (C) 2020 Western Digital Corporation or its
> > affiliates.
> > + * Based on arch/arm64/include/asm/efi.h
> > + */
> > +#ifndef _ASM_EFI_H
> > +#define _ASM_EFI_H
> > +
> > +#include <asm/io.h>
> > +#include <asm/mmu_context.h>
> > +#include <asm/ptrace.h>
> > +#include <asm/tlbflush.h>
> > +
> > +#define VA_BITS_MIN 39
> 
> I don't see this actually being used, but if it's releant to some
> macro that
> I'm missing then EFI support should depend on rv64.
> 

Yeah. This was a left over from the previous patch. Thanks for pointing
out. I will remove it.

> > +
> > +/* on RISC-V, the FDT may be located anywhere in system RAM */
> > +static inline unsigned long efi_get_max_fdt_addr(unsigned long
> > dram_base)
> > +{
> > +	return ULONG_MAX;
> > +}
> > +
> > +/* Load initrd at enough distance from DRAM start */
> > +static inline unsigned long efi_get_max_initrd_addr(unsigned long
> > dram_base,
> > +						    unsigned long
> > image_addr)
> > +{
> > +	return dram_base + SZ_256M;
> > +}
> > +
> > +#define efi_bs_call(func, ...)	efi_system_table()->boottime-
> > >func(__VA_ARGS__)
> > +#define efi_rt_call(func, ...)	efi_system_table()->runtime-
> > >func(__VA_ARGS__)
> > +#define efi_is_native()		(true)
> > +
> > +#define efi_table_attr(inst, attr)	(inst->attr)
> > +
> > +#define efi_call_proto(inst, func, ...) inst->func(inst,
> > ##__VA_ARGS__)
> > +
> > +#define alloc_screen_info(x...)		(&screen_info)
> > +extern char stext_offset[];
> > +
> > +static inline void free_screen_info(struct screen_info *si)
> > +{
> > +}
> > +
> > +#endif /* _ASM_EFI_H */
> > diff --git a/drivers/firmware/efi/Kconfig
> > b/drivers/firmware/efi/Kconfig
> > index 2a2b2b96a1dc..fcdc789d3f87 100644
> > --- a/drivers/firmware/efi/Kconfig
> > +++ b/drivers/firmware/efi/Kconfig
> > @@ -111,7 +111,7 @@ config EFI_GENERIC_STUB
> > 
> >  config EFI_ARMSTUB_DTB_LOADER
> >  	bool "Enable the DTB loader"
> > -	depends on EFI_GENERIC_STUB
> > +	depends on EFI_GENERIC_STUB && !RISCV
> >  	default y
> >  	help
> >  	  Select this config option to add support for the dtb= command
> > diff --git a/drivers/firmware/efi/libstub/Makefile
> > b/drivers/firmware/efi/libstub/Makefile
> > index 0f57293d777e..eb365c55c0fe 100644
> > --- a/drivers/firmware/efi/libstub/Makefile
> > +++ b/drivers/firmware/efi/libstub/Makefile
> > @@ -22,6 +22,8 @@ cflags-$(CONFIG_ARM64)		:= $(subst
> > $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \
> >  cflags-$(CONFIG_ARM)		:= $(subst
> > $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \
> >  				   -fno-builtin -fpic \
> >  				   $(call cc-option,-mno-single-pic-
> > base)
> > +cflags-$(CONFIG_RISCV)		:= $(subst
> > $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \
> > +				   -fpic
> > 
> >  cflags-$(CONFIG_EFI_GENERIC_STUB) +=
> > -I$(srctree)/scripts/dtc/libfdt
> > 
> > @@ -57,6 +59,7 @@ lib-$(CONFIG_EFI_GENERIC_STUB)	+= efi-stub.o
> > fdt.o string.o \
> >  lib-$(CONFIG_ARM)		+= arm32-stub.o
> >  lib-$(CONFIG_ARM64)		+= arm64-stub.o
> >  lib-$(CONFIG_X86)		+= x86-stub.o
> > +lib-$(CONFIG_RISCV)		+= riscv-stub.o
> >  CFLAGS_arm32-stub.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
> >  CFLAGS_arm64-stub.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
> > 
> > @@ -100,6 +103,13 @@ STUBCOPY_FLAGS-$(CONFIG_X86)	+= --rename-
> > section .bss=.bss.efistub,load,alloc
> >  STUBCOPY_RELOC-$(CONFIG_X86_32)	:= R_386_32
> >  STUBCOPY_RELOC-$(CONFIG_X86_64)	:= R_X86_64_64
> > 
> > +# For RISC-V, we don't need anything special other than arm64.
> > Keep all the
> > +# symbols in .init section and make sure that no absolute symbols
> > references
> > +# doesn't exist.
> > +STUBCOPY_FLAGS-$(CONFIG_RISCV)	+= --prefix-alloc-
> > sections=.init \
> > +				   --prefix-symbols=__efistub_
> > +STUBCOPY_RELOC-$(CONFIG_RISCV)	:= R_RISCV_HI20
> > +
> >  $(obj)/%.stub.o: $(obj)/%.o FORCE
> >  	$(call if_changed,stubcopy)
> > 
> > diff --git a/drivers/firmware/efi/libstub/riscv-stub.c
> > b/drivers/firmware/efi/libstub/riscv-stub.c
> > new file mode 100644
> > index 000000000000..bd1d6fed8754
> > --- /dev/null
> > +++ b/drivers/firmware/efi/libstub/riscv-stub.c
> > @@ -0,0 +1,106 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2013, 2014 Linaro Ltd;  <roy.franz@linaro.org>
> > + * Copyright (C) 2020 Western Digital Corporation or its
> > affiliates.
> > + *
> > + * This file implements the EFI boot stub for the RISC-V kernel.
> > + * Adapted from ARM64 version at
> > drivers/firmware/efi/libstub/arm64-stub.c.
> > + */
> > +
> > +#include <linux/efi.h>
> > +#include <linux/libfdt.h>
> > +#include <linux/libfdt_env.h>
> > +#include <asm/efi.h>
> > +#include <asm/sections.h>
> > +
> > +#include "efistub.h"
> > +/*
> > + * RISC-V requires the kernel image to placed 2 MB aligned base
> > for 64 bit and
> > + * 4MB for 32 bit.
> > + */
> > +#ifdef CONFIG_64BIT
> > +#define MIN_KIMG_ALIGN	SZ_2M
> > +#else
> > +#define MIN_KIMG_ALIGN	SZ_4M
> > +#endif
> > +
> > +typedef __attribute__((noreturn)) void
> > (*jump_kernel_func)(unsigned int,
> > +							   unsigned
> > long);
> > +efi_status_t check_platform_features(void)
> > +{
> > +	return EFI_SUCCESS;
> > +}
> > +
> > +static u32 get_boot_hartid_from_fdt(unsigned long fdt)
> > +{
> > +	int chosen_node, len;
> > +	const fdt32_t *prop;
> > +
> > +	chosen_node = fdt_path_offset((void *)fdt, "/chosen");
> > +	if (chosen_node < 0)
> > +		return U32_MAX;
> > +	prop = fdt_getprop((void *)fdt, chosen_node, "boot-hartid",
> > &len);
> > +	if (!prop || len != sizeof(u32))
> > +		return U32_MAX;
> > +
> > +	return fdt32_to_cpu(*prop);
> > +}
> > +
> > +/*
> > + * Jump to real kernel here with following constraints.
> > + * 1. MMU should be disabled.
> > + * 2. a0 should contain hartid
> > + * 3. a1 should DT address
> > + */
> > +void __noreturn efi_enter_kernel(unsigned long entrypoint,
> > unsigned long fdt,
> > +				 unsigned long fdt_size)
> > +{
> > +	unsigned long kernel_entry = entrypoint + (unsigned
> > long)stext_offset;
> > +	jump_kernel_func jump_kernel = (jump_kernel_func) kernel_entry;
> > +	u32 hartid = get_boot_hartid_from_fdt(fdt);
> > +
> > +	if (hartid == U32_MAX)
> > +		/* We can not use panic or BUG at this point */
> > +		__asm__ __volatile__ ("ebreak");
> > +	/* Disable MMU */
> > +	csr_write(CSR_SATP, 0);
> > +	jump_kernel(hartid, fdt);
> > +}
> > +
> > +efi_status_t handle_kernel_image(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 = 0;
> > +	unsigned long preferred_addr;
> > +
> > +	kernel_size = _edata - _start;
> > +	*reserve_size = kernel_size + (_end - _edata);
> > +	*image_addr = (unsigned long)_start;
> > +
> > +	/*
> > +	 * RISC-V kernel maps PAGE_OFFSET virtual address to the same
> > physical
> > +	 * address where kernel is booted. That's why kernel should
> > boot from
> > +	 * as low as possible to avoid wastage of memory. Currently,
> > dram_base
> > +	 * is occupied by the firmware. So the preferred address for
> > kernel to
> > +	 * boot is next aligned address. If preferred address is not
> > available,
> > +	 * relocate_kernel will fall back to efi_low_alloc_above to
> > allocate
> > +	 * lowest possible memory region as long as the address and
> > size meets
> > +	 * the alignment constraints.
> > +	 */
> > +	preferred_addr = round_up(dram_base, MIN_KIMG_ALIGN) +
> > MIN_KIMG_ALIGN;
> > +	status = efi_relocate_kernel(image_addr, kernel_size,
> > *reserve_size,
> > +				     preferred_addr, MIN_KIMG_ALIGN,
> > dram_base);
> > +
> > +	if (status != EFI_SUCCESS) {
> > +		pr_efi_err("Failed to relocate kernel\n");
> > +		*reserve_size = 0;
> > +		return status;
> > +	}
> > +
> > +	return EFI_SUCCESS;
> > +}

-- 
Regards,
Atish

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

end of thread, other threads:[~2020-04-22 17:45 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-21  3:33 [v4 PATCH 0/3] Add UEFI support for RISC-V Atish Patra
2020-04-21  3:33 ` [v4 PATCH 1/3] RISC-V: Define fixmap bindings for generic early ioremap support Atish Patra
2020-04-21 19:52   ` Palmer Dabbelt
2020-04-21 19:56     ` Atish Patra
2020-04-21  3:33 ` [v4 PATCH 2/3] RISC-V: Add PE/COFF header for EFI stub Atish Patra
2020-04-21 17:51   ` Ard Biesheuvel
2020-04-22 17:44     ` Atish Patra
2020-04-21 20:02   ` Palmer Dabbelt
2020-04-22 17:43     ` Atish Patra
2020-04-21  3:33 ` [v4 PATCH 3/3] RISC-V: Add EFI stub support Atish Patra
2020-04-21 20:08   ` Palmer Dabbelt
2020-04-22 17:45     ` Atish Patra
2020-04-21  7:24 ` [v4 PATCH 0/3] Add UEFI support for RISC-V Ard Biesheuvel
2020-04-21 17:29   ` Atish Patra
2020-04-21 20:59   ` Palmer Dabbelt
2020-04-22 16:39     ` Ard Biesheuvel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).