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