From patchwork Tue Apr 9 11:08:18 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10890993 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DE6741515 for ; Tue, 9 Apr 2019 11:11:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CBF6728891 for ; Tue, 9 Apr 2019 11:11:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CA078288D3; Tue, 9 Apr 2019 11:11:05 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 8E9FC288CF for ; Tue, 9 Apr 2019 11:11:02 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hDocj-0005zI-8J; Tue, 09 Apr 2019 11:09:05 +0000 Received: from us1-rack-dfw2.inumbo.com ([104.130.134.6]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hDoci-0005yV-1a for xen-devel@lists.xenproject.org; Tue, 09 Apr 2019 11:09:04 +0000 X-Inumbo-ID: e1d442ff-5ab7-11e9-92d7-bc764e045a96 Received: from SMTP03.CITRIX.COM (unknown [162.221.156.55]) by us1-rack-dfw2.inumbo.com (Halon) with ESMTPS id e1d442ff-5ab7-11e9-92d7-bc764e045a96; Tue, 09 Apr 2019 11:09:02 +0000 (UTC) X-IronPort-AV: E=Sophos;i="5.60,329,1549929600"; d="scan'208";a="83095180" From: Anthony PERARD To: Date: Tue, 9 Apr 2019 12:08:18 +0100 Message-ID: <20190409110844.14746-6-anthony.perard@citrix.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190409110844.14746-1-anthony.perard@citrix.com> References: <20190409110844.14746-1-anthony.perard@citrix.com> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH v2 05/31] OvmfPkg/XenOvmf: Creating an ELF header X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Ard Biesheuvel , Jordan Justen , Julien Grall , Anthony PERARD , xen-devel@lists.xenproject.org, Laszlo Ersek Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP This header replace the embedded variable store. The ELF header explain to a loader to load the binary at the address 1MB, then jump to the PVH entry point which will be created in a later patch. That patch include generate_elf_header.c which can be use to regenerate the ELF header, but this will be a manual step. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Anthony PERARD --- Notes: This "ELF header" might not be the best way, but with it the Xen toolstack can load OVMF like any other PVH-compatible kernel without modification. Is there a better way? The generate_elf_header.c file was used to generate the series of hex number. It isn't at a right place but I'm not sure where to put this C file. Maybe in the commit message or maybe it could be forgotten since I've added all the comments in the .fdf file. OvmfPkg/XenOvmf.fdf | 82 +++++++++++++++++++- generate_elf_header.c | 78 +++++++++++++++++++ 2 files changed, 157 insertions(+), 3 deletions(-) diff --git a/OvmfPkg/XenOvmf.fdf b/OvmfPkg/XenOvmf.fdf index 295e30ca3f..20ebacd673 100644 --- a/OvmfPkg/XenOvmf.fdf +++ b/OvmfPkg/XenOvmf.fdf @@ -21,8 +21,8 @@ [Defines] !include OvmfPkg.fdf.inc # -# Build the variable store and the firmware code as one unified flash device -# image. +# This will allow the flash device image to be recognize as an ELF, with first +# an ELF headers, then the firmware code. # [FD.OVMF] BaseAddress = $(FW_BASE_ADDRESS) @@ -31,7 +31,83 @@ [FD.OVMF] BlockSize = $(BLOCK_SIZE) NumBlocks = $(FW_BLOCKS) -!include VarStore.fdf.inc +!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048) +0x00000000|0x0000e000 +!endif +!if $(FD_SIZE_IN_KB) == 4096 +0x00000000|0x00040000 +!endif +#was NV_VARIABLE_STORE +DATA = { + # ELF file header + 0x7f, 0x45, 0x4c, 0x46, # e_ident[0..3]: Magic number + 0x01, # File class: 32-bit objects + 0x01, # Data encoding: 2's complement, little endian + 0x01, # File version + 0x03, # OS ABI identification: Object uses GNU ELF extensions + 0x00, # ABI version + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # e_ident[EI_PAD...] + + 0x02, 0x00, # e_type = Executable file + 0x03, 0x00, # e_machine = Intel 80386 + 0x01, 0x00, 0x00, 0x00, # e_version + 0xd0, 0xff, 0x2f, 0x00, # e_entry: Entry point virtual address + 0x34, 0x00, 0x00, 0x00, # e_phoff: Program header table file offset + 0x00, 0x00, 0x00, 0x00, # e_shoff: Section header table file offset + 0x00, 0x00, 0x00, 0x00, # e_flags: Processor-specific flags + 0x34, 0x00, # e_ehsize: ELF header size + 0x20, 0x00, # e_phentsize: Program header table entry size + 0x01, 0x00, # e_phnum: Program header table entry count + 0x00, 0x00, # e_shentsize: Section header table entry size + 0x00, 0x00, # e_shnum: Section header table entry count + 0xff, 0xff, # e_shstrndx + + # ELF Program segment header + 0x01, 0x00, 0x00, 0x00, # p_type = Loadable program segment + 0x00, 0x00, 0x00, 0x00, # p_offset + 0x00, 0x00, 0x10, 0x00, # p_vaddr: Segment virtual address + 0x00, 0x00, 0x10, 0x00, # p_paddr: Segment physical address + 0x00, 0x00, 0x20, 0x00, # p_filesz: Segment size in file + 0x00, 0x00, 0x20, 0x00, # p_memsz: Segment size in memory + 0x07, 0x00, 0x00, 0x00, # p_flags = Segment is executable | writable | readable + 0x00, 0x00, 0x00, 0x00 # p_align + +} + +!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048) +0x0000e000|0x00001000 +!endif +!if $(FD_SIZE_IN_KB) == 4096 +0x00040000|0x00001000 +!endif +#NV_EVENT_LOG + +!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048) +0x0000f000|0x00001000 +!endif +!if $(FD_SIZE_IN_KB) == 4096 +0x00041000|0x00001000 +!endif +#NV_FTW_WORKING +DATA = { + # EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER->Signature = gEdkiiWorkingBlockSignatureGuid = + # { 0x9e58292b, 0x7c68, 0x497d, { 0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0x1b, 0x95 }} + 0x2b, 0x29, 0x58, 0x9e, 0x68, 0x7c, 0x7d, 0x49, + 0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0x1b, 0x95, + # Crc:UINT32 #WorkingBlockValid:1, WorkingBlockInvalid:1, Reserved + 0x2c, 0xaf, 0x2c, 0x64, 0xFE, 0xFF, 0xFF, 0xFF, + # WriteQueueSize: UINT64 + 0xE0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +} + +!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048) +0x00010000|0x00010000 +!endif +!if $(FD_SIZE_IN_KB) == 4096 +0x00042000|0x00042000 +!endif +#NV_FTW_SPARE + $(VARS_SIZE)|$(FVMAIN_SIZE) FV = FVMAIN_COMPACT diff --git a/generate_elf_header.c b/generate_elf_header.c new file mode 100644 index 0000000000..5bb87df0d6 --- /dev/null +++ b/generate_elf_header.c @@ -0,0 +1,78 @@ +#include "elf.h" +#include "stdio.h" +#include "stddef.h" + +/* + * TODO: + * this header will need a XEN_ELFNOTE_PHYS32_ENTRY + * right now, it works without, but that might change. + */ + +void print_hdr(void *s, size_t size) { + char *c = s; + + while (size--) { + printf("0x%02hhx, ", *(c++)); + } +} +int main(void){ + // FW_SIZE + size_t ovmf_blob_size = 0x00200000; + // Load OVMF at 1MB when running as PVH guest + uint32_t ovmf_base_address = 0x00100000; + + /* ELF file header */ + Elf32_Ehdr hdr = { + .e_ident = ELFMAG, + .e_type = ET_EXEC, + .e_machine = EM_386, + .e_version = EV_CURRENT, + // PVH entry point + .e_entry = ovmf_base_address + ovmf_blob_size - 0x30, + }; + + hdr.e_ident[EI_CLASS] = ELFCLASS32; + hdr.e_ident[EI_DATA] = ELFDATA2LSB; + hdr.e_ident[EI_VERSION] = EV_CURRENT; + hdr.e_ident[EI_OSABI] = ELFOSABI_LINUX; + hdr.e_flags = R_386_NONE; + hdr.e_ehsize = sizeof (hdr); + /* about program header */ + hdr.e_phoff = sizeof (hdr); + /* about section header */ + hdr.e_shentsize = 0; + hdr.e_shnum = 0; + hdr.e_shstrndx = -1; + + /* program header */ + Elf32_Phdr phdr = { + .p_type = PT_LOAD, + .p_offset = 0, // load everything + .p_paddr = ovmf_base_address, + .p_filesz = ovmf_blob_size, + .p_memsz = ovmf_blob_size, + .p_flags = PF_X | PF_W | PF_R, + .p_align = 0, // is this needed? + }; + phdr.p_vaddr = phdr.p_paddr; + + hdr.e_phnum += 1; + hdr.e_phentsize += sizeof (phdr); + + /* section header */ + Elf32_Shdr shdr = { + }; + + size_t hdr_size = sizeof(hdr); + size_t entry_off = offsetof(typeof(hdr), e_entry); + printf("# ELF file header\n"); + print_hdr(&hdr, entry_off); + printf("\n# hdr.e_entry\n"); + print_hdr(&hdr.e_entry, sizeof(hdr.e_entry)); + printf("\n# the rest\n"); + print_hdr(&hdr.e_entry + 1, hdr_size - entry_off - sizeof(hdr.e_entry)); + printf("\n# Program segment header\n"); + print_hdr(&phdr, sizeof (phdr)); + + return 0; +}