1 /*
2 * Copyright (c) 2025 Intel Corporation
3 * Author: Isaku Yamahata <isaku.yamahata at gmail.com>
4 * <isaku.yamahata at intel.com>
5 * Xiaoyao Li <xiaoyao.li@intel.com>
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10 #include "qemu/osdep.h"
11 #include "qemu/error-report.h"
12 #include "standard-headers/uefi/uefi.h"
13 #include "hw/pci/pcie_host.h"
14 #include "tdvf-hob.h"
15
16 typedef struct TdvfHob {
17 hwaddr hob_addr;
18 void *ptr;
19 int size;
20
21 /* working area */
22 void *current;
23 void *end;
24 } TdvfHob;
25
tdvf_current_guest_addr(const TdvfHob * hob)26 static uint64_t tdvf_current_guest_addr(const TdvfHob *hob)
27 {
28 return hob->hob_addr + (hob->current - hob->ptr);
29 }
30
tdvf_align(TdvfHob * hob,size_t align)31 static void tdvf_align(TdvfHob *hob, size_t align)
32 {
33 hob->current = QEMU_ALIGN_PTR_UP(hob->current, align);
34 }
35
tdvf_get_area(TdvfHob * hob,uint64_t size)36 static void *tdvf_get_area(TdvfHob *hob, uint64_t size)
37 {
38 void *ret;
39
40 if (hob->current + size > hob->end) {
41 error_report("TD_HOB overrun, size = 0x%" PRIx64, size);
42 exit(1);
43 }
44
45 ret = hob->current;
46 hob->current += size;
47 tdvf_align(hob, 8);
48 return ret;
49 }
50
tdvf_hob_add_memory_resources(TdxGuest * tdx,TdvfHob * hob)51 static void tdvf_hob_add_memory_resources(TdxGuest *tdx, TdvfHob *hob)
52 {
53 EFI_HOB_RESOURCE_DESCRIPTOR *region;
54 EFI_RESOURCE_ATTRIBUTE_TYPE attr;
55 EFI_RESOURCE_TYPE resource_type;
56
57 TdxRamEntry *e;
58 int i;
59
60 for (i = 0; i < tdx->nr_ram_entries; i++) {
61 e = &tdx->ram_entries[i];
62
63 if (e->type == TDX_RAM_UNACCEPTED) {
64 resource_type = EFI_RESOURCE_MEMORY_UNACCEPTED;
65 attr = EFI_RESOURCE_ATTRIBUTE_TDVF_UNACCEPTED;
66 } else if (e->type == TDX_RAM_ADDED) {
67 resource_type = EFI_RESOURCE_SYSTEM_MEMORY;
68 attr = EFI_RESOURCE_ATTRIBUTE_TDVF_PRIVATE;
69 } else {
70 error_report("unknown TDX_RAM_ENTRY type %d", e->type);
71 exit(1);
72 }
73
74 region = tdvf_get_area(hob, sizeof(*region));
75 *region = (EFI_HOB_RESOURCE_DESCRIPTOR) {
76 .Header = {
77 .HobType = EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,
78 .HobLength = cpu_to_le16(sizeof(*region)),
79 .Reserved = cpu_to_le32(0),
80 },
81 .Owner = EFI_HOB_OWNER_ZERO,
82 .ResourceType = cpu_to_le32(resource_type),
83 .ResourceAttribute = cpu_to_le32(attr),
84 .PhysicalStart = cpu_to_le64(e->address),
85 .ResourceLength = cpu_to_le64(e->length),
86 };
87 }
88 }
89
tdvf_hob_create(TdxGuest * tdx,TdxFirmwareEntry * td_hob)90 void tdvf_hob_create(TdxGuest *tdx, TdxFirmwareEntry *td_hob)
91 {
92 TdvfHob hob = {
93 .hob_addr = td_hob->address,
94 .size = td_hob->size,
95 .ptr = td_hob->mem_ptr,
96
97 .current = td_hob->mem_ptr,
98 .end = td_hob->mem_ptr + td_hob->size,
99 };
100
101 EFI_HOB_GENERIC_HEADER *last_hob;
102 EFI_HOB_HANDOFF_INFO_TABLE *hit;
103
104 /* Note, Efi{Free}Memory{Bottom,Top} are ignored, leave 'em zeroed. */
105 hit = tdvf_get_area(&hob, sizeof(*hit));
106 *hit = (EFI_HOB_HANDOFF_INFO_TABLE) {
107 .Header = {
108 .HobType = EFI_HOB_TYPE_HANDOFF,
109 .HobLength = cpu_to_le16(sizeof(*hit)),
110 .Reserved = cpu_to_le32(0),
111 },
112 .Version = cpu_to_le32(EFI_HOB_HANDOFF_TABLE_VERSION),
113 .BootMode = cpu_to_le32(0),
114 .EfiMemoryTop = cpu_to_le64(0),
115 .EfiMemoryBottom = cpu_to_le64(0),
116 .EfiFreeMemoryTop = cpu_to_le64(0),
117 .EfiFreeMemoryBottom = cpu_to_le64(0),
118 .EfiEndOfHobList = cpu_to_le64(0), /* initialized later */
119 };
120
121 tdvf_hob_add_memory_resources(tdx, &hob);
122
123 last_hob = tdvf_get_area(&hob, sizeof(*last_hob));
124 *last_hob = (EFI_HOB_GENERIC_HEADER) {
125 .HobType = EFI_HOB_TYPE_END_OF_HOB_LIST,
126 .HobLength = cpu_to_le16(sizeof(*last_hob)),
127 .Reserved = cpu_to_le32(0),
128 };
129 hit->EfiEndOfHobList = tdvf_current_guest_addr(&hob);
130 }
131