[edk2-devel] [PATCH v3 05/35] OvmfPkg/OvmfXen: Creating an ELF header

Anthony PERARD posted 35 patches 5 years, 4 months ago
There is a newer version of this series
[edk2-devel] [PATCH v3 05/35] OvmfPkg/OvmfXen: Creating an ELF header
Posted by Anthony PERARD 5 years, 4 months ago
This patch changes the flash device image of OvmfXen to make it look
like it's an ELF. For this, we replace the empty embedded variable store
by a binary array, which is a ELF file header.

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. The header also includes a Xen ELF note that is part of the
PVH ABI.

That patch include OvmfXenElfHeaderGenerator.c which can be use to
regenerate the ELF header, but this will be a manual step.

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1689
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---

Notes:
    v3:
    - added license to generate_elf_header.c
      which is renamed to OvmfPkg/OvmfXenElfHeaderGenerator.c
    - added an ELF NOTE into the header

 OvmfPkg/OvmfXen.fdf                 | 101 +++++++++++++++++++-
 OvmfPkg/OvmfXenElfHeaderGenerator.c | 140 ++++++++++++++++++++++++++++
 2 files changed, 238 insertions(+), 3 deletions(-)
 create mode 100644 OvmfPkg/OvmfXenElfHeaderGenerator.c

diff --git a/OvmfPkg/OvmfXen.fdf b/OvmfPkg/OvmfXen.fdf
index 2ceff7baa2..43c268f6cb 100644
--- a/OvmfPkg/OvmfXen.fdf
+++ b/OvmfPkg/OvmfXen.fdf
@@ -15,8 +15,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)

@@ -25,7 +25,102 @@ [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

+DATA = {

+  #

+  # This hex array have been generated by OvmfPkg/OvmfXenElfHeaderGenerator.c

+  # and copied manually.

+  #

+  # 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

+  0x02, 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

+  0x00, 0x00, # e_shstrndx

+

+  # ELF Program segment headers

+  # - Load segment

+  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

+  # - ELFNOTE segment

+  0x04, 0x00, 0x00, 0x00, # p_type = PT_NOTE

+  0x74, 0x00, 0x00, 0x00, # p_offset = point to XEN_ELFNOTE_PHYS32_ENTRY below

+  0x74, 0x00, 0x10, 0x00,

+  0x74, 0x00, 0x10, 0x00,

+  0x14, 0x00, 0x00, 0x00,

+  0x14, 0x00, 0x00, 0x00,

+  0x04, 0x00, 0x00, 0x00, # p_flags = Segment is readable

+  0x00, 0x00, 0x00, 0x00,

+

+  # XEN_ELFNOTE_PHYS32_ENTRY

+  0x04, 0x00, 0x00, 0x00, # name size

+  0x04, 0x00, 0x00, 0x00, # desc size

+  0x12, 0x00, 0x00, 0x00, # type = XEN_ELFNOTE_PHYS32_ENTRY

+  0x58, 0x65, 0x6e, 0x00, # name = "Xen"

+  0xd0, 0xff, 0x2f, 0x00, # desc: PVH entry point

+  0x00

+}

+

+!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/OvmfPkg/OvmfXenElfHeaderGenerator.c b/OvmfPkg/OvmfXenElfHeaderGenerator.c
new file mode 100644
index 0000000000..6cbad8fbf7
--- /dev/null
+++ b/OvmfPkg/OvmfXenElfHeaderGenerator.c
@@ -0,0 +1,140 @@
+/*

+ * @file

+ * This program generates a hex array to be manually coppied into

+ * OvmfXen.fdf.

+ * The purpose is for the flash device image to be recognize as an ELF.

+ *

+ * Copyright (c) 2019, Citrix Systems, Inc.

+ *

+ * SPDX-License-Identifier: BSD-2-Clause-Patent

+ */

+

+#include "elf.h"

+#include "stdio.h"

+#include "stddef.h"

+

+void print_hdr(void *s, size_t size)

+{

+  char *c = s;

+

+  while (size--) {

+    printf("0x%02hhx, ", *(c++));

+  }

+}

+

+/* Format for the XEN_ELFNOTE_PHYS32_ENTRY program segment */

+#define XEN_ELFNOTE_PHYS32_ENTRY 18

+typedef struct {

+  uint32_t name_size;

+  uint32_t desc_size;

+  uint32_t type;

+  char name[4];

+  uint32_t desc;

+} xen_elfnote_phys32_entry;

+

+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;

+  /* Xen PVH entry point */

+  uint32_t ovmfxen_pvh_entry_point = ovmf_base_address + ovmf_blob_size - 0x30;

+  size_t offset_into_file = 0;

+

+  /* ELF file header */

+  Elf32_Ehdr hdr = {

+    .e_ident = ELFMAG,

+    .e_type = ET_EXEC,

+    .e_machine = EM_386,

+    .e_version = EV_CURRENT,

+    .e_entry = ovmfxen_pvh_entry_point,

+    .e_flags = R_386_NONE,

+    .e_ehsize = sizeof (hdr),

+    .e_phentsize = sizeof (Elf32_Phdr),

+  };

+  offset_into_file += sizeof (hdr);

+

+  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;

+  /* Placing program headers just after hdr */

+  hdr.e_phoff = sizeof (hdr);

+

+  /* program header */

+  Elf32_Phdr phdr_load = {

+    .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,

+  };

+  phdr_load.p_vaddr = phdr_load.p_paddr;

+  hdr.e_phnum += 1;

+  offset_into_file += sizeof (phdr_load);

+

+  /* Xen ELF Note. */

+

+  xen_elfnote_phys32_entry xen_elf_note = {

+    .type = XEN_ELFNOTE_PHYS32_ENTRY,

+    .name = "Xen",

+    .desc = ovmfxen_pvh_entry_point,

+    .name_size =

+      offsetof (xen_elfnote_phys32_entry, desc) -

+      offsetof (xen_elfnote_phys32_entry, name),

+    .desc_size =

+      sizeof (xen_elfnote_phys32_entry) -

+      offsetof (xen_elfnote_phys32_entry, desc),

+  };

+  Elf32_Phdr phdr_note = {

+    .p_type = PT_NOTE,

+    .p_filesz = sizeof (xen_elf_note),

+    .p_memsz = sizeof (xen_elf_note),

+    .p_flags = PF_R,

+    .p_align = 0,

+  };

+  hdr.e_phnum += 1;

+  offset_into_file += sizeof (phdr_note);

+  phdr_note.p_offset = offset_into_file;

+  phdr_note.p_paddr = ovmf_base_address + phdr_note.p_offset;

+  phdr_note.p_vaddr = phdr_note.p_paddr;

+

+

+  /*

+   * print elf header

+   */

+

+  size_t i;

+  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");

+  print_hdr(&hdr.e_entry, sizeof (hdr.e_entry));

+  printf(" # hdr.e_entry\n");

+  print_hdr(&hdr.e_entry + 1, hdr_size - entry_off - sizeof (hdr.e_entry));

+

+  printf("\n\n# ELF Program segment headers\n");

+  printf("# - Load segment\n");

+  for (i = 0; i < sizeof (phdr_load); i += 4) {

+    print_hdr(((char*)&phdr_load) + i, 4);

+    printf("\n");

+  }

+  printf("# - ELFNOTE segment\n");

+  for (i = 0; i < sizeof (phdr_note); i += 4) {

+    print_hdr(((char*)&phdr_note) + i, 4);

+    printf("\n");

+  }

+

+  printf("\n# XEN_ELFNOTE_PHYS32_ENTRY\n");

+  for (i = 0; i < sizeof (xen_elf_note); i += 4) {

+    print_hdr(((char*)&xen_elf_note) + i, 4);

+    printf("\n");

+  }

+

+  return 0;

+}

