]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/XenAcpiPlatformDxe/AcpiPlatform.c
OvmfPkg/XenAcpiPlatformDxe: create from AcpiPlatformDxe
[mirror_edk2.git] / OvmfPkg / XenAcpiPlatformDxe / AcpiPlatform.c
1 /** @file
2 OVMF ACPI Platform Driver for Xen guests
3
4 Copyright (C) 2021, Red Hat, Inc.
5 Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include <Library/DebugLib.h> // ASSERT_EFI_ERROR()
11 #include <Library/UefiBootServicesTableLib.h> // gBS
12 #include <Library/XenPlatformLib.h> // XenDetected()
13 #include <Protocol/FirmwareVolume2.h> // gEfiFirmwareVolume2Protocol...
14
15 #include "AcpiPlatform.h"
16
17 EFI_STATUS
18 EFIAPI
19 InstallAcpiTable (
20 IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,
21 IN VOID *AcpiTableBuffer,
22 IN UINTN AcpiTableBufferSize,
23 OUT UINTN *TableKey
24 )
25 {
26 return AcpiProtocol->InstallAcpiTable (
27 AcpiProtocol,
28 AcpiTableBuffer,
29 AcpiTableBufferSize,
30 TableKey
31 );
32 }
33
34
35 /**
36 Locate the first instance of a protocol. If the protocol requested is an
37 FV protocol, then it will return the first FV that contains the ACPI table
38 storage file.
39
40 @param Instance Return pointer to the first instance of the protocol
41
42 @return EFI_SUCCESS The function completed successfully.
43 @return EFI_NOT_FOUND The protocol could not be located.
44 @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.
45
46 **/
47 EFI_STATUS
48 LocateFvInstanceWithTables (
49 OUT EFI_FIRMWARE_VOLUME2_PROTOCOL **Instance
50 )
51 {
52 EFI_STATUS Status;
53 EFI_HANDLE *HandleBuffer;
54 UINTN NumberOfHandles;
55 EFI_FV_FILETYPE FileType;
56 UINT32 FvStatus;
57 EFI_FV_FILE_ATTRIBUTES Attributes;
58 UINTN Size;
59 UINTN Index;
60 EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance;
61
62 FvStatus = 0;
63
64 //
65 // Locate protocol.
66 //
67 Status = gBS->LocateHandleBuffer (
68 ByProtocol,
69 &gEfiFirmwareVolume2ProtocolGuid,
70 NULL,
71 &NumberOfHandles,
72 &HandleBuffer
73 );
74 if (EFI_ERROR (Status)) {
75 //
76 // Defined errors at this time are not found and out of resources.
77 //
78 return Status;
79 }
80
81 //
82 // Looking for FV with ACPI storage file
83 //
84 for (Index = 0; Index < NumberOfHandles; Index++) {
85 //
86 // Get the protocol on this handle
87 // This should not fail because of LocateHandleBuffer
88 //
89 Status = gBS->HandleProtocol (
90 HandleBuffer[Index],
91 &gEfiFirmwareVolume2ProtocolGuid,
92 (VOID**) &FvInstance
93 );
94 ASSERT_EFI_ERROR (Status);
95
96 //
97 // See if it has the ACPI storage file
98 //
99 Status = FvInstance->ReadFile (
100 FvInstance,
101 (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),
102 NULL,
103 &Size,
104 &FileType,
105 &Attributes,
106 &FvStatus
107 );
108
109 //
110 // If we found it, then we are done
111 //
112 if (Status == EFI_SUCCESS) {
113 *Instance = FvInstance;
114 break;
115 }
116 }
117
118 //
119 // Our exit status is determined by the success of the previous operations
120 // If the protocol was found, Instance already points to it.
121 //
122
123 //
124 // Free any allocated buffers
125 //
126 gBS->FreePool (HandleBuffer);
127
128 return Status;
129 }
130
131
132 /**
133 Find ACPI tables in an FV and install them.
134
135 This is now a fall-back path. Normally, we will search for tables provided
136 by the VMM first.
137
138 If that fails, we use this function to load the ACPI tables from an FV. The
139 sources for the FV based tables is located under OvmfPkg/AcpiTables.
140
141 @param AcpiTable Protocol instance pointer
142
143 **/
144 EFI_STATUS
145 EFIAPI
146 InstallOvmfFvTables (
147 IN EFI_ACPI_TABLE_PROTOCOL *AcpiTable
148 )
149 {
150 EFI_STATUS Status;
151 EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
152 INTN Instance;
153 EFI_ACPI_COMMON_HEADER *CurrentTable;
154 UINTN TableHandle;
155 UINT32 FvStatus;
156 UINTN TableSize;
157 UINTN Size;
158 EFI_ACPI_TABLE_INSTALL_ACPI_TABLE TableInstallFunction;
159
160 Instance = 0;
161 CurrentTable = NULL;
162 TableHandle = 0;
163
164 if (QemuDetected ()) {
165 TableInstallFunction = QemuInstallAcpiTable;
166 } else {
167 TableInstallFunction = InstallAcpiTable;
168 }
169
170 //
171 // set FwVol (and use an ASSERT() below) to suppress incorrect
172 // compiler/analyzer warnings
173 //
174 FwVol = NULL;
175 //
176 // Locate the firmware volume protocol
177 //
178 Status = LocateFvInstanceWithTables (&FwVol);
179 if (EFI_ERROR (Status)) {
180 return EFI_ABORTED;
181 }
182 ASSERT (FwVol != NULL);
183
184 //
185 // Read tables from the storage file.
186 //
187 while (Status == EFI_SUCCESS) {
188
189 Status = FwVol->ReadSection (
190 FwVol,
191 (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),
192 EFI_SECTION_RAW,
193 Instance,
194 (VOID**) &CurrentTable,
195 &Size,
196 &FvStatus
197 );
198 if (!EFI_ERROR (Status)) {
199 //
200 // Add the table
201 //
202 TableHandle = 0;
203
204 TableSize = ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->Length;
205 ASSERT (Size >= TableSize);
206
207 //
208 // Install ACPI table
209 //
210 Status = TableInstallFunction (
211 AcpiTable,
212 CurrentTable,
213 TableSize,
214 &TableHandle
215 );
216
217 //
218 // Free memory allocated by ReadSection
219 //
220 gBS->FreePool (CurrentTable);
221
222 if (EFI_ERROR (Status)) {
223 return EFI_ABORTED;
224 }
225
226 //
227 // Increment the instance
228 //
229 Instance++;
230 CurrentTable = NULL;
231 }
232 }
233
234 return EFI_SUCCESS;
235 }
236
237 /**
238 Effective entrypoint of Acpi Platform driver.
239
240 @param ImageHandle
241 @param SystemTable
242
243 @return EFI_SUCCESS
244 @return EFI_LOAD_ERROR
245 @return EFI_OUT_OF_RESOURCES
246
247 **/
248 EFI_STATUS
249 EFIAPI
250 InstallAcpiTables (
251 IN EFI_ACPI_TABLE_PROTOCOL *AcpiTable
252 )
253 {
254 EFI_STATUS Status;
255
256 if (XenDetected ()) {
257 Status = InstallXenTables (AcpiTable);
258 } else {
259 Status = InstallQemuFwCfgTables (AcpiTable);
260 }
261
262 if (EFI_ERROR (Status)) {
263 Status = InstallOvmfFvTables (AcpiTable);
264 }
265
266 return Status;
267 }
268