]> git.proxmox.com Git - mirror_edk2.git/blame - DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600Generator.c
DynamicTablesPkg: Apply uncrustify changes
[mirror_edk2.git] / DynamicTablesPkg / Library / Acpi / Arm / AcpiSsdtCmn600LibArm / SsdtCmn600Generator.c
CommitLineData
37568365
PG
1/** @file\r
2 SSDT CMN-600 AML Table Generator.\r
3\r
1f515342 4 Copyright (c) 2020 - 2021, Arm Limited. All rights reserved.<BR>\r
37568365
PG
5\r
6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
7\r
8 @par Reference(s):\r
9 - Arm CoreLink CMN-600 Coherent Mesh Network Technical Reference Manual r3p0\r
10 - Generic ACPI for Arm Components 1.0 Platform Design Document\r
11**/\r
12\r
37568365
PG
13#include <Library/AcpiLib.h>\r
14#include <Library/BaseLib.h>\r
15#include <Library/BaseMemoryLib.h>\r
16#include <Library/DebugLib.h>\r
17#include <Library/MemoryAllocationLib.h>\r
37568365
PG
18#include <Protocol/AcpiTable.h>\r
19\r
20// Module specific include files.\r
21#include <AcpiTableGenerator.h>\r
22#include <ConfigurationManagerObject.h>\r
23#include <ConfigurationManagerHelper.h>\r
0875443f 24#include <Library/AcpiHelperLib.h>\r
37568365 25#include <Library/AmlLib/AmlLib.h>\r
37568365
PG
26#include <Protocol/ConfigurationManagerProtocol.h>\r
27#include "SsdtCmn600Generator.h"\r
28\r
29/** C array containing the compiled AML template.\r
30 This symbol is defined in the auto generated C file\r
31 containing the AML bytecode array.\r
32*/\r
33extern CHAR8 ssdtcmn600template_aml_code[];\r
34\r
35/** SSDT CMN-600 Table Generator.\r
36\r
37 Requirements:\r
38 The following Configuration Manager Object(s) are required by\r
39 this Generator:\r
40 - EArmObjCmn600Info\r
41*/\r
42\r
43/** This macro expands to a function that retrieves the CMN-600\r
44 Information from the Configuration Manager.\r
45*/\r
46GET_OBJECT_LIST (\r
47 EObjNameSpaceArm,\r
48 EArmObjCmn600Info,\r
49 CM_ARM_CMN_600_INFO\r
50 );\r
51\r
52/** Check the CMN-600 Information.\r
53\r
54 @param [in] Cmn600InfoList Array of CMN-600 information structure.\r
55 @param [in] Cmn600Count Count of CMN-600 information structure.\r
56\r
57 @retval EFI_SUCCESS The function completed successfully.\r
58 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
59**/\r
60STATIC\r
61EFI_STATUS\r
62EFIAPI\r
63ValidateCmn600Info (\r
731c67e1
MK
64 IN CONST CM_ARM_CMN_600_INFO *Cmn600InfoList,\r
65 IN CONST UINT32 Cmn600Count\r
37568365
PG
66 )\r
67{\r
731c67e1
MK
68 UINT32 Index;\r
69 UINT32 DtcIndex;\r
70 CONST CM_ARM_CMN_600_INFO *Cmn600Info;\r
71 CONST CM_ARM_GENERIC_INTERRUPT *DtcInterrupt;\r
37568365
PG
72\r
73 if ((Cmn600InfoList == NULL) ||\r
731c67e1
MK
74 (Cmn600Count == 0))\r
75 {\r
37568365
PG
76 return EFI_INVALID_PARAMETER;\r
77 }\r
78\r
79 // Validate each Cmn600Info structure.\r
80 for (Index = 0; Index < Cmn600Count; Index++) {\r
81 Cmn600Info = &Cmn600InfoList[Index];\r
82\r
83 // At least one DTC is required.\r
84 if ((Cmn600Info->DtcCount == 0) ||\r
731c67e1
MK
85 (Cmn600Info->DtcCount > MAX_DTC_COUNT))\r
86 {\r
37568365
PG
87 DEBUG ((\r
88 DEBUG_ERROR,\r
89 "ERROR: SSDT-CMN-600: Invalid DTC configuration:\n"\r
90 ));\r
91 goto error_handler;\r
92 }\r
93\r
94 // Check PERIPHBASE and ROOTNODEBASE address spaces are initialized.\r
95 if ((Cmn600Info->PeriphBaseAddress == 0) ||\r
731c67e1
MK
96 (Cmn600Info->RootNodeBaseAddress == 0))\r
97 {\r
37568365
PG
98 DEBUG ((\r
99 DEBUG_ERROR,\r
100 "ERROR: SSDT-CMN-600: Invalid PERIPHBASE or ROOTNODEBASE.\n"\r
101 ));\r
102 goto error_handler;\r
103 }\r
104\r
105 // The PERIPHBASE address must be 64MB aligned for a (X < 4) && (Y < 4)\r
106 // dimension mesh, and 256MB aligned otherwise.\r
107 // Check it is a least 64MB aligned.\r
108 if ((Cmn600Info->PeriphBaseAddress &\r
731c67e1
MK
109 (PERIPHBASE_MIN_ADDRESS_LENGTH - 1)) != 0)\r
110 {\r
37568365
PG
111 DEBUG ((\r
112 DEBUG_ERROR,\r
113 "ERROR: SSDT-CMN-600: PERIPHBASE address must be 64MB aligned.\n"\r
114 ));\r
115 goto error_handler;\r
116 }\r
117\r
118 // The PERIPHBASE address is at most 64MB for a (X < 4) && (Y < 4)\r
119 // dimension mesh, and 256MB otherwise. Check it is not more than 256MB.\r
120 if (Cmn600Info->PeriphBaseAddressLength > PERIPHBASE_MAX_ADDRESS_LENGTH) {\r
121 DEBUG ((\r
122 DEBUG_ERROR,\r
123 "ERROR: SSDT-CMN-600: PERIPHBASE address range must be < 256MB.\n"\r
124 ));\r
125 goto error_handler;\r
126 }\r
127\r
128 // Check the 16 KB alignment of the ROOTNODEBASE address.\r
129 if ((Cmn600Info->PeriphBaseAddress &\r
731c67e1
MK
130 (ROOTNODEBASE_ADDRESS_LENGTH - 1)) != 0)\r
131 {\r
37568365
PG
132 DEBUG ((\r
133 DEBUG_ERROR,\r
134 "ERROR: SSDT-CMN-600: Root base address must be 16KB aligned.\n"\r
135 ));\r
136 goto error_handler;\r
137 }\r
138\r
139 // The ROOTNODEBASE address space should be included in the PERIPHBASE\r
140 // address space.\r
141 if ((Cmn600Info->PeriphBaseAddress > Cmn600Info->RootNodeBaseAddress) ||\r
142 ((Cmn600Info->PeriphBaseAddress + Cmn600Info->PeriphBaseAddressLength) <\r
731c67e1
MK
143 (Cmn600Info->RootNodeBaseAddress + ROOTNODEBASE_ADDRESS_LENGTH)))\r
144 {\r
37568365
PG
145 DEBUG ((\r
146 DEBUG_ERROR,\r
147 "ERROR: SSDT-CMN-600:"\r
148 " ROOTNODEBASE address space not in PERIPHBASE address space.\n"\r
149 ));\r
150 goto error_handler;\r
151 }\r
152\r
153 for (DtcIndex = 0; DtcIndex < Cmn600Info->DtcCount; DtcIndex++) {\r
154 DtcInterrupt = &Cmn600Info->DtcInterrupt[DtcIndex];\r
155 if (((DtcInterrupt->Flags &\r
731c67e1
MK
156 EFI_ACPI_EXTENDED_INTERRUPT_FLAG_PRODUCER_CONSUMER_MASK) == 0))\r
157 {\r
37568365 158 DEBUG ((\r
731c67e1
MK
159 DEBUG_ERROR,\r
160 "ERROR: SSDT-CMN-600: DTC Interrupt must be consumer.\n"\r
161 ));\r
37568365
PG
162 goto error_handler;\r
163 }\r
164 } // for DTC Interrupt\r
731c67e1 165 } // for Cmn600InfoList\r
37568365
PG
166\r
167 return EFI_SUCCESS;\r
168\r
169error_handler:\r
170\r
171 DEBUG ((\r
172 DEBUG_ERROR,\r
173 "PeriphBaseAddress = 0x%llx\n"\r
174 "PeriphBaseAddressLength = 0x%llx\n"\r
175 "RootNodeBaseAddress = 0x%llx\n"\r
176 "DtcCount = %u\n",\r
177 Cmn600Info->PeriphBaseAddress,\r
178 Cmn600Info->PeriphBaseAddressLength,\r
179 Cmn600Info->RootNodeBaseAddress,\r
180 Cmn600Info->DtcCount\r
181 ));\r
182\r
731c67e1
MK
183 DEBUG_CODE_BEGIN ();\r
184 for (DtcIndex = 0; DtcIndex < Cmn600Info->DtcCount; DtcIndex++) {\r
185 DtcInterrupt = &Cmn600Info->DtcInterrupt[DtcIndex];\r
186 DEBUG ((\r
187 DEBUG_ERROR,\r
188 " DTC[%d]:\n",\r
189 DtcIndex\r
190 ));\r
191 DEBUG ((\r
192 DEBUG_ERROR,\r
193 " Interrupt = 0x%lx\n",\r
194 DtcInterrupt->Interrupt\r
195 ));\r
196 DEBUG ((\r
197 DEBUG_ERROR,\r
198 " Flags = 0x%lx\n",\r
199 DtcInterrupt->Flags\r
200 ));\r
201 } // for\r
202\r
203 DEBUG_CODE_END ();\r
37568365
PG
204\r
205 return EFI_INVALID_PARAMETER;\r
206}\r
207\r
208/** Build a SSDT table describing the CMN-600 device.\r
209\r
210 The table created by this function must be freed by FreeSsdtCmn600Table.\r
211\r
212 @param [in] Cmn600Info Pointer to a Cmn600 structure.\r
213 @param [in] Name The Name to give to the Device.\r
214 Must be a NULL-terminated ASL NameString\r
215 e.g.: "DEV0", "DV15.DEV0", etc.\r
216 @param [in] Uid UID for the CMN600 device.\r
217 @param [out] Table If success, pointer to the created SSDT table.\r
218\r
219 @retval EFI_SUCCESS Table generated successfully.\r
220 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
221 @retval EFI_NOT_FOUND Could not find information.\r
222 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.\r
223**/\r
224STATIC\r
225EFI_STATUS\r
226EFIAPI\r
227FixupCmn600Info (\r
731c67e1
MK
228 IN CONST CM_ARM_CMN_600_INFO *Cmn600Info,\r
229 IN CONST CHAR8 *Name,\r
230 IN CONST UINT64 Uid,\r
231 OUT EFI_ACPI_DESCRIPTION_HEADER **Table\r
37568365
PG
232 )\r
233{\r
731c67e1
MK
234 EFI_STATUS Status;\r
235 EFI_STATUS Status1;\r
236 UINT8 Index;\r
237 CONST CM_ARM_GENERIC_INTERRUPT *DtcInt;\r
238\r
239 EFI_ACPI_DESCRIPTION_HEADER *SsdtCmn600Template;\r
240 AML_ROOT_NODE_HANDLE RootNodeHandle;\r
241 AML_OBJECT_NODE_HANDLE NameOpIdNode;\r
242 AML_OBJECT_NODE_HANDLE NameOpCrsNode;\r
243 AML_DATA_NODE_HANDLE CmnPeriphBaseRdNode;\r
244 AML_DATA_NODE_HANDLE CmnRootNodeBaseRdNode;\r
245 AML_OBJECT_NODE_HANDLE DeviceNode;\r
37568365
PG
246\r
247 // Parse the Ssdt CMN-600 Template.\r
731c67e1
MK
248 SsdtCmn600Template = (EFI_ACPI_DESCRIPTION_HEADER *)\r
249 ssdtcmn600template_aml_code;\r
37568365
PG
250\r
251 RootNodeHandle = NULL;\r
731c67e1
MK
252 Status = AmlParseDefinitionBlock (\r
253 SsdtCmn600Template,\r
254 &RootNodeHandle\r
255 );\r
37568365
PG
256 if (EFI_ERROR (Status)) {\r
257 DEBUG ((\r
258 DEBUG_ERROR,\r
259 "ERROR: SSDT-CMN-600: Failed to parse SSDT CMN-600 Template."\r
260 " Status = %r\n",\r
261 Status\r
262 ));\r
263 return Status;\r
264 }\r
265\r
266 // Get the _UID NameOp object defined by the "Name ()" statement,\r
267 // and update its value.\r
268 Status = AmlFindNode (\r
269 RootNodeHandle,\r
270 "\\_SB_.CMN0._UID",\r
271 &NameOpIdNode\r
272 );\r
273 if (EFI_ERROR (Status)) {\r
274 goto error_handler;\r
275 }\r
276\r
277 Status = AmlNameOpUpdateInteger (NameOpIdNode, (UINT64)Uid);\r
278 if (EFI_ERROR (Status)) {\r
279 goto error_handler;\r
280 }\r
281\r
282 // Get the _CRS object defined by the "Name ()" statement.\r
283 Status = AmlFindNode (\r
284 RootNodeHandle,\r
285 "\\_SB.CMN0._CRS",\r
286 &NameOpCrsNode\r
287 );\r
288 if (EFI_ERROR (Status)) {\r
289 goto error_handler;\r
290 }\r
291\r
292 // Get the first Rd node in the "_CRS" object.\r
293 // This is the PERIPHBASE node.\r
691c5f77 294 Status = AmlNameOpGetFirstRdNode (NameOpCrsNode, &CmnPeriphBaseRdNode);\r
37568365
PG
295 if (EFI_ERROR (Status)) {\r
296 goto error_handler;\r
297 }\r
298\r
299 if (CmnPeriphBaseRdNode == NULL) {\r
300 Status = EFI_INVALID_PARAMETER;\r
301 goto error_handler;\r
302 }\r
303\r
304 // Update the PERIPHBASE base address and length.\r
305 Status = AmlUpdateRdQWord (\r
306 CmnPeriphBaseRdNode,\r
307 Cmn600Info->PeriphBaseAddress,\r
308 Cmn600Info->PeriphBaseAddressLength\r
309 );\r
310 if (EFI_ERROR (Status)) {\r
311 goto error_handler;\r
312 }\r
313\r
314 // Get the QWord node corresponding to the ROOTNODEBASE.\r
315 // It is the second Resource Data element in the BufferNode's\r
316 // variable list of arguments.\r
691c5f77 317 Status = AmlNameOpGetNextRdNode (\r
37568365
PG
318 CmnPeriphBaseRdNode,\r
319 &CmnRootNodeBaseRdNode\r
320 );\r
321 if (EFI_ERROR (Status)) {\r
322 goto error_handler;\r
323 }\r
324\r
325 if (CmnRootNodeBaseRdNode == NULL) {\r
326 Status = EFI_INVALID_PARAMETER;\r
327 goto error_handler;\r
328 }\r
329\r
330 // Update the ROOTNODEBASE base address and length.\r
331 Status = AmlUpdateRdQWord (\r
332 CmnRootNodeBaseRdNode,\r
333 Cmn600Info->RootNodeBaseAddress,\r
334 ROOTNODEBASE_ADDRESS_LENGTH\r
335 );\r
336 if (EFI_ERROR (Status)) {\r
337 goto error_handler;\r
338 }\r
339\r
340 // Add the Interrupt node(s).\r
341 // Generate Resource Data node(s) corresponding to the "Interrupt ()"\r
342 // ASL function and add it at the last position in the list of\r
343 // Resource Data nodes.\r
344 for (Index = 0; Index < Cmn600Info->DtcCount; Index++) {\r
345 DtcInt = &Cmn600Info->DtcInterrupt[Index];\r
22873f58
PG
346\r
347 Status = AmlCodeGenRdInterrupt (\r
37568365
PG
348 ((DtcInt->Flags &\r
349 EFI_ACPI_EXTENDED_INTERRUPT_FLAG_PRODUCER_CONSUMER_MASK) != 0),\r
350 ((DtcInt->Flags &\r
351 EFI_ACPI_EXTENDED_INTERRUPT_FLAG_MODE_MASK) != 0),\r
352 ((DtcInt->Flags &\r
353 EFI_ACPI_EXTENDED_INTERRUPT_FLAG_POLARITY_MASK) != 0),\r
354 ((DtcInt->Flags &\r
355 EFI_ACPI_EXTENDED_INTERRUPT_FLAG_SHARABLE_MASK) != 0),\r
731c67e1 356 (UINT32 *)&DtcInt->Interrupt,\r
22873f58
PG
357 1,\r
358 NameOpCrsNode,\r
359 NULL\r
37568365
PG
360 );\r
361 if (EFI_ERROR (Status)) {\r
362 goto error_handler;\r
363 }\r
364 } // for\r
365\r
366 // Fixup the CMN600 device name.\r
367 // This MUST be done at the end, otherwise AML paths won't be valid anymore.\r
368 // Get the CMN0 variable defined by the "Device ()" statement.\r
369 Status = AmlFindNode (RootNodeHandle, "\\_SB_.CMN0", &DeviceNode);\r
370 if (EFI_ERROR (Status)) {\r
371 goto error_handler;\r
372 }\r
373\r
374 // Update the CMN600 Device's name.\r
731c67e1 375 Status = AmlDeviceOpUpdateName (DeviceNode, (CHAR8 *)Name);\r
37568365
PG
376 if (EFI_ERROR (Status)) {\r
377 goto error_handler;\r
378 }\r
379\r
380 // Serialise the definition block\r
381 Status = AmlSerializeDefinitionBlock (\r
382 RootNodeHandle,\r
383 Table\r
384 );\r
385 if (EFI_ERROR (Status)) {\r
386 DEBUG ((\r
387 DEBUG_ERROR,\r
388 "ERROR: SSDT-CMN-600: Failed to Serialize SSDT Table Data."\r
389 " Status = %r\n",\r
390 Status\r
391 ));\r
392 }\r
393\r
394error_handler:\r
395 // Cleanup\r
396 if (RootNodeHandle != NULL) {\r
397 Status1 = AmlDeleteTree (RootNodeHandle);\r
398 if (EFI_ERROR (Status1)) {\r
399 DEBUG ((\r
400 DEBUG_ERROR,\r
401 "ERROR: SSDT-CMN-600: Failed to cleanup AML tree."\r
402 " Status = %r\n",\r
403 Status1\r
404 ));\r
405 // If Status was success but we failed to delete the AML Tree\r
406 // return Status1 else return the original error code, i.e. Status.\r
407 if (!EFI_ERROR (Status)) {\r
408 return Status1;\r
409 }\r
410 }\r
411 }\r
412\r
413 return Status;\r
414}\r
415\r
416/** Free any resources allocated for constructing the SSDT tables for CMN-600.\r
417\r
418 @param [in] This Pointer to the ACPI table generator.\r
419 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.\r
420 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
421 Protocol Interface.\r
422 @param [in, out] Table Pointer to an array of pointers\r
423 to ACPI Table(s).\r
424 @param [in] TableCount Number of ACPI table(s).\r
425\r
426 @retval EFI_SUCCESS The resources were freed successfully.\r
427 @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.\r
428**/\r
429STATIC\r
430EFI_STATUS\r
431EFIAPI\r
432FreeSsdtCmn600TableResourcesEx (\r
731c67e1
MK
433 IN CONST ACPI_TABLE_GENERATOR *CONST This,\r
434 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,\r
435 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,\r
436 IN OUT EFI_ACPI_DESCRIPTION_HEADER ***CONST Table,\r
37568365
PG
437 IN CONST UINTN TableCount\r
438 )\r
439{\r
731c67e1
MK
440 EFI_ACPI_DESCRIPTION_HEADER **TableList;\r
441 UINTN Index;\r
37568365
PG
442\r
443 ASSERT (This != NULL);\r
444 ASSERT (AcpiTableInfo != NULL);\r
445 ASSERT (CfgMgrProtocol != NULL);\r
446 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);\r
447 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);\r
448\r
449 if ((Table == NULL) ||\r
450 (*Table == NULL) ||\r
731c67e1
MK
451 (TableCount == 0))\r
452 {\r
37568365
PG
453 DEBUG ((DEBUG_ERROR, "ERROR: SSDT-CMN-600: Invalid Table Pointer\n"));\r
454 return EFI_INVALID_PARAMETER;\r
455 }\r
456\r
457 TableList = *Table;\r
458\r
459 for (Index = 0; Index < TableCount; Index++) {\r
460 if ((TableList[Index] != NULL) &&\r
461 (TableList[Index]->Signature ==\r
731c67e1
MK
462 EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE))\r
463 {\r
37568365
PG
464 FreePool (TableList[Index]);\r
465 } else {\r
466 DEBUG ((\r
467 DEBUG_ERROR,\r
468 "ERROR: SSDT-CMN-600: Could not free SSDT table at index %d."\r
469 " Status = %r\n",\r
470 Index,\r
471 EFI_INVALID_PARAMETER\r
472 ));\r
473 return EFI_INVALID_PARAMETER;\r
474 }\r
731c67e1 475 } // for\r
37568365
PG
476\r
477 // Free the table list.\r
478 FreePool (*Table);\r
479 *Table = NULL;\r
480 return EFI_SUCCESS;\r
481}\r
482\r
483/** Construct SSDT tables for describing CMN-600 meshes.\r
484\r
485 This function invokes the Configuration Manager protocol interface\r
486 to get the required hardware information for generating the ACPI\r
487 table.\r
488\r
489 If this function allocates any resources then they must be freed\r
490 in the FreeXXXXTableResourcesEx function.\r
491\r
492 @param [in] This Pointer to the ACPI table generator.\r
493 @param [in] AcpiTableInfo Pointer to the ACPI table information.\r
494 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
495 Protocol interface.\r
496 @param [out] Table Pointer to a list of generated ACPI table(s).\r
497 @param [out] TableCount Number of generated ACPI table(s).\r
498\r
499 @retval EFI_SUCCESS Table generated successfully.\r
500 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration\r
501 Manager is less than the Object size for\r
502 the requested object.\r
503 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
504 @retval EFI_NOT_FOUND Could not find information.\r
505 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.\r
506 @retval EFI_UNSUPPORTED Unsupported configuration.\r
507**/\r
508STATIC\r
509EFI_STATUS\r
510EFIAPI\r
511BuildSsdtCmn600TableEx (\r
731c67e1
MK
512 IN CONST ACPI_TABLE_GENERATOR *This,\r
513 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,\r
514 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,\r
515 OUT EFI_ACPI_DESCRIPTION_HEADER ***Table,\r
516 OUT UINTN *CONST TableCount\r
37568365
PG
517 )\r
518{\r
731c67e1
MK
519 EFI_STATUS Status;\r
520 UINT64 Index;\r
521 CM_ARM_CMN_600_INFO *Cmn600Info;\r
522 UINT32 Cmn600Count;\r
523 CHAR8 NewName[AML_NAME_SEG_SIZE + 1];\r
524 EFI_ACPI_DESCRIPTION_HEADER **TableList;\r
37568365
PG
525\r
526 ASSERT (This != NULL);\r
527 ASSERT (AcpiTableInfo != NULL);\r
528 ASSERT (CfgMgrProtocol != NULL);\r
529 ASSERT (Table != NULL);\r
530 ASSERT (TableCount != NULL);\r
531 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);\r
532 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);\r
533\r
534 *Table = NULL;\r
535\r
536 // Get CMN-600 information.\r
537 Status = GetEArmObjCmn600Info (\r
538 CfgMgrProtocol,\r
539 CM_NULL_TOKEN,\r
540 &Cmn600Info,\r
541 &Cmn600Count\r
542 );\r
543 if (EFI_ERROR (Status)) {\r
544 DEBUG ((\r
545 DEBUG_ERROR,\r
546 "ERROR: SSDT-CMN-600: Failed to get the CMN-600 information."\r
547 " Status = %r\n",\r
548 Status\r
549 ));\r
550 return Status;\r
551 }\r
552\r
553 if ((Cmn600Count == 0) || (Cmn600Count > MAX_CMN600_DEVICES_SUPPORTED)) {\r
554 DEBUG ((\r
555 DEBUG_ERROR,\r
556 "ERROR: SSDT-CMN-600: CMN600 peripheral count = %d."\r
557 " This must be between 1 to 16.\n",\r
558 Cmn600Count\r
559 ));\r
560 return EFI_INVALID_PARAMETER;\r
561 }\r
562\r
563 // Validate the CMN-600 Info.\r
564 Status = ValidateCmn600Info (Cmn600Info, Cmn600Count);\r
565 if (EFI_ERROR (Status)) {\r
566 DEBUG ((\r
567 DEBUG_ERROR,\r
568 "ERROR: SSDT-CMN-600: Invalid CMN600 information. Status = %r\n",\r
569 Status\r
570 ));\r
571 return Status;\r
572 }\r
573\r
574 // Allocate a table to store pointers to the SSDT tables.\r
731c67e1 575 TableList = (EFI_ACPI_DESCRIPTION_HEADER **)\r
37568365 576 AllocateZeroPool (\r
731c67e1 577 (sizeof (EFI_ACPI_DESCRIPTION_HEADER *) * Cmn600Count)\r
37568365
PG
578 );\r
579 if (TableList == NULL) {\r
580 Status = EFI_OUT_OF_RESOURCES;\r
581 DEBUG ((\r
582 DEBUG_ERROR,\r
583 "ERROR: SSDT-CMN-600: Failed to allocate memory for Table List."\r
584 " Status = %r\n",\r
585 Status\r
586 ));\r
587 return Status;\r
588 }\r
589\r
590 // Setup the table list early so that that appropriate cleanup\r
591 // can be done in case of failure.\r
592 *Table = TableList;\r
593\r
594 NewName[0] = 'C';\r
595 NewName[1] = 'M';\r
596 NewName[2] = 'N';\r
597 NewName[4] = '\0';\r
598 for (Index = 0; Index < Cmn600Count; Index++) {\r
599 NewName[3] = AsciiFromHex ((UINT8)(Index));\r
600\r
601 // Build a SSDT table describing the CMN600 device.\r
602 Status = FixupCmn600Info (\r
603 &Cmn600Info[Index],\r
604 NewName,\r
605 Index,\r
606 &TableList[Index]\r
607 );\r
608 if (EFI_ERROR (Status)) {\r
609 DEBUG ((\r
610 DEBUG_ERROR,\r
611 "ERROR: SSDT-CMN-600: Failed to build associated SSDT table."\r
612 " Status = %r\n",\r
613 Status\r
614 ));\r
615 break;\r
616 }\r
617\r
618 // Increment the table count here so that appropriate clean-up\r
619 // can be done in case of failure.\r
620 *TableCount += 1;\r
621 } // for\r
622\r
623 // Note: Table list and CMN600 device count has been setup. The\r
624 // framework will invoke FreeSsdtCmn600TableResourcesEx() even\r
625 // on failure, so appropriate clean-up will be done.\r
626 return Status;\r
627}\r
628\r
629/** This macro defines the Raw Generator revision.\r
630*/\r
731c67e1 631#define SSDT_CMN_600_GENERATOR_REVISION CREATE_REVISION (1, 0)\r
37568365
PG
632\r
633/** The interface for the Raw Table Generator.\r
634*/\r
635STATIC\r
636CONST\r
731c67e1 637ACPI_TABLE_GENERATOR SsdtCmn600Generator = {\r
37568365
PG
638 // Generator ID\r
639 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtCmn600),\r
640 // Generator Description\r
641 L"ACPI.STD.SSDT.CMN600.GENERATOR",\r
642 // ACPI Table Signature\r
643 EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,\r
644 // ACPI Table Revision - Unused\r
645 0,\r
646 // Minimum ACPI Table Revision - Unused\r
647 0,\r
648 // Creator ID\r
649 TABLE_GENERATOR_CREATOR_ID_ARM,\r
650 // Creator Revision\r
651 SSDT_CMN_600_GENERATOR_REVISION,\r
652 // Build table function. Use the extended version instead.\r
653 NULL,\r
654 // Free table function. Use the extended version instead.\r
655 NULL,\r
656 // Build Table function\r
657 BuildSsdtCmn600TableEx,\r
658 // Free Resource function\r
659 FreeSsdtCmn600TableResourcesEx\r
660};\r
661\r
662/** Register the Generator with the ACPI Table Factory.\r
663\r
664 @param [in] ImageHandle The handle to the image.\r
665 @param [in] SystemTable Pointer to the System Table.\r
666\r
667 @retval EFI_SUCCESS The Generator is registered.\r
668 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
669 @retval EFI_ALREADY_STARTED The Generator for the Table ID\r
670 is already registered.\r
671**/\r
672EFI_STATUS\r
673EFIAPI\r
674AcpiSsdtCmn600LibConstructor (\r
731c67e1
MK
675 IN EFI_HANDLE ImageHandle,\r
676 IN EFI_SYSTEM_TABLE *SystemTable\r
37568365
PG
677 )\r
678{\r
679 EFI_STATUS Status;\r
680\r
681 Status = RegisterAcpiTableGenerator (&SsdtCmn600Generator);\r
682 DEBUG ((\r
683 DEBUG_INFO,\r
684 "SSDT-CMN-600: Register Generator. Status = %r\n",\r
685 Status\r
686 ));\r
687 ASSERT_EFI_ERROR (Status);\r
688 return Status;\r
689}\r
690\r
691/** Deregister the Generator from the ACPI Table Factory.\r
692\r
693 @param [in] ImageHandle The handle to the image.\r
694 @param [in] SystemTable Pointer to the System Table.\r
695\r
696 @retval EFI_SUCCESS The Generator is deregistered.\r
697 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
698 @retval EFI_NOT_FOUND The Generator is not registered.\r
699**/\r
700EFI_STATUS\r
701EFIAPI\r
702AcpiSsdtCmn600LibDestructor (\r
731c67e1
MK
703 IN EFI_HANDLE ImageHandle,\r
704 IN EFI_SYSTEM_TABLE *SystemTable\r
37568365
PG
705 )\r
706{\r
707 EFI_STATUS Status;\r
708\r
709 Status = DeregisterAcpiTableGenerator (&SsdtCmn600Generator);\r
710 DEBUG ((\r
711 DEBUG_INFO,\r
712 "SSDT-CMN-600: Deregister Generator. Status = %r\n",\r
713 Status\r
714 ));\r
715 ASSERT_EFI_ERROR (Status);\r
716 return Status;\r
717}\r