]>
Commit | Line | Data |
---|---|---|
b22ac35b MX |
1 | /** @file\r |
2 | Initialize Intel TDX support.\r | |
3 | \r | |
4 | Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>\r | |
5 | \r | |
6 | SPDX-License-Identifier: BSD-2-Clause-Patent\r | |
7 | \r | |
8 | **/\r | |
9 | \r | |
d1e41c62 | 10 | #include <Base.h>\r |
b22ac35b MX |
11 | #include <PiPei.h>\r |
12 | #include <Library/BaseLib.h>\r | |
13 | #include <Library/DebugLib.h>\r | |
14 | #include <Library/HobLib.h>\r | |
15 | #include <Library/BaseMemoryLib.h>\r | |
16 | #include <Library/MemoryAllocationLib.h>\r | |
17 | #include <IndustryStandard/Tdx.h>\r | |
18 | #include <IndustryStandard/IntelTdx.h>\r | |
19 | #include <IndustryStandard/QemuFwCfg.h>\r | |
20 | #include <Library/QemuFwCfgLib.h>\r | |
21 | #include <Library/PeiServicesLib.h>\r | |
22 | #include <Library/TdxLib.h>\r | |
23 | #include <Library/SynchronizationLib.h>\r | |
9b648112 | 24 | #include <Pi/PrePiHob.h>\r |
b22ac35b MX |
25 | #include <WorkArea.h>\r |
26 | #include <ConfidentialComputingGuestAttr.h>\r | |
27 | \r | |
9b648112 | 28 | #define ALIGNED_2MB_MASK 0x1fffff\r |
d1e41c62 | 29 | #define MEGABYTE_SHIFT 20\r |
b22ac35b MX |
30 | \r |
31 | /**\r | |
32 | This function will be called to accept pages. Only BSP accepts pages.\r | |
33 | \r | |
34 | TDCALL(ACCEPT_PAGE) supports the accept page size of 4k and 2M. To\r | |
35 | simplify the implementation, the Memory to be accpeted is splitted\r | |
36 | into 3 parts:\r | |
37 | ----------------- <-- StartAddress1 (not 2M aligned)\r | |
38 | | part 1 | Length1 < 2M\r | |
39 | |---------------| <-- StartAddress2 (2M aligned)\r | |
40 | | | Length2 = Integer multiples of 2M\r | |
41 | | part 2 |\r | |
42 | | |\r | |
43 | |---------------| <-- StartAddress3\r | |
44 | | part 3 | Length3 < 2M\r | |
45 | |---------------|\r | |
46 | \r | |
47 | @param[in] PhysicalAddress Start physical adress\r | |
48 | @param[in] PhysicalEnd End physical address\r | |
49 | \r | |
50 | @retval EFI_SUCCESS Accept memory successfully\r | |
51 | @retval Others Other errors as indicated\r | |
52 | **/\r | |
53 | EFI_STATUS\r | |
54 | EFIAPI\r | |
55 | BspAcceptMemoryResourceRange (\r | |
56 | IN EFI_PHYSICAL_ADDRESS PhysicalAddress,\r | |
57 | IN EFI_PHYSICAL_ADDRESS PhysicalEnd\r | |
58 | )\r | |
59 | {\r | |
60 | EFI_STATUS Status;\r | |
61 | UINT32 AcceptPageSize;\r | |
62 | UINT64 StartAddress1;\r | |
63 | UINT64 StartAddress2;\r | |
64 | UINT64 StartAddress3;\r | |
65 | UINT64 TotalLength;\r | |
66 | UINT64 Length1;\r | |
67 | UINT64 Length2;\r | |
68 | UINT64 Length3;\r | |
69 | UINT64 Pages;\r | |
70 | \r | |
71 | AcceptPageSize = FixedPcdGet32 (PcdTdxAcceptPageSize);\r | |
72 | TotalLength = PhysicalEnd - PhysicalAddress;\r | |
73 | StartAddress1 = 0;\r | |
74 | StartAddress2 = 0;\r | |
75 | StartAddress3 = 0;\r | |
76 | Length1 = 0;\r | |
77 | Length2 = 0;\r | |
78 | Length3 = 0;\r | |
79 | \r | |
80 | if (TotalLength == 0) {\r | |
81 | return EFI_SUCCESS;\r | |
82 | }\r | |
83 | \r | |
84 | DEBUG ((DEBUG_INFO, "TdAccept: 0x%llx - 0x%llx\n", PhysicalAddress, TotalLength));\r | |
85 | \r | |
86 | if (ALIGN_VALUE (PhysicalAddress, SIZE_2MB) != PhysicalAddress) {\r | |
87 | StartAddress1 = PhysicalAddress;\r | |
88 | Length1 = ALIGN_VALUE (PhysicalAddress, SIZE_2MB) - PhysicalAddress;\r | |
89 | if (Length1 >= TotalLength) {\r | |
90 | Length1 = TotalLength;\r | |
91 | }\r | |
92 | \r | |
93 | PhysicalAddress += Length1;\r | |
94 | TotalLength -= Length1;\r | |
95 | }\r | |
96 | \r | |
97 | if (TotalLength > SIZE_2MB) {\r | |
98 | StartAddress2 = PhysicalAddress;\r | |
99 | Length2 = TotalLength & ~(UINT64)ALIGNED_2MB_MASK;\r | |
100 | PhysicalAddress += Length2;\r | |
101 | TotalLength -= Length2;\r | |
102 | }\r | |
103 | \r | |
104 | if (TotalLength) {\r | |
105 | StartAddress3 = PhysicalAddress;\r | |
106 | Length3 = TotalLength;\r | |
107 | }\r | |
108 | \r | |
109 | DEBUG ((DEBUG_INFO, " Part1: 0x%llx - 0x%llx\n", StartAddress1, Length1));\r | |
110 | DEBUG ((DEBUG_INFO, " Part2: 0x%llx - 0x%llx\n", StartAddress2, Length2));\r | |
111 | DEBUG ((DEBUG_INFO, " Part3: 0x%llx - 0x%llx\n", StartAddress3, Length3));\r | |
112 | DEBUG ((DEBUG_INFO, " Page : 0x%x\n", AcceptPageSize));\r | |
113 | \r | |
114 | Status = EFI_SUCCESS;\r | |
115 | if (Length1 > 0) {\r | |
116 | Pages = Length1 / SIZE_4KB;\r | |
117 | Status = TdAcceptPages (StartAddress1, Pages, SIZE_4KB);\r | |
118 | if (EFI_ERROR (Status)) {\r | |
119 | return Status;\r | |
120 | }\r | |
121 | }\r | |
122 | \r | |
123 | if (Length2 > 0) {\r | |
124 | Pages = Length2 / AcceptPageSize;\r | |
125 | Status = TdAcceptPages (StartAddress2, Pages, AcceptPageSize);\r | |
126 | if (EFI_ERROR (Status)) {\r | |
127 | return Status;\r | |
128 | }\r | |
129 | }\r | |
130 | \r | |
131 | if (Length3 > 0) {\r | |
132 | Pages = Length3 / SIZE_4KB;\r | |
133 | Status = TdAcceptPages (StartAddress3, Pages, SIZE_4KB);\r | |
134 | ASSERT (!EFI_ERROR (Status));\r | |
135 | if (EFI_ERROR (Status)) {\r | |
136 | return Status;\r | |
137 | }\r | |
138 | }\r | |
139 | \r | |
140 | return Status;\r | |
141 | }\r | |
142 | \r | |
143 | /**\r | |
144 | Check the value whether in the valid list.\r | |
145 | \r | |
146 | @param[in] Value A value\r | |
147 | @param[in] ValidList A pointer to valid list\r | |
148 | @param[in] ValidListLength Length of valid list\r | |
149 | \r | |
150 | @retval TRUE The value is in valid list.\r | |
151 | @retval FALSE The value is not in valid list.\r | |
152 | \r | |
153 | **/\r | |
154 | BOOLEAN\r | |
155 | EFIAPI\r | |
156 | IsInValidList (\r | |
157 | IN UINT32 Value,\r | |
158 | IN UINT32 *ValidList,\r | |
159 | IN UINT32 ValidListLength\r | |
160 | )\r | |
161 | {\r | |
162 | UINT32 index;\r | |
163 | \r | |
164 | if (ValidList == NULL) {\r | |
165 | return FALSE;\r | |
166 | }\r | |
167 | \r | |
168 | for (index = 0; index < ValidListLength; index++) {\r | |
169 | if (ValidList[index] == Value) {\r | |
170 | return TRUE;\r | |
171 | }\r | |
172 | }\r | |
173 | \r | |
174 | return FALSE;\r | |
175 | }\r | |
176 | \r | |
177 | /**\r | |
178 | Check the integrity of VMM Hob List.\r | |
179 | \r | |
180 | @param[in] VmmHobList A pointer to Hob List\r | |
181 | \r | |
182 | @retval TRUE The Hob List is valid.\r | |
183 | @retval FALSE The Hob List is invalid.\r | |
184 | \r | |
185 | **/\r | |
186 | BOOLEAN\r | |
187 | EFIAPI\r | |
188 | ValidateHobList (\r | |
189 | IN CONST VOID *VmmHobList\r | |
190 | )\r | |
191 | {\r | |
192 | EFI_PEI_HOB_POINTERS Hob;\r | |
193 | UINT32 EFI_BOOT_MODE_LIST[] = {\r | |
194 | BOOT_WITH_FULL_CONFIGURATION,\r | |
195 | BOOT_WITH_MINIMAL_CONFIGURATION,\r | |
196 | BOOT_ASSUMING_NO_CONFIGURATION_CHANGES,\r | |
197 | BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS,\r | |
198 | BOOT_WITH_DEFAULT_SETTINGS,\r | |
199 | BOOT_ON_S4_RESUME,\r | |
200 | BOOT_ON_S5_RESUME,\r | |
201 | BOOT_WITH_MFG_MODE_SETTINGS,\r | |
202 | BOOT_ON_S2_RESUME,\r | |
203 | BOOT_ON_S3_RESUME,\r | |
204 | BOOT_ON_FLASH_UPDATE,\r | |
205 | BOOT_IN_RECOVERY_MODE\r | |
206 | };\r | |
207 | \r | |
208 | UINT32 EFI_RESOURCE_TYPE_LIST[] = {\r | |
209 | EFI_RESOURCE_SYSTEM_MEMORY,\r | |
210 | EFI_RESOURCE_MEMORY_MAPPED_IO,\r | |
211 | EFI_RESOURCE_IO,\r | |
212 | EFI_RESOURCE_FIRMWARE_DEVICE,\r | |
213 | EFI_RESOURCE_MEMORY_MAPPED_IO_PORT,\r | |
214 | EFI_RESOURCE_MEMORY_RESERVED,\r | |
215 | EFI_RESOURCE_IO_RESERVED,\r | |
9b648112 | 216 | BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED\r |
b22ac35b MX |
217 | };\r |
218 | \r | |
219 | if (VmmHobList == NULL) {\r | |
220 | DEBUG ((DEBUG_ERROR, "HOB: HOB data pointer is NULL\n"));\r | |
221 | return FALSE;\r | |
222 | }\r | |
223 | \r | |
224 | Hob.Raw = (UINT8 *)VmmHobList;\r | |
225 | \r | |
226 | //\r | |
227 | // Parse the HOB list until end of list or matching type is found.\r | |
228 | //\r | |
229 | while (!END_OF_HOB_LIST (Hob)) {\r | |
230 | if (Hob.Header->Reserved != (UINT32)0) {\r | |
231 | DEBUG ((DEBUG_ERROR, "HOB: Hob header Reserved filed should be zero\n"));\r | |
232 | return FALSE;\r | |
233 | }\r | |
234 | \r | |
235 | if (Hob.Header->HobLength == 0) {\r | |
236 | DEBUG ((DEBUG_ERROR, "HOB: Hob header LEANGTH should not be zero\n"));\r | |
237 | return FALSE;\r | |
238 | }\r | |
239 | \r | |
240 | switch (Hob.Header->HobType) {\r | |
241 | case EFI_HOB_TYPE_HANDOFF:\r | |
242 | if (Hob.Header->HobLength != sizeof (EFI_HOB_HANDOFF_INFO_TABLE)) {\r | |
243 | DEBUG ((DEBUG_ERROR, "HOB: Hob length is not equal corresponding hob structure. Type: 0x%04x\n", EFI_HOB_TYPE_HANDOFF));\r | |
244 | return FALSE;\r | |
245 | }\r | |
246 | \r | |
247 | if (IsInValidList (Hob.HandoffInformationTable->BootMode, EFI_BOOT_MODE_LIST, ARRAY_SIZE (EFI_BOOT_MODE_LIST)) == FALSE) {\r | |
248 | DEBUG ((DEBUG_ERROR, "HOB: Unknow HandoffInformationTable BootMode type. Type: 0x%08x\n", Hob.HandoffInformationTable->BootMode));\r | |
249 | return FALSE;\r | |
250 | }\r | |
251 | \r | |
252 | if ((Hob.HandoffInformationTable->EfiFreeMemoryTop % 4096) != 0) {\r | |
253 | DEBUG ((DEBUG_ERROR, "HOB: HandoffInformationTable EfiFreeMemoryTop address must be 4-KB aligned to meet page restrictions of UEFI.\\r | |
254 | Address: 0x%016lx\n", Hob.HandoffInformationTable->EfiFreeMemoryTop));\r | |
255 | return FALSE;\r | |
256 | }\r | |
257 | \r | |
258 | break;\r | |
259 | \r | |
260 | case EFI_HOB_TYPE_RESOURCE_DESCRIPTOR:\r | |
261 | if (Hob.Header->HobLength != sizeof (EFI_HOB_RESOURCE_DESCRIPTOR)) {\r | |
262 | DEBUG ((DEBUG_ERROR, "HOB: Hob length is not equal corresponding hob structure. Type: 0x%04x\n", EFI_HOB_TYPE_RESOURCE_DESCRIPTOR));\r | |
263 | return FALSE;\r | |
264 | }\r | |
265 | \r | |
266 | if (IsInValidList (Hob.ResourceDescriptor->ResourceType, EFI_RESOURCE_TYPE_LIST, ARRAY_SIZE (EFI_RESOURCE_TYPE_LIST)) == FALSE) {\r | |
267 | DEBUG ((DEBUG_ERROR, "HOB: Unknow ResourceDescriptor ResourceType type. Type: 0x%08x\n", Hob.ResourceDescriptor->ResourceType));\r | |
268 | return FALSE;\r | |
269 | }\r | |
270 | \r | |
271 | if ((Hob.ResourceDescriptor->ResourceAttribute & (~(EFI_RESOURCE_ATTRIBUTE_PRESENT |\r | |
272 | EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r | |
273 | EFI_RESOURCE_ATTRIBUTE_TESTED |\r | |
274 | EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED |\r | |
275 | EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED |\r | |
276 | EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED |\r | |
277 | EFI_RESOURCE_ATTRIBUTE_PERSISTENT |\r | |
278 | EFI_RESOURCE_ATTRIBUTE_SINGLE_BIT_ECC |\r | |
279 | EFI_RESOURCE_ATTRIBUTE_MULTIPLE_BIT_ECC |\r | |
280 | EFI_RESOURCE_ATTRIBUTE_ECC_RESERVED_1 |\r | |
281 | EFI_RESOURCE_ATTRIBUTE_ECC_RESERVED_2 |\r | |
282 | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |\r | |
283 | EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |\r | |
284 | EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r | |
285 | EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |\r | |
286 | EFI_RESOURCE_ATTRIBUTE_16_BIT_IO |\r | |
287 | EFI_RESOURCE_ATTRIBUTE_32_BIT_IO |\r | |
288 | EFI_RESOURCE_ATTRIBUTE_64_BIT_IO |\r | |
289 | EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED |\r | |
290 | EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE |\r | |
291 | EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE |\r | |
292 | EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE |\r | |
293 | EFI_RESOURCE_ATTRIBUTE_PERSISTABLE |\r | |
294 | EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED |\r | |
295 | EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE |\r | |
296 | EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE))) != 0)\r | |
297 | {\r | |
298 | DEBUG ((DEBUG_ERROR, "HOB: Unknow ResourceDescriptor ResourceAttribute type. Type: 0x%08x\n", Hob.ResourceDescriptor->ResourceAttribute));\r | |
299 | return FALSE;\r | |
300 | }\r | |
301 | \r | |
302 | break;\r | |
303 | \r | |
304 | // EFI_HOB_GUID_TYPE is variable length data, so skip check\r | |
305 | case EFI_HOB_TYPE_GUID_EXTENSION:\r | |
306 | break;\r | |
307 | \r | |
308 | case EFI_HOB_TYPE_FV:\r | |
309 | if (Hob.Header->HobLength != sizeof (EFI_HOB_FIRMWARE_VOLUME)) {\r | |
310 | DEBUG ((DEBUG_ERROR, "HOB: Hob length is not equal corresponding hob structure. Type: 0x%04x\n", EFI_HOB_TYPE_FV));\r | |
311 | return FALSE;\r | |
312 | }\r | |
313 | \r | |
314 | break;\r | |
315 | \r | |
316 | case EFI_HOB_TYPE_FV2:\r | |
317 | if (Hob.Header->HobLength != sizeof (EFI_HOB_FIRMWARE_VOLUME2)) {\r | |
318 | DEBUG ((DEBUG_ERROR, "HOB: Hob length is not equal corresponding hob structure. Type: 0x%04x\n", EFI_HOB_TYPE_FV2));\r | |
319 | return FALSE;\r | |
320 | }\r | |
321 | \r | |
322 | break;\r | |
323 | \r | |
324 | case EFI_HOB_TYPE_FV3:\r | |
325 | if (Hob.Header->HobLength != sizeof (EFI_HOB_FIRMWARE_VOLUME3)) {\r | |
326 | DEBUG ((DEBUG_ERROR, "HOB: Hob length is not equal corresponding hob structure. Type: 0x%04x\n", EFI_HOB_TYPE_FV3));\r | |
327 | return FALSE;\r | |
328 | }\r | |
329 | \r | |
330 | break;\r | |
331 | \r | |
332 | case EFI_HOB_TYPE_CPU:\r | |
333 | if (Hob.Header->HobLength != sizeof (EFI_HOB_CPU)) {\r | |
334 | DEBUG ((DEBUG_ERROR, "HOB: Hob length is not equal corresponding hob structure. Type: 0x%04x\n", EFI_HOB_TYPE_CPU));\r | |
335 | return FALSE;\r | |
336 | }\r | |
337 | \r | |
338 | for (UINT32 index = 0; index < 6; index++) {\r | |
339 | if (Hob.Cpu->Reserved[index] != 0) {\r | |
340 | DEBUG ((DEBUG_ERROR, "HOB: Cpu Reserved field will always be set to zero.\n"));\r | |
341 | return FALSE;\r | |
342 | }\r | |
343 | }\r | |
344 | \r | |
345 | break;\r | |
346 | \r | |
347 | default:\r | |
348 | DEBUG ((DEBUG_ERROR, "HOB: Hob type is not know. Type: 0x%04x\n", Hob.Header->HobType));\r | |
349 | return FALSE;\r | |
350 | }\r | |
351 | \r | |
352 | // Get next HOB\r | |
353 | Hob.Raw = (UINT8 *)(Hob.Raw + Hob.Header->HobLength);\r | |
354 | }\r | |
355 | \r | |
356 | return TRUE;\r | |
357 | }\r | |
358 | \r | |
359 | /**\r | |
360 | Processing the incoming HobList for the TDX\r | |
361 | \r | |
362 | Firmware must parse list, and accept the pages of memory before their can be\r | |
363 | use by the guest.\r | |
364 | \r | |
365 | @param[in] VmmHobList The Hoblist pass the firmware\r | |
366 | \r | |
367 | @retval EFI_SUCCESS Process the HobList successfully\r | |
368 | @retval Others Other errors as indicated\r | |
369 | \r | |
370 | **/\r | |
371 | EFI_STATUS\r | |
372 | EFIAPI\r | |
373 | ProcessHobList (\r | |
374 | IN CONST VOID *VmmHobList\r | |
375 | )\r | |
376 | {\r | |
377 | EFI_STATUS Status;\r | |
378 | EFI_PEI_HOB_POINTERS Hob;\r | |
379 | EFI_PHYSICAL_ADDRESS PhysicalEnd;\r | |
d1e41c62 MX |
380 | UINT64 ResourceLength;\r |
381 | UINT64 AccumulateAcceptedMemory;\r | |
b22ac35b MX |
382 | \r |
383 | Status = EFI_SUCCESS;\r | |
384 | ASSERT (VmmHobList != NULL);\r | |
385 | Hob.Raw = (UINT8 *)VmmHobList;\r | |
386 | \r | |
d1e41c62 MX |
387 | AccumulateAcceptedMemory = 0;\r |
388 | \r | |
b22ac35b MX |
389 | //\r |
390 | // Parse the HOB list until end of list or matching type is found.\r | |
391 | //\r | |
392 | while (!END_OF_HOB_LIST (Hob)) {\r | |
393 | if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r | |
394 | DEBUG ((DEBUG_INFO, "\nResourceType: 0x%x\n", Hob.ResourceDescriptor->ResourceType));\r | |
395 | \r | |
9b648112 | 396 | if (Hob.ResourceDescriptor->ResourceType == BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED) {\r |
b22ac35b MX |
397 | DEBUG ((DEBUG_INFO, "ResourceAttribute: 0x%x\n", Hob.ResourceDescriptor->ResourceAttribute));\r |
398 | DEBUG ((DEBUG_INFO, "PhysicalStart: 0x%llx\n", Hob.ResourceDescriptor->PhysicalStart));\r | |
399 | DEBUG ((DEBUG_INFO, "ResourceLength: 0x%llx\n", Hob.ResourceDescriptor->ResourceLength));\r | |
400 | DEBUG ((DEBUG_INFO, "Owner: %g\n\n", &Hob.ResourceDescriptor->Owner));\r | |
401 | \r | |
d1e41c62 MX |
402 | PhysicalEnd = Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength;\r |
403 | ResourceLength = Hob.ResourceDescriptor->ResourceLength;\r | |
404 | \r | |
405 | if (Hob.ResourceDescriptor->PhysicalStart >= BASE_4GB) {\r | |
406 | //\r | |
407 | // In current stage, we only accept the memory under 4G\r | |
408 | //\r | |
409 | break;\r | |
410 | }\r | |
b22ac35b MX |
411 | \r |
412 | Status = BspAcceptMemoryResourceRange (\r | |
413 | Hob.ResourceDescriptor->PhysicalStart,\r | |
414 | PhysicalEnd\r | |
415 | );\r | |
416 | if (EFI_ERROR (Status)) {\r | |
417 | break;\r | |
418 | }\r | |
d1e41c62 MX |
419 | \r |
420 | AccumulateAcceptedMemory += ResourceLength;\r | |
b22ac35b MX |
421 | }\r |
422 | }\r | |
423 | \r | |
424 | Hob.Raw = GET_NEXT_HOB (Hob);\r | |
425 | }\r | |
426 | \r | |
427 | return Status;\r | |
428 | }\r | |
429 | \r | |
430 | /**\r | |
431 | In Tdx guest, some information need to be passed from host VMM to guest\r | |
432 | firmware. For example, the memory resource, etc. These information are\r | |
433 | prepared by host VMM and put in HobList which is described in TdxMetadata.\r | |
434 | \r | |
435 | Information in HobList is treated as external input. From the security\r | |
436 | perspective before it is consumed, it should be validated.\r | |
437 | \r | |
438 | @retval EFI_SUCCESS Successfully process the hoblist\r | |
439 | @retval Others Other error as indicated\r | |
440 | **/\r | |
441 | EFI_STATUS\r | |
442 | EFIAPI\r | |
443 | ProcessTdxHobList (\r | |
444 | VOID\r | |
445 | )\r | |
446 | {\r | |
447 | EFI_STATUS Status;\r | |
448 | VOID *TdHob;\r | |
449 | TD_RETURN_DATA TdReturnData;\r | |
450 | \r | |
451 | TdHob = (VOID *)(UINTN)FixedPcdGet32 (PcdOvmfSecGhcbBase);\r | |
452 | Status = TdCall (TDCALL_TDINFO, 0, 0, 0, &TdReturnData);\r | |
453 | if (EFI_ERROR (Status)) {\r | |
454 | return Status;\r | |
455 | }\r | |
456 | \r | |
457 | DEBUG ((\r | |
458 | DEBUG_INFO,\r | |
459 | "Intel Tdx Started with (GPAW: %d, Cpus: %d)\n",\r | |
460 | TdReturnData.TdInfo.Gpaw,\r | |
461 | TdReturnData.TdInfo.NumVcpus\r | |
462 | ));\r | |
463 | \r | |
464 | //\r | |
465 | // Validate HobList\r | |
466 | //\r | |
467 | if (ValidateHobList (TdHob) == FALSE) {\r | |
468 | return EFI_INVALID_PARAMETER;\r | |
469 | }\r | |
470 | \r | |
471 | //\r | |
472 | // Process Hoblist to accept memory\r | |
473 | //\r | |
474 | Status = ProcessHobList (TdHob);\r | |
475 | \r | |
476 | return Status;\r | |
477 | }\r | |
478 | \r | |
d1e41c62 MX |
479 | /**\r |
480 | * Build ResourceDescriptorHob for the unaccepted memory region.\r | |
481 | * This memory region may be splitted into 2 parts because of lazy accept.\r | |
482 | *\r | |
483 | * @param Hob Point to the EFI_HOB_RESOURCE_DESCRIPTOR\r | |
484 | * @return VOID\r | |
485 | */\r | |
486 | VOID\r | |
487 | BuildResourceDescriptorHobForUnacceptedMemory (\r | |
488 | IN EFI_HOB_RESOURCE_DESCRIPTOR *Hob\r | |
489 | )\r | |
490 | {\r | |
491 | EFI_PHYSICAL_ADDRESS PhysicalStart;\r | |
492 | EFI_PHYSICAL_ADDRESS PhysicalEnd;\r | |
493 | UINT64 ResourceLength;\r | |
494 | EFI_RESOURCE_TYPE ResourceType;\r | |
495 | EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute;\r | |
496 | UINT64 MaxAcceptedMemoryAddress;\r | |
497 | \r | |
498 | ASSERT (Hob->ResourceType == BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED);\r | |
499 | \r | |
500 | ResourceType = BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED;\r | |
501 | ResourceAttribute = Hob->ResourceAttribute;\r | |
502 | PhysicalStart = Hob->PhysicalStart;\r | |
503 | ResourceLength = Hob->ResourceLength;\r | |
504 | PhysicalEnd = PhysicalStart + ResourceLength;\r | |
505 | \r | |
506 | //\r | |
507 | // In the first stage of lazy-accept, all the memory under 4G will be accepted.\r | |
508 | // The memory above 4G will not be accepted.\r | |
509 | //\r | |
510 | MaxAcceptedMemoryAddress = BASE_4GB;\r | |
511 | \r | |
512 | if (PhysicalEnd <= MaxAcceptedMemoryAddress) {\r | |
513 | //\r | |
514 | // This memory region has been accepted.\r | |
515 | //\r | |
516 | ResourceType = EFI_RESOURCE_SYSTEM_MEMORY;\r | |
517 | ResourceAttribute |= (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_TESTED);\r | |
518 | } else if (PhysicalStart >= MaxAcceptedMemoryAddress) {\r | |
519 | //\r | |
520 | // This memory region hasn't been accepted.\r | |
521 | // So keep the ResourceType and ResourceAttribute unchange.\r | |
522 | //\r | |
523 | }\r | |
524 | \r | |
525 | BuildResourceDescriptorHob (\r | |
526 | ResourceType,\r | |
527 | ResourceAttribute,\r | |
528 | PhysicalStart,\r | |
529 | ResourceLength\r | |
530 | );\r | |
531 | }\r | |
532 | \r | |
b22ac35b MX |
533 | /**\r |
534 | Transfer the incoming HobList for the TD to the final HobList for Dxe.\r | |
535 | The Hobs transferred in this function are ResourceDescriptor hob and\r | |
536 | MemoryAllocation hob.\r | |
537 | \r | |
538 | @param[in] VmmHobList The Hoblist pass the firmware\r | |
539 | \r | |
540 | **/\r | |
541 | VOID\r | |
542 | EFIAPI\r | |
543 | TransferTdxHobList (\r | |
544 | VOID\r | |
545 | )\r | |
546 | {\r | |
547 | EFI_PEI_HOB_POINTERS Hob;\r | |
548 | EFI_RESOURCE_TYPE ResourceType;\r | |
549 | EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute;\r | |
550 | \r | |
551 | //\r | |
552 | // PcdOvmfSecGhcbBase is used as the TD_HOB in Tdx guest.\r | |
553 | //\r | |
554 | Hob.Raw = (UINT8 *)(UINTN)FixedPcdGet32 (PcdOvmfSecGhcbBase);\r | |
555 | while (!END_OF_HOB_LIST (Hob)) {\r | |
556 | switch (Hob.Header->HobType) {\r | |
557 | case EFI_HOB_TYPE_RESOURCE_DESCRIPTOR:\r | |
558 | ResourceType = Hob.ResourceDescriptor->ResourceType;\r | |
559 | ResourceAttribute = Hob.ResourceDescriptor->ResourceAttribute;\r | |
560 | \r | |
9b648112 | 561 | if (ResourceType == BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED) {\r |
d1e41c62 MX |
562 | BuildResourceDescriptorHobForUnacceptedMemory (Hob.ResourceDescriptor);\r |
563 | } else {\r | |
564 | BuildResourceDescriptorHob (\r | |
565 | ResourceType,\r | |
566 | ResourceAttribute,\r | |
567 | Hob.ResourceDescriptor->PhysicalStart,\r | |
568 | Hob.ResourceDescriptor->ResourceLength\r | |
569 | );\r | |
b22ac35b MX |
570 | }\r |
571 | \r | |
b22ac35b MX |
572 | break;\r |
573 | case EFI_HOB_TYPE_MEMORY_ALLOCATION:\r | |
574 | BuildMemoryAllocationHob (\r | |
575 | Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress,\r | |
576 | Hob.MemoryAllocation->AllocDescriptor.MemoryLength,\r | |
577 | Hob.MemoryAllocation->AllocDescriptor.MemoryType\r | |
578 | );\r | |
579 | break;\r | |
580 | }\r | |
581 | \r | |
582 | Hob.Raw = GET_NEXT_HOB (Hob);\r | |
583 | }\r | |
584 | }\r | |
e23f8f52 MX |
585 | \r |
586 | /**\r | |
587 | In Tdx guest, the system memory is passed in TdHob by host VMM. So\r | |
588 | the major task of PlatformTdxPublishRamRegions is to walk thru the\r | |
589 | TdHob list and transfer the ResourceDescriptorHob and MemoryAllocationHob\r | |
590 | to the hobs in DXE phase.\r | |
591 | \r | |
592 | MemoryAllocationHob should also be created for Mailbox and Ovmf work area.\r | |
593 | **/\r | |
594 | VOID\r | |
595 | EFIAPI\r | |
596 | PlatformTdxPublishRamRegions (\r | |
597 | VOID\r | |
598 | )\r | |
599 | {\r | |
600 | if (!TdIsEnabled ()) {\r | |
601 | return;\r | |
602 | }\r | |
603 | \r | |
604 | TransferTdxHobList ();\r | |
605 | \r | |
606 | //\r | |
607 | // The memory region defined by PcdOvmfSecGhcbBackupBase is pre-allocated by\r | |
608 | // host VMM and used as the td mailbox at the beginning of system boot.\r | |
609 | //\r | |
610 | BuildMemoryAllocationHob (\r | |
611 | FixedPcdGet32 (PcdOvmfSecGhcbBackupBase),\r | |
612 | FixedPcdGet32 (PcdOvmfSecGhcbBackupSize),\r | |
613 | EfiACPIMemoryNVS\r | |
614 | );\r | |
615 | \r | |
616 | if (FixedPcdGet32 (PcdOvmfWorkAreaSize) != 0) {\r | |
617 | //\r | |
618 | // Reserve the work area.\r | |
619 | //\r | |
620 | // Since this memory range will be used by the Reset Vector on S3\r | |
621 | // resume, it must be reserved as ACPI NVS.\r | |
622 | //\r | |
623 | // If S3 is unsupported, then various drivers might still write to the\r | |
624 | // work area. We ought to prevent DXE from serving allocation requests\r | |
625 | // such that they would overlap the work area.\r | |
626 | //\r | |
627 | BuildMemoryAllocationHob (\r | |
628 | (EFI_PHYSICAL_ADDRESS)(UINTN)FixedPcdGet32 (PcdOvmfWorkAreaBase),\r | |
629 | (UINT64)(UINTN)FixedPcdGet32 (PcdOvmfWorkAreaSize),\r | |
630 | EfiBootServicesData\r | |
631 | );\r | |
632 | }\r | |
633 | }\r |