[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH] xen/riscv: PE/COFF image header for RISC-V target
From: Nikola Jelic <nikola.jelic@xxxxxxxxx> Extended RISC-V xen image with PE/COFF headers, in order to support xen boot from popular bootloaders like U-boot. Image header is optionally included (with CONFIG_RISCV_EFI) so both plain ELF and image with PE/COFF header can now be generated as build artifacts. Note that this patch also represents initial EFI application format support (image contains EFI application header embeded into binary when CONFIG_RISCV_EFI is enabled). For full EFI application Xen support, boot/runtime services and system table handling are yet to be implemented. Tested on both QEMU and StarFive VisionFive 2 with OpenSBI->U-Boot->xen->dom0 boot chain. Signed-off-by: Nikola Jelic <nikola.jelic@xxxxxxxxx> --- Changes since v1 (following review comments from Jan Beulich): * Fix coding style * Extended image header with all the necessary PE/COFF (EFI) fields (instead of only those used by U-boot) * Removed usage of deprecated types --- xen/arch/riscv/Kconfig | 9 ++ xen/arch/riscv/include/asm/pe.h | 148 ++++++++++++++++++ .../riscv/include/asm/riscv_image_header.h | 54 +++++++ xen/arch/riscv/riscv64/head.S | 141 ++++++++++++++++- xen/arch/riscv/xen.lds.S | 6 +- 5 files changed, 356 insertions(+), 2 deletions(-) create mode 100644 xen/arch/riscv/include/asm/pe.h create mode 100644 xen/arch/riscv/include/asm/riscv_image_header.h diff --git a/xen/arch/riscv/Kconfig b/xen/arch/riscv/Kconfig index f382b36f6c..59bf5aa2a6 100644 --- a/xen/arch/riscv/Kconfig +++ b/xen/arch/riscv/Kconfig @@ -9,6 +9,15 @@ config ARCH_DEFCONFIG string default "arch/riscv/configs/tiny64_defconfig" +config RISCV_EFI + bool "UEFI boot service support" + depends on RISCV_64 + default n + help + This option provides support for boot services through + UEFI firmware. A UEFI stub is provided to allow Xen to + be booted as an EFI application. + menu "Architecture Features" source "arch/Kconfig" diff --git a/xen/arch/riscv/include/asm/pe.h b/xen/arch/riscv/include/asm/pe.h new file mode 100644 index 0000000000..084de1e712 --- /dev/null +++ b/xen/arch/riscv/include/asm/pe.h @@ -0,0 +1,148 @@ +#ifndef _ASM_RISCV_PE_H +#define _ASM_RISCV_PE_H + +#define LINUX_EFISTUB_MAJOR_VERSION 0x1 +#define LINUX_EFISTUB_MINOR_VERSION 0x0 + +#define MZ_MAGIC 0x5a4d /* "MZ" */ + +#define PE_MAGIC 0x00004550 /* "PE\0\0" */ +#define PE_OPT_MAGIC_PE32 0x010b +#define PE_OPT_MAGIC_PE32PLUS 0x020b + +/* machine type */ +#define IMAGE_FILE_MACHINE_RISCV32 0x5032 +#define IMAGE_FILE_MACHINE_RISCV64 0x5064 + +/* flags */ +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 +#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 + +#define IMAGE_SCN_CNT_CODE 0x00000020 /* .text */ +#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 /* .data */ +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 +#define IMAGE_SCN_MEM_READ 0x40000000 /* readable */ +#define IMAGE_SCN_MEM_WRITE 0x80000000 /* writeable */ + +#ifndef __ASSEMBLY__ + +struct mz_hdr { + uint16_t magic; /* MZ_MAGIC */ + uint16_t lbsize; /* size of last used block */ + uint16_t blocks; /* pages in file, 0x3 */ + uint16_t relocs; /* relocations */ + uint16_t hdrsize; /* header size in "paragraphs" */ + uint16_t min_extra_pps; /* .bss */ + uint16_t max_extra_pps; /* runtime limit for the arena size */ + uint16_t ss; /* relative stack segment */ + uint16_t sp; /* initial %sp register */ + uint16_t checksum; /* word checksum */ + uint16_t ip; /* initial %ip register */ + uint16_t cs; /* initial %cs relative to load segment */ + uint16_t reloc_table_offset; /* offset of the first relocation */ + uint16_t overlay_num; + uint16_t reserved0[4]; + uint16_t oem_id; + uint16_t oem_info; + uint16_t reserved1[10]; + uint32_t peaddr; /* address of pe header */ + char message[]; /* message to print */ +}; + +struct pe_hdr { + uint32_t magic; /* PE magic */ + uint16_t machine; /* machine type */ + uint16_t sections; /* number of sections */ + uint32_t timestamp; + uint32_t symbol_table; /* symbol table offset */ + uint32_t symbols; /* number of symbols */ + uint16_t opt_hdr_size; /* size of optional header */ + uint16_t flags; /* flags */ +}; + +struct pe32_opt_hdr { + /* "standard" header */ + uint16_t magic; /* file type */ + uint8_t ld_major; /* linker major version */ + uint8_t ld_minor; /* linker minor version */ + uint32_t text_size; + uint32_t data_size; + uint32_t bss_size; + uint32_t entry_point; /* file offset of entry point */ + uint32_t code_base; /* relative code addr in ram */ + uint32_t data_base; /* relative data addr in ram */ + /* "extra" header fields */ + uint32_t image_base; /* preferred load address */ + uint32_t section_align; /* alignment in bytes */ + uint32_t file_align; /* file alignment in bytes */ + uint16_t os_major; + uint16_t os_minor; + uint16_t image_major; + uint16_t image_minor; + uint16_t subsys_major; + uint16_t subsys_minor; + uint32_t win32_version; /* reserved, must be 0 */ + uint32_t image_size; + uint32_t header_size; + uint32_t csum; + uint16_t subsys; + uint16_t dll_flags; + uint32_t stack_size_req; /* amt of stack requested */ + uint32_t stack_size; /* amt of stack required */ + uint32_t heap_size_req; /* amt of heap requested */ + uint32_t heap_size; /* amt of heap required */ + uint32_t loader_flags; /* reserved, must be 0 */ + uint32_t data_dirs; /* number of data dir entries */ +}; + +struct pe32plus_opt_hdr { + uint16_t magic; /* file type */ + uint8_t ld_major; /* linker major version */ + uint8_t ld_minor; /* linker minor version */ + uint32_t text_size; + uint32_t data_size; + uint32_t bss_size; + uint32_t entry_point; /* file offset of entry point */ + uint32_t code_base; /* relative code addr in ram */ + /* "extra" header fields */ + uint64_t image_base; /* preferred load address */ + uint32_t section_align; /* alignment in bytes */ + uint32_t file_align; /* file alignment in bytes */ + uint16_t os_major; + uint16_t os_minor; + uint16_t image_major; + uint16_t image_minor; + uint16_t subsys_major; + uint16_t subsys_minor; + uint32_t win32_version; /* reserved, must be 0 */ + uint32_t image_size; + uint32_t header_size; + uint32_t csum; + uint16_t subsys; + uint16_t dll_flags; + uint64_t stack_size_req; /* amt of stack requested */ + uint64_t stack_size; /* amt of stack required */ + uint64_t heap_size_req; /* amt of heap requested */ + uint64_t heap_size; /* amt of heap required */ + uint32_t loader_flags; /* reserved, must be 0 */ + uint32_t data_dirs; /* number of data dir entries */ +}; + +struct section_header { + char name[8]; /* name or "/12\0" string tbl offset */ + uint32_t virtual_size; /* size of loaded section in ram */ + uint32_t virtual_address; /* relative virtual address */ + uint32_t raw_data_size; /* size of the section */ + uint32_t data_addr; /* file pointer to first page of section */ + uint32_t relocs; /* file pointer to relocation entries */ + uint32_t line_numbers; + uint16_t num_relocs; + uint16_t num_lin_numbers; + uint32_t flags; +}; + +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_RISCV_PE_H */ diff --git a/xen/arch/riscv/include/asm/riscv_image_header.h b/xen/arch/riscv/include/asm/riscv_image_header.h new file mode 100644 index 0000000000..89c7511d56 --- /dev/null +++ b/xen/arch/riscv/include/asm/riscv_image_header.h @@ -0,0 +1,54 @@ +#ifndef _ASM_RISCV_IMAGE_H +#define _ASM_RISCV_IMAGE_H + +#define RISCV_IMAGE_MAGIC "RISCV\0\0\0" +#define RISCV_IMAGE_MAGIC2 "RSC\x05" + +#define RISCV_IMAGE_FLAG_BE_SHIFT 0 + +#define RISCV_IMAGE_FLAG_LE 0 +#define RISCV_IMAGE_FLAG_BE 1 + +#define __HEAD_FLAG_BE RISCV_IMAGE_FLAG_LE + +#define __HEAD_FLAG(field) (__HEAD_FLAG_##field << RISCV_IMAGE_FLAG_##field##_SHIFT) + +#define __HEAD_FLAGS (__HEAD_FLAG(BE)) + +#define RISCV_HEADER_VERSION_MAJOR 0 +#define RISCV_HEADER_VERSION_MINOR 2 + +#define RISCV_HEADER_VERSION (RISCV_HEADER_VERSION_MAJOR << 16 | \ + RISCV_HEADER_VERSION_MINOR) + +#ifndef __ASSEMBLY__ +/* + * struct riscv_image_header - riscv xen image header + * + * @code0: Executable code + * @code1: Executable code + * @text_offset: Image load offset + * @image_size: Effective Image size + * @reserved: reserved + * @reserved: reserved + * @reserved: reserved + * @magic: Magic number + * @reserved: reserved + * @reserved: reserved (will be used for PE COFF offset) + */ + +struct riscv_image_header +{ + uint32_t code0; + uint32_t code1; + uint64_t text_offset; + uint64_t image_size; + uint64_t res1; + uint64_t res2; + uint64_t res3; + uint64_t magic; + uint32_t res4; + uint32_t res5; +}; +#endif /* __ASSEMBLY__ */ +#endif /* _ASM_RISCV_IMAGE_H */ diff --git a/xen/arch/riscv/riscv64/head.S b/xen/arch/riscv/riscv64/head.S index 3261e9fce8..609638b921 100644 --- a/xen/arch/riscv/riscv64/head.S +++ b/xen/arch/riscv/riscv64/head.S @@ -1,14 +1,150 @@ #include <asm/asm.h> #include <asm/riscv_encoding.h> +#include <asm/riscv_image_header.h> +#ifdef CONFIG_RISCV_EFI +#include <asm/pe.h> +#endif .section .text.header, "ax", %progbits /* * OpenSBI pass to start(): * a0 -> hart_id ( bootcpu_id ) - * a1 -> dtb_base + * a1 -> dtb_base */ FUNC(start) + +efi_head: + +#ifdef CONFIG_RISCV_EFI + /* + * This instruction decodes to "MZ" ASCII required by UEFI. + */ + c.li s4,-13 + j xen_start +#else + /* jump to start kernel */ + j xen_start + /* reserved */ + .word 0 +#endif + .balign 8 +#ifdef CONFIG_RISCV_64 + /* Image load offset(2MB) from start of RAM */ + .dword 0x200000 +#else + /* Image load offset(4MB) from start of RAM */ + .dword 0x400000 +#endif + /* Effective size of xen image */ + .dword _end - _start + .dword __HEAD_FLAGS + .word RISCV_HEADER_VERSION + .word 0 + .dword 0 + .ascii RISCV_IMAGE_MAGIC + .balign 4 + .ascii RISCV_IMAGE_MAGIC2 +#ifndef CONFIG_RISCV_EFI + .word 0 +#else + .word pe_head_start - efi_head +pe_head_start: + .long PE_MAGIC +coff_header: +#ifdef CONFIG_RISCV_64 + .short IMAGE_FILE_MACHINE_RISCV64 /* Machine */ +#else + .short IMAGE_FILE_MACHINE_RISCV32 /* Machine */ +#endif + .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: +#ifdef CONFIG_RISCV_64 + .short PE_OPT_MAGIC_PE32PLUS /* PE32+ format */ +#else + .short PE_OPT_MAGIC_PE32 /* PE32 format */ +#endif + .byte 0x02 /* MajorLinkerVersion */ + .byte 0x14 /* MinorLinkerVersion */ + .long _end - xen_start /* SizeOfCode */ + .long 0 /* SizeOfInitializedData */ + .long 0 /* SizeOfUninitializedData */ + .long 0 /* AddressOfEntryPoint */ + .long xen_start - efi_head /* BaseOfCode */ + +extra_header_fields: + .quad 0 /* ImageBase */ + .long PECOFF_SECTION_ALIGNMENT /* 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 - efi_head /* SizeOfImage */ + + /* Everything before the xen image is considered part of the header */ + .long xen_start - efi_head /* 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 0 + .long 0 + .long 0 /* SizeOfRawData */ + .long 0 /* 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 _end - xen_start /* VirtualSize */ + .long xen_start - efi_head /* VirtualAddress */ + .long __init_end_efi - xen_start /* SizeOfRawData */ + .long xen_start - efi_head /* 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 + + .balign 0x1000 +#endif/* CONFIG_RISCV_EFI */ + +FUNC(xen_start) /* Mask all interrupts */ csrw CSR_SIE, zero @@ -60,6 +196,9 @@ FUNC(start) mv a1, s1 tail start_xen + +END(xen_start) + END(start) .section .text, "ax", %progbits diff --git a/xen/arch/riscv/xen.lds.S b/xen/arch/riscv/xen.lds.S index 8510a87c4d..2eddde43c1 100644 --- a/xen/arch/riscv/xen.lds.S +++ b/xen/arch/riscv/xen.lds.S @@ -12,6 +12,9 @@ PHDRS #endif } +PECOFF_SECTION_ALIGNMENT = 0x1000; +PECOFF_FILE_ALIGNMENT = 0x200; + SECTIONS { . = XEN_VIRT_START; @@ -144,7 +147,7 @@ SECTIONS .got.plt : { *(.got.plt) } : text - + __init_end_efi = .; . = ALIGN(POINTER_ALIGN); __init_end = .; @@ -165,6 +168,7 @@ SECTIONS . = ALIGN(POINTER_ALIGN); __bss_end = .; } :text + _end = . ; /* Section for the device tree blob (if any). */ -- 2.25.1
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |