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