]> git.proxmox.com Git - mirror_edk2.git/blame - DynamicTablesPkg/Library/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c
DynamicTablesPkg: Remove GIC Distributor Id field
[mirror_edk2.git] / DynamicTablesPkg / Library / Acpi / Arm / AcpiMadtLibArm / MadtGenerator.c
CommitLineData
015a797a
SM
1/** @file\r
2 MADT Table Generator\r
3\r
4 Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.\r
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13 @par Reference(s):\r
14 - ACPI 6.2 Specification - Errata A, September 2017\r
15\r
16**/\r
17\r
18#include <Library/AcpiLib.h>\r
19#include <Library/DebugLib.h>\r
20#include <Library/MemoryAllocationLib.h>\r
21#include <Protocol/AcpiTable.h>\r
22\r
23// Module specific include files.\r
24#include <AcpiTableGenerator.h>\r
25#include <ConfigurationManagerObject.h>\r
26#include <ConfigurationManagerHelper.h>\r
27#include <Library/TableHelperLib.h>\r
28#include <Protocol/ConfigurationManagerProtocol.h>\r
29\r
30/** ARM standard MADT Generator\r
31\r
32Requirements:\r
33 The following Configuration Manager Object(s) are required by\r
34 this Generator:\r
35 - EArmObjGicCInfo\r
36 - EArmObjGicDInfo\r
37 - EArmObjGicMsiFrameInfo (OPTIONAL)\r
38 - EArmObjGicRedistributorInfo (OPTIONAL)\r
39 - EArmObjGicItsInfo (OPTIONAL)\r
40*/\r
41\r
42/** This macro expands to a function that retrieves the GIC\r
43 CPU interface Information from the Configuration Manager.\r
44*/\r
45GET_OBJECT_LIST (\r
46 EObjNameSpaceArm,\r
47 EArmObjGicCInfo,\r
48 CM_ARM_GICC_INFO\r
49 );\r
50\r
51/** This macro expands to a function that retrieves the GIC\r
52 Distributor Information from the Configuration Manager.\r
53*/\r
54\r
55GET_OBJECT_LIST (\r
56 EObjNameSpaceArm,\r
57 EArmObjGicDInfo,\r
58 CM_ARM_GICD_INFO\r
59 );\r
60\r
61/** This macro expands to a function that retrieves the GIC\r
62 MSI Frame Information from the Configuration Manager.\r
63*/\r
64GET_OBJECT_LIST (\r
65 EObjNameSpaceArm,\r
66 EArmObjGicMsiFrameInfo,\r
67 CM_ARM_GIC_MSI_FRAME_INFO\r
68 );\r
69\r
70/** This macro expands to a function that retrieves the GIC\r
71 Redistributor Information from the Configuration Manager.\r
72*/\r
73\r
74GET_OBJECT_LIST (\r
75 EObjNameSpaceArm,\r
76 EArmObjGicRedistributorInfo,\r
77 CM_ARM_GIC_REDIST_INFO\r
78 );\r
79\r
80/** This macro expands to a function that retrieves the GIC\r
81 Interrupt Translation Service Information from the\r
82 Configuration Manager.\r
83*/\r
84GET_OBJECT_LIST (\r
85 EObjNameSpaceArm,\r
86 EArmObjGicItsInfo,\r
87 CM_ARM_GIC_ITS_INFO\r
88 );\r
89\r
90/** This function updates the GIC CPU Interface Information in the\r
91 EFI_ACPI_6_2_GIC_STRUCTURE structure.\r
92\r
93 @param [in] Gicc Pointer to GIC CPU Interface structure.\r
94 @param [in] GicCInfo Pointer to the GIC CPU Interface Information.\r
95**/\r
96STATIC\r
97VOID\r
98AddGICC (\r
99 IN EFI_ACPI_6_2_GIC_STRUCTURE * CONST Gicc,\r
100 IN CONST CM_ARM_GICC_INFO * CONST GicCInfo\r
101 )\r
102{\r
103 ASSERT (Gicc != NULL);\r
104 ASSERT (GicCInfo != NULL);\r
105\r
106 // UINT8 Type\r
107 Gicc->Type = EFI_ACPI_6_2_GIC;\r
108 // UINT8 Length\r
109 Gicc->Length = sizeof (EFI_ACPI_6_2_GIC_STRUCTURE);\r
110 // UINT16 Reserved\r
111 Gicc->Reserved = EFI_ACPI_RESERVED_WORD;\r
112\r
113 // UINT32 CPUInterfaceNumber\r
114 Gicc->CPUInterfaceNumber = GicCInfo->CPUInterfaceNumber;\r
115 // UINT32 AcpiProcessorUid\r
116 Gicc->AcpiProcessorUid = GicCInfo->AcpiProcessorUid;\r
117 // UINT32 Flags\r
118 Gicc->Flags = GicCInfo->Flags;\r
119 // UINT32 ParkingProtocolVersion\r
120 Gicc->ParkingProtocolVersion = GicCInfo->ParkingProtocolVersion;\r
121 // UINT32 PerformanceInterruptGsiv\r
122 Gicc->PerformanceInterruptGsiv = GicCInfo->PerformanceInterruptGsiv;\r
123 // UINT64 ParkedAddress\r
124 Gicc->ParkedAddress = GicCInfo->ParkedAddress;\r
125\r
126 // UINT64 PhysicalBaseAddress\r
127 Gicc->PhysicalBaseAddress = GicCInfo->PhysicalBaseAddress;\r
128 // UINT64 GICV\r
129 Gicc->GICV = GicCInfo->GICV;\r
130 // UINT64 GICH\r
131 Gicc->GICH = GicCInfo->GICH;\r
132\r
133 // UINT32 VGICMaintenanceInterrupt\r
134 Gicc->VGICMaintenanceInterrupt = GicCInfo->VGICMaintenanceInterrupt;\r
135 // UINT64 GICRBaseAddress\r
136 Gicc->GICRBaseAddress = GicCInfo->GICRBaseAddress;\r
137\r
138 // UINT64 MPIDR\r
139 Gicc->MPIDR = GicCInfo->MPIDR;\r
140 // UINT8 ProcessorPowerEfficiencyClass\r
141 Gicc->ProcessorPowerEfficiencyClass =\r
142 GicCInfo->ProcessorPowerEfficiencyClass;\r
143 // UINT8 Reserved2[3]\r
144 Gicc->Reserved2[0] = EFI_ACPI_RESERVED_BYTE;\r
145 Gicc->Reserved2[1] = EFI_ACPI_RESERVED_BYTE;\r
146 Gicc->Reserved2[2] = EFI_ACPI_RESERVED_BYTE;\r
147}\r
148\r
149/** Add the GIC CPU Interface Information to the MADT Table.\r
150\r
151 @param [in] Gicc Pointer to GIC CPU Interface\r
152 structure list.\r
153 @param [in] GicCInfo Pointer to the GIC CPU\r
154 Information list.\r
155 @param [in] GicCCount Count of GIC CPU Interfaces.\r
156**/\r
157STATIC\r
158VOID\r
159AddGICCList (\r
160 IN EFI_ACPI_6_2_GIC_STRUCTURE * Gicc,\r
161 IN CONST CM_ARM_GICC_INFO * GicCInfo,\r
162 IN UINT32 GicCCount\r
163 )\r
164{\r
165 ASSERT (Gicc != NULL);\r
166 ASSERT (GicCInfo != NULL);\r
167\r
168 while (GicCCount-- != 0) {\r
169 AddGICC (Gicc++, GicCInfo++);\r
170 }\r
171}\r
172\r
173/** Update the GIC Distributor Information in the MADT Table.\r
174\r
175 @param [in] Gicd Pointer to GIC Distributor structure.\r
176 @param [in] GicDInfo Pointer to the GIC Distributor Information.\r
177**/\r
178STATIC\r
179VOID\r
180AddGICD (\r
181 EFI_ACPI_6_2_GIC_DISTRIBUTOR_STRUCTURE * CONST Gicd,\r
182 CONST CM_ARM_GICD_INFO * CONST GicDInfo\r
183)\r
184{\r
185 ASSERT (Gicd != NULL);\r
186 ASSERT (GicDInfo != NULL);\r
187\r
188 // UINT8 Type\r
189 Gicd->Type = EFI_ACPI_6_2_GICD;\r
190 // UINT8 Length\r
191 Gicd->Length = sizeof (EFI_ACPI_6_2_GIC_DISTRIBUTOR_STRUCTURE);\r
192 // UINT16 Reserved\r
193 Gicd->Reserved1 = EFI_ACPI_RESERVED_WORD;\r
194 // UINT32 Identifier\r
d3a15f43
SM
195 // One, and only one, GIC distributor structure must be present\r
196 // in the MADT for an ARM based system\r
197 Gicd->GicId = 0;\r
015a797a
SM
198 // UINT64 PhysicalBaseAddress\r
199 Gicd->PhysicalBaseAddress = GicDInfo->PhysicalBaseAddress;\r
200 // UINT32 VectorBase\r
201 Gicd->SystemVectorBase = EFI_ACPI_RESERVED_DWORD;\r
202 // UINT8 GicVersion\r
203 Gicd->GicVersion = GicDInfo->GicVersion;\r
204 // UINT8 Reserved2[3]\r
205 Gicd->Reserved2[0] = EFI_ACPI_RESERVED_BYTE;\r
206 Gicd->Reserved2[1] = EFI_ACPI_RESERVED_BYTE;\r
207 Gicd->Reserved2[2] = EFI_ACPI_RESERVED_BYTE;\r
208}\r
209\r
210/** Update the GIC MSI Frame Information.\r
211\r
212 @param [in] GicMsiFrame Pointer to GIC MSI Frame structure.\r
213 @param [in] GicMsiFrameInfo Pointer to the GIC MSI Frame Information.\r
214**/\r
215STATIC\r
216VOID\r
217AddGICMsiFrame (\r
218 IN EFI_ACPI_6_2_GIC_MSI_FRAME_STRUCTURE * CONST GicMsiFrame,\r
219 IN CONST CM_ARM_GIC_MSI_FRAME_INFO * CONST GicMsiFrameInfo\r
220)\r
221{\r
222 ASSERT (GicMsiFrame != NULL);\r
223 ASSERT (GicMsiFrameInfo != NULL);\r
224\r
225 GicMsiFrame->Type = EFI_ACPI_6_2_GIC_MSI_FRAME;\r
226 GicMsiFrame->Length = sizeof (EFI_ACPI_6_2_GIC_MSI_FRAME_STRUCTURE);\r
227 GicMsiFrame->Reserved1 = EFI_ACPI_RESERVED_WORD;\r
228 GicMsiFrame->GicMsiFrameId = GicMsiFrameInfo->GicMsiFrameId;\r
229 GicMsiFrame->PhysicalBaseAddress = GicMsiFrameInfo->PhysicalBaseAddress;\r
230\r
231 GicMsiFrame->Flags = GicMsiFrameInfo->Flags;\r
232 GicMsiFrame->SPICount = GicMsiFrameInfo->SPICount;\r
233 GicMsiFrame->SPIBase = GicMsiFrameInfo->SPIBase;\r
234}\r
235\r
236/** Add the GIC MSI Frame Information to the MADT Table.\r
237\r
238 @param [in] GicMsiFrame Pointer to GIC MSI Frame structure list.\r
239 @param [in] GicMsiFrameInfo Pointer to the GIC MSI Frame info list.\r
240 @param [in] GicMsiFrameCount Count of GIC MSI Frames.\r
241**/\r
242STATIC\r
243VOID\r
244AddGICMsiFrameInfoList (\r
245 IN EFI_ACPI_6_2_GIC_MSI_FRAME_STRUCTURE * GicMsiFrame,\r
246 IN CONST CM_ARM_GIC_MSI_FRAME_INFO * GicMsiFrameInfo,\r
247 IN UINT32 GicMsiFrameCount\r
248)\r
249{\r
250 ASSERT (GicMsiFrame != NULL);\r
251 ASSERT (GicMsiFrameInfo != NULL);\r
252\r
253 while (GicMsiFrameCount-- != 0) {\r
254 AddGICMsiFrame (GicMsiFrame++, GicMsiFrameInfo++);\r
255 }\r
256}\r
257\r
258/** Update the GIC Redistributor Information.\r
259\r
260 @param [in] Gicr Pointer to GIC Redistributor structure.\r
261 @param [in] GicRedisributorInfo Pointer to the GIC Redistributor Info.\r
262**/\r
263STATIC\r
264VOID\r
265AddGICRedistributor (\r
266 IN EFI_ACPI_6_2_GICR_STRUCTURE * CONST Gicr,\r
267 IN CONST CM_ARM_GIC_REDIST_INFO * CONST GicRedisributorInfo\r
268 )\r
269{\r
270 ASSERT (Gicr != NULL);\r
271 ASSERT (GicRedisributorInfo != NULL);\r
272\r
273 Gicr->Type = EFI_ACPI_6_2_GICR;\r
274 Gicr->Length = sizeof (EFI_ACPI_6_2_GICR_STRUCTURE);\r
275 Gicr->Reserved = EFI_ACPI_RESERVED_WORD;\r
276 Gicr->DiscoveryRangeBaseAddress =\r
277 GicRedisributorInfo->DiscoveryRangeBaseAddress;\r
278 Gicr->DiscoveryRangeLength = GicRedisributorInfo->DiscoveryRangeLength;\r
279}\r
280\r
281/** Add the GIC Redistributor Information to the MADT Table.\r
282\r
283 @param [in] Gicr Pointer to GIC Redistributor structure list.\r
284 @param [in] GicRInfo Pointer to the GIC Distributor info list.\r
285 @param [in] GicRCount Count of GIC Distributors.\r
286**/\r
287STATIC\r
288VOID\r
289AddGICRedistributorList (\r
290 IN EFI_ACPI_6_2_GICR_STRUCTURE * Gicr,\r
291 IN CONST CM_ARM_GIC_REDIST_INFO * GicRInfo,\r
292 IN UINT32 GicRCount\r
293)\r
294{\r
295 ASSERT (Gicr != NULL);\r
296 ASSERT (GicRInfo != NULL);\r
297\r
298 while (GicRCount-- != 0) {\r
299 AddGICRedistributor (Gicr++, GicRInfo++);\r
300 }\r
301}\r
302\r
303/** Update the GIC Interrupt Translation Service Information\r
304\r
305 @param [in] GicIts Pointer to GIC ITS structure.\r
306 @param [in] GicItsInfo Pointer to the GIC ITS Information.\r
307**/\r
308STATIC\r
309VOID\r
310AddGICInterruptTranslationService (\r
311 IN EFI_ACPI_6_2_GIC_ITS_STRUCTURE * CONST GicIts,\r
312 IN CONST CM_ARM_GIC_ITS_INFO * CONST GicItsInfo\r
313)\r
314{\r
315 ASSERT (GicIts != NULL);\r
316 ASSERT (GicItsInfo != NULL);\r
317\r
318 GicIts->Type = EFI_ACPI_6_2_GIC_ITS;\r
319 GicIts->Length = sizeof (EFI_ACPI_6_2_GIC_ITS_STRUCTURE);\r
320 GicIts->Reserved = EFI_ACPI_RESERVED_WORD;\r
321 GicIts->GicItsId = GicItsInfo->GicItsId;\r
322 GicIts->PhysicalBaseAddress = GicItsInfo->PhysicalBaseAddress;\r
323 GicIts->Reserved2 = EFI_ACPI_RESERVED_DWORD;\r
324}\r
325\r
326/** Add the GIC Interrupt Translation Service Information\r
327 to the MADT Table.\r
328\r
329 @param [in] GicIts Pointer to GIC ITS structure list.\r
330 @param [in] GicItsInfo Pointer to the GIC ITS list.\r
331 @param [in] GicItsCount Count of GIC ITS.\r
332**/\r
333STATIC\r
334VOID\r
335AddGICItsList (\r
336 IN EFI_ACPI_6_2_GIC_ITS_STRUCTURE * GicIts,\r
337 IN CONST CM_ARM_GIC_ITS_INFO * GicItsInfo,\r
338 IN UINT32 GicItsCount\r
339)\r
340{\r
341 ASSERT (GicIts != NULL);\r
342 ASSERT (GicItsInfo != NULL);\r
343\r
344 while (GicItsCount-- != 0) {\r
345 AddGICInterruptTranslationService (GicIts++, GicItsInfo++);\r
346 }\r
347}\r
348\r
349/** Construct the MADT ACPI table.\r
350\r
351 This function invokes the Configuration Manager protocol interface\r
352 to get the required hardware information for generating the ACPI\r
353 table.\r
354\r
355 If this function allocates any resources then they must be freed\r
356 in the FreeXXXXTableResources function.\r
357\r
358 @param [in] This Pointer to the table generator.\r
359 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.\r
360 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
361 Protocol Interface.\r
362 @param [out] Table Pointer to the constructed ACPI Table.\r
363\r
364 @retval EFI_SUCCESS Table generated successfully.\r
365 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
366 @retval EFI_NOT_FOUND The required object was not found.\r
367 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration\r
368 Manager is less than the Object size for the\r
369 requested object.\r
370**/\r
371STATIC\r
372EFI_STATUS\r
373EFIAPI\r
374BuildMadtTable (\r
375 IN CONST ACPI_TABLE_GENERATOR * CONST This,\r
376 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,\r
377 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
378 OUT EFI_ACPI_DESCRIPTION_HEADER ** CONST Table\r
379 )\r
380{\r
381 EFI_STATUS Status;\r
382 UINT32 TableSize;\r
383 UINT32 GicCCount;\r
384 UINT32 GicDCount;\r
385 UINT32 GicMSICount;\r
386 UINT32 GicRedistCount;\r
387 UINT32 GicItsCount;\r
388 CM_ARM_GICC_INFO * GicCInfo;\r
389 CM_ARM_GICD_INFO * GicDInfo;\r
390 CM_ARM_GIC_MSI_FRAME_INFO * GicMSIInfo;\r
391 CM_ARM_GIC_REDIST_INFO * GicRedistInfo;\r
392 CM_ARM_GIC_ITS_INFO * GicItsInfo;\r
393 UINT32 GicCOffset;\r
394 UINT32 GicDOffset;\r
395 UINT32 GicMSIOffset;\r
396 UINT32 GicRedistOffset;\r
397 UINT32 GicItsOffset;\r
398\r
399 EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER * Madt;\r
400\r
401 ASSERT (This != NULL);\r
402 ASSERT (AcpiTableInfo != NULL);\r
403 ASSERT (CfgMgrProtocol != NULL);\r
404 ASSERT (Table != NULL);\r
405 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);\r
406 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);\r
407\r
408 if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) ||\r
409 (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) {\r
410 DEBUG ((\r
411 DEBUG_ERROR,\r
412 "ERROR: MADT: Requested table revision = %d, is not supported."\r
413 "Supported table revision: Minimum = %d, Maximum = %d\n",\r
414 AcpiTableInfo->AcpiTableRevision,\r
415 This->MinAcpiTableRevision,\r
416 This->AcpiTableRevision\r
417 ));\r
418 return EFI_INVALID_PARAMETER;\r
419 }\r
420\r
421 *Table = NULL;\r
422\r
423 Status = GetEArmObjGicCInfo (\r
424 CfgMgrProtocol,\r
425 CM_NULL_TOKEN,\r
426 &GicCInfo,\r
427 &GicCCount\r
428 );\r
429 if (EFI_ERROR (Status)) {\r
430 DEBUG ((\r
431 DEBUG_ERROR,\r
432 "ERROR: MADT: Failed to get GICC Info. Status = %r\n",\r
433 Status\r
434 ));\r
435 goto error_handler;\r
436 }\r
437\r
438 if (GicCCount == 0) {\r
439 DEBUG ((\r
440 DEBUG_ERROR,\r
441 "ERROR: MADT: GIC CPU Interface information not provided.\n"\r
442 ));\r
443 ASSERT (GicCCount != 0);\r
444 Status = EFI_INVALID_PARAMETER;\r
445 goto error_handler;\r
446 }\r
447\r
448 Status = GetEArmObjGicDInfo (\r
449 CfgMgrProtocol,\r
450 CM_NULL_TOKEN,\r
451 &GicDInfo,\r
452 &GicDCount\r
453 );\r
454 if (EFI_ERROR (Status)) {\r
455 DEBUG ((\r
456 DEBUG_ERROR,\r
457 "ERROR: MADT: Failed to get GICD Info. Status = %r\n",\r
458 Status\r
459 ));\r
460 goto error_handler;\r
461 }\r
462\r
463 if (GicDCount == 0) {\r
464 DEBUG ((\r
465 DEBUG_ERROR,\r
466 "ERROR: MADT: GIC Distributor information not provided.\n"\r
467 ));\r
468 ASSERT (GicDCount != 0);\r
469 Status = EFI_INVALID_PARAMETER;\r
470 goto error_handler;\r
471 }\r
472\r
473 if (GicDCount > 1) {\r
474 DEBUG ((\r
475 DEBUG_ERROR,\r
476 "ERROR: MADT: One, and only one, GIC distributor must be present."\r
477 "GicDCount = %d\n",\r
478 GicDCount\r
479 ));\r
480 ASSERT (GicDCount <= 1);\r
481 Status = EFI_INVALID_PARAMETER;\r
482 goto error_handler;\r
483 }\r
484\r
485 Status = GetEArmObjGicMsiFrameInfo (\r
486 CfgMgrProtocol,\r
487 CM_NULL_TOKEN,\r
488 &GicMSIInfo,\r
489 &GicMSICount\r
490 );\r
491 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
492 DEBUG ((\r
493 DEBUG_ERROR,\r
494 "ERROR: MADT: Failed to get GIC MSI Info. Status = %r\n",\r
495 Status\r
496 ));\r
497 goto error_handler;\r
498 }\r
499\r
500 Status = GetEArmObjGicRedistributorInfo (\r
501 CfgMgrProtocol,\r
502 CM_NULL_TOKEN,\r
503 &GicRedistInfo,\r
504 &GicRedistCount\r
505 );\r
506 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
507 DEBUG ((\r
508 DEBUG_ERROR,\r
509 "ERROR: MADT: Failed to get GIC Redistributor Info. Status = %r\n",\r
510 Status\r
511 ));\r
512 goto error_handler;\r
513 }\r
514\r
515 Status = GetEArmObjGicItsInfo (\r
516 CfgMgrProtocol,\r
517 CM_NULL_TOKEN,\r
518 &GicItsInfo,\r
519 &GicItsCount\r
520 );\r
521 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
522 DEBUG ((\r
523 DEBUG_ERROR,\r
524 "ERROR: MADT: Failed to get GIC ITS Info. Status = %r\n",\r
525 Status\r
526 ));\r
527 goto error_handler;\r
528 }\r
529\r
530 TableSize = sizeof (EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER);\r
531\r
532 GicCOffset = TableSize;\r
533 TableSize += (sizeof (EFI_ACPI_6_2_GIC_STRUCTURE) * GicCCount);\r
534\r
535 GicDOffset = TableSize;\r
536 TableSize += (sizeof (EFI_ACPI_6_2_GIC_DISTRIBUTOR_STRUCTURE) * GicDCount);\r
537\r
538 GicMSIOffset = TableSize;\r
539 TableSize += (sizeof (EFI_ACPI_6_2_GIC_MSI_FRAME_STRUCTURE) * GicMSICount);\r
540\r
541 GicRedistOffset = TableSize;\r
542 TableSize += (sizeof (EFI_ACPI_6_2_GICR_STRUCTURE) * GicRedistCount);\r
543\r
544 GicItsOffset = TableSize;\r
545 TableSize += (sizeof (EFI_ACPI_6_2_GIC_ITS_STRUCTURE) * GicItsCount);\r
546\r
547 // Allocate the Buffer for MADT table\r
548 *Table = (EFI_ACPI_DESCRIPTION_HEADER*)AllocateZeroPool (TableSize);\r
549 if (*Table == NULL) {\r
550 Status = EFI_OUT_OF_RESOURCES;\r
551 DEBUG ((\r
552 DEBUG_ERROR,\r
553 "ERROR: MADT: Failed to allocate memory for MADT Table, Size = %d," \\r
554 " Status = %r\n",\r
555 TableSize,\r
556 Status\r
557 ));\r
558 goto error_handler;\r
559 }\r
560\r
561 Madt = (EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER*)*Table;\r
562\r
563 DEBUG ((\r
564 DEBUG_INFO,\r
565 "MADT: Madt = 0x%p TableSize = 0x%x\n",\r
566 Madt,\r
567 TableSize\r
568 ));\r
569\r
570 Status = AddAcpiHeader (\r
571 CfgMgrProtocol,\r
572 This,\r
573 &Madt->Header,\r
c788bdab 574 AcpiTableInfo,\r
015a797a
SM
575 TableSize\r
576 );\r
577 if (EFI_ERROR (Status)) {\r
578 DEBUG ((\r
579 DEBUG_ERROR,\r
580 "ERROR: MADT: Failed to add ACPI header. Status = %r\n",\r
581 Status\r
582 ));\r
583 goto error_handler;\r
584 }\r
585\r
586 AddGICCList (\r
587 (EFI_ACPI_6_2_GIC_STRUCTURE*)((UINT8*)Madt + GicCOffset),\r
588 GicCInfo,\r
589 GicCCount\r
590 );\r
591\r
592 AddGICD (\r
593 (EFI_ACPI_6_2_GIC_DISTRIBUTOR_STRUCTURE*)((UINT8*)Madt + GicDOffset),\r
594 GicDInfo\r
595 );\r
596\r
597 if (GicMSICount != 0) {\r
598 AddGICMsiFrameInfoList (\r
599 (EFI_ACPI_6_2_GIC_MSI_FRAME_STRUCTURE*)((UINT8*)Madt + GicMSIOffset),\r
600 GicMSIInfo,\r
601 GicMSICount\r
602 );\r
603 }\r
604\r
605 if (GicRedistCount != 0) {\r
606 AddGICRedistributorList (\r
607 (EFI_ACPI_6_2_GICR_STRUCTURE*)((UINT8*)Madt + GicRedistOffset),\r
608 GicRedistInfo,\r
609 GicRedistCount\r
610 );\r
611 }\r
612\r
613 if (GicItsCount != 0) {\r
614 AddGICItsList (\r
615 (EFI_ACPI_6_2_GIC_ITS_STRUCTURE*)((UINT8*)Madt + GicItsOffset),\r
616 GicItsInfo,\r
617 GicItsCount\r
618 );\r
619 }\r
620\r
621 return EFI_SUCCESS;\r
622\r
623error_handler:\r
624 if (*Table != NULL) {\r
625 FreePool (*Table);\r
626 *Table = NULL;\r
627 }\r
628 return Status;\r
629}\r
630\r
631/** Free any resources allocated for constructing the MADT\r
632\r
633 @param [in] This Pointer to the table generator.\r
634 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.\r
635 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
636 Protocol Interface.\r
637 @param [in, out] Table Pointer to the ACPI Table.\r
638\r
639 @retval EFI_SUCCESS The resources were freed successfully.\r
640 @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.\r
641**/\r
642STATIC\r
643EFI_STATUS\r
644FreeMadtTableResources (\r
645 IN CONST ACPI_TABLE_GENERATOR * CONST This,\r
646 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,\r
647 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
648 IN OUT EFI_ACPI_DESCRIPTION_HEADER ** CONST Table\r
649 )\r
650{\r
651 ASSERT (This != NULL);\r
652 ASSERT (AcpiTableInfo != NULL);\r
653 ASSERT (CfgMgrProtocol != NULL);\r
654 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);\r
655 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);\r
656\r
657 if ((Table == NULL) || (*Table == NULL)) {\r
658 DEBUG ((DEBUG_ERROR, "ERROR: MADT: Invalid Table Pointer\n"));\r
659 ASSERT ((Table != NULL) && (*Table != NULL));\r
660 return EFI_INVALID_PARAMETER;\r
661 }\r
662\r
663 FreePool (*Table);\r
664 *Table = NULL;\r
665 return EFI_SUCCESS;\r
666}\r
667\r
668/** The MADT Table Generator revision.\r
669*/\r
670#define MADT_GENERATOR_REVISION CREATE_REVISION (1, 0)\r
671\r
672/** The interface for the MADT Table Generator.\r
673*/\r
674STATIC\r
675CONST\r
676ACPI_TABLE_GENERATOR MadtGenerator = {\r
677 // Generator ID\r
678 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdMadt),\r
679 // Generator Description\r
680 L"ACPI.STD.MADT.GENERATOR",\r
681 // ACPI Table Signature\r
682 EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE,\r
683 // ACPI Table Revision supported by this Generator\r
684 EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION,\r
685 // Minimum supported ACPI Table Revision\r
686 EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION,\r
687 // Creator ID\r
688 TABLE_GENERATOR_CREATOR_ID_ARM,\r
689 // Creator Revision\r
690 MADT_GENERATOR_REVISION,\r
691 // Build Table function\r
692 BuildMadtTable,\r
693 // Free Resource function\r
694 FreeMadtTableResources,\r
695 // Extended build function not needed\r
696 NULL,\r
697 // Extended build function not implemented by the generator.\r
698 // Hence extended free resource function is not required.\r
699 NULL\r
700};\r
701\r
702/** Register the Generator with the ACPI Table Factory.\r
703\r
704 @param [in] ImageHandle The handle to the image.\r
705 @param [in] SystemTable Pointer to the System Table.\r
706\r
707 @retval EFI_SUCCESS The Generator is registered.\r
708 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
709 @retval EFI_ALREADY_STARTED The Generator for the Table ID\r
710 is already registered.\r
711**/\r
712EFI_STATUS\r
713EFIAPI\r
714AcpiMadtLibConstructor (\r
715 IN CONST EFI_HANDLE ImageHandle,\r
716 IN EFI_SYSTEM_TABLE * CONST SystemTable\r
717 )\r
718{\r
719 EFI_STATUS Status;\r
720 Status = RegisterAcpiTableGenerator (&MadtGenerator);\r
721 DEBUG ((DEBUG_INFO, "MADT: Register Generator. Status = %r\n", Status));\r
722 ASSERT_EFI_ERROR (Status);\r
723 return Status;\r
724}\r
725\r
726/** Deregister the Generator from the ACPI Table Factory.\r
727\r
728 @param [in] ImageHandle The handle to the image.\r
729 @param [in] SystemTable Pointer to the System Table.\r
730\r
731 @retval EFI_SUCCESS The Generator is deregistered.\r
732 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
733 @retval EFI_NOT_FOUND The Generator is not registered.\r
734**/\r
735EFI_STATUS\r
736EFIAPI\r
737AcpiMadtLibDestructor (\r
738 IN CONST EFI_HANDLE ImageHandle,\r
739 IN EFI_SYSTEM_TABLE * CONST SystemTable\r
740 )\r
741{\r
742 EFI_STATUS Status;\r
743 Status = DeregisterAcpiTableGenerator (&MadtGenerator);\r
744 DEBUG ((DEBUG_INFO, "MADT: Deregister Generator. Status = %r\n", Status));\r
745 ASSERT_EFI_ERROR (Status);\r
746 return Status;\r
747}\r