OvmfXenElfHeaderGenerator.c 5.4 KB

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