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