Pārlūkot izejas kodu

OvmfPkg: Make the Xen ELF header generator more flexible

Adding some flexibility to the program through optional parameters and
global define, so that other targets can use the generator.

* A global define is added so that we can choose at build time if we
  want to use 32-bit or 64-bit base structures.
* A first optional parameter is added so the user can provide the
  expected blob size of the generated binary.
* A second optional parameter is added so the user can specify an output
  file to which the generated output will be printed.

The default behavior isn't modified.

Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
Sebastien Boeuf 2 gadi atpakaļ
vecāks
revīzija
b909b4ad09
1 mainītis faili ar 109 papildinājumiem un 32 dzēšanām
  1. 109 32
      OvmfPkg/OvmfXenElfHeaderGenerator.c

+ 109 - 32
OvmfPkg/OvmfXenElfHeaderGenerator.c

@@ -10,19 +10,31 @@
 **/
 
 #include "elf.h"
-#include "stdio.h"
+#include "fcntl.h"
+#include "stdbool.h"
 #include "stddef.h"
+#include "stdio.h"
+#include "stdlib.h"
 
 void
 print_hdr (
+  FILE    *file,
   void    *s,
-  size_t  size
+  size_t  size,
+  bool    end_delimiter
   )
 {
   char  *c = s;
 
-  while (size--) {
-    printf ("0x%02hhx, ", *(c++));
+  fprintf (file, "  ");
+  while (size-- > 1) {
+    fprintf (file, "0x%02hhx, ", *(c++));
+  }
+
+  if (end_delimiter) {
+    fprintf (file, "0x%02hhx,", *c);
+  } else {
+    fprintf (file, "0x%02hhx", *c);
   }
 }
 
@@ -36,34 +48,79 @@ typedef struct {
   uint32_t    desc;
 } xen_elfnote_phys32_entry;
 
+#define LICENSE_HDR  "\
+## @file\r\n\
+#  FDF include file that defines a PVH ELF header.\r\n\
+#\r\n\
+#  Copyright (c) 2022, Intel Corporation. All rights reserved.\r\n\
+#\r\n\
+#  SPDX-License-Identifier: BSD-2-Clause-Patent\r\n\
+#\r\n\
+##\r\n\
+\r\n\
+"
+
 int
 main (
-  void
+  int   argc,
+  char  *argv[]
   )
 {
   /* FW_SIZE */
   size_t  ovmf_blob_size = 0x00200000;
   /* Load OVMF at 1MB when running as PVH guest */
   uint32_t  ovmf_base_address = 0x00100000;
+  uint32_t  ovmfxen_pvh_entry_point;
+  size_t    offset_into_file = 0;
+  char      *endptr, *str;
+  long      param;
+  FILE      *file = stdout;
+
+  /* Parse the size parameter */
+  if (argc > 1) {
+    str   = argv[1];
+    param = strtol (str, &endptr, 10);
+    if (endptr != str) {
+      ovmf_blob_size = (size_t)param;
+    }
+  }
+
+  /* Parse the filepath parameter */
+  if (argc > 2) {
+    file = fopen (argv[2], "w");
+    fprintf (file, LICENSE_HDR);
+  }
+
   /* Xen PVH entry point */
-  uint32_t  ovmfxen_pvh_entry_point = ovmf_base_address + ovmf_blob_size - 0x30;
-  size_t    offset_into_file        = 0;
+  ovmfxen_pvh_entry_point = ovmf_base_address + ovmf_blob_size - 0x30;
 
   /* ELF file header */
+ #ifdef PVH64
+  Elf64_Ehdr  hdr = {
+ #else
   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),
+ #endif
+    .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),
+ #ifdef PVH64
+    .e_phentsize = sizeof (Elf64_Phdr),
+ #else
     .e_phentsize = sizeof (Elf32_Phdr),
+ #endif
   };
 
   offset_into_file += sizeof (hdr);
 
