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