]>
Commit | Line | Data |
---|---|---|
71f2b906 SM |
1 | /** @file\r |
2 | Dynamic Table Manager Dxe\r | |
3 | \r | |
4 | Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.\r | |
5 | \r | |
9cd9bdc6 | 6 | SPDX-License-Identifier: BSD-2-Clause-Patent\r |
71f2b906 SM |
7 | \r |
8 | **/\r | |
9 | \r | |
10 | #include <Library/DebugLib.h>\r | |
11 | #include <Library/PcdLib.h>\r | |
12 | #include <Library/UefiBootServicesTableLib.h>\r | |
5236d478 | 13 | #include <Protocol/AcpiSystemDescriptionTable.h>\r |
71f2b906 SM |
14 | #include <Protocol/AcpiTable.h>\r |
15 | \r | |
16 | // Module specific include files.\r | |
17 | #include <AcpiTableGenerator.h>\r | |
18 | #include <ConfigurationManagerObject.h>\r | |
19 | #include <ConfigurationManagerHelper.h>\r | |
20 | #include <DeviceTreeTableGenerator.h>\r | |
21 | #include <Library/TableHelperLib.h>\r | |
22 | #include <Protocol/ConfigurationManagerProtocol.h>\r | |
23 | #include <Protocol/DynamicTableFactoryProtocol.h>\r | |
24 | #include <SmbiosTableGenerator.h>\r | |
25 | \r | |
5236d478 KQ |
26 | ///\r |
27 | /// Bit definitions for acceptable ACPI table presence formats.\r | |
28 | /// Currently only ACPI tables present in the ACPI info list and\r | |
29 | /// already installed will count towards "Table Present" during\r | |
30 | /// verification routine.\r | |
31 | ///\r | |
32 | #define ACPI_TABLE_PRESENT_INFO_LIST BIT0\r | |
33 | #define ACPI_TABLE_PRESENT_INSTALLED BIT1\r | |
34 | \r | |
35 | ///\r | |
36 | /// Order of ACPI table being verified during presence inspection.\r | |
37 | ///\r | |
38 | #define ACPI_TABLE_VERIFY_FADT 0\r | |
39 | #define ACPI_TABLE_VERIFY_MADT 1\r | |
40 | #define ACPI_TABLE_VERIFY_GTDT 2\r | |
41 | #define ACPI_TABLE_VERIFY_DSDT 3\r | |
42 | #define ACPI_TABLE_VERIFY_DBG2 4\r | |
43 | #define ACPI_TABLE_VERIFY_SPCR 5\r | |
44 | #define ACPI_TABLE_VERIFY_COUNT 6\r | |
45 | \r | |
46 | ///\r | |
47 | /// Private data structure to verify the presence of mandatory\r | |
48 | /// or optional ACPI tables.\r | |
49 | ///\r | |
50 | typedef struct {\r | |
51 | /// ESTD ID for the ACPI table of interest.\r | |
52 | ESTD_ACPI_TABLE_ID EstdTableId;\r | |
53 | /// Standard UINT32 ACPI signature.\r | |
54 | UINT32 AcpiTableSignature;\r | |
55 | /// 4 character ACPI table name (the 5th char8 is for null terminator).\r | |
56 | CHAR8 AcpiTableName[sizeof (UINT32) + 1];\r | |
57 | /// Indicator on whether the ACPI table is required.\r | |
58 | BOOLEAN IsMandatory;\r | |
59 | /// Formats of verified presences, as defined by ACPI_TABLE_PRESENT_*\r | |
60 | /// This field should be initialized to 0 and will be populated during\r | |
61 | /// verification routine.\r | |
62 | UINT16 Presence;\r | |
63 | } ACPI_TABLE_PRESENCE_INFO;\r | |
64 | \r | |
65 | ///\r | |
66 | /// We require the FADT, MADT, GTDT and the DSDT tables to boot.\r | |
67 | /// This list also include optional ACPI tables: DBG2, SPCR.\r | |
68 | ///\r | |
69 | ACPI_TABLE_PRESENCE_INFO mAcpiVerifyTables[ACPI_TABLE_VERIFY_COUNT] = {\r | |
70 | { EStdAcpiTableIdFadt, EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, "FADT", TRUE, 0 },\r | |
71 | { EStdAcpiTableIdMadt, EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE, "MADT", TRUE, 0 },\r | |
72 | { EStdAcpiTableIdGtdt, EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE, "GTDT", TRUE, 0 },\r | |
73 | { EStdAcpiTableIdDsdt, EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE, "DSDT", TRUE, 0 },\r | |
74 | { EStdAcpiTableIdDbg2, EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE, "DBG2", FALSE, 0 },\r | |
75 | { EStdAcpiTableIdSpcr, EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE, "SPCR", FALSE, 0 },\r | |
76 | };\r | |
77 | \r | |
71f2b906 SM |
78 | /** This macro expands to a function that retrieves the ACPI Table\r |
79 | List from the Configuration Manager.\r | |
80 | */\r | |
81 | GET_OBJECT_LIST (\r | |
82 | EObjNameSpaceStandard,\r | |
83 | EStdObjAcpiTableList,\r | |
84 | CM_STD_OBJ_ACPI_TABLE_INFO\r | |
85 | )\r | |
86 | \r | |
87 | /** A helper function to build and install a single ACPI table.\r | |
88 | \r | |
89 | This is a helper function that invokes the Table generator interface\r | |
90 | for building an ACPI table. It uses the AcpiTableProtocol to install the\r | |
91 | table, then frees the resources allocated for generating it.\r | |
92 | \r | |
93 | @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol\r | |
94 | interface.\r | |
95 | @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r | |
96 | Protocol Interface.\r | |
97 | @param [in] Generator Pointer to the AcpiTable generator.\r | |
98 | @param [in] AcpiTableProtocol Pointer to the AcpiTable protocol.\r | |
99 | @param [in] AcpiTableInfo Pointer to the ACPI table Info.\r | |
100 | \r | |
101 | @retval EFI_SUCCESS Success.\r | |
102 | @retval EFI_INVALID_PARAMETER A parameter is invalid.\r | |
103 | @retval EFI_NOT_FOUND Required object is not found.\r | |
104 | @retval EFI_BAD_BUFFER_SIZE Size returned by the Configuration Manager\r | |
105 | is less than the Object size for the\r | |
106 | requested object.\r | |
107 | **/\r | |
108 | STATIC\r | |
109 | EFI_STATUS\r | |
110 | EFIAPI\r | |
111 | BuildAndInstallSingleAcpiTable (\r | |
731c67e1 MK |
112 | IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol,\r |
113 | IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,\r | |
114 | IN CONST ACPI_TABLE_GENERATOR *CONST Generator,\r | |
115 | IN EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol,\r | |
116 | IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo\r | |
71f2b906 SM |
117 | )\r |
118 | {\r | |
731c67e1 MK |
119 | EFI_STATUS Status;\r |
120 | EFI_STATUS Status1;\r | |
121 | EFI_ACPI_DESCRIPTION_HEADER *AcpiTable;\r | |
122 | UINTN TableHandle;\r | |
71f2b906 SM |
123 | \r |
124 | AcpiTable = NULL;\r | |
731c67e1 MK |
125 | Status = Generator->BuildAcpiTable (\r |
126 | Generator,\r | |
127 | AcpiTableInfo,\r | |
128 | CfgMgrProtocol,\r | |
129 | &AcpiTable\r | |
130 | );\r | |
71f2b906 SM |
131 | if (EFI_ERROR (Status)) {\r |
132 | DEBUG ((\r | |
133 | DEBUG_ERROR,\r | |
134 | "ERROR: Failed to Build Table." \\r | |
135 | " TableGeneratorId = 0x%x. Status = %r\n",\r | |
136 | AcpiTableInfo->TableGeneratorId,\r | |
137 | Status\r | |
138 | ));\r | |
139 | // Free any allocated resources.\r | |
140 | goto exit_handler;\r | |
141 | }\r | |
142 | \r | |
143 | if (AcpiTable == NULL) {\r | |
144 | Status = EFI_NOT_FOUND;\r | |
145 | goto exit_handler;\r | |
146 | }\r | |
147 | \r | |
148 | // Dump ACPI Table Header\r | |
149 | DUMP_ACPI_TABLE_HEADER (AcpiTable);\r | |
150 | \r | |
151 | // Install ACPI table\r | |
152 | Status = AcpiTableProtocol->InstallAcpiTable (\r | |
153 | AcpiTableProtocol,\r | |
154 | AcpiTable,\r | |
155 | AcpiTable->Length,\r | |
156 | &TableHandle\r | |
157 | );\r | |
158 | if (EFI_ERROR (Status)) {\r | |
159 | DEBUG ((\r | |
160 | DEBUG_ERROR,\r | |
161 | "ERROR: Failed to Install ACPI Table. Status = %r\n",\r | |
162 | Status\r | |
163 | ));\r | |
164 | // Free any allocated resources.\r | |
165 | goto exit_handler;\r | |
166 | }\r | |
167 | \r | |
168 | DEBUG ((\r | |
169 | DEBUG_INFO,\r | |
170 | "INFO: ACPI Table installed. Status = %r\n",\r | |
171 | Status\r | |
172 | ));\r | |
173 | \r | |
174 | exit_handler:\r | |
175 | // Free any resources allocated for generating the tables.\r | |
176 | if (Generator->FreeTableResources != NULL) {\r | |
177 | Status1 = Generator->FreeTableResources (\r | |
731c67e1 MK |
178 | Generator,\r |
179 | AcpiTableInfo,\r | |
180 | CfgMgrProtocol,\r | |
181 | &AcpiTable\r | |
182 | );\r | |
71f2b906 SM |
183 | if (EFI_ERROR (Status1)) {\r |
184 | DEBUG ((\r | |
185 | DEBUG_ERROR,\r | |
186 | "ERROR: Failed to Free Table Resources." \\r | |
187 | "TableGeneratorId = 0x%x. Status = %r\n",\r | |
188 | AcpiTableInfo->TableGeneratorId,\r | |
189 | Status1\r | |
190 | ));\r | |
191 | }\r | |
192 | \r | |
193 | // Return the first error status in case of failure\r | |
194 | if (!EFI_ERROR (Status)) {\r | |
195 | Status = Status1;\r | |
196 | }\r | |
197 | }\r | |
731c67e1 | 198 | \r |
71f2b906 SM |
199 | return Status;\r |
200 | }\r | |
201 | \r | |
202 | /** A helper function to build and install multiple ACPI tables.\r | |
203 | \r | |
204 | This is a helper function that invokes the Table generator interface\r | |
205 | for building an ACPI table. It uses the AcpiTableProtocol to install the\r | |
206 | table, then frees the resources allocated for generating it.\r | |
207 | \r | |
208 | @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol\r | |
209 | interface.\r | |
210 | @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r | |
211 | Protocol Interface.\r | |
212 | @param [in] Generator Pointer to the AcpiTable generator.\r | |
213 | @param [in] AcpiTableProtocol Pointer to the AcpiTable protocol.\r | |
214 | @param [in] AcpiTableInfo Pointer to the ACPI table Info.\r | |
215 | \r | |
216 | @retval EFI_SUCCESS Success.\r | |
217 | @retval EFI_INVALID_PARAMETER A parameter is invalid.\r | |
218 | @retval EFI_NOT_FOUND Required object is not found.\r | |
219 | @retval EFI_BAD_BUFFER_SIZE Size returned by the Configuration Manager\r | |
220 | is less than the Object size for the\r | |
221 | requested object.\r | |
222 | **/\r | |
223 | STATIC\r | |
224 | EFI_STATUS\r | |
225 | EFIAPI\r | |
226 | BuildAndInstallMultipleAcpiTable (\r | |
731c67e1 MK |
227 | IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol,\r |
228 | IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,\r | |
229 | IN CONST ACPI_TABLE_GENERATOR *CONST Generator,\r | |
230 | IN EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol,\r | |
231 | IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo\r | |
71f2b906 SM |
232 | )\r |
233 | {\r | |
731c67e1 MK |
234 | EFI_STATUS Status;\r |
235 | EFI_STATUS Status1;\r | |
236 | EFI_ACPI_DESCRIPTION_HEADER **AcpiTable;\r | |
237 | UINTN TableCount;\r | |
238 | UINTN TableHandle;\r | |
239 | UINTN Index;\r | |
240 | \r | |
241 | AcpiTable = NULL;\r | |
71f2b906 | 242 | TableCount = 0;\r |
731c67e1 MK |
243 | Status = Generator->BuildAcpiTableEx (\r |
244 | Generator,\r | |
245 | AcpiTableInfo,\r | |
246 | CfgMgrProtocol,\r | |
247 | &AcpiTable,\r | |
248 | &TableCount\r | |
249 | );\r | |
71f2b906 SM |
250 | if (EFI_ERROR (Status)) {\r |
251 | DEBUG ((\r | |
252 | DEBUG_ERROR,\r | |
253 | "ERROR: Failed to Build Table." \\r | |
254 | " TableGeneratorId = 0x%x. Status = %r\n",\r | |
255 | AcpiTableInfo->TableGeneratorId,\r | |
256 | Status\r | |
257 | ));\r | |
258 | // Free any allocated resources.\r | |
259 | goto exit_handler;\r | |
260 | }\r | |
261 | \r | |
262 | if ((AcpiTable == NULL) || (TableCount == 0)) {\r | |
263 | Status = EFI_NOT_FOUND;\r | |
264 | goto exit_handler;\r | |
265 | }\r | |
266 | \r | |
267 | for (Index = 0; Index < TableCount; Index++) {\r | |
268 | // Dump ACPI Table Header\r | |
269 | DUMP_ACPI_TABLE_HEADER (AcpiTable[Index]);\r | |
270 | // Install ACPI table\r | |
271 | Status = AcpiTableProtocol->InstallAcpiTable (\r | |
272 | AcpiTableProtocol,\r | |
273 | AcpiTable[Index],\r | |
274 | AcpiTable[Index]->Length,\r | |
275 | &TableHandle\r | |
276 | );\r | |
277 | if (EFI_ERROR (Status)) {\r | |
278 | DEBUG ((\r | |
279 | DEBUG_ERROR,\r | |
280 | "ERROR: Failed to Install ACPI Table. Status = %r\n",\r | |
281 | Status\r | |
282 | ));\r | |
283 | // Free any allocated resources.\r | |
284 | goto exit_handler;\r | |
285 | }\r | |
286 | \r | |
287 | DEBUG ((\r | |
288 | DEBUG_INFO,\r | |
289 | "INFO: ACPI Table installed. Status = %r\n",\r | |
290 | Status\r | |
291 | ));\r | |
292 | }\r | |
293 | \r | |
294 | exit_handler:\r | |
295 | // Free any resources allocated for generating the tables.\r | |
296 | if (Generator->FreeTableResourcesEx != NULL) {\r | |
297 | Status1 = Generator->FreeTableResourcesEx (\r | |
731c67e1 MK |
298 | Generator,\r |
299 | AcpiTableInfo,\r | |
300 | CfgMgrProtocol,\r | |
301 | &AcpiTable,\r | |
302 | TableCount\r | |
303 | );\r | |
71f2b906 SM |
304 | if (EFI_ERROR (Status1)) {\r |
305 | DEBUG ((\r | |
306 | DEBUG_ERROR,\r | |
307 | "ERROR: Failed to Free Table Resources." \\r | |
308 | "TableGeneratorId = 0x%x. Status = %r\n",\r | |
309 | AcpiTableInfo->TableGeneratorId,\r | |
310 | Status1\r | |
311 | ));\r | |
312 | }\r | |
313 | \r | |
314 | // Return the first error status in case of failure\r | |
315 | if (!EFI_ERROR (Status)) {\r | |
316 | Status = Status1;\r | |
317 | }\r | |
318 | }\r | |
731c67e1 | 319 | \r |
71f2b906 SM |
320 | return Status;\r |
321 | }\r | |
322 | \r | |
323 | /** A helper function to invoke a Table generator\r | |
324 | \r | |
325 | This is a helper function that invokes the Table generator interface\r | |
326 | for building an ACPI table. It uses the AcpiTableProtocol to install the\r | |
327 | table, then frees the resources allocated for generating it.\r | |
328 | \r | |
329 | @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol\r | |
330 | interface.\r | |
331 | @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r | |
332 | Protocol Interface.\r | |
333 | @param [in] AcpiTableProtocol Pointer to the AcpiTable protocol.\r | |
334 | @param [in] AcpiTableInfo Pointer to the ACPI table Info.\r | |
335 | \r | |
336 | @retval EFI_SUCCESS Success.\r | |
337 | @retval EFI_INVALID_PARAMETER A parameter is invalid.\r | |
338 | @retval EFI_NOT_FOUND Required object is not found.\r | |
339 | @retval EFI_BAD_BUFFER_SIZE Size returned by the Configuration Manager\r | |
340 | is less than the Object size for the\r | |
341 | requested object.\r | |
342 | **/\r | |
343 | STATIC\r | |
344 | EFI_STATUS\r | |
345 | EFIAPI\r | |
346 | BuildAndInstallAcpiTable (\r | |
731c67e1 MK |
347 | IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol,\r |
348 | IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,\r | |
349 | IN EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol,\r | |
350 | IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo\r | |
71f2b906 SM |
351 | )\r |
352 | {\r | |
731c67e1 MK |
353 | EFI_STATUS Status;\r |
354 | CONST ACPI_TABLE_GENERATOR *Generator;\r | |
71f2b906 SM |
355 | \r |
356 | ASSERT (TableFactoryProtocol != NULL);\r | |
357 | ASSERT (CfgMgrProtocol != NULL);\r | |
358 | ASSERT (AcpiTableProtocol != NULL);\r | |
359 | ASSERT (AcpiTableInfo != NULL);\r | |
360 | \r | |
361 | DEBUG ((\r | |
362 | DEBUG_INFO,\r | |
363 | "INFO: EStdObjAcpiTableList: Address = 0x%p," \\r | |
364 | " TableGeneratorId = 0x%x\n",\r | |
365 | AcpiTableInfo,\r | |
366 | AcpiTableInfo->TableGeneratorId\r | |
367 | ));\r | |
368 | \r | |
369 | Generator = NULL;\r | |
731c67e1 MK |
370 | Status = TableFactoryProtocol->GetAcpiTableGenerator (\r |
371 | TableFactoryProtocol,\r | |
372 | AcpiTableInfo->TableGeneratorId,\r | |
373 | &Generator\r | |
374 | );\r | |
71f2b906 SM |
375 | if (EFI_ERROR (Status)) {\r |
376 | DEBUG ((\r | |
377 | DEBUG_ERROR,\r | |
378 | "ERROR: Table Generator not found." \\r | |
379 | " TableGeneratorId = 0x%x. Status = %r\n",\r | |
380 | AcpiTableInfo->TableGeneratorId,\r | |
381 | Status\r | |
382 | ));\r | |
383 | return Status;\r | |
384 | }\r | |
385 | \r | |
386 | if (Generator == NULL) {\r | |
387 | return EFI_NOT_FOUND;\r | |
388 | }\r | |
389 | \r | |
390 | DEBUG ((\r | |
391 | DEBUG_INFO,\r | |
392 | "INFO: Generator found : %s\n",\r | |
393 | Generator->Description\r | |
394 | ));\r | |
395 | \r | |
396 | if (Generator->BuildAcpiTableEx != NULL) {\r | |
397 | Status = BuildAndInstallMultipleAcpiTable (\r | |
398 | TableFactoryProtocol,\r | |
399 | CfgMgrProtocol,\r | |
400 | Generator,\r | |
401 | AcpiTableProtocol,\r | |
402 | AcpiTableInfo\r | |
403 | );\r | |
404 | if (EFI_ERROR (Status)) {\r | |
405 | DEBUG ((\r | |
406 | DEBUG_ERROR,\r | |
407 | "ERROR: Failed to find build and install ACPI Table." \\r | |
408 | " Status = %r\n",\r | |
409 | Status\r | |
410 | ));\r | |
411 | }\r | |
412 | } else if (Generator->BuildAcpiTable != NULL) {\r | |
413 | Status = BuildAndInstallSingleAcpiTable (\r | |
414 | TableFactoryProtocol,\r | |
415 | CfgMgrProtocol,\r | |
416 | Generator,\r | |
417 | AcpiTableProtocol,\r | |
418 | AcpiTableInfo\r | |
419 | );\r | |
420 | if (EFI_ERROR (Status)) {\r | |
421 | DEBUG ((\r | |
422 | DEBUG_ERROR,\r | |
423 | "ERROR: Failed to find build and install ACPI Table." \\r | |
424 | " Status = %r\n",\r | |
425 | Status\r | |
426 | ));\r | |
427 | }\r | |
428 | } else {\r | |
429 | Status = EFI_INVALID_PARAMETER;\r | |
430 | DEBUG ((\r | |
431 | DEBUG_ERROR,\r | |
432 | "ERROR: Table Generator does not implement the" \\r | |
433 | " ACPI_TABLE_GENERATOR_BUILD_TABLE interface." \\r | |
434 | " TableGeneratorId = 0x%x. Status = %r\n",\r | |
435 | AcpiTableInfo->TableGeneratorId,\r | |
436 | Status\r | |
437 | ));\r | |
438 | }\r | |
439 | \r | |
440 | return Status;\r | |
441 | }\r | |
442 | \r | |
443 | /** The function checks if the Configuration Manager has provided the\r | |
444 | mandatory ACPI tables for installation.\r | |
445 | \r | |
446 | @param [in] AcpiTableInfo Pointer to the ACPI Table Info list.\r | |
447 | @param [in] AcpiTableCount Count of ACPI Table Info.\r | |
448 | \r | |
449 | @retval EFI_SUCCESS Success.\r | |
450 | @retval EFI_NOT_FOUND If mandatory table is not found.\r | |
5236d478 | 451 | @retval EFI_ALREADY_STARTED If mandatory table found in AcpiTableInfo is already installed.\r |
71f2b906 SM |
452 | **/\r |
453 | STATIC\r | |
454 | EFI_STATUS\r | |
455 | EFIAPI\r | |
456 | VerifyMandatoryTablesArePresent (\r | |
731c67e1 | 457 | IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,\r |
71f2b906 SM |
458 | IN UINT32 AcpiTableCount\r |
459 | )\r | |
460 | {\r | |
5236d478 KQ |
461 | EFI_STATUS Status;\r |
462 | UINTN Handle;\r | |
463 | UINTN Index;\r | |
464 | UINTN InstalledTableIndex;\r | |
465 | EFI_ACPI_DESCRIPTION_HEADER *DescHeader;\r | |
466 | EFI_ACPI_TABLE_VERSION Version;\r | |
467 | EFI_ACPI_SDT_PROTOCOL *AcpiSdt;\r | |
468 | \r | |
71f2b906 SM |
469 | ASSERT (AcpiTableInfo != NULL);\r |
470 | \r | |
5236d478 KQ |
471 | Status = EFI_SUCCESS;\r |
472 | \r | |
473 | // Check against the statically initialized ACPI tables to see if they are in ACPI info list\r | |
71f2b906 | 474 | while (AcpiTableCount-- != 0) {\r |
5236d478 KQ |
475 | for (Index = 0; Index < ACPI_TABLE_VERIFY_COUNT; Index++) {\r |
476 | if (AcpiTableInfo[AcpiTableCount].AcpiTableSignature == mAcpiVerifyTables[Index].AcpiTableSignature) {\r | |
477 | mAcpiVerifyTables[Index].Presence |= ACPI_TABLE_PRESENT_INFO_LIST;\r | |
478 | // Found this table, skip the rest.\r | |
71f2b906 | 479 | break;\r |
5236d478 | 480 | }\r |
71f2b906 SM |
481 | }\r |
482 | }\r | |
483 | \r | |
5236d478 KQ |
484 | // They also might be published already, so we can search from there\r |
485 | if (FeaturePcdGet (PcdInstallAcpiSdtProtocol)) {\r | |
486 | AcpiSdt = NULL;\r | |
487 | Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID **)&AcpiSdt);\r | |
731c67e1 | 488 | \r |
5236d478 KQ |
489 | if (EFI_ERROR (Status) || (AcpiSdt == NULL)) {\r |
490 | DEBUG ((DEBUG_ERROR, "ERROR: Failed to locate ACPI SDT protocol (0x%p) - %r\n", AcpiSdt, Status));\r | |
491 | return Status;\r | |
492 | }\r | |
731c67e1 | 493 | \r |
5236d478 KQ |
494 | for (Index = 0; Index < ACPI_TABLE_VERIFY_COUNT; Index++) {\r |
495 | Handle = 0;\r | |
496 | InstalledTableIndex = 0;\r | |
497 | do {\r | |
498 | Status = AcpiSdt->GetAcpiTable (InstalledTableIndex, (EFI_ACPI_SDT_HEADER **)&DescHeader, &Version, &Handle);\r | |
499 | if (EFI_ERROR (Status)) {\r | |
500 | break;\r | |
501 | }\r | |
731c67e1 | 502 | \r |
5236d478 KQ |
503 | InstalledTableIndex++;\r |
504 | } while (DescHeader->Signature != mAcpiVerifyTables[Index].AcpiTableSignature);\r | |
731c67e1 | 505 | \r |
5236d478 KQ |
506 | if (!EFI_ERROR (Status)) {\r |
507 | mAcpiVerifyTables[Index].Presence |= ACPI_TABLE_PRESENT_INSTALLED;\r | |
508 | }\r | |
509 | }\r | |
71f2b906 | 510 | }\r |
731c67e1 | 511 | \r |
5236d478 KQ |
512 | // Reset the return Status value to EFI_SUCCESS. We do not fully care if the table look up has failed.\r |
513 | Status = EFI_SUCCESS;\r | |
514 | for (Index = 0; Index < ACPI_TABLE_VERIFY_COUNT; Index++) {\r | |
515 | if (mAcpiVerifyTables[Index].Presence == 0) {\r | |
516 | if (mAcpiVerifyTables[Index].IsMandatory) {\r | |
517 | DEBUG ((DEBUG_ERROR, "ERROR: %a Table not found.\n", mAcpiVerifyTables[Index].AcpiTableName));\r | |
518 | Status = EFI_NOT_FOUND;\r | |
519 | } else {\r | |
520 | DEBUG ((DEBUG_WARN, "WARNING: %a Table not found.\n", mAcpiVerifyTables[Index].AcpiTableName));\r | |
521 | }\r | |
522 | } else if (mAcpiVerifyTables[Index].Presence ==\r | |
523 | (ACPI_TABLE_PRESENT_INFO_LIST | ACPI_TABLE_PRESENT_INSTALLED))\r | |
524 | {\r | |
525 | DEBUG ((DEBUG_ERROR, "ERROR: %a Table found while already published.\n", mAcpiVerifyTables[Index].AcpiTableName));\r | |
526 | Status = EFI_ALREADY_STARTED;\r | |
527 | }\r | |
71f2b906 | 528 | }\r |
731c67e1 | 529 | \r |
71f2b906 SM |
530 | return Status;\r |
531 | }\r | |
532 | \r | |
533 | /** Generate and install ACPI tables.\r | |
534 | \r | |
535 | The function gathers the information necessary for installing the\r | |
536 | ACPI tables from the Configuration Manager, invokes the generators\r | |
537 | and installs them (via BuildAndInstallAcpiTable).\r | |
538 | \r | |
539 | @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol\r | |
540 | interface.\r | |
541 | @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r | |
542 | Protocol Interface.\r | |
543 | \r | |
5236d478 KQ |
544 | @retval EFI_SUCCESS Success.\r |
545 | @retval EFI_NOT_FOUND If a mandatory table or a generator is not found.\r | |
546 | @retval EFI_ALREADY_STARTED If mandatory table found in AcpiTableInfo is already installed.\r | |
71f2b906 SM |
547 | **/\r |
548 | STATIC\r | |
549 | EFI_STATUS\r | |
550 | EFIAPI\r | |
551 | ProcessAcpiTables (\r | |
731c67e1 MK |
552 | IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol,\r |
553 | IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol\r | |
71f2b906 SM |
554 | )\r |
555 | {\r | |
731c67e1 MK |
556 | EFI_STATUS Status;\r |
557 | EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;\r | |
558 | CM_STD_OBJ_ACPI_TABLE_INFO *AcpiTableInfo;\r | |
559 | UINT32 AcpiTableCount;\r | |
560 | UINT32 Idx;\r | |
71f2b906 SM |
561 | \r |
562 | ASSERT (TableFactoryProtocol != NULL);\r | |
563 | ASSERT (CfgMgrProtocol != NULL);\r | |
564 | \r | |
565 | // Find the AcpiTable protocol\r | |
566 | Status = gBS->LocateProtocol (\r | |
567 | &gEfiAcpiTableProtocolGuid,\r | |
568 | NULL,\r | |
731c67e1 | 569 | (VOID **)&AcpiTableProtocol\r |
71f2b906 SM |
570 | );\r |
571 | if (EFI_ERROR (Status)) {\r | |
572 | DEBUG ((\r | |
573 | DEBUG_ERROR,\r | |
574 | "ERROR: Failed to find AcpiTable protocol. Status = %r\n",\r | |
575 | Status\r | |
576 | ));\r | |
577 | return Status;\r | |
578 | }\r | |
579 | \r | |
580 | Status = GetEStdObjAcpiTableList (\r | |
581 | CfgMgrProtocol,\r | |
582 | CM_NULL_TOKEN,\r | |
583 | &AcpiTableInfo,\r | |
584 | &AcpiTableCount\r | |
585 | );\r | |
586 | if (EFI_ERROR (Status)) {\r | |
587 | DEBUG ((\r | |
588 | DEBUG_ERROR,\r | |
589 | "ERROR: Failed to get ACPI Table List. Status = %r\n",\r | |
590 | Status\r | |
591 | ));\r | |
592 | return Status;\r | |
593 | }\r | |
594 | \r | |
595 | if (0 == AcpiTableCount) {\r | |
596 | DEBUG ((\r | |
597 | DEBUG_ERROR,\r | |
598 | "ERROR: EStdObjAcpiTableList: AcpiTableCount = %d\n",\r | |
599 | AcpiTableCount\r | |
600 | ));\r | |
601 | return EFI_NOT_FOUND;\r | |
602 | }\r | |
603 | \r | |
604 | DEBUG ((\r | |
605 | DEBUG_INFO,\r | |
606 | "INFO: EStdObjAcpiTableList: AcpiTableCount = %d\n",\r | |
607 | AcpiTableCount\r | |
608 | ));\r | |
609 | \r | |
610 | // Check if mandatory ACPI tables are present.\r | |
611 | Status = VerifyMandatoryTablesArePresent (\r | |
612 | AcpiTableInfo,\r | |
613 | AcpiTableCount\r | |
614 | );\r | |
615 | if (EFI_ERROR (Status)) {\r | |
616 | DEBUG ((\r | |
617 | DEBUG_ERROR,\r | |
5236d478 | 618 | "ERROR: Failed to verify mandatory ACPI Table(s) presence."\r |
71f2b906 SM |
619 | " Status = %r\n",\r |
620 | Status\r | |
621 | ));\r | |
622 | return Status;\r | |
623 | }\r | |
624 | \r | |
625 | // Add the FADT Table first.\r | |
5236d478 KQ |
626 | if ((mAcpiVerifyTables[ACPI_TABLE_VERIFY_FADT].Presence & ACPI_TABLE_PRESENT_INSTALLED) == 0) {\r |
627 | // FADT is not yet installed\r | |
628 | for (Idx = 0; Idx < AcpiTableCount; Idx++) {\r | |
629 | if (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt) ==\r | |
630 | AcpiTableInfo[Idx].TableGeneratorId)\r | |
631 | {\r | |
632 | Status = BuildAndInstallAcpiTable (\r | |
633 | TableFactoryProtocol,\r | |
634 | CfgMgrProtocol,\r | |
635 | AcpiTableProtocol,\r | |
636 | &AcpiTableInfo[Idx]\r | |
637 | );\r | |
638 | if (EFI_ERROR (Status)) {\r | |
639 | DEBUG ((\r | |
640 | DEBUG_ERROR,\r | |
641 | "ERROR: Failed to find build and install ACPI FADT Table." \\r | |
642 | " Status = %r\n",\r | |
643 | Status\r | |
644 | ));\r | |
645 | return Status;\r | |
646 | }\r | |
731c67e1 | 647 | \r |
5236d478 KQ |
648 | break;\r |
649 | }\r | |
650 | } // for\r | |
651 | }\r | |
71f2b906 SM |
652 | \r |
653 | // Add remaining ACPI Tables\r | |
654 | for (Idx = 0; Idx < AcpiTableCount; Idx++) {\r | |
655 | DEBUG ((\r | |
656 | DEBUG_INFO,\r | |
657 | "INFO: AcpiTableInfo[%d].TableGeneratorId = 0x%x\n",\r | |
658 | Idx,\r | |
659 | AcpiTableInfo[Idx].TableGeneratorId\r | |
660 | ));\r | |
661 | \r | |
662 | // Skip FADT Table since we have already added\r | |
663 | if (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt) ==\r | |
731c67e1 MK |
664 | AcpiTableInfo[Idx].TableGeneratorId)\r |
665 | {\r | |
71f2b906 SM |
666 | continue;\r |
667 | }\r | |
668 | \r | |
669 | // Skip the Reserved table Generator ID for standard generators\r | |
670 | if ((IS_GENERATOR_NAMESPACE_STD (AcpiTableInfo[Idx].TableGeneratorId)) &&\r | |
671 | ((CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdReserved) >=\r | |
731c67e1 | 672 | AcpiTableInfo[Idx].TableGeneratorId) ||\r |
71f2b906 | 673 | (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdMax) <=\r |
731c67e1 MK |
674 | AcpiTableInfo[Idx].TableGeneratorId)))\r |
675 | {\r | |
71f2b906 SM |
676 | DEBUG ((\r |
677 | DEBUG_WARN,\r | |
678 | "WARNING: Invalid ACPI Generator table ID = 0x%x, Skipping...\n",\r | |
679 | AcpiTableInfo[Idx].TableGeneratorId\r | |
680 | ));\r | |
681 | continue;\r | |
682 | }\r | |
683 | \r | |
684 | Status = BuildAndInstallAcpiTable (\r | |
685 | TableFactoryProtocol,\r | |
686 | CfgMgrProtocol,\r | |
687 | AcpiTableProtocol,\r | |
688 | &AcpiTableInfo[Idx]\r | |
689 | );\r | |
690 | if (EFI_ERROR (Status)) {\r | |
691 | DEBUG ((\r | |
692 | DEBUG_ERROR,\r | |
693 | "ERROR: Failed to find, build, and install ACPI Table." \\r | |
694 | " Status = %r\n",\r | |
695 | Status\r | |
696 | ));\r | |
697 | return Status;\r | |
698 | }\r | |
699 | } // for\r | |
700 | \r | |
701 | return Status;\r | |
702 | }\r | |
703 | \r | |
704 | /** Entrypoint of Dynamic Table Manager Dxe.\r | |
705 | \r | |
706 | The Dynamic Table Manager uses the Configuration Manager Protocol\r | |
707 | to get the list of ACPI and SMBIOS tables to install. For each table\r | |
708 | in the list it requests the corresponding ACPI/SMBIOS table factory for\r | |
709 | a generator capable of building the ACPI/SMBIOS table.\r | |
710 | If a suitable table generator is found, it invokes the generator interface\r | |
711 | to build the table. The Dynamic Table Manager then installs the\r | |
712 | table and invokes another generator interface to free any resources\r | |
713 | allocated for building the table.\r | |
714 | \r | |
715 | @param ImageHandle\r | |
716 | @param SystemTable\r | |
717 | \r | |
718 | @retval EFI_SUCCESS Success.\r | |
719 | @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r | |
720 | @retval EFI_NOT_FOUND Required interface/object was not found.\r | |
721 | @retval EFI_INVALID_PARAMETER Some parameter is incorrect/invalid.\r | |
722 | **/\r | |
723 | EFI_STATUS\r | |
724 | EFIAPI\r | |
725 | DynamicTableManagerDxeInitialize (\r | |
731c67e1 MK |
726 | IN EFI_HANDLE ImageHandle,\r |
727 | IN EFI_SYSTEM_TABLE *SystemTable\r | |
71f2b906 SM |
728 | )\r |
729 | {\r | |
731c67e1 MK |
730 | EFI_STATUS Status;\r |
731 | EDKII_CONFIGURATION_MANAGER_PROTOCOL *CfgMgrProtocol;\r | |
732 | CM_STD_OBJ_CONFIGURATION_MANAGER_INFO *CfgMfrInfo;\r | |
733 | EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *TableFactoryProtocol;\r | |
71f2b906 SM |
734 | \r |
735 | // Locate the Dynamic Table Factory\r | |
736 | Status = gBS->LocateProtocol (\r | |
737 | &gEdkiiDynamicTableFactoryProtocolGuid,\r | |
738 | NULL,\r | |
731c67e1 | 739 | (VOID **)&TableFactoryProtocol\r |
71f2b906 SM |
740 | );\r |
741 | if (EFI_ERROR (Status)) {\r | |
742 | DEBUG ((\r | |
743 | DEBUG_ERROR,\r | |
744 | "ERROR: Failed to find Dynamic Table Factory protocol." \\r | |
745 | " Status = %r\n",\r | |
746 | Status\r | |
747 | ));\r | |
748 | return Status;\r | |
749 | }\r | |
750 | \r | |
751 | // Locate the Configuration Manager for the Platform\r | |
752 | Status = gBS->LocateProtocol (\r | |
753 | &gEdkiiConfigurationManagerProtocolGuid,\r | |
754 | NULL,\r | |
731c67e1 | 755 | (VOID **)&CfgMgrProtocol\r |
71f2b906 SM |
756 | );\r |
757 | if (EFI_ERROR (Status)) {\r | |
758 | DEBUG ((\r | |
759 | DEBUG_ERROR,\r | |
760 | "ERROR: Failed to find Configuration Manager protocol. Status = %r\n",\r | |
761 | Status\r | |
762 | ));\r | |
763 | return Status;\r | |
764 | }\r | |
765 | \r | |
766 | Status = GetCgfMgrInfo (CfgMgrProtocol, &CfgMfrInfo);\r | |
767 | if (EFI_ERROR (Status)) {\r | |
768 | DEBUG ((\r | |
769 | DEBUG_ERROR,\r | |
770 | "ERROR: Failed to get Configuration Manager info. Status = %r\n",\r | |
771 | Status\r | |
772 | ));\r | |
773 | return Status;\r | |
774 | }\r | |
775 | \r | |
776 | DEBUG ((\r | |
777 | DEBUG_INFO,\r | |
778 | "INFO: Configuration Manager Version = 0x%x, OemID = %c%c%c%c%c%c\n",\r | |
779 | CfgMfrInfo->Revision,\r | |
780 | CfgMfrInfo->OemId[0],\r | |
781 | CfgMfrInfo->OemId[1],\r | |
782 | CfgMfrInfo->OemId[2],\r | |
783 | CfgMfrInfo->OemId[3],\r | |
784 | CfgMfrInfo->OemId[4],\r | |
785 | CfgMfrInfo->OemId[5]\r | |
786 | ));\r | |
787 | \r | |
788 | Status = ProcessAcpiTables (TableFactoryProtocol, CfgMgrProtocol);\r | |
789 | if (EFI_ERROR (Status)) {\r | |
790 | DEBUG ((\r | |
791 | DEBUG_ERROR,\r | |
792 | "ERROR: ACPI Table processing failure. Status = %r\n",\r | |
793 | Status\r | |
794 | ));\r | |
795 | }\r | |
731c67e1 | 796 | \r |
71f2b906 SM |
797 | return Status;\r |
798 | }\r |