]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/TdxDxe/TdxAcpiTable.c
OvmfPkg: require self-signed PK when secure boot is enabled
[mirror_edk2.git] / OvmfPkg / TdxDxe / TdxAcpiTable.c
CommitLineData
fae5c146
MX
1/** @file\r
2 OVMF ACPI QEMU support\r
3\r
4 Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>\r
5\r
6 Copyright (C) 2012-2014, Red Hat, Inc.\r
7\r
8 SPDX-License-Identifier: BSD-2-Clause-Patent\r
9\r
10**/\r
11\r
12#include <Library/DebugLib.h>\r
13#include <Library/BaseLib.h>\r
14#include <Library/BaseMemoryLib.h>\r
15#include <Library/MemoryAllocationLib.h>\r
16#include <Library/QemuFwCfgLib.h>\r
17#include <Library/DxeServicesTableLib.h>\r
18#include <Library/PcdLib.h>\r
19#include <Library/OrderedCollectionLib.h>\r
20#include <Library/TdxLib.h>\r
21#include <IndustryStandard/Acpi.h>\r
22#include <Protocol/AcpiSystemDescriptionTable.h>\r
23#include <Protocol/AcpiTable.h>\r
24#include <Library/UefiBootServicesTableLib.h>\r
25#include <Library/UefiLib.h>\r
26#include <Library/TdxMailboxLib.h>\r
27#include <Protocol/Cpu.h>\r
28#include <Uefi.h>\r
29#include <TdxAcpiTable.h>\r
30\r
31/**\r
32 At the beginning of system boot, a 4K-aligned, 4K-size memory (Td mailbox) is\r
33 pre-allocated by host VMM. BSP & APs do the page accept together in that memory\r
34 region.\r
35\r
36 After that TDVF is designed to relocate the mailbox to a 4K-aligned, 4K-size\r
37 memory block which is allocated in the ACPI Nvs memory. APs are waken up and\r
38 spin around the relocated mailbox for further command.\r
39\r
40 @return EFI_PHYSICAL_ADDRESS Address of the relocated mailbox\r
41**/\r
42EFI_PHYSICAL_ADDRESS\r
43EFIAPI\r
44RelocateMailbox (\r
45 VOID\r
46 )\r
47{\r
48 EFI_PHYSICAL_ADDRESS Address;\r
49 VOID *ApLoopFunc;\r
50 UINT32 RelocationPages;\r
51 MP_RELOCATION_MAP RelocationMap;\r
52 MP_WAKEUP_MAILBOX *RelocatedMailBox;\r
53 EFI_STATUS Status;\r
54\r
55 Address = 0;\r
56 ApLoopFunc = NULL;\r
57 ZeroMem (&RelocationMap, sizeof (RelocationMap));\r
58\r
59 //\r
60 // Get information needed to setup aps running in their\r
61 // run loop in allocated acpi reserved memory\r
62 // Add another page for mailbox\r
63 //\r
64 AsmGetRelocationMap (&RelocationMap);\r
65 if ((RelocationMap.RelocateApLoopFuncAddress == 0) || (RelocationMap.RelocateApLoopFuncSize == 0)) {\r
66 DEBUG ((DEBUG_ERROR, "Failed to get the RelocationMap.\n"));\r
67 return 0;\r
68 }\r
69\r
70 RelocationPages = EFI_SIZE_TO_PAGES ((UINT32)RelocationMap.RelocateApLoopFuncSize) + 1;\r
71\r
72 Status = gBS->AllocatePages (AllocateAnyPages, EfiACPIMemoryNVS, RelocationPages, &Address);\r
73 if (EFI_ERROR (Status)) {\r
74 DEBUG ((DEBUG_ERROR, "Failed to allocate pages for MailboxRelocation. %r\n", Status));\r
75 return 0;\r
76 }\r
77\r
78 ZeroMem ((VOID *)Address, EFI_PAGES_TO_SIZE (RelocationPages));\r
79\r
80 ApLoopFunc = (VOID *)((UINTN)Address + EFI_PAGE_SIZE);\r
81\r
82 CopyMem (\r
83 ApLoopFunc,\r
84 RelocationMap.RelocateApLoopFuncAddress,\r
85 RelocationMap.RelocateApLoopFuncSize\r
86 );\r
87\r
88 DEBUG ((\r
89 DEBUG_INFO,\r
90 "Ap Relocation: mailbox %llx, loop %p\n",\r
91 Address,\r
92 ApLoopFunc\r
93 ));\r
94\r
95 //\r
96 // Initialize mailbox\r
97 //\r
98 RelocatedMailBox = (MP_WAKEUP_MAILBOX *)Address;\r
99 RelocatedMailBox->Command = MpProtectedModeWakeupCommandNoop;\r
100 RelocatedMailBox->ApicId = MP_CPU_PROTECTED_MODE_MAILBOX_APICID_INVALID;\r
101 RelocatedMailBox->WakeUpVector = 0;\r
102\r
103 //\r
104 // Wakup APs and have been move to the finalized run loop\r
105 // They will spin until guest OS wakes them\r
106 //\r
107 MpSerializeStart ();\r
108\r
109 MpSendWakeupCommand (\r
110 MpProtectedModeWakeupCommandWakeup,\r
111 (UINT64)ApLoopFunc,\r
112 (UINT64)RelocatedMailBox,\r
113 0,\r
114 0,\r
115 0\r
116 );\r
117\r
118 return Address;\r
119}\r
120\r
121/**\r
122 Alter the MADT when ACPI Table from QEMU is available.\r
123\r
124 @param[in] Event Event whose notification function is being invoked\r
125 @param[in] Context Pointer to the notification function's context\r
126**/\r
127VOID\r
128EFIAPI\r
129AlterAcpiTable (\r
130 IN EFI_EVENT Event,\r
131 IN VOID *Context\r
132 )\r
133{\r
134 EFI_ACPI_SDT_PROTOCOL *AcpiSdtProtocol;\r
135 EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;\r
136 EFI_STATUS Status;\r
137 UINTN Index;\r
138 EFI_ACPI_SDT_HEADER *Table;\r
139 EFI_ACPI_TABLE_VERSION Version;\r
140 UINTN OriginalTableKey;\r
141 UINTN NewTableKey;\r
142 UINT8 *NewMadtTable;\r
143 UINTN NewMadtTableLength;\r
144 EFI_PHYSICAL_ADDRESS RelocateMailboxAddress;\r
145 EFI_ACPI_6_4_MULTIPROCESSOR_WAKEUP_STRUCTURE *MadtMpWk;\r
146 EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *MadtHeader;\r
147\r
148 Index = 0;\r
149 NewMadtTable = NULL;\r
150 MadtHeader = NULL;\r
151\r
152 Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (void **)&AcpiSdtProtocol);\r
153 if (EFI_ERROR (Status)) {\r
154 DEBUG ((DEBUG_ERROR, "Unable to locate ACPI SDT protocol.\n"));\r
155 return;\r
156 }\r
157\r
158 RelocateMailboxAddress = RelocateMailbox ();\r
159 if (RelocateMailboxAddress == 0) {\r
160 ASSERT (FALSE);\r
161 DEBUG ((DEBUG_ERROR, "Failed to relocate Td mailbox\n"));\r
162 return;\r
163 }\r
164\r
165 do {\r
166 Status = AcpiSdtProtocol->GetAcpiTable (Index, &Table, &Version, &OriginalTableKey);\r
167\r
168 if (!EFI_ERROR (Status) && (Table->Signature == EFI_ACPI_1_0_APIC_SIGNATURE)) {\r
169 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (void **)&AcpiTableProtocol);\r
170 if (EFI_ERROR (Status)) {\r
171 DEBUG ((DEBUG_ERROR, "Unable to locate ACPI Table protocol.\n"));\r
172 break;\r
173 }\r
174\r
175 NewMadtTableLength = Table->Length + sizeof (EFI_ACPI_6_4_MULTIPROCESSOR_WAKEUP_STRUCTURE);\r
176 NewMadtTable = AllocatePool (NewMadtTableLength);\r
177 if (NewMadtTable == NULL) {\r
178 DEBUG ((DEBUG_ERROR, "%a: OUT_OF_SOURCES error.\n", __FUNCTION__));\r
179 break;\r
180 }\r
181\r
182 CopyMem (NewMadtTable, (UINT8 *)Table, Table->Length);\r
183 MadtHeader = (EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *)NewMadtTable;\r
184 MadtHeader->Header.Length = (UINT32)NewMadtTableLength;\r
185\r
186 MadtMpWk = (EFI_ACPI_6_4_MULTIPROCESSOR_WAKEUP_STRUCTURE *)(NewMadtTable + Table->Length);\r
187 MadtMpWk->Type = EFI_ACPI_6_4_MULTIPROCESSOR_WAKEUP;\r
188 MadtMpWk->Length = sizeof (EFI_ACPI_6_4_MULTIPROCESSOR_WAKEUP_STRUCTURE);\r
189 MadtMpWk->MailBoxVersion = 1;\r
190 MadtMpWk->Reserved = 0;\r
191 MadtMpWk->MailBoxAddress = RelocateMailboxAddress;\r
192\r
193 Status = AcpiTableProtocol->InstallAcpiTable (AcpiTableProtocol, NewMadtTable, NewMadtTableLength, &NewTableKey);\r
194 if (EFI_ERROR (Status)) {\r
195 DEBUG ((DEBUG_ERROR, "Failed to install new MADT table. %r\n", Status));\r
196 break;\r
197 }\r
198\r
199 Status = AcpiTableProtocol->UninstallAcpiTable (AcpiTableProtocol, OriginalTableKey);\r
200 if (EFI_ERROR (Status)) {\r
201 DEBUG ((DEBUG_ERROR, "Uninstall old MADT table error.\n"));\r
202 }\r
203\r
204 break;\r
205 }\r
206\r
207 Index++;\r
208 } while (!EFI_ERROR (Status));\r
209\r
210 if (NewMadtTable != NULL) {\r
211 FreePool (NewMadtTable);\r
212 }\r
213}\r