-- 
Anthony PERARD


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#43281): https://edk2.groups.io/g/devel/message/43281
Mute This Topic: https://groups.io/mt/32308566/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-

Re: [edk2-devel] [PATCH v3 05/35] OvmfPkg/OvmfXen: Creating an ELF header
Posted by Laszlo Ersek 5 years, 4 months ago
On 07/04/19 16:42, Anthony PERARD wrote:
> This patch changes the flash device image of OvmfXen to make it look
> like it's an ELF. For this, we replace the empty embedded variable store
> by a binary array, which is a ELF file header.
> 
> 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. The header also includes a Xen ELF note that is part of the
> PVH ABI.
> 
> That patch include OvmfXenElfHeaderGenerator.c which can be use to
> regenerate the ELF header, but this will be a manual step.
> 
> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1689
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> ---
> 
> Notes:
>     v3:
>     - added license to generate_elf_header.c
>       which is renamed to OvmfPkg/OvmfXenElfHeaderGenerator.c
>     - added an ELF NOTE into the header
> 
>  OvmfPkg/OvmfXen.fdf                 | 101 +++++++++++++++++++-
>  OvmfPkg/OvmfXenElfHeaderGenerator.c | 140 ++++++++++++++++++++++++++++
>  2 files changed, 238 insertions(+), 3 deletions(-)
>  create mode 100644 OvmfPkg/OvmfXenElfHeaderGenerator.c

[...]

> diff --git a/OvmfPkg/OvmfXenElfHeaderGenerator.c b/OvmfPkg/OvmfXenElfHeaderGenerator.c
> new file mode 100644
> index 0000000000..6cbad8fbf7
> --- /dev/null
> +++ b/OvmfPkg/OvmfXenElfHeaderGenerator.c
> @@ -0,0 +1,140 @@
> +/*
> + * @file
> + * This program generates a hex array to be manually coppied into
> + * OvmfXen.fdf.
> + * The purpose is for the flash device image to be recognize as an ELF.
> + *
> + * Copyright (c) 2019, Citrix Systems, Inc.
> + *
> + * SPDX-License-Identifier: BSD-2-Clause-Patent
> + */

(1) This patch is almost complete, just please update the comment style,
for this top-level comment, from

/*
 * @file
 * blah
 */

to:

/** @file
  blah
**/

Please refer to e.g. "OvmfPkg/XenBusDxe/XenBusDxe.c".

With that comment style update:

Acked-by: Laszlo Ersek <lersek@redhat.com>

Thanks
Laszlo

-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#43359): https://edk2.groups.io/g/devel/message/43359
Mute This Topic: https://groups.io/mt/32308566/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-