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 26 static uint64_t tdvf_current_guest_addr(const TdvfHob *hob) 27 { 28 return hob->hob_addr + (hob->current - hob->ptr); 29 } 30 31 static void tdvf_align(TdvfHob *hob, size_t align) 32 { 33 hob->current = QEMU_ALIGN_PTR_UP(hob->current, align); 34 } 35 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 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 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