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