]> git.proxmox.com Git - mirror_edk2.git/blame - DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c
DynamicTablesPkg: DynamicTableManagerDxe: Added check for installed tables
[mirror_edk2.git] / DynamicTablesPkg / Drivers / DynamicTableManagerDxe / DynamicTableManagerDxe.c
CommitLineData
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
50typedef 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
69ACPI_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
81GET_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
108STATIC\r
109EFI_STATUS\r
110EFIAPI\r
111BuildAndInstallSingleAcpiTable (\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
174exit_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
223STATIC\r
224EFI_STATUS\r
225EFIAPI\r
226BuildAndInstallMultipleAcpiTable (\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
294exit_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
343STATIC\r
344EFI_STATUS\r
345EFIAPI\r
346BuildAndInstallAcpiTable (\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
453STATIC\r
454EFI_STATUS\r
455EFIAPI\r
456VerifyMandatoryTablesArePresent (\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
548STATIC\r
549EFI_STATUS\r
550EFIAPI\r
551ProcessAcpiTables (\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
723EFI_STATUS\r
724EFIAPI\r
725DynamicTableManagerDxeInitialize (\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