]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/AcpiPlatformDxe/Qemu.c
OvmfPkg: install an SSDT with a dynamic OperationRegion called FWDT
[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
19\r
20\r
21BOOLEAN\r
22QemuDetected (\r
23 VOID\r
24 )\r
25{\r
26 if (!QemuFwCfgIsAvailable ()) {\r
27 return FALSE;\r
28 }\r
29\r
30 return TRUE;\r
31}\r
32\r
33\r
255b4184 34STATIC\r
35EFI_STATUS\r
36EFIAPI\r
37QemuInstallAcpiMadtTable (\r
38 IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,\r
39 IN VOID *AcpiTableBuffer,\r
40 IN UINTN AcpiTableBufferSize,\r
41 OUT UINTN *TableKey\r
42 )\r
43{\r
44 EFI_STATUS Status;\r
45 UINTN Count;\r
46 UINTN Loop;\r
47 EFI_ACPI_DESCRIPTION_HEADER *Hdr;\r
48 UINTN NewBufferSize;\r
49 EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE *LocalApic;\r
50\r
51 QemuFwCfgSelectItem (QemuFwCfgItemSmpCpuCount);\r
52 Count = (UINTN) QemuFwCfgRead16 ();\r
53 ASSERT (Count >= 1);\r
54\r
55 if (Count == 1) {\r
56 //\r
57 // The pre-built MADT table covers the single CPU case\r
58 //\r
59 return InstallAcpiTable (\r
60 AcpiProtocol,\r
61 AcpiTableBuffer,\r
62 AcpiTableBufferSize,\r
63 TableKey\r
64 );\r
65 }\r
66\r
67 //\r
68 // We need to add additional Local APIC entries to the MADT\r
69 //\r
70 NewBufferSize = AcpiTableBufferSize + ((Count - 1) * sizeof (*LocalApic));\r
71 Hdr = (EFI_ACPI_DESCRIPTION_HEADER*) AllocatePool (NewBufferSize);\r
72 ASSERT (Hdr != NULL);\r
73\r
74 CopyMem (Hdr, AcpiTableBuffer, AcpiTableBufferSize);\r
75\r
76 LocalApic = (EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE*)\r
77 (((UINT8*) Hdr) + AcpiTableBufferSize);\r
78\r
79 //\r
80 // Add Local APIC entries for the APs to the MADT\r
81 //\r
82 for (Loop = 1; Loop < Count; Loop++) {\r
83 LocalApic->Type = EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC;\r
84 LocalApic->Length = sizeof (*LocalApic);\r
75ccc2b2 85 LocalApic->AcpiProcessorId = (UINT8) Loop;\r
86 LocalApic->ApicId = (UINT8) Loop;\r
255b4184 87 LocalApic->Flags = 1;\r
88 LocalApic++;\r
89 }\r
90\r
75ccc2b2 91 Hdr->Length = (UINT32) NewBufferSize;\r
255b4184 92\r
93 Status = InstallAcpiTable (AcpiProtocol, Hdr, NewBufferSize, TableKey);\r
94\r
95 FreePool (Hdr);\r
96\r
97 return Status;\r
98}\r
99\r
100\r
253a2ea7 101#pragma pack(1)\r
102\r
103typedef struct {\r
104 UINT64 Base;\r
105 UINT64 End;\r
106 UINT64 Length;\r
107} PCI_WINDOW;\r
108\r
109typedef struct {\r
110 PCI_WINDOW PciWindow32;\r
111 PCI_WINDOW PciWindow64;\r
112} FIRMWARE_DATA;\r
113\r
114#pragma pack()\r
115\r
116\r
117STATIC\r
118EFI_STATUS\r
119EFIAPI\r
120PopulateFwData(\r
121 OUT FIRMWARE_DATA *FwData\r
122 )\r
123{\r
124 return EFI_SUCCESS;\r
125}\r
126\r
127\r
128STATIC\r
129EFI_STATUS\r
130EFIAPI\r
131QemuInstallAcpiSsdtTable (\r
132 IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,\r
133 IN VOID *AcpiTableBuffer,\r
134 IN UINTN AcpiTableBufferSize,\r
135 OUT UINTN *TableKey\r
136 )\r
137{\r
138 EFI_STATUS Status;\r
139 FIRMWARE_DATA *FwData;\r
140\r
141 Status = EFI_OUT_OF_RESOURCES;\r
142\r
143 FwData = AllocateReservedPool (sizeof (*FwData));\r
144 if (FwData != NULL) {\r
145 UINTN SsdtSize;\r
146 UINT8 *Ssdt;\r
147\r
148 SsdtSize = AcpiTableBufferSize + 17;\r
149 Ssdt = AllocatePool (SsdtSize);\r
150\r
151 if (Ssdt != NULL) {\r
152 Status = PopulateFwData (FwData);\r
153\r
154 if (Status == EFI_SUCCESS) {\r
155 UINT8 *SsdtPtr;\r
156\r
157 SsdtPtr = Ssdt;\r
158\r
159 CopyMem (SsdtPtr, AcpiTableBuffer, AcpiTableBufferSize);\r
160 SsdtPtr += AcpiTableBufferSize;\r
161\r
162 //\r
163 // build "OperationRegion(FWDT, SystemMemory, 0x12345678, 0x87654321)"\r
164 //\r
165 *(SsdtPtr++) = 0x5B; // ExtOpPrefix\r
166 *(SsdtPtr++) = 0x80; // OpRegionOp\r
167 *(SsdtPtr++) = 'F';\r
168 *(SsdtPtr++) = 'W';\r
169 *(SsdtPtr++) = 'D';\r
170 *(SsdtPtr++) = 'T';\r
171 *(SsdtPtr++) = 0x00; // SystemMemory\r
172 *(SsdtPtr++) = 0x0C; // DWordPrefix\r
173\r
174 //\r
175 // no virtual addressing yet, take the four least significant bytes\r
176 //\r
177 CopyMem(SsdtPtr, &FwData, 4);\r
178 SsdtPtr += 4;\r
179\r
180 *(SsdtPtr++) = 0x0C; // DWordPrefix\r
181\r
182 *(UINT32*) SsdtPtr = sizeof (*FwData);\r
183 SsdtPtr += 4;\r
184\r
185 ASSERT(SsdtPtr - Ssdt == SsdtSize);\r
186 ((EFI_ACPI_DESCRIPTION_HEADER *) Ssdt)->Length = SsdtSize;\r
187 Status = InstallAcpiTable (AcpiProtocol, Ssdt, SsdtSize, TableKey);\r
188 }\r
189\r
190 FreePool(Ssdt);\r
191 }\r
192\r
193 if (Status != EFI_SUCCESS) {\r
194 FreePool(FwData);\r
195 }\r
196 }\r
197\r
198 return Status;\r
199}\r
200\r
201\r
522203de 202EFI_STATUS\r
203EFIAPI\r
204QemuInstallAcpiTable (\r
205 IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,\r
206 IN VOID *AcpiTableBuffer,\r
207 IN UINTN AcpiTableBufferSize,\r
208 OUT UINTN *TableKey\r
209 )\r
210{\r
255b4184 211 EFI_ACPI_DESCRIPTION_HEADER *Hdr;\r
212 EFI_ACPI_TABLE_INSTALL_ACPI_TABLE TableInstallFunction;\r
213\r
214 Hdr = (EFI_ACPI_DESCRIPTION_HEADER*) AcpiTableBuffer;\r
215 switch (Hdr->Signature) {\r
216 case EFI_ACPI_1_0_APIC_SIGNATURE:\r
217 TableInstallFunction = QemuInstallAcpiMadtTable;\r
218 break;\r
253a2ea7 219 case EFI_ACPI_1_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:\r
220 TableInstallFunction = QemuInstallAcpiSsdtTable;\r
221 break;\r
255b4184 222 default:\r
223 TableInstallFunction = InstallAcpiTable;\r
224 }\r
225\r
226 return TableInstallFunction (\r
522203de 227 AcpiProtocol,\r
228 AcpiTableBuffer,\r
229 AcpiTableBufferSize,\r
230 TableKey\r
231 );\r
232}\r
233\r