]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/AcpiPlatformDxe/Qemu.c
Fix memory leak
[mirror_edk2.git] / OvmfPkg / AcpiPlatformDxe / Qemu.c
CommitLineData
522203de 1/** @file\r
2 OVMF ACPI QEMU support\r
3\r
4 Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>\r
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
253a2ea7 13**/\r
522203de 14\r
15#include "AcpiPlatform.h"\r
255b4184 16#include <Library/BaseMemoryLib.h>\r
17#include <Library/MemoryAllocationLib.h>\r
522203de 18#include <Library/QemuFwCfgLib.h>\r
57c0beb6 19#include <Library/DxeServicesTableLib.h>\r
522203de 20\r
21\r
22BOOLEAN\r
23QemuDetected (\r
24 VOID\r
25 )\r
26{\r
27 if (!QemuFwCfgIsAvailable ()) {\r
28 return FALSE;\r
29 }\r
30\r
31 return TRUE;\r
32}\r
33\r
34\r
255b4184 35STATIC\r
36EFI_STATUS\r
37EFIAPI\r
38QemuInstallAcpiMadtTable (\r
39 IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,\r
40 IN VOID *AcpiTableBuffer,\r
41 IN UINTN AcpiTableBufferSize,\r
42 OUT UINTN *TableKey\r
43 )\r
44{\r
45 EFI_STATUS Status;\r
46 UINTN Count;\r
47 UINTN Loop;\r
48 EFI_ACPI_DESCRIPTION_HEADER *Hdr;\r
49 UINTN NewBufferSize;\r
50 EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE *LocalApic;\r
51\r
52 QemuFwCfgSelectItem (QemuFwCfgItemSmpCpuCount);\r
53 Count = (UINTN) QemuFwCfgRead16 ();\r
54 ASSERT (Count >= 1);\r
55\r
56 if (Count == 1) {\r
57 //\r
58 // The pre-built MADT table covers the single CPU case\r
59 //\r
60 return InstallAcpiTable (\r
61 AcpiProtocol,\r
62 AcpiTableBuffer,\r
63 AcpiTableBufferSize,\r
64 TableKey\r
65 );\r
66 }\r
67\r
68 //\r
69 // We need to add additional Local APIC entries to the MADT\r
70 //\r
71 NewBufferSize = AcpiTableBufferSize + ((Count - 1) * sizeof (*LocalApic));\r
72 Hdr = (EFI_ACPI_DESCRIPTION_HEADER*) AllocatePool (NewBufferSize);\r
73 ASSERT (Hdr != NULL);\r
74\r
75 CopyMem (Hdr, AcpiTableBuffer, AcpiTableBufferSize);\r
76\r
77 LocalApic = (EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE*)\r
78 (((UINT8*) Hdr) + AcpiTableBufferSize);\r
79\r
80 //\r
81 // Add Local APIC entries for the APs to the MADT\r
82 //\r
83 for (Loop = 1; Loop < Count; Loop++) {\r
84 LocalApic->Type = EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC;\r
85 LocalApic->Length = sizeof (*LocalApic);\r
75ccc2b2 86 LocalApic->AcpiProcessorId = (UINT8) Loop;\r
87 LocalApic->ApicId = (UINT8) Loop;\r
255b4184 88 LocalApic->Flags = 1;\r
89 LocalApic++;\r
90 }\r
91\r
75ccc2b2 92 Hdr->Length = (UINT32) NewBufferSize;\r
255b4184 93\r
94 Status = InstallAcpiTable (AcpiProtocol, Hdr, NewBufferSize, TableKey);\r
95\r
96 FreePool (Hdr);\r
97\r
98 return Status;\r
99}\r
100\r
101\r
253a2ea7 102#pragma pack(1)\r
103\r
104typedef struct {\r
105 UINT64 Base;\r
106 UINT64 End;\r
107 UINT64 Length;\r
108} PCI_WINDOW;\r
109\r
110typedef struct {\r
111 PCI_WINDOW PciWindow32;\r
112 PCI_WINDOW PciWindow64;\r
113} FIRMWARE_DATA;\r
114\r
115#pragma pack()\r
116\r
117\r
118STATIC\r
119EFI_STATUS\r
120EFIAPI\r
121PopulateFwData(\r
122 OUT FIRMWARE_DATA *FwData\r
123 )\r
124{\r
57c0beb6 125 EFI_STATUS Status;\r
126 UINTN NumDesc;\r
127 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *AllDesc;\r
128\r
129 Status = gDS->GetMemorySpaceMap (&NumDesc, &AllDesc);\r
130 if (Status == EFI_SUCCESS) {\r
131 UINT64 NonMmio32MaxExclTop;\r
132 UINT64 Mmio32MinBase;\r
133 UINT64 Mmio32MaxExclTop;\r
134 UINTN CurDesc;\r
135\r
136 Status = EFI_UNSUPPORTED;\r
137\r
138 NonMmio32MaxExclTop = 0;\r
139 Mmio32MinBase = BASE_4GB;\r
140 Mmio32MaxExclTop = 0;\r
141\r
142 for (CurDesc = 0; CurDesc < NumDesc; ++CurDesc) {\r
143 CONST EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Desc;\r
144 UINT64 ExclTop;\r
145\r
146 Desc = &AllDesc[CurDesc];\r
147 ExclTop = Desc->BaseAddress + Desc->Length;\r
148\r
149 if (ExclTop <= BASE_4GB) {\r
150 switch (Desc->GcdMemoryType) {\r
151 case EfiGcdMemoryTypeNonExistent:\r
152 break;\r
153\r
154 case EfiGcdMemoryTypeReserved:\r
155 case EfiGcdMemoryTypeSystemMemory:\r
156 if (NonMmio32MaxExclTop < ExclTop) {\r
157 NonMmio32MaxExclTop = ExclTop;\r
158 }\r
159 break;\r
160\r
161 case EfiGcdMemoryTypeMemoryMappedIo:\r
162 if (Mmio32MinBase > Desc->BaseAddress) {\r
163 Mmio32MinBase = Desc->BaseAddress;\r
164 }\r
165 if (Mmio32MaxExclTop < ExclTop) {\r
166 Mmio32MaxExclTop = ExclTop;\r
167 }\r
168 break;\r
169\r
170 default:\r
171 ASSERT(0);\r
172 }\r
173 }\r
174 }\r
175\r
176 if (Mmio32MinBase < NonMmio32MaxExclTop) {\r
177 Mmio32MinBase = NonMmio32MaxExclTop;\r
178 }\r
179\r
180 if (Mmio32MinBase < Mmio32MaxExclTop) {\r
181 FwData->PciWindow32.Base = Mmio32MinBase;\r
182 FwData->PciWindow32.End = Mmio32MaxExclTop - 1;\r
183 FwData->PciWindow32.Length = Mmio32MaxExclTop - Mmio32MinBase;\r
184\r
185 FwData->PciWindow64.Base = 0;\r
186 FwData->PciWindow64.End = 0;\r
187 FwData->PciWindow64.Length = 0;\r
188\r
189 Status = EFI_SUCCESS;\r
190 }\r
191\r
192 FreePool (AllDesc);\r
193 }\r
194\r
195 DEBUG ((\r
196 DEBUG_INFO,\r
197 "ACPI PciWindow32: Base=0x%08lx End=0x%08lx Length=0x%08lx\n",\r
198 FwData->PciWindow32.Base,\r
199 FwData->PciWindow32.End,\r
200 FwData->PciWindow32.Length\r
201 ));\r
202 DEBUG ((\r
203 DEBUG_INFO,\r
204 "ACPI PciWindow64: Base=0x%08lx End=0x%08lx Length=0x%08lx\n",\r
205 FwData->PciWindow64.Base,\r
206 FwData->PciWindow64.End,\r
207 FwData->PciWindow64.Length\r
208 ));\r
209\r
210 return Status;\r
253a2ea7 211}\r
212\r
213\r
214STATIC\r
215EFI_STATUS\r
216EFIAPI\r
217QemuInstallAcpiSsdtTable (\r
218 IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,\r
219 IN VOID *AcpiTableBuffer,\r
220 IN UINTN AcpiTableBufferSize,\r
221 OUT UINTN *TableKey\r
222 )\r
223{\r
224 EFI_STATUS Status;\r
225 FIRMWARE_DATA *FwData;\r
226\r
227 Status = EFI_OUT_OF_RESOURCES;\r
228\r
229 FwData = AllocateReservedPool (sizeof (*FwData));\r
230 if (FwData != NULL) {\r
231 UINTN SsdtSize;\r
232 UINT8 *Ssdt;\r
233\r
234 SsdtSize = AcpiTableBufferSize + 17;\r
235 Ssdt = AllocatePool (SsdtSize);\r
236\r
237 if (Ssdt != NULL) {\r
238 Status = PopulateFwData (FwData);\r
239\r
240 if (Status == EFI_SUCCESS) {\r
241 UINT8 *SsdtPtr;\r
242\r
243 SsdtPtr = Ssdt;\r
244\r
245 CopyMem (SsdtPtr, AcpiTableBuffer, AcpiTableBufferSize);\r
246 SsdtPtr += AcpiTableBufferSize;\r
247\r
248 //\r
249 // build "OperationRegion(FWDT, SystemMemory, 0x12345678, 0x87654321)"\r
250 //\r
251 *(SsdtPtr++) = 0x5B; // ExtOpPrefix\r
252 *(SsdtPtr++) = 0x80; // OpRegionOp\r
253 *(SsdtPtr++) = 'F';\r
254 *(SsdtPtr++) = 'W';\r
255 *(SsdtPtr++) = 'D';\r
256 *(SsdtPtr++) = 'T';\r
257 *(SsdtPtr++) = 0x00; // SystemMemory\r
258 *(SsdtPtr++) = 0x0C; // DWordPrefix\r
259\r
260 //\r
261 // no virtual addressing yet, take the four least significant bytes\r
262 //\r
263 CopyMem(SsdtPtr, &FwData, 4);\r
264 SsdtPtr += 4;\r
265\r
266 *(SsdtPtr++) = 0x0C; // DWordPrefix\r
267\r
268 *(UINT32*) SsdtPtr = sizeof (*FwData);\r
269 SsdtPtr += 4;\r
270\r
271 ASSERT(SsdtPtr - Ssdt == SsdtSize);\r
272 ((EFI_ACPI_DESCRIPTION_HEADER *) Ssdt)->Length = SsdtSize;\r
273 Status = InstallAcpiTable (AcpiProtocol, Ssdt, SsdtSize, TableKey);\r
274 }\r
275\r
276 FreePool(Ssdt);\r
277 }\r
278\r
279 if (Status != EFI_SUCCESS) {\r
280 FreePool(FwData);\r
281 }\r
282 }\r
283\r
284 return Status;\r
285}\r
286\r
287\r
522203de 288EFI_STATUS\r
289EFIAPI\r
290QemuInstallAcpiTable (\r
291 IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,\r
292 IN VOID *AcpiTableBuffer,\r
293 IN UINTN AcpiTableBufferSize,\r
294 OUT UINTN *TableKey\r
295 )\r
296{\r
255b4184 297 EFI_ACPI_DESCRIPTION_HEADER *Hdr;\r
298 EFI_ACPI_TABLE_INSTALL_ACPI_TABLE TableInstallFunction;\r
299\r
300 Hdr = (EFI_ACPI_DESCRIPTION_HEADER*) AcpiTableBuffer;\r
301 switch (Hdr->Signature) {\r
302 case EFI_ACPI_1_0_APIC_SIGNATURE:\r
303 TableInstallFunction = QemuInstallAcpiMadtTable;\r
304 break;\r
253a2ea7 305 case EFI_ACPI_1_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:\r
306 TableInstallFunction = QemuInstallAcpiSsdtTable;\r
307 break;\r
255b4184 308 default:\r
309 TableInstallFunction = InstallAcpiTable;\r
310 }\r
311\r
312 return TableInstallFunction (\r
522203de 313 AcpiProtocol,\r
314 AcpiTableBuffer,\r
315 AcpiTableBufferSize,\r
316 TableKey\r
317 );\r
318}\r
319\r