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
tdvf_get_metadata(void * flash_ptr,int size)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
tdvf_parse_and_check_section_entry(const TdvfSectionEntry * src,TdxFirmwareEntry * entry)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) {
104*6f1035fcSCédric Le Goater error_report("Broken metadata RawDataSize 0x%x MemoryDataSize 0x%"PRIx64,
105b65a6011SIsaku Yamahata entry->data_len, entry->size);
106b65a6011SIsaku Yamahata return -1;
107b65a6011SIsaku Yamahata }
108b65a6011SIsaku Yamahata if (!QEMU_IS_ALIGNED(entry->address, TDVF_ALIGNMENT)) {
109*6f1035fcSCédric Le Goater error_report("MemoryAddress 0x%"PRIx64" not page aligned", entry->address);
110b65a6011SIsaku Yamahata return -1;
111b65a6011SIsaku Yamahata }
112b65a6011SIsaku Yamahata if (!QEMU_IS_ALIGNED(entry->size, TDVF_ALIGNMENT)) {
113*6f1035fcSCédric Le Goater error_report("MemoryDataSize 0x%"PRIx64" 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
tdvf_parse_metadata(TdxFirmware * fw,void * flash_ptr,int size)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
1824420ba0eSXiaoyao 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