]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/OvmfXenElfHeaderGenerator.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / OvmfPkg / OvmfXenElfHeaderGenerator.c
1 /** @file
2 This program generates a hex array to be manually coppied into
3 OvmfXen.fdf.
4
5 The purpose is for the flash device image to be recognize as an ELF.
6
7 Copyright (c) 2019, Citrix Systems, Inc.
8
9 SPDX-License-Identifier: BSD-2-Clause-Patent
10 **/
11
12 #include "elf.h"
13 #include "fcntl.h"
14 #include "stdbool.h"
15 #include "stddef.h"
16 #include "stdio.h"
17 #include "stdlib.h"
18
19 void
20 print_hdr (
21 FILE *file,
22 void *s,
23 size_t size,
24 bool end_delimiter
25 )
26 {
27 char *c = s;
28
29 fprintf (file, " ");
30 while (size-- > 1) {
31 fprintf (file, "0x%02hhx, ", *(c++));
32 }
33
34 if (end_delimiter) {
35 fprintf (file, "0x%02hhx,", *c);
36 } else {
37 fprintf (file, "0x%02hhx", *c);
38 }
39 }
40
41 /* Format for the XEN_ELFNOTE_PHYS32_ENTRY program segment */
42 #define XEN_ELFNOTE_PHYS32_ENTRY 18
43 typedef struct {
44 uint32_t name_size;
45 uint32_t desc_size;
46 uint32_t type;
47 char name[4];
48 uint32_t desc;
49 } xen_elfnote_phys32_entry;
50
51 #define LICENSE_HDR "\
52 ## @file\r\n\
53 # FDF include file that defines a PVH ELF header.\r\n\
54 #\r\n\
55 # Copyright (c) 2022, Intel Corporation. All rights reserved.\r\n\
56 #\r\n\
57 # SPDX-License-Identifier: BSD-2-Clause-Patent\r\n\
58 #\r\n\
59 ##\r\n\
60 \r\n\
61 "
62
63 int
64 main (
65 int argc,
66 char *argv[]
67 )
68 {
69 /* FW_SIZE */
70 size_t ovmf_blob_size = 0x00200000;
71 /* Load OVMF at 1MB when running as PVH guest */
72 uint32_t ovmf_base_address = 0x00100000;
73 uint32_t ovmfxen_pvh_entry_point;
74 size_t offset_into_file = 0;
75 char *endptr, *str;
76 long param;
77 FILE *file = stdout;
78
79 /* Parse the size parameter */
80 if (argc > 1) {
81 str = argv[1];
82 param = strtol (str, &endptr, 10);
83 if (endptr != str) {
84 ovmf_blob_size = (size_t)param;
85 }
86 }
87
88 /* Parse the filepath parameter */
89 if (argc > 2) {
90 file = fopen (argv[2], "w");
91 fprintf (file, LICENSE_HDR);
92 }
93
94 /* Xen PVH entry point */
95 ovmfxen_pvh_entry_point = ovmf_base_address + ovmf_blob_size - 0x30;
96
97 /* ELF file header */
98 #ifdef PVH64
99 Elf64_Ehdr hdr = {
100 #else
101 Elf32_Ehdr hdr = {
102 #endif
103 .e_ident = ELFMAG,
104 .e_type = ET_EXEC,
105 .e_machine = EM_386,
106 .e_version = EV_CURRENT,
107 .e_entry = ovmfxen_pvh_entry_point,
108 .e_flags = R_386_NONE,
109 .e_ehsize = sizeof (hdr),
110 #ifdef PVH64
111 .e_phentsize = sizeof (Elf64_Phdr),
112 #else
113 .e_phentsize = sizeof (Elf32_Phdr),
114 #endif
115 };
116
117 offset_into_file += sizeof (hdr);
118
119 #ifdef PVH64
120 hdr.e_ident[EI_CLASS] = ELFCLASS64;
121 #else
122 hdr.e_ident[EI_CLASS] = ELFCLASS32;
123 #endif
124 hdr.e_ident[EI_DATA] = ELFDATA2LSB;
125 hdr.e_ident[EI_VERSION] = EV_CURRENT;
126 hdr.e_ident[EI_OSABI] = ELFOSABI_LINUX;
127 /* Placing program headers just after hdr */
128 hdr.e_phoff = sizeof (hdr);
129
130 /* program header */
131 #ifdef PVH64
132 Elf64_Phdr phdr_load = {
133 #else
134 Elf32_Phdr phdr_load = {
135 #endif
136 .p_type = PT_LOAD,
137 .p_offset = 0, /* load everything */
138 .p_paddr = ovmf_base_address,
139 .p_filesz = ovmf_blob_size,
140 .p_memsz = ovmf_blob_size,
141 .p_flags = PF_X | PF_W | PF_R,
142 #ifdef PVH64
143 .p_align = 4,
144 #else
145 .p_align = 0,
146 #endif
147 };
148
149 phdr_load.p_vaddr = phdr_load.p_paddr;
150 hdr.e_phnum += 1;
151 offset_into_file += sizeof (phdr_load);
152
153 /* Xen ELF Note. */
154
155 xen_elfnote_phys32_entry xen_elf_note = {
156 .type = XEN_ELFNOTE_PHYS32_ENTRY,
157 .name = "Xen",
158 .desc = ovmfxen_pvh_entry_point,
159 .name_size =
160 offsetof (xen_elfnote_phys32_entry, desc) -
161 offsetof (xen_elfnote_phys32_entry, name),
162 .desc_size =
163 sizeof (xen_elfnote_phys32_entry) -
164 offsetof (xen_elfnote_phys32_entry, desc),
165 };
166 #ifdef PVH64
167 Elf64_Phdr phdr_note = {
168 #else
169 Elf32_Phdr phdr_note = {
170 #endif
171 .p_type = PT_NOTE,
172 .p_filesz = sizeof (xen_elf_note),
173 .p_memsz = sizeof (xen_elf_note),
174 .p_flags = PF_R,
175 #ifdef PVH64
176 .p_align = 4,
177 #else
178 .p_align = 0,
179 #endif
180 };
181
182 hdr.e_phnum += 1;
183 offset_into_file += sizeof (phdr_note);
184 phdr_note.p_offset = offset_into_file;
185 phdr_note.p_paddr = ovmf_base_address + phdr_note.p_offset;
186 phdr_note.p_vaddr = phdr_note.p_paddr;
187
188 /*
189 * print elf header
190 */
191
192 size_t i;
193 size_t hdr_size = sizeof (hdr);
194 size_t entry_off = offsetof (typeof(hdr), e_entry);
195
196 fprintf (file, "DATA = {\r\n");
197
198 fprintf (file, " # ELF file header\r\n");
199 print_hdr (file, &hdr, entry_off, true);
200 fprintf (file, "\r\n");
201 print_hdr (file, &hdr.e_entry, sizeof (hdr.e_entry), true);
202 fprintf (file, " # hdr.e_entry\r\n");
203 print_hdr (file, &hdr.e_entry + 1, hdr_size - entry_off - sizeof (hdr.e_entry), true);
204
205 fprintf (file, "\r\n\r\n # ELF Program segment headers\r\n");
206 fprintf (file, " # - Load segment\r\n");
207 for (i = 0; i < sizeof (phdr_load); i += 4) {
208 print_hdr (file, ((char *)&phdr_load) + i, 4, true);
209 fprintf (file, "\r\n");
210 }
211
212 fprintf (file, " # - ELFNOTE segment\r\n");
213 for (i = 0; i < sizeof (phdr_note); i += 4) {
214 print_hdr (file, ((char *)&phdr_note) + i, 4, true);
215 fprintf (file, "\r\n");
216 }
217
218 fprintf (file, "\r\n # XEN_ELFNOTE_PHYS32_ENTRY\r\n");
219 for (i = 0; i < sizeof (xen_elf_note); i += 4) {
220 print_hdr (file, ((char *)&xen_elf_note) + i, 4, (sizeof (xen_elf_note) - i) > 4);
221 fprintf (file, "\r\n");
222 }
223
224 fprintf (file, "}\r\n");
225
226 return 0;
227 }