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 | }
|
---|