mirror of https://github.com/acidanthera/audk.git
141 lines
3.6 KiB
C
141 lines
3.6 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 "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;
|
|
}
|