-  hdr.e_ident[EI_CLASS]   = ELFCLASS32;
+ #ifdef PVH64
+  hdr.e_ident[EI_CLASS] = ELFCLASS64;
+ #else
+  hdr.e_ident[EI_CLASS] = ELFCLASS32;
+ #endif
   hdr.e_ident[EI_DATA]    = ELFDATA2LSB;
   hdr.e_ident[EI_VERSION] = EV_CURRENT;
   hdr.e_ident[EI_OSABI]   = ELFOSABI_LINUX;
@@ -71,14 +128,22 @@ main (
   hdr.e_phoff = sizeof (hdr);
 
   /* program header */
+ #ifdef PVH64
+  Elf64_Phdr  phdr_load = {
+ #else
   Elf32_Phdr  phdr_load = {
+ #endif
     .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,
+ #ifdef PVH64
+    .p_align  = 4,
+ #else
     .p_align  = 0,
+ #endif
   };
 
   phdr_load.p_vaddr = phdr_load.p_paddr;
@@ -98,12 +163,20 @@ main (
       sizeof (xen_elfnote_phys32_entry) -
       offsetof (xen_elfnote_phys32_entry, desc),
   };
-  Elf32_Phdr                phdr_note = {
+ #ifdef PVH64
+  Elf64_Phdr  phdr_note = {
+ #else
+  Elf32_Phdr  phdr_note = {
+ #endif
     .p_type   = PT_NOTE,
     .p_filesz = sizeof (xen_elf_note),
     .p_memsz  = sizeof (xen_elf_note),
     .p_flags  = PF_R,
+ #ifdef PVH64
+    .p_align  = 4,
+ #else
     .p_align  = 0,
+ #endif
   };
 
   hdr.e_phnum       += 1;
@@ -120,31 +193,35 @@ main (
   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));
+  fprintf (file, "DATA = {\r\n");
 
-  printf ("\n\n# ELF Program segment headers\n");
-  printf ("# - Load segment\n");
+  fprintf (file, "  # ELF file header\r\n");
+  print_hdr (file, &hdr, entry_off, true);
+  fprintf (file, "\r\n");
+  print_hdr (file, &hdr.e_entry, sizeof (hdr.e_entry), true);
+  fprintf (file, " # hdr.e_entry\r\n");
+  print_hdr (file, &hdr.e_entry + 1, hdr_size - entry_off - sizeof (hdr.e_entry), true);
+
+  fprintf (file, "\r\n\r\n  # ELF Program segment headers\r\n");
+  fprintf (file, "  # - Load segment\r\n");
   for (i = 0; i < sizeof (phdr_load); i += 4) {
-    print_hdr (((char *)&phdr_load) + i, 4);
-    printf ("\n");
+    print_hdr (file, ((char *)&phdr_load) + i, 4, true);
+    fprintf (file, "\r\n");
   }
 
-  printf ("# - ELFNOTE segment\n");
+  fprintf (file, "  # - ELFNOTE segment\r\n");
   for (i = 0; i < sizeof (phdr_note); i += 4) {
-    print_hdr (((char *)&phdr_note) + i, 4);
-    printf ("\n");
+    print_hdr (file, ((char *)&phdr_note) + i, 4, true);
+    fprintf (file, "\r\n");
   }
 
-  printf ("\n# XEN_ELFNOTE_PHYS32_ENTRY\n");
+  fprintf (file, "\r\n  # XEN_ELFNOTE_PHYS32_ENTRY\r\n");
   for (i = 0; i < sizeof (xen_elf_note); i += 4) {
-    print_hdr (((char *)&xen_elf_note) + i, 4);
-    printf ("\n");
+    print_hdr (file, ((char *)&xen_elf_note) + i, 4, (sizeof (xen_elf_note) - i) > 4);
+    fprintf (file, "\r\n");
   }
 
+  fprintf (file, "}\r\n");
+
   return 0;
 }