]> git.proxmox.com Git - mirror_edk2.git/blame - DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
DynamicTablesPkg: AcpiSsdtPcieLibArm: Correct translation value
[mirror_edk2.git] / DynamicTablesPkg / Library / Acpi / Arm / AcpiSsdtPcieLibArm / SsdtPcieGenerator.c
CommitLineData
e35a746c
PG
1/** @file\r
2 SSDT Pcie Table Generator.\r
3\r
5816bd3e 4 Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.<BR>\r
e35a746c
PG
5\r
6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
7\r
8 @par Reference(s):\r
9 - PCI Firmware Specification - Revision 3.0\r
10 - ACPI 6.4 specification:\r
11 - s6.2.13 "_PRT (PCI Routing Table)"\r
12 - s6.1.1 "_ADR (Address)"\r
13 - linux kernel code\r
14 - Arm Base Boot Requirements v1.0\r
5816bd3e 15 - Arm Base System Architecture v1.0\r
e35a746c
PG
16**/\r
17\r
18#include <Library/AcpiLib.h>\r
19#include <Library/BaseLib.h>\r
20#include <Library/BaseMemoryLib.h>\r
21#include <Library/DebugLib.h>\r
22#include <Library/MemoryAllocationLib.h>\r
23#include <Protocol/AcpiTable.h>\r
24\r
25// Module specific include files.\r
26#include <AcpiTableGenerator.h>\r
27#include <ConfigurationManagerObject.h>\r
28#include <ConfigurationManagerHelper.h>\r
29#include <Library/AcpiHelperLib.h>\r
30#include <Library/TableHelperLib.h>\r
31#include <Library/AmlLib/AmlLib.h>\r
32#include <Protocol/ConfigurationManagerProtocol.h>\r
33\r
34#include "SsdtPcieGenerator.h"\r
35\r
36/** ARM standard SSDT Pcie Table Generator.\r
37\r
38Requirements:\r
39 The following Configuration Manager Object(s) are required by\r
40 this Generator:\r
41 - EArmObjCmRef\r
42 - EArmObjPciConfigSpaceInfo\r
43 - EArmObjPciAddressMapInfo\r
44 - EArmObjPciInterruptMapInfo\r
45*/\r
46\r
47/** This macro expands to a function that retrieves the cross-CM-object-\r
48 reference information from the Configuration Manager.\r
49*/\r
50GET_OBJECT_LIST (\r
51 EObjNameSpaceArm,\r
52 EArmObjCmRef,\r
53 CM_ARM_OBJ_REF\r
54 );\r
55\r
56/** This macro expands to a function that retrieves the Pci\r
57 Configuration Space Information from the Configuration Manager.\r
58*/\r
59GET_OBJECT_LIST (\r
60 EObjNameSpaceArm,\r
61 EArmObjPciConfigSpaceInfo,\r
62 CM_ARM_PCI_CONFIG_SPACE_INFO\r
63 );\r
64\r
65/** This macro expands to a function that retrieves the Pci\r
66 Address Mapping Information from the Configuration Manager.\r
67*/\r
68GET_OBJECT_LIST (\r
69 EObjNameSpaceArm,\r
70 EArmObjPciAddressMapInfo,\r
71 CM_ARM_PCI_ADDRESS_MAP_INFO\r
72 );\r
73\r
74/** This macro expands to a function that retrieves the Pci\r
75 Interrupt Mapping Information from the Configuration Manager.\r
76*/\r
77GET_OBJECT_LIST (\r
78 EObjNameSpaceArm,\r
79 EArmObjPciInterruptMapInfo,\r
80 CM_ARM_PCI_INTERRUPT_MAP_INFO\r
81 );\r
82\r
83/** Initialize the MappingTable.\r
84\r
85 @param [in] MappingTable The mapping table structure.\r
86 @param [in] Count Number of entries to allocate in the\r
87 MappingTable.\r
88\r
89 @retval EFI_SUCCESS Success.\r
90 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
91 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
92**/\r
93STATIC\r
94EFI_STATUS\r
95EFIAPI\r
96MappingTableInitialize (\r
97 IN MAPPING_TABLE *MappingTable,\r
98 IN UINT32 Count\r
99 )\r
100{\r
101 UINT32 *Table;\r
102\r
103 if ((MappingTable == NULL) ||\r
104 (Count == 0))\r
105 {\r
106 ASSERT (0);\r
107 return EFI_INVALID_PARAMETER;\r
108 }\r
109\r
110 Table = AllocateZeroPool (sizeof (*Table) * Count);\r
111 if (Table == NULL) {\r
112 ASSERT (0);\r
113 return EFI_OUT_OF_RESOURCES;\r
114 }\r
115\r
116 MappingTable->Table = Table;\r
117 MappingTable->LastIndex = 0;\r
118 MappingTable->MaxIndex = Count;\r
119\r
120 return EFI_SUCCESS;\r
121}\r
122\r
123/** Free the MappingTable.\r
124\r
125 @param [in, out] MappingTable The mapping table structure.\r
126**/\r
127STATIC\r
128VOID\r
129EFIAPI\r
130MappingTableFree (\r
131 IN OUT MAPPING_TABLE *MappingTable\r
132 )\r
133{\r
134 ASSERT (MappingTable != NULL);\r
135 ASSERT (MappingTable->Table != NULL);\r
136\r
137 if (MappingTable->Table != NULL) {\r
138 FreePool (MappingTable->Table);\r
139 }\r
140}\r
141\r
142/** Add a new entry to the MappingTable and return its index.\r
143\r
144 If an entry with [Integer] is already available in the table,\r
145 return its index without adding a new entry.\r
146\r
147 @param [in] MappingTable The mapping table structure.\r
148 @param [in] Integer New Integer entry to add.\r
149\r
150 @retval The index of the Integer entry in the MappingTable.\r
151**/\r
152STATIC\r
153UINT32\r
154EFIAPI\r
155MappingTableAdd (\r
156 IN MAPPING_TABLE *MappingTable,\r
157 IN UINT32 Integer\r
158 )\r
159{\r
160 UINT32 *Table;\r
161 UINT32 Index;\r
162 UINT32 LastIndex;\r
163\r
164 ASSERT (MappingTable != NULL);\r
165 ASSERT (MappingTable->Table != NULL);\r
166\r
167 Table = MappingTable->Table;\r
168 LastIndex = MappingTable->LastIndex;\r
169\r
170 // Search if there is already an entry with this Integer.\r
171 for (Index = 0; Index < LastIndex; Index++) {\r
172 if (Table[Index] == Integer) {\r
173 return Index;\r
174 }\r
175 }\r
176\r
177 ASSERT (LastIndex < MappingTable->MaxIndex);\r
178\r
179 // If no, create a new entry.\r
180 Table[LastIndex] = Integer;\r
181\r
182 return MappingTable->LastIndex++;\r
183}\r
184\r
185/** Generate required Pci device information.\r
186\r
187 ASL code:\r
188 Name (_UID, <Uid>) // Uid of the Pci device\r
189 Name (_HID, EISAID ("PNP0A08")) // PCI Express Root Bridge\r
190 Name (_CID, EISAID ("PNP0A03")) // Compatible PCI Root Bridge\r
191 Name (_SEG, <Pci segment group>) // PCI Segment Group number\r
192 Name (_BBN, <Bus number>) // PCI Base Bus Number\r
193 Name (_CCA, 1) // Initially mark the PCI coherent\r
194\r
195 @param [in] PciInfo Pci device information.\r
196 @param [in] Uid Unique Id of the Pci device.\r
197 @param [in, out] PciNode Pci node to amend.\r
198\r
199 @retval EFI_SUCCESS Success.\r
200 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
201 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
202**/\r
203STATIC\r
204EFI_STATUS\r
205EFIAPI\r
206GeneratePciDeviceInfo (\r
207 IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo,\r
208 IN UINT32 Uid,\r
209 IN OUT AML_OBJECT_NODE_HANDLE PciNode\r
210 )\r
211{\r
212 EFI_STATUS Status;\r
213 UINT32 EisaId;\r
214\r
215 ASSERT (PciInfo != NULL);\r
216 ASSERT (PciNode != NULL);\r
217\r
218 // ASL: Name (_UID, <Uid>)\r
219 Status = AmlCodeGenNameInteger ("_UID", Uid, PciNode, NULL);\r
220 if (EFI_ERROR (Status)) {\r
221 ASSERT (0);\r
222 return Status;\r
223 }\r
224\r
225 // ASL: Name (_HID, EISAID ("PNP0A08"))\r
226 Status = AmlGetEisaIdFromString ("PNP0A08", &EisaId);\r
227 if (EFI_ERROR (Status)) {\r
228 ASSERT (0);\r
229 return Status;\r
230 }\r
231\r
232 Status = AmlCodeGenNameInteger ("_HID", EisaId, PciNode, NULL);\r
233 if (EFI_ERROR (Status)) {\r
234 ASSERT (0);\r
235 return Status;\r
236 }\r
237\r
238 // ASL: Name (_CID, EISAID ("PNP0A03"))\r
239 Status = AmlGetEisaIdFromString ("PNP0A03", &EisaId);\r
240 if (EFI_ERROR (Status)) {\r
241 ASSERT (0);\r
242 return Status;\r
243 }\r
244\r
245 Status = AmlCodeGenNameInteger ("_CID", EisaId, PciNode, NULL);\r
246 if (EFI_ERROR (Status)) {\r
247 ASSERT (0);\r
248 return Status;\r
249 }\r
250\r
251 // ASL: Name (_SEG, <Pci segment group>)\r
252 Status = AmlCodeGenNameInteger (\r
253 "_SEG",\r
254 PciInfo->PciSegmentGroupNumber,\r
255 PciNode,\r
256 NULL\r
257 );\r
258 if (EFI_ERROR (Status)) {\r
259 ASSERT (0);\r
260 return Status;\r
261 }\r
262\r
263 // ASL: Name (_BBN, <Bus number>)\r
264 Status = AmlCodeGenNameInteger (\r
265 "_BBN",\r
266 PciInfo->StartBusNumber,\r
267 PciNode,\r
268 NULL\r
269 );\r
270 if (EFI_ERROR (Status)) {\r
271 ASSERT (0);\r
272 return Status;\r
273 }\r
274\r
275 // ASL: Name (_CCA, 1)\r
276 // Must be aligned with the IORT CCA property in\r
277 // "Table 14 Memory access properties"\r
278 Status = AmlCodeGenNameInteger ("_CCA", 1, PciNode, NULL);\r
279 ASSERT_EFI_ERROR (Status);\r
280 return Status;\r
281}\r
282\r
e35a746c
PG
283/** Generate Pci slots devices.\r
284\r
285 PCI Firmware Specification - Revision 3.3,\r
286 s4.8 "Generic ACPI PCI Slot Description" requests to describe the PCI slot\r
287 used. It should be possible to enumerate them, but this is additional\r
288 information.\r
289\r
290 @param [in] MappingTable The mapping table structure.\r
291 @param [in, out] PciNode Pci node to amend.\r
292\r
293 @retval EFI_SUCCESS Success.\r
294 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
295 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
296**/\r
297STATIC\r
298EFI_STATUS\r
299EFIAPI\r
300GeneratePciSlots (\r
301 IN CONST MAPPING_TABLE *MappingTable,\r
302 IN OUT AML_OBJECT_NODE_HANDLE PciNode\r
303 )\r
304{\r
305 EFI_STATUS Status;\r
306 UINT32 Index;\r
307 UINT32 LastIndex;\r
308 UINT32 DeviceId;\r
309 CHAR8 AslName[AML_NAME_SEG_SIZE + 1];\r
310 AML_OBJECT_NODE_HANDLE DeviceNode;\r
311\r
312 ASSERT (MappingTable != NULL);\r
313 ASSERT (PciNode != NULL);\r
314\r
315 // Generic device name is "Dxx".\r
316 CopyMem (AslName, "Dxx_", AML_NAME_SEG_SIZE + 1);\r
317\r
318 LastIndex = MappingTable->LastIndex;\r
319\r
320 // There are at most 32 devices on a Pci bus.\r
321 if (LastIndex >= 32) {\r
322 ASSERT (0);\r
323 return EFI_INVALID_PARAMETER;\r
324 }\r
325\r
326 for (Index = 0; Index < LastIndex; Index++) {\r
327 DeviceId = MappingTable->Table[Index];\r
328 AslName[AML_NAME_SEG_SIZE - 3] = AsciiFromHex (DeviceId & 0xF);\r
329 AslName[AML_NAME_SEG_SIZE - 2] = AsciiFromHex ((DeviceId >> 4) & 0xF);\r
330\r
331 // ASL:\r
332 // Device (Dxx) {\r
333 // Name (_ADR, <address value>)\r
334 // }\r
335 Status = AmlCodeGenDevice (AslName, PciNode, &DeviceNode);\r
336 if (EFI_ERROR (Status)) {\r
337 ASSERT (0);\r
338 return Status;\r
339 }\r
340\r
341 /* ACPI 6.4 specification, Table 6.2: "ADR Object Address Encodings"\r
342 High word-Device #, Low word-Function #. (for example, device 3,\r
343 function 2 is 0x00030002). To refer to all the functions on a device #,\r
344 use a function number of FFFF).\r
345 */\r
346 Status = AmlCodeGenNameInteger (\r
347 "_ADR",\r
348 (DeviceId << 16) | 0xFFFF,\r
349 DeviceNode,\r
350 NULL\r
351 );\r
352 if (EFI_ERROR (Status)) {\r
353 ASSERT (0);\r
354 return Status;\r
355 }\r
356\r
357 // _SUN object is not generated as we don't know which slot will be used.\r
358 }\r
359\r
360 return Status;\r
361}\r
362\r
363/** Generate a _PRT object (Pci Routing Table) for the Pci device.\r
364\r
365 Cf. ACPI 6.4 specification, s6.2.13 "_PRT (PCI Routing Table)"\r
366\r
367 The first model (defining a _CRS object) is used. This is necessary because\r
368 PCI legacy interrupts are active low and GICv2 SPI interrupts are active\r
369 high.\r
370 Even though PCI interrupts cannot be re-routed, only the first model allows\r
371 to specify the activation state (low/high).\r
372\r
373 @param [in] Generator The SSDT Pci generator.\r
374 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
375 Protocol interface.\r
376 @param [in] PciInfo Pci device information.\r
377 @param [in, out] PciNode Pci node to amend.\r
378\r
379 @retval EFI_SUCCESS The function completed successfully.\r
380 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
381 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.\r
382**/\r
383STATIC\r
384EFI_STATUS\r
385EFIAPI\r
386GeneratePrt (\r
387 IN ACPI_PCI_GENERATOR *Generator,\r
388 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,\r
389 IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo,\r
390 IN OUT AML_OBJECT_NODE_HANDLE PciNode\r
391 )\r
392{\r
393 EFI_STATUS Status;\r
394 INT32 Index;\r
e35a746c 395 AML_OBJECT_NODE_HANDLE PrtNode;\r
e35a746c
PG
396 CM_ARM_OBJ_REF *RefInfo;\r
397 UINT32 RefCount;\r
398 CM_ARM_PCI_INTERRUPT_MAP_INFO *IrqMapInfo;\r
e35a746c
PG
399\r
400 ASSERT (Generator != NULL);\r
401 ASSERT (CfgMgrProtocol != NULL);\r
402 ASSERT (PciInfo != NULL);\r
403 ASSERT (PciNode != NULL);\r
404\r
405 PrtNode = NULL;\r
406\r
407 // Get the array of CM_ARM_OBJ_REF referencing the\r
408 // CM_ARM_PCI_INTERRUPT_MAP_INFO objects.\r
409 Status = GetEArmObjCmRef (\r
410 CfgMgrProtocol,\r
411 PciInfo->InterruptMapToken,\r
412 &RefInfo,\r
413 &RefCount\r
414 );\r
415 if (EFI_ERROR (Status)) {\r
416 ASSERT (0);\r
417 return Status;\r
418 }\r
419\r
e35a746c
PG
420 // Initialized DeviceTable.\r
421 Status = MappingTableInitialize (&Generator->DeviceTable, RefCount);\r
422 if (EFI_ERROR (Status)) {\r
423 ASSERT (0);\r
424 goto exit_handler0;\r
425 }\r
426\r
427 // ASL: Name (_PRT, Package () {})\r
428 Status = AmlCodeGenNamePackage ("_PRT", NULL, &PrtNode);\r
429 if (EFI_ERROR (Status)) {\r
430 ASSERT (0);\r
431 goto exit_handler;\r
432 }\r
433\r
e35a746c
PG
434 for (Index = 0; Index < RefCount; Index++) {\r
435 // Get CM_ARM_PCI_INTERRUPT_MAP_INFO structures one by one.\r
436 Status = GetEArmObjPciInterruptMapInfo (\r
437 CfgMgrProtocol,\r
438 RefInfo[Index].ReferenceToken,\r
439 &IrqMapInfo,\r
440 NULL\r
441 );\r
442 if (EFI_ERROR (Status)) {\r
443 ASSERT (0);\r
444 goto exit_handler;\r
445 }\r
446\r
5816bd3e
PG
447 // Check that the interrupts flags are SPIs, level high.\r
448 // Cf. Arm BSA v1.0, sE.6 "Legacy interrupts"\r
449 if ((Index > 0) &&\r
450 (IrqMapInfo->IntcInterrupt.Interrupt >= 32) &&\r
451 (IrqMapInfo->IntcInterrupt.Interrupt < 1020) &&\r
fc4a132c 452 ((IrqMapInfo->IntcInterrupt.Flags & 0xB) != 0))\r
5816bd3e 453 {\r
e35a746c 454 Status = EFI_INVALID_PARAMETER;\r
5816bd3e 455 ASSERT_EFI_ERROR (Status);\r
e35a746c
PG
456 goto exit_handler;\r
457 }\r
458\r
459 // Add the device to the DeviceTable.\r
460 MappingTableAdd (&Generator->DeviceTable, IrqMapInfo->PciDevice);\r
461\r
462 /* Add a _PRT entry.\r
463 ASL\r
464 Name (_PRT, Package () {\r
465 <OldPrtEntries>,\r
466 <NewPrtEntry>\r
467 })\r
468\r
469 Address is set as:\r
470 ACPI 6.4 specification, Table 6.2: "ADR Object Address Encodings"\r
471 High word-Device #, Low word-Function #. (for example, device 3,\r
472 function 2 is 0x00030002). To refer to all the functions on a device #,\r
473 use a function number of FFFF).\r
474 */\r
475 Status = AmlAddPrtEntry (\r
476 (IrqMapInfo->PciDevice << 16) | 0xFFFF,\r
477 IrqMapInfo->PciInterrupt,\r
5816bd3e
PG
478 NULL,\r
479 IrqMapInfo->IntcInterrupt.Interrupt,\r
e35a746c
PG
480 PrtNode\r
481 );\r
482 if (EFI_ERROR (Status)) {\r
483 ASSERT (0);\r
484 goto exit_handler;\r
485 }\r
486 } // for\r
487\r
5816bd3e 488 // Attach the _PRT entry.\r
e35a746c
PG
489 Status = AmlAttachNode (PciNode, PrtNode);\r
490 if (EFI_ERROR (Status)) {\r
5816bd3e 491 ASSERT_EFI_ERROR (Status);\r
e35a746c
PG
492 goto exit_handler;\r
493 }\r
494\r
495 PrtNode = NULL;\r
496\r
497 // Generate the Pci slots once all the device have been added.\r
498 Status = GeneratePciSlots (&Generator->DeviceTable, PciNode);\r
499 if (EFI_ERROR (Status)) {\r
500 ASSERT (0);\r
501 goto exit_handler;\r
502 }\r
503\r
504exit_handler:\r
505 MappingTableFree (&Generator->DeviceTable);\r
506exit_handler0:\r
e35a746c
PG
507 if (PrtNode != NULL) {\r
508 AmlDeleteTree (PrtNode);\r
509 }\r
510\r
511 return Status;\r
512}\r
513\r
514/** Generate a _CRS method for the Pci device.\r
515\r
516 @param [in] Generator The SSDT Pci generator.\r
517 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
518 Protocol interface.\r
519 @param [in] PciInfo Pci device information.\r
520 @param [in, out] PciNode Pci node to amend.\r
521\r
522 @retval EFI_SUCCESS The function completed successfully.\r
523 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
524 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.\r
525**/\r
526STATIC\r
527EFI_STATUS\r
528EFIAPI\r
529GeneratePciCrs (\r
530 IN ACPI_PCI_GENERATOR *Generator,\r
531 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,\r
532 IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo,\r
533 IN OUT AML_OBJECT_NODE_HANDLE PciNode\r
534 )\r
535{\r
536 EFI_STATUS Status;\r
537 BOOLEAN Translation;\r
538 UINT32 Index;\r
539 CM_ARM_OBJ_REF *RefInfo;\r
540 UINT32 RefCount;\r
541 CM_ARM_PCI_ADDRESS_MAP_INFO *AddrMapInfo;\r
542 AML_OBJECT_NODE_HANDLE CrsNode;\r
6cda306d 543 BOOLEAN IsPosDecode;\r
e35a746c
PG
544\r
545 ASSERT (Generator != NULL);\r
546 ASSERT (CfgMgrProtocol != NULL);\r
547 ASSERT (PciInfo != NULL);\r
548 ASSERT (PciNode != NULL);\r
549\r
550 // ASL: Name (_CRS, ResourceTemplate () {})\r
551 Status = AmlCodeGenNameResourceTemplate ("_CRS", PciNode, &CrsNode);\r
552 if (EFI_ERROR (Status)) {\r
553 ASSERT (0);\r
554 return Status;\r
555 }\r
556\r
557 // ASL:\r
558 // WordBusNumber ( // Bus numbers assigned to this root\r
559 // ResourceProducer, MinFixed, MaxFixed, PosDecode,\r
560 // 0, // AddressGranularity\r
561 // <Start>, // AddressMinimum - Minimum Bus Number\r
562 // <End>, // AddressMaximum - Maximum Bus Number\r
563 // 0, // AddressTranslation - Set to 0\r
564 // <End> - <Start> + 1 // RangeLength - Number of Busses\r
565 // )\r
566 Status = AmlCodeGenRdWordBusNumber (\r
567 FALSE,\r
568 TRUE,\r
569 TRUE,\r
570 TRUE,\r
571 0,\r
572 PciInfo->StartBusNumber,\r
573 PciInfo->EndBusNumber,\r
574 0,\r
575 PciInfo->EndBusNumber - PciInfo->StartBusNumber + 1,\r
576 0,\r
577 NULL,\r
578 CrsNode,\r
579 NULL\r
580 );\r
581 if (EFI_ERROR (Status)) {\r
582 ASSERT (0);\r
583 return Status;\r
584 }\r
585\r
586 // Get the array of CM_ARM_OBJ_REF referencing the\r
587 // CM_ARM_PCI_ADDRESS_MAP_INFO objects.\r
588 Status = GetEArmObjCmRef (\r
589 CfgMgrProtocol,\r
590 PciInfo->AddressMapToken,\r
591 &RefInfo,\r
592 &RefCount\r
593 );\r
594 if (EFI_ERROR (Status)) {\r
595 ASSERT (0);\r
596 return Status;\r
597 }\r
598\r
599 for (Index = 0; Index < RefCount; Index++) {\r
600 // Get CM_ARM_PCI_ADDRESS_MAP_INFO structures one by one.\r
601 Status = GetEArmObjPciAddressMapInfo (\r
602 CfgMgrProtocol,\r
603 RefInfo[Index].ReferenceToken,\r
604 &AddrMapInfo,\r
605 NULL\r
606 );\r
607 if (EFI_ERROR (Status)) {\r
608 ASSERT (0);\r
609 return Status;\r
610 }\r
611\r
612 Translation = (AddrMapInfo->CpuAddress != AddrMapInfo->PciAddress);\r
6cda306d
JB
613 if (AddrMapInfo->CpuAddress >= AddrMapInfo->PciAddress) {\r
614 IsPosDecode = TRUE;\r
615 } else {\r
616 IsPosDecode = FALSE;\r
617 }\r
e35a746c
PG
618\r
619 switch (AddrMapInfo->SpaceCode) {\r
620 case PCI_SS_IO:\r
621 Status = AmlCodeGenRdDWordIo (\r
622 FALSE,\r
623 TRUE,\r
624 TRUE,\r
6cda306d 625 IsPosDecode,\r
e35a746c
PG
626 3,\r
627 0,\r
628 AddrMapInfo->PciAddress,\r
629 AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,\r
6cda306d 630 Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0,\r
e35a746c
PG
631 AddrMapInfo->AddressSize,\r
632 0,\r
633 NULL,\r
634 TRUE,\r
635 FALSE,\r
636 CrsNode,\r
637 NULL\r
638 );\r
639 break;\r
640\r
641 case PCI_SS_M32:\r
642 Status = AmlCodeGenRdDWordMemory (\r
643 FALSE,\r
6cda306d 644 IsPosDecode,\r
e35a746c
PG
645 TRUE,\r
646 TRUE,\r
647 TRUE,\r
648 TRUE,\r
649 0,\r
650 AddrMapInfo->PciAddress,\r
651 AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,\r
6cda306d 652 Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0,\r
e35a746c
PG
653 AddrMapInfo->AddressSize,\r
654 0,\r
655 NULL,\r
656 0,\r
657 TRUE,\r
658 CrsNode,\r
659 NULL\r
660 );\r
661 break;\r
662\r
663 case PCI_SS_M64:\r
664 Status = AmlCodeGenRdQWordMemory (\r
665 FALSE,\r
6cda306d 666 IsPosDecode,\r
e35a746c
PG
667 TRUE,\r
668 TRUE,\r
669 TRUE,\r
670 TRUE,\r
671 0,\r
672 AddrMapInfo->PciAddress,\r
673 AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,\r
6cda306d 674 Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0,\r
e35a746c
PG
675 AddrMapInfo->AddressSize,\r
676 0,\r
677 NULL,\r
678 0,\r
679 TRUE,\r
680 CrsNode,\r
681 NULL\r
682 );\r
683 break;\r
684\r
685 default:\r
686 Status = EFI_INVALID_PARAMETER;\r
687 } // switch\r
688\r
689 if (EFI_ERROR (Status)) {\r
690 ASSERT (0);\r
691 return Status;\r
692 }\r
693 } // for\r
694\r
695 return Status;\r
696}\r
697\r
698/** Add an _OSC template method to the PciNode.\r
699\r
700 The _OSC method is provided as an AML blob. The blob is\r
701 parsed and attached at the end of the PciNode list of variable elements.\r
702\r
703 @param [in, out] PciNode Pci node to amend.\r
704\r
705 @retval EFI_SUCCESS The function completed successfully.\r
706 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
707 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.\r
708**/\r
709STATIC\r
710EFI_STATUS\r
711EFIAPI\r
712AddOscMethod (\r
713 IN OUT AML_OBJECT_NODE_HANDLE PciNode\r
714 )\r
715{\r
716 EFI_STATUS Status;\r
717 EFI_STATUS Status1;\r
718 EFI_ACPI_DESCRIPTION_HEADER *SsdtPcieOscTemplate;\r
719 AML_ROOT_NODE_HANDLE OscTemplateRoot;\r
720 AML_OBJECT_NODE_HANDLE OscNode;\r
721\r
722 ASSERT (PciNode != NULL);\r
723\r
724 // Parse the Ssdt Pci Osc Template.\r
725 SsdtPcieOscTemplate = (EFI_ACPI_DESCRIPTION_HEADER *)\r
726 ssdtpcieosctemplate_aml_code;\r
727\r
728 OscNode = NULL;\r
729 OscTemplateRoot = NULL;\r
730 Status = AmlParseDefinitionBlock (\r
731 SsdtPcieOscTemplate,\r
732 &OscTemplateRoot\r
733 );\r
734 if (EFI_ERROR (Status)) {\r
735 DEBUG ((\r
736 DEBUG_ERROR,\r
737 "ERROR: SSDT-PCI-OSC: Failed to parse SSDT PCI OSC Template."\r
738 " Status = %r\n",\r
739 Status\r
740 ));\r
741 return Status;\r
742 }\r
743\r
744 Status = AmlFindNode (OscTemplateRoot, "\\_OSC", &OscNode);\r
745 if (EFI_ERROR (Status)) {\r
746 goto error_handler;\r
747 }\r
748\r
749 Status = AmlDetachNode (OscNode);\r
750 if (EFI_ERROR (Status)) {\r
751 goto error_handler;\r
752 }\r
753\r
754 Status = AmlAttachNode (PciNode, OscNode);\r
755 if (EFI_ERROR (Status)) {\r
756 // Free the detached node.\r
757 AmlDeleteTree (OscNode);\r
758 goto error_handler;\r
759 }\r
760\r
761error_handler:\r
762 // Cleanup\r
763 Status1 = AmlDeleteTree (OscTemplateRoot);\r
764 if (EFI_ERROR (Status1)) {\r
765 DEBUG ((\r
766 DEBUG_ERROR,\r
767 "ERROR: SSDT-PCI-OSC: Failed to cleanup AML tree."\r
768 " Status = %r\n",\r
769 Status1\r
770 ));\r
771 // If Status was success but we failed to delete the AML Tree\r
772 // return Status1 else return the original error code, i.e. Status.\r
773 if (!EFI_ERROR (Status)) {\r
774 return Status1;\r
775 }\r
776 }\r
777\r
778 return Status;\r
779}\r
780\r
781/** Generate a Pci device.\r
782\r
783 @param [in] Generator The SSDT Pci generator.\r
784 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
785 Protocol interface.\r
786 @param [in] PciInfo Pci device information.\r
787 @param [in] Uid Unique Id of the Pci device.\r
788 @param [in, out] RootNode RootNode of the AML tree to populate.\r
789\r
790 @retval EFI_SUCCESS The function completed successfully.\r
791 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
792 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.\r
793**/\r
794STATIC\r
795EFI_STATUS\r
796EFIAPI\r
797GeneratePciDevice (\r
798 IN ACPI_PCI_GENERATOR *Generator,\r
799 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,\r
800 IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo,\r
801 IN UINT32 Uid,\r
802 IN OUT AML_ROOT_NODE_HANDLE *RootNode\r
803 )\r
804{\r
805 EFI_STATUS Status;\r
806\r
807 CHAR8 AslName[AML_NAME_SEG_SIZE + 1];\r
808 AML_OBJECT_NODE_HANDLE ScopeNode;\r
809 AML_OBJECT_NODE_HANDLE PciNode;\r
810\r
811 ASSERT (Generator != NULL);\r
812 ASSERT (CfgMgrProtocol != NULL);\r
813 ASSERT (PciInfo != NULL);\r
814 ASSERT (RootNode != NULL);\r
815\r
816 PciNode = NULL;\r
817\r
818 // ASL: Scope (\_SB) {}\r
819 Status = AmlCodeGenScope (SB_SCOPE, RootNode, &ScopeNode);\r
820 if (EFI_ERROR (Status)) {\r
821 ASSERT (0);\r
822 return Status;\r
823 }\r
824\r
825 // Write the name of the PCI device.\r
826 CopyMem (AslName, "PCIx", AML_NAME_SEG_SIZE + 1);\r
827 AslName[AML_NAME_SEG_SIZE - 1] = AsciiFromHex (Uid);\r
828\r
829 // ASL: Device (PCIx) {}\r
830 Status = AmlCodeGenDevice (AslName, ScopeNode, &PciNode);\r
831 if (EFI_ERROR (Status)) {\r
832 ASSERT (0);\r
833 return Status;\r
834 }\r
835\r
836 // Populate the PCIx node with some Id values.\r
837 Status = GeneratePciDeviceInfo (PciInfo, Uid, PciNode);\r
838 if (EFI_ERROR (Status)) {\r
839 ASSERT (0);\r
840 return Status;\r
841 }\r
842\r
843 // Generate the Pci Routing Table (_PRT).\r
844 if (PciInfo->InterruptMapToken != CM_NULL_TOKEN) {\r
845 Status = GeneratePrt (\r
846 Generator,\r
847 CfgMgrProtocol,\r
848 PciInfo,\r
849 PciNode\r
850 );\r
851 if (EFI_ERROR (Status)) {\r
852 ASSERT (0);\r
853 return Status;\r
854 }\r
855 }\r
856\r
857 // Generate the _CRS method.\r
858 Status = GeneratePciCrs (Generator, CfgMgrProtocol, PciInfo, PciNode);\r
859 if (EFI_ERROR (Status)) {\r
860 ASSERT (0);\r
861 return Status;\r
862 }\r
863\r
864 // Add the template _OSC method.\r
865 Status = AddOscMethod (PciNode);\r
866 ASSERT_EFI_ERROR (Status);\r
867 return Status;\r
868}\r
869\r
870/** Build an Ssdt table describing a Pci device.\r
871\r
872 @param [in] Generator The SSDT Pci generator.\r
873 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
874 Protocol interface.\r
875 @param [in] AcpiTableInfo Pointer to the ACPI table information.\r
876 @param [in] PciInfo Pci device information.\r
877 @param [in] Uid Unique Id of the Pci device.\r
878 @param [out] Table If success, contains the created SSDT table.\r
879\r
880 @retval EFI_SUCCESS The function completed successfully.\r
881 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
882 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.\r
883**/\r
884STATIC\r
885EFI_STATUS\r
886EFIAPI\r
887BuildSsdtPciTable (\r
888 IN ACPI_PCI_GENERATOR *Generator,\r
889 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,\r
890 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,\r
891 IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo,\r
892 IN UINT32 Uid,\r
893 OUT EFI_ACPI_DESCRIPTION_HEADER **Table\r
894 )\r
895{\r
896 EFI_STATUS Status;\r
897 EFI_STATUS Status1;\r
898 AML_ROOT_NODE_HANDLE RootNode;\r
899\r
900 ASSERT (Generator != NULL);\r
901 ASSERT (CfgMgrProtocol != NULL);\r
902 ASSERT (PciInfo != NULL);\r
903 ASSERT (Table != NULL);\r
904\r
905 // Create a new Ssdt table.\r
906 Status = AddSsdtAcpiHeader (\r
907 CfgMgrProtocol,\r
908 &Generator->Header,\r
909 AcpiTableInfo,\r
910 &RootNode\r
911 );\r
912 if (EFI_ERROR (Status)) {\r
913 ASSERT (0);\r
914 return Status;\r
915 }\r
916\r
917 Status = GeneratePciDevice (\r
918 Generator,\r
919 CfgMgrProtocol,\r
920 PciInfo,\r
921 Uid,\r
922 RootNode\r
923 );\r
924 if (EFI_ERROR (Status)) {\r
925 ASSERT (0);\r
926 goto exit_handler;\r
927 }\r
928\r
929 // Serialize the tree.\r
930 Status = AmlSerializeDefinitionBlock (\r
931 RootNode,\r
932 Table\r
933 );\r
934 if (EFI_ERROR (Status)) {\r
935 DEBUG ((\r
936 DEBUG_ERROR,\r
937 "ERROR: SSDT-PCI: Failed to Serialize SSDT Table Data."\r
938 " Status = %r\n",\r
939 Status\r
940 ));\r
941 }\r
942\r
943exit_handler:\r
944 // Cleanup\r
945 Status1 = AmlDeleteTree (RootNode);\r
946 if (EFI_ERROR (Status1)) {\r
947 DEBUG ((\r
948 DEBUG_ERROR,\r
949 "ERROR: SSDT-PCI: Failed to cleanup AML tree."\r
950 " Status = %r\n",\r
951 Status1\r
952 ));\r
953 // If Status was success but we failed to delete the AML Tree\r
954 // return Status1 else return the original error code, i.e. Status.\r
955 if (!EFI_ERROR (Status)) {\r
956 return Status1;\r
957 }\r
958 }\r
959\r
960 return Status;\r
961}\r
962\r
963/** Construct SSDT tables describing Pci root complexes.\r
964\r
965 This function invokes the Configuration Manager protocol interface\r
966 to get the required hardware information for generating the ACPI\r
967 table.\r
968\r
969 If this function allocates any resources then they must be freed\r
970 in the FreeXXXXTableResourcesEx function.\r
971\r
972 @param [in] This Pointer to the ACPI table generator.\r
973 @param [in] AcpiTableInfo Pointer to the ACPI table information.\r
974 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
975 Protocol interface.\r
976 @param [out] Table Pointer to a list of generated ACPI table(s).\r
977 @param [out] TableCount Number of generated ACPI table(s).\r
978\r
979 @retval EFI_SUCCESS Table generated successfully.\r
980 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration\r
981 Manager is less than the Object size for\r
982 the requested object.\r
983 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
984 @retval EFI_NOT_FOUND Could not find information.\r
985 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.\r
986 @retval EFI_UNSUPPORTED Unsupported configuration.\r
987**/\r
988STATIC\r
989EFI_STATUS\r
990EFIAPI\r
991BuildSsdtPciTableEx (\r
992 IN CONST ACPI_TABLE_GENERATOR *This,\r
993 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,\r
994 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,\r
995 OUT EFI_ACPI_DESCRIPTION_HEADER ***Table,\r
996 OUT UINTN *CONST TableCount\r
997 )\r
998{\r
999 EFI_STATUS Status;\r
1000 CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo;\r
1001 UINT32 PciCount;\r
1002 UINTN Index;\r
1003 EFI_ACPI_DESCRIPTION_HEADER **TableList;\r
1004 ACPI_PCI_GENERATOR *Generator;\r
1005\r
1006 ASSERT (This != NULL);\r
1007 ASSERT (AcpiTableInfo != NULL);\r
1008 ASSERT (CfgMgrProtocol != NULL);\r
1009 ASSERT (Table != NULL);\r
1010 ASSERT (TableCount != NULL);\r
1011 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);\r
1012 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);\r
1013\r
1014 *TableCount = 0;\r
1015 Generator = (ACPI_PCI_GENERATOR *)This;\r
1016\r
1017 Status = GetEArmObjPciConfigSpaceInfo (\r
1018 CfgMgrProtocol,\r
1019 CM_NULL_TOKEN,\r
1020 &PciInfo,\r
1021 &PciCount\r
1022 );\r
1023 if (EFI_ERROR (Status)) {\r
1024 ASSERT (0);\r
1025 return Status;\r
1026 }\r
1027\r
1028 if (PciCount > MAX_PCI_ROOT_COMPLEXES_SUPPORTED) {\r
1029 DEBUG ((\r
1030 DEBUG_ERROR,\r
1031 "ERROR: SSDT-PCI: Too many Pci root complexes: %d."\r
1032 " Maximum Pci root complexes supported = %d.\n",\r
1033 PciCount,\r
1034 MAX_PCI_ROOT_COMPLEXES_SUPPORTED\r
1035 ));\r
1036 return EFI_INVALID_PARAMETER;\r
1037 }\r
1038\r
1039 // Allocate a table to store pointers to the SSDT tables.\r
1040 TableList = (EFI_ACPI_DESCRIPTION_HEADER **)\r
1041 AllocateZeroPool (\r
1042 (sizeof (EFI_ACPI_DESCRIPTION_HEADER *) * PciCount)\r
1043 );\r
1044 if (TableList == NULL) {\r
1045 Status = EFI_OUT_OF_RESOURCES;\r
1046 DEBUG ((\r
1047 DEBUG_ERROR,\r
1048 "ERROR: SSDT-PCI: Failed to allocate memory for Table List."\r
1049 " Status = %r\n",\r
1050 Status\r
1051 ));\r
1052 return Status;\r
1053 }\r
1054\r
1055 // Setup the table list early so that appropriate cleanup\r
1056 // can be done in case of failure.\r
1057 *Table = TableList;\r
1058\r
1059 for (Index = 0; Index < PciCount; Index++) {\r
1060 // Build a SSDT table describing the Pci devices.\r
1061 Status = BuildSsdtPciTable (\r
1062 Generator,\r
1063 CfgMgrProtocol,\r
1064 AcpiTableInfo,\r
1065 &PciInfo[Index],\r
1066 Index,\r
1067 &TableList[Index]\r
1068 );\r
1069 if (EFI_ERROR (Status)) {\r
1070 DEBUG ((\r
1071 DEBUG_ERROR,\r
1072 "ERROR: SSDT-PCI: Failed to build associated SSDT table."\r
1073 " Status = %r\n",\r
1074 Status\r
1075 ));\r
1076 goto error_handler;\r
1077 }\r
1078\r
1079 *TableCount += 1;\r
1080 } // for\r
1081\r
1082error_handler:\r
1083 // Note: Table list and Table count have been setup. The\r
1084 // error handler does nothing here as the framework will invoke\r
1085 // FreeSsdtPciTableEx () even on failure.\r
1086 return Status;\r
1087}\r
1088\r
1089/** Free any resources allocated for constructing the tables.\r
1090\r
1091 @param [in] This Pointer to the ACPI table generator.\r
1092 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.\r
1093 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
1094 Protocol Interface.\r
1095 @param [in, out] Table Pointer to an array of pointers\r
1096 to ACPI Table(s).\r
1097 @param [in] TableCount Number of ACPI table(s).\r
1098\r
1099 @retval EFI_SUCCESS The resources were freed successfully.\r
1100 @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.\r
1101**/\r
1102STATIC\r
1103EFI_STATUS\r
1104EFIAPI\r
1105FreeSsdtPciTableEx (\r
1106 IN CONST ACPI_TABLE_GENERATOR *CONST This,\r
1107 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,\r
1108 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,\r
1109 IN OUT EFI_ACPI_DESCRIPTION_HEADER ***CONST Table,\r
1110 IN CONST UINTN TableCount\r
1111 )\r
1112{\r
1113 EFI_ACPI_DESCRIPTION_HEADER **TableList;\r
1114 UINTN Index;\r
1115\r
1116 ASSERT (This != NULL);\r
1117 ASSERT (AcpiTableInfo != NULL);\r
1118 ASSERT (CfgMgrProtocol != NULL);\r
1119 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);\r
1120 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);\r
1121\r
1122 if ((Table == NULL) ||\r
1123 (*Table == NULL) ||\r
1124 (TableCount == 0))\r
1125 {\r
1126 DEBUG ((DEBUG_ERROR, "ERROR: SSDT-PCI: Invalid Table Pointer\n"));\r
1127 return EFI_INVALID_PARAMETER;\r
1128 }\r
1129\r
1130 TableList = *Table;\r
1131 for (Index = 0; Index < TableCount; Index++) {\r
1132 if ((TableList[Index] != NULL) &&\r
1133 (TableList[Index]->Signature ==\r
1134 EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE))\r
1135 {\r
1136 FreePool (TableList[Index]);\r
1137 } else {\r
1138 DEBUG ((\r
1139 DEBUG_ERROR,\r
1140 "ERROR: SSDT-PCI: Could not free SSDT table at index %d.",\r
1141 Index\r
1142 ));\r
1143 return EFI_INVALID_PARAMETER;\r
1144 }\r
1145 } // for\r
1146\r
1147 // Free the table list.\r
1148 FreePool (*Table);\r
1149\r
1150 return EFI_SUCCESS;\r
1151}\r
1152\r
1153/** This macro defines the SSDT Pci Table Generator revision.\r
1154*/\r
1155#define SSDT_PCI_GENERATOR_REVISION CREATE_REVISION (1, 0)\r
1156\r
1157/** The interface for the SSDT Pci Table Generator.\r
1158*/\r
1159STATIC\r
1160ACPI_PCI_GENERATOR SsdtPcieGenerator = {\r
1161 // ACPI table generator header\r
1162 {\r
1163 // Generator ID\r
1164 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtPciExpress),\r
1165 // Generator Description\r
1166 L"ACPI.STD.SSDT.PCI.GENERATOR",\r
1167 // ACPI Table Signature\r
1168 EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,\r
1169 // ACPI Table Revision - Unused\r
1170 0,\r
1171 // Minimum ACPI Table Revision - Unused\r
1172 0,\r
1173 // Creator ID\r
1174 TABLE_GENERATOR_CREATOR_ID_ARM,\r
1175 // Creator Revision\r
1176 SSDT_PCI_GENERATOR_REVISION,\r
1177 // Build table function. Use the extended version instead.\r
1178 NULL,\r
1179 // Free table function. Use the extended version instead.\r
1180 NULL,\r
1181 // Extended Build table function.\r
1182 BuildSsdtPciTableEx,\r
1183 // Extended free function.\r
1184 FreeSsdtPciTableEx\r
1185 },\r
1186\r
1187 // Private fields are defined from here.\r
1188\r
e35a746c
PG
1189 // DeviceTable\r
1190 {\r
1191 // Table\r
1192 NULL,\r
1193 // LastIndex\r
1194 0,\r
1195 // MaxIndex\r
1196 0\r
1197 },\r
1198};\r
1199\r
1200/** Register the Generator with the ACPI Table Factory.\r
1201\r
1202 @param [in] ImageHandle The handle to the image.\r
1203 @param [in] SystemTable Pointer to the System Table.\r
1204\r
1205 @retval EFI_SUCCESS The Generator is registered.\r
1206 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
1207 @retval EFI_ALREADY_STARTED The Generator for the Table ID\r
1208 is already registered.\r
1209**/\r
1210EFI_STATUS\r
1211EFIAPI\r
1212AcpiSsdtPcieLibConstructor (\r
1213 IN EFI_HANDLE ImageHandle,\r
1214 IN EFI_SYSTEM_TABLE *SystemTable\r
1215 )\r
1216{\r
1217 EFI_STATUS Status;\r
1218\r
1219 Status = RegisterAcpiTableGenerator (&SsdtPcieGenerator.Header);\r
1220 DEBUG ((\r
1221 DEBUG_INFO,\r
1222 "SSDT-PCI: Register Generator. Status = %r\n",\r
1223 Status\r
1224 ));\r
1225 ASSERT_EFI_ERROR (Status);\r
1226 return Status;\r
1227}\r
1228\r
1229/** Deregister the Generator from the ACPI Table Factory.\r
1230\r
1231 @param [in] ImageHandle The handle to the image.\r
1232 @param [in] SystemTable Pointer to the System Table.\r
1233\r
1234 @retval EFI_SUCCESS The Generator is deregistered.\r
1235 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
1236 @retval EFI_NOT_FOUND The Generator is not registered.\r
1237**/\r
1238EFI_STATUS\r
1239EFIAPI\r
1240AcpiSsdtPcieLibDestructor (\r
1241 IN EFI_HANDLE ImageHandle,\r
1242 IN EFI_SYSTEM_TABLE *SystemTable\r
1243 )\r
1244{\r
1245 EFI_STATUS Status;\r
1246\r
1247 Status = DeregisterAcpiTableGenerator (&SsdtPcieGenerator.Header);\r
1248 DEBUG ((\r
1249 DEBUG_INFO,\r
1250 "SSDT-PCI: Deregister Generator. Status = %r\n",\r
1251 Status\r
1252 ));\r
1253 ASSERT_EFI_ERROR (Status);\r
1254 return Status;\r
1255}\r