]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/AcpiPlatformDxe/Qemu.c
OvmfPkg: install an SSDT with a dynamic OperationRegion called FWDT
[mirror_edk2.git] / OvmfPkg / AcpiPlatformDxe / Qemu.c
1 /** @file
2 OVMF ACPI QEMU support
3
4 Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "AcpiPlatform.h"
16 #include <Library/BaseMemoryLib.h>
17 #include <Library/MemoryAllocationLib.h>
18 #include <Library/QemuFwCfgLib.h>
19
20
21 BOOLEAN
22 QemuDetected (
23 VOID
24 )
25 {
26 if (!QemuFwCfgIsAvailable ()) {
27 return FALSE;
28 }
29
30 return TRUE;
31 }
32
33
34 STATIC
35 EFI_STATUS
36 EFIAPI
37 QemuInstallAcpiMadtTable (
38 IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,
39 IN VOID *AcpiTableBuffer,
40 IN UINTN AcpiTableBufferSize,
41 OUT UINTN *TableKey
42 )
43 {
44 EFI_STATUS Status;
45 UINTN Count;
46 UINTN Loop;
47 EFI_ACPI_DESCRIPTION_HEADER *Hdr;
48 UINTN NewBufferSize;
49 EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE *LocalApic;
50
51 QemuFwCfgSelectItem (QemuFwCfgItemSmpCpuCount);
52 Count = (UINTN) QemuFwCfgRead16 ();
53 ASSERT (Count >= 1);
54
55 if (Count == 1) {
56 //
57 // The pre-built MADT table covers the single CPU case
58 //
59 return InstallAcpiTable (
60 AcpiProtocol,
61 AcpiTableBuffer,
62 AcpiTableBufferSize,
63 TableKey
64 );
65 }
66
67 //
68 // We need to add additional Local APIC entries to the MADT
69 //
70 NewBufferSize = AcpiTableBufferSize + ((Count - 1) * sizeof (*LocalApic));
71 Hdr = (EFI_ACPI_DESCRIPTION_HEADER*) AllocatePool (NewBufferSize);
72 ASSERT (Hdr != NULL);
73
74 CopyMem (Hdr, AcpiTableBuffer, AcpiTableBufferSize);
75
76 LocalApic = (EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE*)
77 (((UINT8*) Hdr) + AcpiTableBufferSize);
78
79 //
80 // Add Local APIC entries for the APs to the MADT
81 //
82 for (Loop = 1; Loop < Count; Loop++) {
83 LocalApic->Type = EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC;
84 LocalApic->Length = sizeof (*LocalApic);
85 LocalApic->AcpiProcessorId = (UINT8) Loop;
86 LocalApic->ApicId = (UINT8) Loop;
87 LocalApic->Flags = 1;
88 LocalApic++;
89 }
90
91 Hdr->Length = (UINT32) NewBufferSize;
92
93 Status = InstallAcpiTable (AcpiProtocol, Hdr, NewBufferSize, TableKey);
94
95 FreePool (Hdr);
96
97 return Status;
98 }
99
100
101 #pragma pack(1)
102
103 typedef struct {
104 UINT64 Base;
105 UINT64 End;
106 UINT64 Length;
107 } PCI_WINDOW;
108
109 typedef struct {
110 PCI_WINDOW PciWindow32;
111 PCI_WINDOW PciWindow64;
112 } FIRMWARE_DATA;
113
114 #pragma pack()
115
116
117 STATIC
118 EFI_STATUS
119 EFIAPI
120 PopulateFwData(
121 OUT FIRMWARE_DATA *FwData
122 )
123 {
124 return EFI_SUCCESS;
125 }
126
127
128 STATIC
129 EFI_STATUS
130 EFIAPI
131 QemuInstallAcpiSsdtTable (
132 IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,
133 IN VOID *AcpiTableBuffer,
134 IN UINTN AcpiTableBufferSize,
135 OUT UINTN *TableKey
136 )
137 {
138 EFI_STATUS Status;
139 FIRMWARE_DATA *FwData;
140
141 Status = EFI_OUT_OF_RESOURCES;
142
143 FwData = AllocateReservedPool (sizeof (*FwData));
144 if (FwData != NULL) {
145 UINTN SsdtSize;
146 UINT8 *Ssdt;
147
148 SsdtSize = AcpiTableBufferSize + 17;
149 Ssdt = AllocatePool (SsdtSize);
150
151 if (Ssdt != NULL) {
152 Status = PopulateFwData (FwData);
153
154 if (Status == EFI_SUCCESS) {
155 UINT8 *SsdtPtr;
156
157 SsdtPtr = Ssdt;
158
159 CopyMem (SsdtPtr, AcpiTableBuffer, AcpiTableBufferSize);
160 SsdtPtr += AcpiTableBufferSize;
161
162 //
163 // build "OperationRegion(FWDT, SystemMemory, 0x12345678, 0x87654321)"
164 //
165 *(SsdtPtr++) = 0x5B; // ExtOpPrefix
166 *(SsdtPtr++) = 0x80; // OpRegionOp
167 *(SsdtPtr++) = 'F';
168 *(SsdtPtr++) = 'W';
169 *(SsdtPtr++) = 'D';
170 *(SsdtPtr++) = 'T';
171 *(SsdtPtr++) = 0x00; // SystemMemory
172 *(SsdtPtr++) = 0x0C; // DWordPrefix
173
174 //
175 // no virtual addressing yet, take the four least significant bytes
176 //
177 CopyMem(SsdtPtr, &FwData, 4);
178 SsdtPtr += 4;
179
180 *(SsdtPtr++) = 0x0C; // DWordPrefix
181
182 *(UINT32*) SsdtPtr = sizeof (*FwData);
183 SsdtPtr += 4;
184
185 ASSERT(SsdtPtr - Ssdt == SsdtSize);
186 ((EFI_ACPI_DESCRIPTION_HEADER *) Ssdt)->Length = SsdtSize;
187 Status = InstallAcpiTable (AcpiProtocol, Ssdt, SsdtSize, TableKey);
188 }
189
190 FreePool(Ssdt);
191 }
192
193 if (Status != EFI_SUCCESS) {
194 FreePool(FwData);
195 }
196 }
197
198 return Status;
199 }
200
201
202 EFI_STATUS
203 EFIAPI
204 QemuInstallAcpiTable (
205 IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,
206 IN VOID *AcpiTableBuffer,
207 IN UINTN AcpiTableBufferSize,
208 OUT UINTN *TableKey
209 )
210 {
211 EFI_ACPI_DESCRIPTION_HEADER *Hdr;
212 EFI_ACPI_TABLE_INSTALL_ACPI_TABLE TableInstallFunction;
213
214 Hdr = (EFI_ACPI_DESCRIPTION_HEADER*) AcpiTableBuffer;
215 switch (Hdr->Signature) {
216 case EFI_ACPI_1_0_APIC_SIGNATURE:
217 TableInstallFunction = QemuInstallAcpiMadtTable;
218 break;
219 case EFI_ACPI_1_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
220 TableInstallFunction = QemuInstallAcpiSsdtTable;
221 break;
222 default:
223 TableInstallFunction = InstallAcpiTable;
224 }
225
226 return TableInstallFunction (
227 AcpiProtocol,
228 AcpiTableBuffer,
229 AcpiTableBufferSize,
230 TableKey
231 );
232 }
233