]> git.proxmox.com Git - mirror_edk2.git/blame - DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
DynamicTablesPkg: AcpiSsdtPcieLibArm: Allow use of segment number as UID
[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
0a4079ad 301 @param [in] Uid Unique Id of the Pci device.\r
e35a746c
PG
302 @param [in, out] PciNode Pci node to amend.\r
303\r
304 @retval EFI_SUCCESS The function completed successfully.\r
305 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
306 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.\r
307**/\r
308STATIC\r
309EFI_STATUS\r
310EFIAPI\r
311GeneratePrt (\r
312 IN ACPI_PCI_GENERATOR *Generator,\r
313 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,\r
314 IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo,\r
0a4079ad 315 IN UINT32 Uid,\r
e35a746c
PG
316 IN OUT AML_OBJECT_NODE_HANDLE PciNode\r
317 )\r
318{\r
319 EFI_STATUS Status;\r
320 INT32 Index;\r
e35a746c 321 AML_OBJECT_NODE_HANDLE PrtNode;\r
e35a746c
PG
322 CM_ARM_OBJ_REF *RefInfo;\r
323 UINT32 RefCount;\r
324 CM_ARM_PCI_INTERRUPT_MAP_INFO *IrqMapInfo;\r
e35a746c
PG
325\r
326 ASSERT (Generator != NULL);\r
327 ASSERT (CfgMgrProtocol != NULL);\r
328 ASSERT (PciInfo != NULL);\r
329 ASSERT (PciNode != NULL);\r
330\r
331 PrtNode = NULL;\r
332\r
333 // Get the array of CM_ARM_OBJ_REF referencing the\r
334 // CM_ARM_PCI_INTERRUPT_MAP_INFO objects.\r
335 Status = GetEArmObjCmRef (\r
336 CfgMgrProtocol,\r
337 PciInfo->InterruptMapToken,\r
338 &RefInfo,\r
339 &RefCount\r
340 );\r
341 if (EFI_ERROR (Status)) {\r
342 ASSERT (0);\r
343 return Status;\r
344 }\r
345\r
e35a746c
PG
346 // Initialized DeviceTable.\r
347 Status = MappingTableInitialize (&Generator->DeviceTable, RefCount);\r
348 if (EFI_ERROR (Status)) {\r
349 ASSERT (0);\r
350 goto exit_handler0;\r
351 }\r
352\r
353 // ASL: Name (_PRT, Package () {})\r
354 Status = AmlCodeGenNamePackage ("_PRT", NULL, &PrtNode);\r
355 if (EFI_ERROR (Status)) {\r
356 ASSERT (0);\r
357 goto exit_handler;\r
358 }\r
359\r
e35a746c
PG
360 for (Index = 0; Index < RefCount; Index++) {\r
361 // Get CM_ARM_PCI_INTERRUPT_MAP_INFO structures one by one.\r
362 Status = GetEArmObjPciInterruptMapInfo (\r
363 CfgMgrProtocol,\r
364 RefInfo[Index].ReferenceToken,\r
365 &IrqMapInfo,\r
366 NULL\r
367 );\r
368 if (EFI_ERROR (Status)) {\r
369 ASSERT (0);\r
370 goto exit_handler;\r
371 }\r
372\r
5816bd3e
PG
373 // Check that the interrupts flags are SPIs, level high.\r
374 // Cf. Arm BSA v1.0, sE.6 "Legacy interrupts"\r
375 if ((Index > 0) &&\r
376 (IrqMapInfo->IntcInterrupt.Interrupt >= 32) &&\r
377 (IrqMapInfo->IntcInterrupt.Interrupt < 1020) &&\r
fc4a132c 378 ((IrqMapInfo->IntcInterrupt.Flags & 0xB) != 0))\r
5816bd3e 379 {\r
e35a746c 380 Status = EFI_INVALID_PARAMETER;\r
5816bd3e 381 ASSERT_EFI_ERROR (Status);\r
e35a746c
PG
382 goto exit_handler;\r
383 }\r
384\r
385 // Add the device to the DeviceTable.\r
386 MappingTableAdd (&Generator->DeviceTable, IrqMapInfo->PciDevice);\r
387\r
388 /* Add a _PRT entry.\r
389 ASL\r
390 Name (_PRT, Package () {\r
391 <OldPrtEntries>,\r
392 <NewPrtEntry>\r
393 })\r
394\r
395 Address is set as:\r
396 ACPI 6.4 specification, Table 6.2: "ADR Object Address Encodings"\r
397 High word-Device #, Low word-Function #. (for example, device 3,\r
398 function 2 is 0x00030002). To refer to all the functions on a device #,\r
399 use a function number of FFFF).\r
400 */\r
401 Status = AmlAddPrtEntry (\r
402 (IrqMapInfo->PciDevice << 16) | 0xFFFF,\r
403 IrqMapInfo->PciInterrupt,\r
5816bd3e
PG
404 NULL,\r
405 IrqMapInfo->IntcInterrupt.Interrupt,\r
e35a746c
PG
406 PrtNode\r
407 );\r
408 if (EFI_ERROR (Status)) {\r
409 ASSERT (0);\r
410 goto exit_handler;\r
411 }\r
412 } // for\r
413\r
5816bd3e 414 // Attach the _PRT entry.\r
e35a746c
PG
415 Status = AmlAttachNode (PciNode, PrtNode);\r
416 if (EFI_ERROR (Status)) {\r
5816bd3e 417 ASSERT_EFI_ERROR (Status);\r
e35a746c
PG
418 goto exit_handler;\r
419 }\r
420\r
421 PrtNode = NULL;\r
422\r
423 // Generate the Pci slots once all the device have been added.\r
0a4079ad 424 Status = GeneratePciSlots (PciInfo, &Generator->DeviceTable, Uid, PciNode);\r
e35a746c
PG
425 if (EFI_ERROR (Status)) {\r
426 ASSERT (0);\r
427 goto exit_handler;\r
428 }\r
429\r
430exit_handler:\r
431 MappingTableFree (&Generator->DeviceTable);\r
432exit_handler0:\r
e35a746c
PG
433 if (PrtNode != NULL) {\r
434 AmlDeleteTree (PrtNode);\r
435 }\r
436\r
437 return Status;\r
438}\r
439\r
440/** Generate a _CRS method for the Pci device.\r
441\r
442 @param [in] Generator The SSDT Pci generator.\r
443 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
444 Protocol interface.\r
445 @param [in] PciInfo Pci device information.\r
446 @param [in, out] PciNode Pci node to amend.\r
447\r
448 @retval EFI_SUCCESS The function completed successfully.\r
449 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
450 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.\r
451**/\r
452STATIC\r
453EFI_STATUS\r
454EFIAPI\r
455GeneratePciCrs (\r
456 IN ACPI_PCI_GENERATOR *Generator,\r
457 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,\r
458 IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo,\r
459 IN OUT AML_OBJECT_NODE_HANDLE PciNode\r
460 )\r
461{\r
462 EFI_STATUS Status;\r
463 BOOLEAN Translation;\r
464 UINT32 Index;\r
465 CM_ARM_OBJ_REF *RefInfo;\r
466 UINT32 RefCount;\r
467 CM_ARM_PCI_ADDRESS_MAP_INFO *AddrMapInfo;\r
468 AML_OBJECT_NODE_HANDLE CrsNode;\r
6cda306d 469 BOOLEAN IsPosDecode;\r
e35a746c
PG
470\r
471 ASSERT (Generator != NULL);\r
472 ASSERT (CfgMgrProtocol != NULL);\r
473 ASSERT (PciInfo != NULL);\r
474 ASSERT (PciNode != NULL);\r
475\r
476 // ASL: Name (_CRS, ResourceTemplate () {})\r
477 Status = AmlCodeGenNameResourceTemplate ("_CRS", PciNode, &CrsNode);\r
478 if (EFI_ERROR (Status)) {\r
479 ASSERT (0);\r
480 return Status;\r
481 }\r
482\r
483 // ASL:\r
484 // WordBusNumber ( // Bus numbers assigned to this root\r
485 // ResourceProducer, MinFixed, MaxFixed, PosDecode,\r
486 // 0, // AddressGranularity\r
487 // <Start>, // AddressMinimum - Minimum Bus Number\r
488 // <End>, // AddressMaximum - Maximum Bus Number\r
489 // 0, // AddressTranslation - Set to 0\r
490 // <End> - <Start> + 1 // RangeLength - Number of Busses\r
491 // )\r
492 Status = AmlCodeGenRdWordBusNumber (\r
493 FALSE,\r
494 TRUE,\r
495 TRUE,\r
496 TRUE,\r
497 0,\r
498 PciInfo->StartBusNumber,\r
499 PciInfo->EndBusNumber,\r
500 0,\r
501 PciInfo->EndBusNumber - PciInfo->StartBusNumber + 1,\r
502 0,\r
503 NULL,\r
504 CrsNode,\r
505 NULL\r
506 );\r
507 if (EFI_ERROR (Status)) {\r
508 ASSERT (0);\r
509 return Status;\r
510 }\r
511\r
512 // Get the array of CM_ARM_OBJ_REF referencing the\r
513 // CM_ARM_PCI_ADDRESS_MAP_INFO objects.\r
514 Status = GetEArmObjCmRef (\r
515 CfgMgrProtocol,\r
516 PciInfo->AddressMapToken,\r
517 &RefInfo,\r
518 &RefCount\r
519 );\r
520 if (EFI_ERROR (Status)) {\r
521 ASSERT (0);\r
522 return Status;\r
523 }\r
524\r
525 for (Index = 0; Index < RefCount; Index++) {\r
526 // Get CM_ARM_PCI_ADDRESS_MAP_INFO structures one by one.\r
527 Status = GetEArmObjPciAddressMapInfo (\r
528 CfgMgrProtocol,\r
529 RefInfo[Index].ReferenceToken,\r
530 &AddrMapInfo,\r
531 NULL\r
532 );\r
533 if (EFI_ERROR (Status)) {\r
534 ASSERT (0);\r
535 return Status;\r
536 }\r
537\r
538 Translation = (AddrMapInfo->CpuAddress != AddrMapInfo->PciAddress);\r
6cda306d
JB
539 if (AddrMapInfo->CpuAddress >= AddrMapInfo->PciAddress) {\r
540 IsPosDecode = TRUE;\r
541 } else {\r
542 IsPosDecode = FALSE;\r
543 }\r
e35a746c
PG
544\r
545 switch (AddrMapInfo->SpaceCode) {\r
546 case PCI_SS_IO:\r
547 Status = AmlCodeGenRdDWordIo (\r
548 FALSE,\r
549 TRUE,\r
550 TRUE,\r
6cda306d 551 IsPosDecode,\r
e35a746c
PG
552 3,\r
553 0,\r
554 AddrMapInfo->PciAddress,\r
555 AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,\r
6cda306d 556 Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0,\r
e35a746c
PG
557 AddrMapInfo->AddressSize,\r
558 0,\r
559 NULL,\r
560 TRUE,\r
561 FALSE,\r
562 CrsNode,\r
563 NULL\r
564 );\r
565 break;\r
566\r
567 case PCI_SS_M32:\r
568 Status = AmlCodeGenRdDWordMemory (\r
569 FALSE,\r
6cda306d 570 IsPosDecode,\r
e35a746c
PG
571 TRUE,\r
572 TRUE,\r
573 TRUE,\r
574 TRUE,\r
575 0,\r
576 AddrMapInfo->PciAddress,\r
577 AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,\r
6cda306d 578 Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0,\r
e35a746c
PG
579 AddrMapInfo->AddressSize,\r
580 0,\r
581 NULL,\r
582 0,\r
583 TRUE,\r
584 CrsNode,\r
585 NULL\r
586 );\r
587 break;\r
588\r
589 case PCI_SS_M64:\r
590 Status = AmlCodeGenRdQWordMemory (\r
591 FALSE,\r
6cda306d 592 IsPosDecode,\r
e35a746c
PG
593 TRUE,\r
594 TRUE,\r
595 TRUE,\r
596 TRUE,\r
597 0,\r
598 AddrMapInfo->PciAddress,\r
599 AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,\r
6cda306d 600 Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0,\r
e35a746c
PG
601 AddrMapInfo->AddressSize,\r
602 0,\r
603 NULL,\r
604 0,\r
605 TRUE,\r
606 CrsNode,\r
607 NULL\r
608 );\r
609 break;\r
610\r
611 default:\r
612 Status = EFI_INVALID_PARAMETER;\r
613 } // switch\r
614\r
615 if (EFI_ERROR (Status)) {\r
616 ASSERT (0);\r
617 return Status;\r
618 }\r
619 } // for\r
620\r
621 return Status;\r
622}\r
623\r
033ba8bb
KQ
624/** Generate a RES0 device node to reserve PNP motherboard resources\r
625 for a given PCI node.\r
626\r
627 @param [in] PciNode Parent PCI node handle of the generated\r
628 resource object.\r
629 @param [out] CrsNode CRS node of the AML tree to populate.\r
630\r
631 @retval EFI_SUCCESS The function completed successfully.\r
632 @retval EFI_INVALID_PARAMETER Invalid input parameter.\r
633 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.\r
634**/\r
635STATIC\r
636EFI_STATUS\r
637EFIAPI\r
638GenerateMotherboardDevice (\r
639 IN AML_OBJECT_NODE_HANDLE PciNode,\r
640 OUT AML_OBJECT_NODE_HANDLE *CrsNode\r
641 )\r
642{\r
643 EFI_STATUS Status;\r
644 UINT32 EisaId;\r
645 AML_OBJECT_NODE_HANDLE ResNode;\r
646\r
647 if (CrsNode == NULL) {\r
648 ASSERT (0);\r
649 return EFI_INVALID_PARAMETER;\r
650 }\r
651\r
652 // ASL: Device (RES0) {}\r
653 Status = AmlCodeGenDevice ("RES0", PciNode, &ResNode);\r
654 if (EFI_ERROR (Status)) {\r
655 ASSERT (0);\r
656 return Status;\r
657 }\r
658\r
659 // ASL: Name (_HID, EISAID ("PNP0C02"))\r
660 Status = AmlGetEisaIdFromString ("PNP0C02", &EisaId); /* PNP Motherboard Resources */\r
661 if (EFI_ERROR (Status)) {\r
662 ASSERT (0);\r
663 return Status;\r
664 }\r
665\r
666 Status = AmlCodeGenNameInteger ("_HID", EisaId, ResNode, NULL);\r
667 if (EFI_ERROR (Status)) {\r
668 ASSERT (0);\r
669 return Status;\r
670 }\r
671\r
672 // ASL: Name (_CRS, ResourceTemplate () {})\r
673 Status = AmlCodeGenNameResourceTemplate ("_CRS", ResNode, CrsNode);\r
674 if (EFI_ERROR (Status)) {\r
675 ASSERT (0);\r
676 return Status;\r
677 }\r
678\r
679 return Status;\r
680}\r
681\r
682/** Reserves ECAM space for PCI config space\r
683\r
684 @param [in] Generator The SSDT Pci generator.\r
685 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
686 Protocol interface.\r
687 @param [in] PciInfo Pci device information.\r
688 @param [in, out] PciNode RootNode of the AML tree to populate.\r
689\r
690 @retval EFI_SUCCESS The function completed successfully.\r
691 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
692 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.\r
693**/\r
694STATIC\r
695EFI_STATUS\r
696EFIAPI\r
697ReserveEcamSpace (\r
698 IN ACPI_PCI_GENERATOR *Generator,\r
699 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,\r
700 IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo,\r
701 IN OUT AML_OBJECT_NODE_HANDLE PciNode\r
702 )\r
703{\r
704 EFI_STATUS Status;\r
705 AML_OBJECT_NODE_HANDLE CrsNode;\r
706 UINT64 AddressMinimum;\r
707 UINT64 AddressMaximum;\r
708\r
709 Status = GenerateMotherboardDevice (PciNode, &CrsNode);\r
710 if (EFI_ERROR (Status)) {\r
711 ASSERT (0);\r
712 return Status;\r
713 }\r
714\r
715 AddressMinimum = PciInfo->BaseAddress + (PciInfo->StartBusNumber *\r
716 PCI_MAX_DEVICE_COUNT_PER_BUS * PCI_MAX_FUNCTION_COUNT_PER_DEVICE * SIZE_4KB);\r
717 AddressMaximum = PciInfo->BaseAddress + ((PciInfo->EndBusNumber + 1) *\r
718 PCI_MAX_DEVICE_COUNT_PER_BUS * PCI_MAX_FUNCTION_COUNT_PER_DEVICE * SIZE_4KB) - 1;\r
719\r
720 Status = AmlCodeGenRdQWordMemory (\r
721 FALSE,\r
722 TRUE,\r
723 TRUE,\r
724 TRUE,\r
725 FALSE, // non-cacheable\r
726 TRUE,\r
727 0,\r
728 AddressMinimum,\r
729 AddressMaximum,\r
730 0, // no translation\r
731 AddressMaximum - AddressMinimum + 1,\r
732 0,\r
733 NULL,\r
734 0,\r
735 TRUE,\r
736 CrsNode,\r
737 NULL\r
738 );\r
739\r
740 if (EFI_ERROR (Status)) {\r
741 ASSERT (0);\r
742 return Status;\r
743 }\r
744\r
745 return Status;\r
746}\r
747\r
e35a746c
PG
748/** Generate a Pci device.\r
749\r
750 @param [in] Generator The SSDT Pci generator.\r
751 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
752 Protocol interface.\r
753 @param [in] PciInfo Pci device information.\r
754 @param [in] Uid Unique Id of the Pci device.\r
755 @param [in, out] RootNode RootNode of the AML tree to populate.\r
756\r
757 @retval EFI_SUCCESS The function completed successfully.\r
758 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
759 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.\r
760**/\r
761STATIC\r
762EFI_STATUS\r
763EFIAPI\r
764GeneratePciDevice (\r
765 IN ACPI_PCI_GENERATOR *Generator,\r
766 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,\r
767 IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo,\r
768 IN UINT32 Uid,\r
769 IN OUT AML_ROOT_NODE_HANDLE *RootNode\r
770 )\r
771{\r
772 EFI_STATUS Status;\r
773\r
774 CHAR8 AslName[AML_NAME_SEG_SIZE + 1];\r
775 AML_OBJECT_NODE_HANDLE ScopeNode;\r
776 AML_OBJECT_NODE_HANDLE PciNode;\r
777\r
778 ASSERT (Generator != NULL);\r
779 ASSERT (CfgMgrProtocol != NULL);\r
780 ASSERT (PciInfo != NULL);\r
781 ASSERT (RootNode != NULL);\r
782\r
783 PciNode = NULL;\r
784\r
785 // ASL: Scope (\_SB) {}\r
786 Status = AmlCodeGenScope (SB_SCOPE, RootNode, &ScopeNode);\r
787 if (EFI_ERROR (Status)) {\r
788 ASSERT (0);\r
789 return Status;\r
790 }\r
791\r
792 // Write the name of the PCI device.\r
793 CopyMem (AslName, "PCIx", AML_NAME_SEG_SIZE + 1);\r
9ac155bf
JB
794 AslName[AML_NAME_SEG_SIZE - 1] = AsciiFromHex (Uid & 0xF);\r
795 if (Uid > 0xF) {\r
796 AslName[AML_NAME_SEG_SIZE - 2] = AsciiFromHex ((Uid >> 4) & 0xF);\r
797 }\r
e35a746c
PG
798\r
799 // ASL: Device (PCIx) {}\r
800 Status = AmlCodeGenDevice (AslName, ScopeNode, &PciNode);\r
801 if (EFI_ERROR (Status)) {\r
802 ASSERT (0);\r
803 return Status;\r
804 }\r
805\r
806 // Populate the PCIx node with some Id values.\r
807 Status = GeneratePciDeviceInfo (PciInfo, Uid, PciNode);\r
808 if (EFI_ERROR (Status)) {\r
809 ASSERT (0);\r
810 return Status;\r
811 }\r
812\r
813 // Generate the Pci Routing Table (_PRT).\r
814 if (PciInfo->InterruptMapToken != CM_NULL_TOKEN) {\r
815 Status = GeneratePrt (\r
816 Generator,\r
817 CfgMgrProtocol,\r
818 PciInfo,\r
0a4079ad 819 Uid,\r
e35a746c
PG
820 PciNode\r
821 );\r
822 if (EFI_ERROR (Status)) {\r
823 ASSERT (0);\r
824 return Status;\r
825 }\r
826 }\r
827\r
828 // Generate the _CRS method.\r
829 Status = GeneratePciCrs (Generator, CfgMgrProtocol, PciInfo, PciNode);\r
830 if (EFI_ERROR (Status)) {\r
831 ASSERT (0);\r
832 return Status;\r
833 }\r
834\r
033ba8bb
KQ
835 // Add the PNP Motherboard Resources Device to reserve ECAM space\r
836 Status = ReserveEcamSpace (Generator, CfgMgrProtocol, PciInfo, PciNode);\r
837 if (EFI_ERROR (Status)) {\r
838 ASSERT (0);\r
839 return Status;\r
840 }\r
841\r
e35a746c 842 // Add the template _OSC method.\r
19a87683 843 Status = AddOscMethod (PciInfo, PciNode);\r
e35a746c 844 ASSERT_EFI_ERROR (Status);\r
033ba8bb 845\r
e35a746c
PG
846 return Status;\r
847}\r
848\r
849/** Build an Ssdt table describing a Pci device.\r
850\r
851 @param [in] Generator The SSDT Pci generator.\r
852 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
853 Protocol interface.\r
854 @param [in] AcpiTableInfo Pointer to the ACPI table information.\r
855 @param [in] PciInfo Pci device information.\r
856 @param [in] Uid Unique Id of the Pci device.\r
857 @param [out] Table If success, contains the created SSDT table.\r
858\r
859 @retval EFI_SUCCESS The function completed successfully.\r
860 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
861 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.\r
862**/\r
863STATIC\r
864EFI_STATUS\r
865EFIAPI\r
866BuildSsdtPciTable (\r
867 IN ACPI_PCI_GENERATOR *Generator,\r
868 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,\r
869 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,\r
870 IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo,\r
871 IN UINT32 Uid,\r
872 OUT EFI_ACPI_DESCRIPTION_HEADER **Table\r
873 )\r
874{\r
875 EFI_STATUS Status;\r
876 EFI_STATUS Status1;\r
877 AML_ROOT_NODE_HANDLE RootNode;\r
878\r
879 ASSERT (Generator != NULL);\r
880 ASSERT (CfgMgrProtocol != NULL);\r
881 ASSERT (PciInfo != NULL);\r
882 ASSERT (Table != NULL);\r
883\r
884 // Create a new Ssdt table.\r
885 Status = AddSsdtAcpiHeader (\r
886 CfgMgrProtocol,\r
887 &Generator->Header,\r
888 AcpiTableInfo,\r
889 &RootNode\r
890 );\r
891 if (EFI_ERROR (Status)) {\r
892 ASSERT (0);\r
893 return Status;\r
894 }\r
895\r
896 Status = GeneratePciDevice (\r
897 Generator,\r
898 CfgMgrProtocol,\r
899 PciInfo,\r
900 Uid,\r
901 RootNode\r
902 );\r
903 if (EFI_ERROR (Status)) {\r
904 ASSERT (0);\r
905 goto exit_handler;\r
906 }\r
907\r
908 // Serialize the tree.\r
909 Status = AmlSerializeDefinitionBlock (\r
910 RootNode,\r
911 Table\r
912 );\r
913 if (EFI_ERROR (Status)) {\r
914 DEBUG ((\r
915 DEBUG_ERROR,\r
916 "ERROR: SSDT-PCI: Failed to Serialize SSDT Table Data."\r
917 " Status = %r\n",\r
918 Status\r
919 ));\r
920 }\r
921\r
922exit_handler:\r
923 // Cleanup\r
924 Status1 = AmlDeleteTree (RootNode);\r
925 if (EFI_ERROR (Status1)) {\r
926 DEBUG ((\r
927 DEBUG_ERROR,\r
928 "ERROR: SSDT-PCI: Failed to cleanup AML tree."\r
929 " Status = %r\n",\r
930 Status1\r
931 ));\r
932 // If Status was success but we failed to delete the AML Tree\r
933 // return Status1 else return the original error code, i.e. Status.\r
934 if (!EFI_ERROR (Status)) {\r
935 return Status1;\r
936 }\r
937 }\r
938\r
939 return Status;\r
940}\r
941\r
942/** Construct SSDT tables describing Pci root complexes.\r
943\r
944 This function invokes the Configuration Manager protocol interface\r
945 to get the required hardware information for generating the ACPI\r
946 table.\r
947\r
948 If this function allocates any resources then they must be freed\r
949 in the FreeXXXXTableResourcesEx function.\r
950\r
951 @param [in] This Pointer to the ACPI table generator.\r
952 @param [in] AcpiTableInfo Pointer to the ACPI table information.\r
953 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
954 Protocol interface.\r
955 @param [out] Table Pointer to a list of generated ACPI table(s).\r
956 @param [out] TableCount Number of generated ACPI table(s).\r
957\r
958 @retval EFI_SUCCESS Table generated successfully.\r
959 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration\r
960 Manager is less than the Object size for\r
961 the requested object.\r
962 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
963 @retval EFI_NOT_FOUND Could not find information.\r
964 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.\r
965 @retval EFI_UNSUPPORTED Unsupported configuration.\r
966**/\r
967STATIC\r
968EFI_STATUS\r
969EFIAPI\r
970BuildSsdtPciTableEx (\r
971 IN CONST ACPI_TABLE_GENERATOR *This,\r
972 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,\r
973 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,\r
974 OUT EFI_ACPI_DESCRIPTION_HEADER ***Table,\r
975 OUT UINTN *CONST TableCount\r
976 )\r
977{\r
978 EFI_STATUS Status;\r
979 CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo;\r
980 UINT32 PciCount;\r
981 UINTN Index;\r
982 EFI_ACPI_DESCRIPTION_HEADER **TableList;\r
983 ACPI_PCI_GENERATOR *Generator;\r
8c92a950 984 UINT32 Uid;\r
e35a746c
PG
985\r
986 ASSERT (This != NULL);\r
987 ASSERT (AcpiTableInfo != NULL);\r
988 ASSERT (CfgMgrProtocol != NULL);\r
989 ASSERT (Table != NULL);\r
990 ASSERT (TableCount != NULL);\r
991 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);\r
992 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);\r
993\r
994 *TableCount = 0;\r
995 Generator = (ACPI_PCI_GENERATOR *)This;\r
996\r
997 Status = GetEArmObjPciConfigSpaceInfo (\r
998 CfgMgrProtocol,\r
999 CM_NULL_TOKEN,\r
1000 &PciInfo,\r
1001 &PciCount\r
1002 );\r
1003 if (EFI_ERROR (Status)) {\r
1004 ASSERT (0);\r
1005 return Status;\r
1006 }\r
1007\r
1008 if (PciCount > MAX_PCI_ROOT_COMPLEXES_SUPPORTED) {\r
1009 DEBUG ((\r
1010 DEBUG_ERROR,\r
1011 "ERROR: SSDT-PCI: Too many Pci root complexes: %d."\r
1012 " Maximum Pci root complexes supported = %d.\n",\r
1013 PciCount,\r
1014 MAX_PCI_ROOT_COMPLEXES_SUPPORTED\r
1015 ));\r
1016 return EFI_INVALID_PARAMETER;\r
1017 }\r
1018\r
1019 // Allocate a table to store pointers to the SSDT tables.\r
1020 TableList = (EFI_ACPI_DESCRIPTION_HEADER **)\r
1021 AllocateZeroPool (\r
1022 (sizeof (EFI_ACPI_DESCRIPTION_HEADER *) * PciCount)\r
1023 );\r
1024 if (TableList == NULL) {\r
1025 Status = EFI_OUT_OF_RESOURCES;\r
1026 DEBUG ((\r
1027 DEBUG_ERROR,\r
1028 "ERROR: SSDT-PCI: Failed to allocate memory for Table List."\r
1029 " Status = %r\n",\r
1030 Status\r
1031 ));\r
1032 return Status;\r
1033 }\r
1034\r
1035 // Setup the table list early so that appropriate cleanup\r
1036 // can be done in case of failure.\r
1037 *Table = TableList;\r
1038\r
1039 for (Index = 0; Index < PciCount; Index++) {\r
8c92a950
JB
1040 if (PcdGetBool (PcdPciUseSegmentAsUid)) {\r
1041 Uid = PciInfo[Index].PciSegmentGroupNumber;\r
1042 if (Uid > MAX_PCI_ROOT_COMPLEXES_SUPPORTED) {\r
1043 DEBUG ((\r
1044 DEBUG_ERROR,\r
1045 "ERROR: SSDT-PCI: Pci root complexes segment number: %d."\r
1046 " Greater than maximum number of Pci root complexes supported = %d.\n",\r
1047 Uid,\r
1048 MAX_PCI_ROOT_COMPLEXES_SUPPORTED\r
1049 ));\r
1050 return EFI_INVALID_PARAMETER;\r
1051 }\r
1052 } else {\r
1053 Uid = Index;\r
1054 }\r
1055\r
e35a746c
PG
1056 // Build a SSDT table describing the Pci devices.\r
1057 Status = BuildSsdtPciTable (\r
1058 Generator,\r
1059 CfgMgrProtocol,\r
1060 AcpiTableInfo,\r
1061 &PciInfo[Index],\r
8c92a950 1062 Uid,\r
e35a746c
PG
1063 &TableList[Index]\r
1064 );\r
1065 if (EFI_ERROR (Status)) {\r
1066 DEBUG ((\r
1067 DEBUG_ERROR,\r
1068 "ERROR: SSDT-PCI: Failed to build associated SSDT table."\r
1069 " Status = %r\n",\r
1070 Status\r
1071 ));\r
1072 goto error_handler;\r
1073 }\r
1074\r
1075 *TableCount += 1;\r
1076 } // for\r
1077\r
1078error_handler:\r
1079 // Note: Table list and Table count have been setup. The\r
1080 // error handler does nothing here as the framework will invoke\r
1081 // FreeSsdtPciTableEx () even on failure.\r
1082 return Status;\r
1083}\r
1084\r
1085/** Free any resources allocated for constructing the tables.\r
1086\r
1087 @param [in] This Pointer to the ACPI table generator.\r
1088 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.\r
1089 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
1090 Protocol Interface.\r
1091 @param [in, out] Table Pointer to an array of pointers\r
1092 to ACPI Table(s).\r
1093 @param [in] TableCount Number of ACPI table(s).\r
1094\r
1095 @retval EFI_SUCCESS The resources were freed successfully.\r
1096 @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.\r
1097**/\r
1098STATIC\r
1099EFI_STATUS\r
1100EFIAPI\r
1101FreeSsdtPciTableEx (\r
1102 IN CONST ACPI_TABLE_GENERATOR *CONST This,\r
1103 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,\r
1104 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,\r
1105 IN OUT EFI_ACPI_DESCRIPTION_HEADER ***CONST Table,\r
1106 IN CONST UINTN TableCount\r
1107 )\r
1108{\r
1109 EFI_ACPI_DESCRIPTION_HEADER **TableList;\r
1110 UINTN Index;\r
1111\r
1112 ASSERT (This != NULL);\r
1113 ASSERT (AcpiTableInfo != NULL);\r
1114 ASSERT (CfgMgrProtocol != NULL);\r
1115 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);\r
1116 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);\r
1117\r
1118 if ((Table == NULL) ||\r
1119 (*Table == NULL) ||\r
1120 (TableCount == 0))\r
1121 {\r
1122 DEBUG ((DEBUG_ERROR, "ERROR: SSDT-PCI: Invalid Table Pointer\n"));\r
1123 return EFI_INVALID_PARAMETER;\r
1124 }\r
1125\r
1126 TableList = *Table;\r
1127 for (Index = 0; Index < TableCount; Index++) {\r
1128 if ((TableList[Index] != NULL) &&\r
1129 (TableList[Index]->Signature ==\r
1130 EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE))\r
1131 {\r
1132 FreePool (TableList[Index]);\r
1133 } else {\r
1134 DEBUG ((\r
1135 DEBUG_ERROR,\r
1136 "ERROR: SSDT-PCI: Could not free SSDT table at index %d.",\r
1137 Index\r
1138 ));\r
1139 return EFI_INVALID_PARAMETER;\r
1140 }\r
1141 } // for\r
1142\r
1143 // Free the table list.\r
1144 FreePool (*Table);\r
1145\r
1146 return EFI_SUCCESS;\r
1147}\r
1148\r
1149/** This macro defines the SSDT Pci Table Generator revision.\r
1150*/\r
1151#define SSDT_PCI_GENERATOR_REVISION CREATE_REVISION (1, 0)\r
1152\r
1153/** The interface for the SSDT Pci Table Generator.\r
1154*/\r
1155STATIC\r
1156ACPI_PCI_GENERATOR SsdtPcieGenerator = {\r
1157 // ACPI table generator header\r
1158 {\r
1159 // Generator ID\r
1160 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtPciExpress),\r
1161 // Generator Description\r
1162 L"ACPI.STD.SSDT.PCI.GENERATOR",\r
1163 // ACPI Table Signature\r
1164 EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,\r
1165 // ACPI Table Revision - Unused\r
1166 0,\r
1167 // Minimum ACPI Table Revision - Unused\r
1168 0,\r
1169 // Creator ID\r
1170 TABLE_GENERATOR_CREATOR_ID_ARM,\r
1171 // Creator Revision\r
1172 SSDT_PCI_GENERATOR_REVISION,\r
1173 // Build table function. Use the extended version instead.\r
1174 NULL,\r
1175 // Free table function. Use the extended version instead.\r
1176 NULL,\r
1177 // Extended Build table function.\r
1178 BuildSsdtPciTableEx,\r
1179 // Extended free function.\r
1180 FreeSsdtPciTableEx\r
1181 },\r
1182\r
1183 // Private fields are defined from here.\r
1184\r
e35a746c
PG
1185 // DeviceTable\r
1186 {\r
1187 // Table\r
1188 NULL,\r
1189 // LastIndex\r
1190 0,\r
1191 // MaxIndex\r
1192 0\r
1193 },\r
1194};\r
1195\r
1196/** Register the Generator with the ACPI Table Factory.\r
1197\r
1198 @param [in] ImageHandle The handle to the image.\r
1199 @param [in] SystemTable Pointer to the System Table.\r
1200\r
1201 @retval EFI_SUCCESS The Generator is registered.\r
1202 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
1203 @retval EFI_ALREADY_STARTED The Generator for the Table ID\r
1204 is already registered.\r
1205**/\r
1206EFI_STATUS\r
1207EFIAPI\r
1208AcpiSsdtPcieLibConstructor (\r
1209 IN EFI_HANDLE ImageHandle,\r
1210 IN EFI_SYSTEM_TABLE *SystemTable\r
1211 )\r
1212{\r
1213 EFI_STATUS Status;\r
1214\r
1215 Status = RegisterAcpiTableGenerator (&SsdtPcieGenerator.Header);\r
1216 DEBUG ((\r
1217 DEBUG_INFO,\r
1218 "SSDT-PCI: Register Generator. Status = %r\n",\r
1219 Status\r
1220 ));\r
1221 ASSERT_EFI_ERROR (Status);\r
1222 return Status;\r
1223}\r
1224\r
1225/** Deregister the Generator from the ACPI Table Factory.\r
1226\r
1227 @param [in] ImageHandle The handle to the image.\r
1228 @param [in] SystemTable Pointer to the System Table.\r
1229\r
1230 @retval EFI_SUCCESS The Generator is deregistered.\r
1231 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
1232 @retval EFI_NOT_FOUND The Generator is not registered.\r
1233**/\r
1234EFI_STATUS\r
1235EFIAPI\r
1236AcpiSsdtPcieLibDestructor (\r
1237 IN EFI_HANDLE ImageHandle,\r
1238 IN EFI_SYSTEM_TABLE *SystemTable\r
1239 )\r
1240{\r
1241 EFI_STATUS Status;\r
1242\r
1243 Status = DeregisterAcpiTableGenerator (&SsdtPcieGenerator.Header);\r
1244 DEBUG ((\r
1245 DEBUG_INFO,\r
1246 "SSDT-PCI: Deregister Generator. Status = %r\n",\r
1247 Status\r
1248 ));\r
1249 ASSERT_EFI_ERROR (Status);\r
1250 return Status;\r
1251}\r