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>
		
			
				
	
	
		
			228 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			228 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @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 "fcntl.h"
 | 
						|
#include "stdbool.h"
 | 
						|
#include "stddef.h"
 | 
						|
#include "stdio.h"
 | 
						|
#include "stdlib.h"
 | 
						|
 | 
						|
void
 | 
						|
print_hdr (
 | 
						|
  FILE    *file,
 | 
						|
  void    *s,
 | 
						|
  size_t  size,
 | 
						|
  bool    end_delimiter
 | 
						|
  )
 | 
						|
{
 | 
						|
  char  *c = s;
 | 
						|
 | 
						|
  fprintf (file, "  ");
 | 
						|
  while (size-- > 1) {
 | 
						|
    fprintf (file, "0x%02hhx, ", *(c++));
 | 
						|
  }
 | 
						|
 | 
						|
  if (end_delimiter) {
 | 
						|
    fprintf (file, "0x%02hhx,", *c);
 | 
						|
  } else {
 | 
						|
    fprintf (file, "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;
 | 
						|
 | 
						|
#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 (
 | 
						|
  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 */
 | 
						|
  ovmfxen_pvh_entry_point = ovmf_base_address + ovmf_blob_size - 0x30;
 | 
						|
 | 
						|
  /* ELF file header */
 | 
						|
 #ifdef PVH64
 | 
						|
  Elf64_Ehdr  hdr = {
 | 
						|
 #else
 | 
						|
  Elf32_Ehdr  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);
 | 
						|
 | 
						|
 #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;
 | 
						|
  /* Placing program headers just after hdr */
 | 
						|
  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;
 | 
						|
  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),
 | 
						|
  };
 | 
						|
 #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;
 | 
						|
  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);
 | 
						|
 | 
						|
  fprintf (file, "DATA = {\r\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 (file, ((char *)&phdr_load) + i, 4, true);
 | 
						|
    fprintf (file, "\r\n");
 | 
						|
  }
 | 
						|
 | 
						|
  fprintf (file, "  # - ELFNOTE segment\r\n");
 | 
						|
  for (i = 0; i < sizeof (phdr_note); i += 4) {
 | 
						|
    print_hdr (file, ((char *)&phdr_note) + i, 4, true);
 | 
						|
    fprintf (file, "\r\n");
 | 
						|
  }
 | 
						|
 | 
						|
  fprintf (file, "\r\n  # XEN_ELFNOTE_PHYS32_ENTRY\r\n");
 | 
						|
  for (i = 0; i < sizeof (xen_elf_note); i += 4) {
 | 
						|
    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;
 | 
						|
}
 |