]> git.proxmox.com Git - mirror_edk2.git/blob - EmbeddedPkg/Library/AcpiLib/AcpiLib.c
EmbeddedPkg/AcpiLib: Fix code formatting errors
[mirror_edk2.git] / EmbeddedPkg / Library / AcpiLib / AcpiLib.c
1 /** @file
2 *
3 * Copyright (c) 2014-2015, ARM Limited. All rights reserved.
4 * Copyright (c) 2021, Ampere Computing LLC. All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-2-Clause-Patent
7 *
8 **/
9
10 #include <Uefi.h>
11
12 #include <Library/AcpiLib.h>
13 #include <Library/BaseLib.h>
14 #include <Library/BaseMemoryLib.h>
15 #include <Library/DebugLib.h>
16 #include <Library/UefiBootServicesTableLib.h>
17
18 #include <Protocol/AcpiSystemDescriptionTable.h>
19 #include <Protocol/AcpiTable.h>
20 #include <Protocol/FirmwareVolume2.h>
21
22 #include <IndustryStandard/Acpi.h>
23
24 /**
25 Locate and Install the ACPI tables from the Firmware Volume if it verifies
26 the function condition.
27
28 @param AcpiFile Guid of the ACPI file into the Firmware Volume
29 @param CheckAcpiTableFunction Function that checks if the ACPI table should be installed
30
31 @return EFI_SUCCESS The function completed successfully.
32 @return EFI_NOT_FOUND The protocol could not be located.
33 @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.
34
35 **/
36 EFI_STATUS
37 LocateAndInstallAcpiFromFvConditional (
38 IN CONST EFI_GUID *AcpiFile,
39 IN EFI_LOCATE_ACPI_CHECK CheckAcpiTableFunction
40 )
41 {
42 EFI_STATUS Status;
43 EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol;
44 EFI_HANDLE *HandleBuffer;
45 UINTN NumberOfHandles;
46 UINT32 FvStatus;
47 UINTN Index;
48 EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance;
49 INTN SectionInstance;
50 UINTN SectionSize;
51 EFI_ACPI_COMMON_HEADER *AcpiTable;
52 UINTN AcpiTableSize;
53 UINTN AcpiTableKey;
54 BOOLEAN Valid;
55
56 // Ensure the ACPI Table is present
57 Status = gBS->LocateProtocol (
58 &gEfiAcpiTableProtocolGuid,
59 NULL,
60 (VOID **)&AcpiProtocol
61 );
62 if (EFI_ERROR (Status)) {
63 return Status;
64 }
65
66 FvStatus = 0;
67 SectionInstance = 0;
68
69 // Locate all the Firmware Volume protocols.
70 Status = gBS->LocateHandleBuffer (
71 ByProtocol,
72 &gEfiFirmwareVolume2ProtocolGuid,
73 NULL,
74 &NumberOfHandles,
75 &HandleBuffer
76 );
77 if (EFI_ERROR (Status)) {
78 return Status;
79 }
80
81 // Looking for FV with ACPI storage file
82 for (Index = 0; Index < NumberOfHandles; Index++) {
83 //
84 // Get the protocol on this handle
85 // This should not fail because of LocateHandleBuffer
86 //
87 Status = gBS->HandleProtocol (
88 HandleBuffer[Index],
89 &gEfiFirmwareVolume2ProtocolGuid,
90 (VOID **)&FvInstance
91 );
92 if (EFI_ERROR (Status)) {
93 goto FREE_HANDLE_BUFFER;
94 }
95
96 while (Status == EFI_SUCCESS) {
97 // AcpiTable must be allocated by ReadSection (ie: AcpiTable == NULL)
98 AcpiTable = NULL;
99
100 // See if it has the ACPI storage file
101 Status = FvInstance->ReadSection (
102 FvInstance,
103 AcpiFile,
104 EFI_SECTION_RAW,
105 SectionInstance,
106 (VOID **)&AcpiTable,
107 &SectionSize,
108 &FvStatus
109 );
110 if (!EFI_ERROR (Status)) {
111 AcpiTableKey = 0;
112 AcpiTableSize = ((EFI_ACPI_DESCRIPTION_HEADER *)AcpiTable)->Length;
113 ASSERT (SectionSize >= AcpiTableSize);
114
115 DEBUG ((
116 DEBUG_ERROR,
117 "- Found '%c%c%c%c' ACPI Table\n",
118 (((EFI_ACPI_DESCRIPTION_HEADER *)AcpiTable)->Signature & 0xFF),
119 ((((EFI_ACPI_DESCRIPTION_HEADER *)AcpiTable)->Signature >> 8) & 0xFF),
120 ((((EFI_ACPI_DESCRIPTION_HEADER *)AcpiTable)->Signature >> 16) & 0xFF),
121 ((((EFI_ACPI_DESCRIPTION_HEADER *)AcpiTable)->Signature >> 24) & 0xFF)
122 ));
123
124 // Is the ACPI table valid?
125 if (CheckAcpiTableFunction) {
126 Valid = CheckAcpiTableFunction ((EFI_ACPI_DESCRIPTION_HEADER *)AcpiTable);
127 } else {
128 Valid = TRUE;
129 }
130
131 // Install the ACPI Table
132 if (Valid) {
133 Status = AcpiProtocol->InstallAcpiTable (
134 AcpiProtocol,
135 AcpiTable,
136 AcpiTableSize,
137 &AcpiTableKey
138 );
139 }
140
141 // Free memory allocated by ReadSection
142 gBS->FreePool (AcpiTable);
143
144 if (EFI_ERROR (Status)) {
145 break;
146 }
147
148 // Increment the section instance
149 SectionInstance++;
150 }
151 }
152 }
153
154 FREE_HANDLE_BUFFER:
155 //
156 // Free any allocated buffers
157 //
158 gBS->FreePool (HandleBuffer);
159
160 return EFI_SUCCESS;
161 }
162
163 /**
164 Locate and Install the ACPI tables from the Firmware Volume
165
166 @param AcpiFile Guid of the ACPI file into the Firmware Volume
167
168 @return EFI_SUCCESS The function completed successfully.
169 @return EFI_NOT_FOUND The protocol could not be located.
170 @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.
171
172 **/
173 EFI_STATUS
174 LocateAndInstallAcpiFromFv (
175 IN CONST EFI_GUID *AcpiFile
176 )
177 {
178 return LocateAndInstallAcpiFromFvConditional (AcpiFile, NULL);
179 }
180
181 /**
182 This function calculates and updates a UINT8 checksum
183 in an ACPI description table header.
184
185 @param Buffer Pointer to buffer to checksum
186 @param Size Number of bytes to checksum
187
188 @retval EFI_SUCCESS The function completed successfully.
189 @retval EFI_INVALID_PARAMETER Invalid parameter.
190
191 **/
192 EFI_STATUS
193 EFIAPI
194 AcpiUpdateChecksum (
195 IN OUT UINT8 *Buffer,
196 IN UINTN Size
197 )
198 {
199 UINTN ChecksumOffset;
200
201 if ((Buffer == NULL) || (Size == 0)) {
202 return EFI_INVALID_PARAMETER;
203 }
204
205 ChecksumOffset = OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Checksum);
206
207 //
208 // Set checksum to 0 first
209 //
210 Buffer[ChecksumOffset] = 0;
211
212 //
213 // Update checksum value
214 //
215 Buffer[ChecksumOffset] = CalculateCheckSum8 (Buffer, Size);
216
217 return EFI_SUCCESS;
218 }
219
220 /**
221 This function uses the ACPI SDT protocol to search an ACPI table
222 with a given signature.
223
224 @param AcpiTableSdtProtocol Pointer to ACPI SDT protocol.
225 @param TableSignature ACPI table signature.
226 @param Index The zero-based index of the table where to search the table.
227 The index will be updated to the next instance if the table
228 is found with the matched TableSignature.
229 @param Table Pointer to the table.
230 @param TableKey Pointer to the table key.
231
232 @return EFI_SUCCESS The function completed successfully.
233 @return EFI_INVALID_PARAMETER At least one of parameters is invalid.
234 @retval EFI_NOT_FOUND The requested index is too large and a table was not found.
235
236 **/
237 EFI_STATUS
238 EFIAPI
239 AcpiLocateTableBySignature (
240 IN EFI_ACPI_SDT_PROTOCOL *AcpiSdtProtocol,
241 IN UINT32 TableSignature,
242 IN OUT UINTN *Index,
243 OUT EFI_ACPI_DESCRIPTION_HEADER **Table,
244 OUT UINTN *TableKey
245 )
246 {
247 EFI_STATUS Status;
248 EFI_ACPI_SDT_HEADER *TempTable;
249 EFI_ACPI_TABLE_VERSION TableVersion;
250 UINTN TableIndex;
251
252 if ( (AcpiSdtProtocol == NULL)
253 || (Table == NULL)
254 || (TableKey == NULL))
255 {
256 return EFI_INVALID_PARAMETER;
257 }
258
259 Status = EFI_SUCCESS;
260
261 //
262 // Search for ACPI Table with matching signature
263 //
264 TableVersion = 0;
265 TableIndex = *Index;
266 while (!EFI_ERROR (Status)) {
267 Status = AcpiSdtProtocol->GetAcpiTable (
268 TableIndex,
269 &TempTable,
270 &TableVersion,
271 TableKey
272 );
273 if (!EFI_ERROR (Status)) {
274 TableIndex++;
275
276 if (((EFI_ACPI_DESCRIPTION_HEADER *)TempTable)->Signature == TableSignature) {
277 *Table = (EFI_ACPI_DESCRIPTION_HEADER *)TempTable;
278 *Index = TableIndex;
279 break;
280 }
281 }
282 }
283
284 return Status;
285 }
286
287 /**
288 This function updates the integer value of an AML Object.
289
290 @param AcpiTableSdtProtocol Pointer to ACPI SDT protocol.
291 @param TableHandle Points to the table representing the starting point
292 for the object path search.
293 @param AsciiObjectPath Pointer to the ACPI path of the object being updated.
294 @param Value New value to write to the object.
295
296 @return EFI_SUCCESS The function completed successfully.
297 @return EFI_INVALID_PARAMETER At least one of parameters is invalid or the data type
298 of the ACPI object is not an integer value.
299 @retval EFI_NOT_FOUND The object is not found with the given path.
300
301 **/
302 EFI_STATUS
303 EFIAPI
304 AcpiAmlObjectUpdateInteger (
305 IN EFI_ACPI_SDT_PROTOCOL *AcpiSdtProtocol,
306 IN EFI_ACPI_HANDLE TableHandle,
307 IN CHAR8 *AsciiObjectPath,
308 IN UINTN Value
309 )
310 {
311 EFI_STATUS Status;
312 EFI_ACPI_HANDLE ObjectHandle;
313 EFI_ACPI_HANDLE DataHandle;
314 EFI_ACPI_DATA_TYPE DataType;
315 UINT8 *Buffer;
316 UINTN BufferSize;
317 UINTN DataSize;
318
319 if ((AcpiSdtProtocol == NULL) || (AsciiObjectPath == NULL)) {
320 return EFI_INVALID_PARAMETER;
321 }
322
323 ObjectHandle = NULL;
324 DataHandle = NULL;
325
326 Status = AcpiSdtProtocol->FindPath (TableHandle, AsciiObjectPath, &ObjectHandle);
327 if (EFI_ERROR (Status)) {
328 return Status;
329 }
330
331 Status = AcpiSdtProtocol->GetOption (ObjectHandle, 0, &DataType, (VOID *)&Buffer, &BufferSize);
332 if (EFI_ERROR (Status)) {
333 Status = EFI_NOT_FOUND;
334 goto Exit;
335 }
336
337 ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
338 ASSERT (Buffer != NULL);
339
340 if (Buffer[0] != AML_NAME_OP) {
341 Status = EFI_NOT_FOUND;
342 goto Exit;
343 }
344
345 //
346 // Get handle of data object
347 //
348 Status = AcpiSdtProtocol->GetChild (ObjectHandle, &DataHandle);
349 ASSERT_EFI_ERROR (Status);
350
351 Status = AcpiSdtProtocol->GetOption (DataHandle, 0, &DataType, (VOID *)&Buffer, &BufferSize);
352 ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
353 ASSERT (Buffer != NULL);
354
355 if ((Buffer[0] == AML_ZERO_OP) || (Buffer[0] == AML_ONE_OP)) {
356 Status = AcpiSdtProtocol->SetOption (DataHandle, 0, (VOID *)&Value, sizeof (UINT8));
357 ASSERT_EFI_ERROR (Status);
358 } else {
359 //
360 // Check the size of data object
361 //
362 switch (Buffer[0]) {
363 case AML_BYTE_PREFIX:
364 DataSize = sizeof (UINT8);
365 break;
366
367 case AML_WORD_PREFIX:
368 DataSize = sizeof (UINT16);
369 break;
370
371 case AML_DWORD_PREFIX:
372 DataSize = sizeof (UINT32);
373 break;
374
375 case AML_QWORD_PREFIX:
376 DataSize = sizeof (UINT64);
377 break;
378
379 default:
380 // The data type of the ACPI object is not an integer
381 Status = EFI_INVALID_PARAMETER;
382 goto Exit;
383 }
384
385 Status = AcpiSdtProtocol->SetOption (DataHandle, 1, (VOID *)&Value, DataSize);
386 ASSERT_EFI_ERROR (Status);
387 }
388
389 Exit:
390 AcpiSdtProtocol->Close (DataHandle);
391 AcpiSdtProtocol->Close (ObjectHandle);
392
393 return Status;
394 }