1b65a6011SIsaku Yamahata /* 2b65a6011SIsaku Yamahata * Copyright (c) 2025 Intel Corporation 3b65a6011SIsaku Yamahata * Author: Isaku Yamahata <isaku.yamahata at gmail.com> 4b65a6011SIsaku Yamahata * <isaku.yamahata at intel.com> 5b65a6011SIsaku Yamahata * Xiaoyao Li <xiaoyao.li@intel.com> 6b65a6011SIsaku Yamahata * 7b65a6011SIsaku Yamahata * SPDX-License-Identifier: GPL-2.0-or-later 8b65a6011SIsaku Yamahata */ 9b65a6011SIsaku Yamahata 10b65a6011SIsaku Yamahata #include "qemu/osdep.h" 11b65a6011SIsaku Yamahata #include "qemu/error-report.h" 12b65a6011SIsaku Yamahata 13b65a6011SIsaku Yamahata #include "hw/i386/pc.h" 14b65a6011SIsaku Yamahata #include "hw/i386/tdvf.h" 15b65a6011SIsaku Yamahata #include "system/kvm.h" 16b65a6011SIsaku Yamahata 17b65a6011SIsaku Yamahata #define TDX_METADATA_OFFSET_GUID "e47a6535-984a-4798-865e-4685a7bf8ec2" 18b65a6011SIsaku Yamahata #define TDX_METADATA_VERSION 1 19b65a6011SIsaku Yamahata #define TDVF_SIGNATURE 0x46564454 /* TDVF as little endian */ 20b65a6011SIsaku Yamahata #define TDVF_ALIGNMENT 4096 21b65a6011SIsaku Yamahata 22b65a6011SIsaku Yamahata /* 23b65a6011SIsaku Yamahata * the raw structs read from TDVF keeps the name convention in 24b65a6011SIsaku Yamahata * TDVF Design Guide spec. 25b65a6011SIsaku Yamahata */ 26b65a6011SIsaku Yamahata typedef struct { 27b65a6011SIsaku Yamahata uint32_t DataOffset; 28b65a6011SIsaku Yamahata uint32_t RawDataSize; 29b65a6011SIsaku Yamahata uint64_t MemoryAddress; 30b65a6011SIsaku Yamahata uint64_t MemoryDataSize; 31b65a6011SIsaku Yamahata uint32_t Type; 32b65a6011SIsaku Yamahata uint32_t Attributes; 33b65a6011SIsaku Yamahata } TdvfSectionEntry; 34b65a6011SIsaku Yamahata 35b65a6011SIsaku Yamahata typedef struct { 36b65a6011SIsaku Yamahata uint32_t Signature; 37b65a6011SIsaku Yamahata uint32_t Length; 38b65a6011SIsaku Yamahata uint32_t Version; 39b65a6011SIsaku Yamahata uint32_t NumberOfSectionEntries; 40b65a6011SIsaku Yamahata TdvfSectionEntry SectionEntries[]; 41b65a6011SIsaku Yamahata } TdvfMetadata; 42b65a6011SIsaku Yamahata 43b65a6011SIsaku Yamahata struct tdx_metadata_offset { 44b65a6011SIsaku Yamahata uint32_t offset; 45b65a6011SIsaku Yamahata }; 46b65a6011SIsaku Yamahata 47b65a6011SIsaku Yamahata static TdvfMetadata *tdvf_get_metadata(void *flash_ptr, int size) 48b65a6011SIsaku Yamahata { 49b65a6011SIsaku Yamahata TdvfMetadata *metadata; 50b65a6011SIsaku Yamahata uint32_t offset = 0; 51b65a6011SIsaku Yamahata uint8_t *data; 52b65a6011SIsaku Yamahata 53b65a6011SIsaku Yamahata if ((uint32_t) size != size) { 54b65a6011SIsaku Yamahata return NULL; 55b65a6011SIsaku Yamahata } 56b65a6011SIsaku Yamahata 57b65a6011SIsaku Yamahata if (pc_system_ovmf_table_find(TDX_METADATA_OFFSET_GUID, &data, NULL)) { 58b65a6011SIsaku Yamahata offset = size - le32_to_cpu(((struct tdx_metadata_offset *)data)->offset); 59b65a6011SIsaku Yamahata 60b65a6011SIsaku Yamahata if (offset + sizeof(*metadata) > size) { 61b65a6011SIsaku Yamahata return NULL; 62b65a6011SIsaku Yamahata } 63b65a6011SIsaku Yamahata } else { 64b65a6011SIsaku Yamahata error_report("Cannot find TDX_METADATA_OFFSET_GUID"); 65b65a6011SIsaku Yamahata return NULL; 66b65a6011SIsaku Yamahata } 67b65a6011SIsaku Yamahata 68b65a6011SIsaku Yamahata metadata = flash_ptr + offset; 69b65a6011SIsaku Yamahata 70b65a6011SIsaku Yamahata /* Finally, verify the signature to determine if this is a TDVF image. */ 71b65a6011SIsaku Yamahata metadata->Signature = le32_to_cpu(metadata->Signature); 72b65a6011SIsaku Yamahata if (metadata->Signature != TDVF_SIGNATURE) { 73b65a6011SIsaku Yamahata error_report("Invalid TDVF signature in metadata!"); 74b65a6011SIsaku Yamahata return NULL; 75b65a6011SIsaku Yamahata } 76b65a6011SIsaku Yamahata 77b65a6011SIsaku Yamahata /* Sanity check that the TDVF doesn't overlap its own metadata. */ 78b65a6011SIsaku Yamahata metadata->Length = le32_to_cpu(metadata->Length); 79b65a6011SIsaku Yamahata if (offset + metadata->Length > size) { 80b65a6011SIsaku Yamahata return NULL; 81b65a6011SIsaku Yamahata } 82b65a6011SIsaku Yamahata 83b65a6011SIsaku Yamahata /* Only version 1 is supported/defined. */ 84b65a6011SIsaku Yamahata metadata->Version = le32_to_cpu(metadata->Version); 85b65a6011SIsaku Yamahata if (metadata->Version != TDX_METADATA_VERSION) { 86b65a6011SIsaku Yamahata return NULL; 87b65a6011SIsaku Yamahata } 88b65a6011SIsaku Yamahata 89b65a6011SIsaku Yamahata return metadata; 90b65a6011SIsaku Yamahata } 91b65a6011SIsaku Yamahata 92b65a6011SIsaku Yamahata static int tdvf_parse_and_check_section_entry(const TdvfSectionEntry *src, 93b65a6011SIsaku Yamahata TdxFirmwareEntry *entry) 94b65a6011SIsaku Yamahata { 95b65a6011SIsaku Yamahata entry->data_offset = le32_to_cpu(src->DataOffset); 96b65a6011SIsaku Yamahata entry->data_len = le32_to_cpu(src->RawDataSize); 97b65a6011SIsaku Yamahata entry->address = le64_to_cpu(src->MemoryAddress); 98b65a6011SIsaku Yamahata entry->size = le64_to_cpu(src->MemoryDataSize); 99b65a6011SIsaku Yamahata entry->type = le32_to_cpu(src->Type); 100b65a6011SIsaku Yamahata entry->attributes = le32_to_cpu(src->Attributes); 101b65a6011SIsaku Yamahata 102b65a6011SIsaku Yamahata /* sanity check */ 103b65a6011SIsaku Yamahata if (entry->size < entry->data_len) { 104b65a6011SIsaku Yamahata error_report("Broken metadata RawDataSize 0x%x MemoryDataSize 0x%lx", 105b65a6011SIsaku Yamahata entry->data_len, entry->size); 106b65a6011SIsaku Yamahata return -1; 107b65a6011SIsaku Yamahata } 108b65a6011SIsaku Yamahata if (!QEMU_IS_ALIGNED(entry->address, TDVF_ALIGNMENT)) { 109b65a6011SIsaku Yamahata error_report("MemoryAddress 0x%lx not page aligned", entry->address); 110b65a6011SIsaku Yamahata return -1; 111b65a6011SIsaku Yamahata } 112b65a6011SIsaku Yamahata if (!QEMU_IS_ALIGNED(entry->size, TDVF_ALIGNMENT)) { 113b65a6011SIsaku Yamahata error_report("MemoryDataSize 0x%lx not page aligned", entry->size); 114b65a6011SIsaku Yamahata return -1; 115b65a6011SIsaku Yamahata } 116b65a6011SIsaku Yamahata 117b65a6011SIsaku Yamahata switch (entry->type) { 118b65a6011SIsaku Yamahata case TDVF_SECTION_TYPE_BFV: 119b65a6011SIsaku Yamahata case TDVF_SECTION_TYPE_CFV: 120b65a6011SIsaku Yamahata /* The sections that must be copied from firmware image to TD memory */ 121b65a6011SIsaku Yamahata if (entry->data_len == 0) { 122b65a6011SIsaku Yamahata error_report("%d section with RawDataSize == 0", entry->type); 123b65a6011SIsaku Yamahata return -1; 124b65a6011SIsaku Yamahata } 125b65a6011SIsaku Yamahata break; 126b65a6011SIsaku Yamahata case TDVF_SECTION_TYPE_TD_HOB: 127b65a6011SIsaku Yamahata case TDVF_SECTION_TYPE_TEMP_MEM: 128b65a6011SIsaku Yamahata /* The sections that no need to be copied from firmware image */ 129b65a6011SIsaku Yamahata if (entry->data_len != 0) { 130b65a6011SIsaku Yamahata error_report("%d section with RawDataSize 0x%x != 0", 131b65a6011SIsaku Yamahata entry->type, entry->data_len); 132b65a6011SIsaku Yamahata return -1; 133b65a6011SIsaku Yamahata } 134b65a6011SIsaku Yamahata break; 135b65a6011SIsaku Yamahata default: 136b65a6011SIsaku Yamahata error_report("TDVF contains unsupported section type %d", entry->type); 137b65a6011SIsaku Yamahata return -1; 138b65a6011SIsaku Yamahata } 139b65a6011SIsaku Yamahata 140b65a6011SIsaku Yamahata return 0; 141b65a6011SIsaku Yamahata } 142b65a6011SIsaku Yamahata 143b65a6011SIsaku Yamahata int tdvf_parse_metadata(TdxFirmware *fw, void *flash_ptr, int size) 144b65a6011SIsaku Yamahata { 145b65a6011SIsaku Yamahata g_autofree TdvfSectionEntry *sections = NULL; 146b65a6011SIsaku Yamahata TdvfMetadata *metadata; 147b65a6011SIsaku Yamahata ssize_t entries_size; 148b65a6011SIsaku Yamahata int i; 149b65a6011SIsaku Yamahata 150b65a6011SIsaku Yamahata metadata = tdvf_get_metadata(flash_ptr, size); 151b65a6011SIsaku Yamahata if (!metadata) { 152b65a6011SIsaku Yamahata return -EINVAL; 153b65a6011SIsaku Yamahata } 154b65a6011SIsaku Yamahata 155b65a6011SIsaku Yamahata /* load and parse metadata entries */ 156b65a6011SIsaku Yamahata fw->nr_entries = le32_to_cpu(metadata->NumberOfSectionEntries); 157b65a6011SIsaku Yamahata if (fw->nr_entries < 2) { 158b65a6011SIsaku Yamahata error_report("Invalid number of fw entries (%u) in TDVF Metadata", 159b65a6011SIsaku Yamahata fw->nr_entries); 160b65a6011SIsaku Yamahata return -EINVAL; 161b65a6011SIsaku Yamahata } 162b65a6011SIsaku Yamahata 163b65a6011SIsaku Yamahata entries_size = fw->nr_entries * sizeof(TdvfSectionEntry); 164b65a6011SIsaku Yamahata if (metadata->Length != sizeof(*metadata) + entries_size) { 165b65a6011SIsaku Yamahata error_report("TDVF metadata len (0x%x) mismatch, expected (0x%x)", 166b65a6011SIsaku Yamahata metadata->Length, 167b65a6011SIsaku Yamahata (uint32_t)(sizeof(*metadata) + entries_size)); 168b65a6011SIsaku Yamahata return -EINVAL; 169b65a6011SIsaku Yamahata } 170b65a6011SIsaku Yamahata 171b65a6011SIsaku Yamahata fw->entries = g_new(TdxFirmwareEntry, fw->nr_entries); 172b65a6011SIsaku Yamahata sections = g_new(TdvfSectionEntry, fw->nr_entries); 173b65a6011SIsaku Yamahata 174b65a6011SIsaku Yamahata memcpy(sections, (void *)metadata + sizeof(*metadata), entries_size); 175b65a6011SIsaku Yamahata 176b65a6011SIsaku Yamahata for (i = 0; i < fw->nr_entries; i++) { 177b65a6011SIsaku Yamahata if (tdvf_parse_and_check_section_entry(§ions[i], &fw->entries[i])) { 178b65a6011SIsaku Yamahata goto err; 179b65a6011SIsaku Yamahata } 180b65a6011SIsaku Yamahata } 181b65a6011SIsaku Yamahata 182*4420ba0eSXiaoyao Li fw->mem_ptr = flash_ptr; 183b65a6011SIsaku Yamahata return 0; 184b65a6011SIsaku Yamahata 185b65a6011SIsaku Yamahata err: 186b65a6011SIsaku Yamahata fw->entries = 0; 187b65a6011SIsaku Yamahata g_free(fw->entries); 188b65a6011SIsaku Yamahata return -EINVAL; 189b65a6011SIsaku Yamahata } 190