]> git.proxmox.com Git - mirror_edk2.git/blob - DynamicTablesPkg/Library/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c
DynamicTablesPkg: Replace BSD License with BSD+Patent License
[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 /** Add the GIC CPU Interface Information to the MADT Table.
144
145 @param [in] Gicc Pointer to GIC CPU Interface
146 structure list.
147 @param [in] GicCInfo Pointer to the GIC CPU
148 Information list.
149 @param [in] GicCCount Count of GIC CPU Interfaces.
150 **/
151 STATIC
152 VOID
153 AddGICCList (
154 IN EFI_ACPI_6_2_GIC_STRUCTURE * Gicc,
155 IN CONST CM_ARM_GICC_INFO * GicCInfo,
156 IN UINT32 GicCCount
157 )
158 {
159 ASSERT (Gicc != NULL);
160 ASSERT (GicCInfo != NULL);
161
162 while (GicCCount-- != 0) {
163 AddGICC (Gicc++, GicCInfo++);
164 }
165 }
166
167 /** Update the GIC Distributor Information in the MADT Table.
168
169 @param [in] Gicd Pointer to GIC Distributor structure.
170 @param [in] GicDInfo Pointer to the GIC Distributor Information.
171 **/
172 STATIC
173 VOID
174 AddGICD (
175 EFI_ACPI_6_2_GIC_DISTRIBUTOR_STRUCTURE * CONST Gicd,
176 CONST CM_ARM_GICD_INFO * CONST GicDInfo
177 )
178 {
179 ASSERT (Gicd != NULL);
180 ASSERT (GicDInfo != NULL);
181
182 // UINT8 Type
183 Gicd->Type = EFI_ACPI_6_2_GICD;
184 // UINT8 Length
185 Gicd->Length = sizeof (EFI_ACPI_6_2_GIC_DISTRIBUTOR_STRUCTURE);
186 // UINT16 Reserved
187 Gicd->Reserved1 = EFI_ACPI_RESERVED_WORD;
188 // UINT32 Identifier
189 // One, and only one, GIC distributor structure must be present
190 // in the MADT for an ARM based system
191 Gicd->GicId = 0;
192 // UINT64 PhysicalBaseAddress
193 Gicd->PhysicalBaseAddress = GicDInfo->PhysicalBaseAddress;
194 // UINT32 VectorBase
195 Gicd->SystemVectorBase = EFI_ACPI_RESERVED_DWORD;
196 // UINT8 GicVersion
197 Gicd->GicVersion = GicDInfo->GicVersion;
198 // UINT8 Reserved2[3]
199 Gicd->Reserved2[0] = EFI_ACPI_RESERVED_BYTE;
200 Gicd->Reserved2[1] = EFI_ACPI_RESERVED_BYTE;
201 Gicd->Reserved2[2] = EFI_ACPI_RESERVED_BYTE;
202 }
203
204 /** Update the GIC MSI Frame Information.
205
206 @param [in] GicMsiFrame Pointer to GIC MSI Frame structure.
207 @param [in] GicMsiFrameInfo Pointer to the GIC MSI Frame Information.
208 **/
209 STATIC
210 VOID
211 AddGICMsiFrame (
212 IN EFI_ACPI_6_2_GIC_MSI_FRAME_STRUCTURE * CONST GicMsiFrame,
213 IN CONST CM_ARM_GIC_MSI_FRAME_INFO * CONST GicMsiFrameInfo
214 )
215 {
216 ASSERT (GicMsiFrame != NULL);
217 ASSERT (GicMsiFrameInfo != NULL);
218
219 GicMsiFrame->Type = EFI_ACPI_6_2_GIC_MSI_FRAME;
220 GicMsiFrame->Length = sizeof (EFI_ACPI_6_2_GIC_MSI_FRAME_STRUCTURE);
221 GicMsiFrame->Reserved1 = EFI_ACPI_RESERVED_WORD;
222 GicMsiFrame->GicMsiFrameId = GicMsiFrameInfo->GicMsiFrameId;
223 GicMsiFrame->PhysicalBaseAddress = GicMsiFrameInfo->PhysicalBaseAddress;
224
225 GicMsiFrame->Flags = GicMsiFrameInfo->Flags;
226 GicMsiFrame->SPICount = GicMsiFrameInfo->SPICount;
227 GicMsiFrame->SPIBase = GicMsiFrameInfo->SPIBase;
228 }
229
230 /** Add the GIC MSI Frame Information to the MADT Table.
231
232 @param [in] GicMsiFrame Pointer to GIC MSI Frame structure list.
233 @param [in] GicMsiFrameInfo Pointer to the GIC MSI Frame info list.
234 @param [in] GicMsiFrameCount Count of GIC MSI Frames.
235 **/
236 STATIC
237 VOID
238 AddGICMsiFrameInfoList (
239 IN EFI_ACPI_6_2_GIC_MSI_FRAME_STRUCTURE * GicMsiFrame,
240 IN CONST CM_ARM_GIC_MSI_FRAME_INFO * GicMsiFrameInfo,
241 IN UINT32 GicMsiFrameCount
242 )
243 {
244 ASSERT (GicMsiFrame != NULL);
245 ASSERT (GicMsiFrameInfo != NULL);
246
247 while (GicMsiFrameCount-- != 0) {
248 AddGICMsiFrame (GicMsiFrame++, GicMsiFrameInfo++);
249 }
250 }
251
252 /** Update the GIC Redistributor Information.
253
254 @param [in] Gicr Pointer to GIC Redistributor structure.
255 @param [in] GicRedisributorInfo Pointer to the GIC Redistributor Info.
256 **/
257 STATIC
258 VOID
259 AddGICRedistributor (
260 IN EFI_ACPI_6_2_GICR_STRUCTURE * CONST Gicr,
261 IN CONST CM_ARM_GIC_REDIST_INFO * CONST GicRedisributorInfo
262 )
263 {
264 ASSERT (Gicr != NULL);
265 ASSERT (GicRedisributorInfo != NULL);
266
267 Gicr->Type = EFI_ACPI_6_2_GICR;
268 Gicr->Length = sizeof (EFI_ACPI_6_2_GICR_STRUCTURE);
269 Gicr->Reserved = EFI_ACPI_RESERVED_WORD;
270 Gicr->DiscoveryRangeBaseAddress =
271 GicRedisributorInfo->DiscoveryRangeBaseAddress;
272 Gicr->DiscoveryRangeLength = GicRedisributorInfo->DiscoveryRangeLength;
273 }
274
275 /** Add the GIC Redistributor Information to the MADT Table.
276
277 @param [in] Gicr Pointer to GIC Redistributor structure list.
278 @param [in] GicRInfo Pointer to the GIC Distributor info list.
279 @param [in] GicRCount Count of GIC Distributors.
280 **/
281 STATIC
282 VOID
283 AddGICRedistributorList (
284 IN EFI_ACPI_6_2_GICR_STRUCTURE * Gicr,
285 IN CONST CM_ARM_GIC_REDIST_INFO * GicRInfo,
286 IN UINT32 GicRCount
287 )
288 {
289 ASSERT (Gicr != NULL);
290 ASSERT (GicRInfo != NULL);
291
292 while (GicRCount-- != 0) {
293 AddGICRedistributor (Gicr++, GicRInfo++);
294 }
295 }
296
297 /** Update the GIC Interrupt Translation Service Information
298
299 @param [in] GicIts Pointer to GIC ITS structure.
300 @param [in] GicItsInfo Pointer to the GIC ITS Information.
301 **/
302 STATIC
303 VOID
304 AddGICInterruptTranslationService (
305 IN EFI_ACPI_6_2_GIC_ITS_STRUCTURE * CONST GicIts,
306 IN CONST CM_ARM_GIC_ITS_INFO * CONST GicItsInfo
307 )
308 {
309 ASSERT (GicIts != NULL);
310 ASSERT (GicItsInfo != NULL);
311
312 GicIts->Type = EFI_ACPI_6_2_GIC_ITS;
313 GicIts->Length = sizeof (EFI_ACPI_6_2_GIC_ITS_STRUCTURE);
314 GicIts->Reserved = EFI_ACPI_RESERVED_WORD;
315 GicIts->GicItsId = GicItsInfo->GicItsId;
316 GicIts->PhysicalBaseAddress = GicItsInfo->PhysicalBaseAddress;
317 GicIts->Reserved2 = EFI_ACPI_RESERVED_DWORD;
318 }
319
320 /** Add the GIC Interrupt Translation Service Information
321 to the MADT Table.
322
323 @param [in] GicIts Pointer to GIC ITS structure list.
324 @param [in] GicItsInfo Pointer to the GIC ITS list.
325 @param [in] GicItsCount Count of GIC ITS.
326 **/
327 STATIC
328 VOID
329 AddGICItsList (
330 IN EFI_ACPI_6_2_GIC_ITS_STRUCTURE * GicIts,
331 IN CONST CM_ARM_GIC_ITS_INFO * GicItsInfo,
332 IN UINT32 GicItsCount
333 )
334 {
335 ASSERT (GicIts != NULL);
336 ASSERT (GicItsInfo != NULL);
337
338 while (GicItsCount-- != 0) {
339 AddGICInterruptTranslationService (GicIts++, GicItsInfo++);
340 }
341 }
342
343 /** Construct the MADT ACPI table.
344
345 This function invokes the Configuration Manager protocol interface
346 to get the required hardware information for generating the ACPI
347 table.
348
349 If this function allocates any resources then they must be freed
350 in the FreeXXXXTableResources function.
351
352 @param [in] This Pointer to the table generator.
353 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.
354 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
355 Protocol Interface.
356 @param [out] Table Pointer to the constructed ACPI Table.
357
358 @retval EFI_SUCCESS Table generated successfully.
359 @retval EFI_INVALID_PARAMETER A parameter is invalid.
360 @retval EFI_NOT_FOUND The required object was not found.
361 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
362 Manager is less than the Object size for the
363 requested object.
364 **/
365 STATIC
366 EFI_STATUS
367 EFIAPI
368 BuildMadtTable (
369 IN CONST ACPI_TABLE_GENERATOR * CONST This,
370 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,
371 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
372 OUT EFI_ACPI_DESCRIPTION_HEADER ** CONST Table
373 )
374 {
375 EFI_STATUS Status;
376 UINT32 TableSize;
377 UINT32 GicCCount;
378 UINT32 GicDCount;
379 UINT32 GicMSICount;
380 UINT32 GicRedistCount;
381 UINT32 GicItsCount;
382 CM_ARM_GICC_INFO * GicCInfo;
383 CM_ARM_GICD_INFO * GicDInfo;
384 CM_ARM_GIC_MSI_FRAME_INFO * GicMSIInfo;
385 CM_ARM_GIC_REDIST_INFO * GicRedistInfo;
386 CM_ARM_GIC_ITS_INFO * GicItsInfo;
387 UINT32 GicCOffset;
388 UINT32 GicDOffset;
389 UINT32 GicMSIOffset;
390 UINT32 GicRedistOffset;
391 UINT32 GicItsOffset;
392
393 EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER * Madt;
394
395 ASSERT (This != NULL);
396 ASSERT (AcpiTableInfo != NULL);
397 ASSERT (CfgMgrProtocol != NULL);
398 ASSERT (Table != NULL);
399 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
400 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
401
402 if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) ||
403 (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) {
404 DEBUG ((
405 DEBUG_ERROR,
406 "ERROR: MADT: Requested table revision = %d, is not supported."
407 "Supported table revision: Minimum = %d, Maximum = %d\n",
408 AcpiTableInfo->AcpiTableRevision,
409 This->MinAcpiTableRevision,
410 This->AcpiTableRevision
411 ));
412 return EFI_INVALID_PARAMETER;
413 }
414
415 *Table = NULL;
416
417 Status = GetEArmObjGicCInfo (
418 CfgMgrProtocol,
419 CM_NULL_TOKEN,
420 &GicCInfo,
421 &GicCCount
422 );
423 if (EFI_ERROR (Status)) {
424 DEBUG ((
425 DEBUG_ERROR,
426 "ERROR: MADT: Failed to get GICC Info. Status = %r\n",
427 Status
428 ));
429 goto error_handler;
430 }
431
432 if (GicCCount == 0) {
433 DEBUG ((
434 DEBUG_ERROR,
435 "ERROR: MADT: GIC CPU Interface information not provided.\n"
436 ));
437 ASSERT (GicCCount != 0);
438 Status = EFI_INVALID_PARAMETER;
439 goto error_handler;
440 }
441
442 Status = GetEArmObjGicDInfo (
443 CfgMgrProtocol,
444 CM_NULL_TOKEN,
445 &GicDInfo,
446 &GicDCount
447 );
448 if (EFI_ERROR (Status)) {
449 DEBUG ((
450 DEBUG_ERROR,
451 "ERROR: MADT: Failed to get GICD Info. Status = %r\n",
452 Status
453 ));
454 goto error_handler;
455 }
456
457 if (GicDCount == 0) {
458 DEBUG ((
459 DEBUG_ERROR,
460 "ERROR: MADT: GIC Distributor information not provided.\n"
461 ));
462 ASSERT (GicDCount != 0);
463 Status = EFI_INVALID_PARAMETER;
464 goto error_handler;
465 }
466
467 if (GicDCount > 1) {
468 DEBUG ((
469 DEBUG_ERROR,
470 "ERROR: MADT: One, and only one, GIC distributor must be present."
471 "GicDCount = %d\n",
472 GicDCount
473 ));
474 ASSERT (GicDCount <= 1);
475 Status = EFI_INVALID_PARAMETER;
476 goto error_handler;
477 }
478
479 Status = GetEArmObjGicMsiFrameInfo (
480 CfgMgrProtocol,
481 CM_NULL_TOKEN,
482 &GicMSIInfo,
483 &GicMSICount
484 );
485 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
486 DEBUG ((
487 DEBUG_ERROR,
488 "ERROR: MADT: Failed to get GIC MSI Info. Status = %r\n",
489 Status
490 ));
491 goto error_handler;
492 }
493
494 Status = GetEArmObjGicRedistributorInfo (
495 CfgMgrProtocol,
496 CM_NULL_TOKEN,
497 &GicRedistInfo,
498 &GicRedistCount
499 );
500 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
501 DEBUG ((
502 DEBUG_ERROR,
503 "ERROR: MADT: Failed to get GIC Redistributor Info. Status = %r\n",
504 Status
505 ));
506 goto error_handler;
507 }
508
509 Status = GetEArmObjGicItsInfo (
510 CfgMgrProtocol,
511 CM_NULL_TOKEN,
512 &GicItsInfo,
513 &GicItsCount
514 );
515 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
516 DEBUG ((
517 DEBUG_ERROR,
518 "ERROR: MADT: Failed to get GIC ITS Info. Status = %r\n",
519 Status
520 ));
521 goto error_handler;
522 }
523
524 TableSize = sizeof (EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER);
525
526 GicCOffset = TableSize;
527 TableSize += (sizeof (EFI_ACPI_6_2_GIC_STRUCTURE) * GicCCount);
528
529 GicDOffset = TableSize;
530 TableSize += (sizeof (EFI_ACPI_6_2_GIC_DISTRIBUTOR_STRUCTURE) * GicDCount);
531
532 GicMSIOffset = TableSize;
533 TableSize += (sizeof (EFI_ACPI_6_2_GIC_MSI_FRAME_STRUCTURE) * GicMSICount);
534
535 GicRedistOffset = TableSize;
536 TableSize += (sizeof (EFI_ACPI_6_2_GICR_STRUCTURE) * GicRedistCount);
537
538 GicItsOffset = TableSize;
539 TableSize += (sizeof (EFI_ACPI_6_2_GIC_ITS_STRUCTURE) * GicItsCount);
540
541 // Allocate the Buffer for MADT table
542 *Table = (EFI_ACPI_DESCRIPTION_HEADER*)AllocateZeroPool (TableSize);
543 if (*Table == NULL) {
544 Status = EFI_OUT_OF_RESOURCES;
545 DEBUG ((
546 DEBUG_ERROR,
547 "ERROR: MADT: Failed to allocate memory for MADT Table, Size = %d," \
548 " Status = %r\n",
549 TableSize,
550 Status
551 ));
552 goto error_handler;
553 }
554
555 Madt = (EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER*)*Table;
556
557 DEBUG ((
558 DEBUG_INFO,
559 "MADT: Madt = 0x%p TableSize = 0x%x\n",
560 Madt,
561 TableSize
562 ));
563
564 Status = AddAcpiHeader (
565 CfgMgrProtocol,
566 This,
567 &Madt->Header,
568 AcpiTableInfo,
569 TableSize
570 );
571 if (EFI_ERROR (Status)) {
572 DEBUG ((
573 DEBUG_ERROR,
574 "ERROR: MADT: Failed to add ACPI header. Status = %r\n",
575 Status
576 ));
577 goto error_handler;
578 }
579
580 AddGICCList (
581 (EFI_ACPI_6_2_GIC_STRUCTURE*)((UINT8*)Madt + GicCOffset),
582 GicCInfo,
583 GicCCount
584 );
585
586 AddGICD (
587 (EFI_ACPI_6_2_GIC_DISTRIBUTOR_STRUCTURE*)((UINT8*)Madt + GicDOffset),
588 GicDInfo
589 );
590
591 if (GicMSICount != 0) {
592 AddGICMsiFrameInfoList (
593 (EFI_ACPI_6_2_GIC_MSI_FRAME_STRUCTURE*)((UINT8*)Madt + GicMSIOffset),
594 GicMSIInfo,
595 GicMSICount
596 );
597 }
598
599 if (GicRedistCount != 0) {
600 AddGICRedistributorList (
601 (EFI_ACPI_6_2_GICR_STRUCTURE*)((UINT8*)Madt + GicRedistOffset),
602 GicRedistInfo,
603 GicRedistCount
604 );
605 }
606
607 if (GicItsCount != 0) {
608 AddGICItsList (
609 (EFI_ACPI_6_2_GIC_ITS_STRUCTURE*)((UINT8*)Madt + GicItsOffset),
610 GicItsInfo,
611 GicItsCount
612 );
613 }
614
615 return EFI_SUCCESS;
616
617 error_handler:
618 if (*Table != NULL) {
619 FreePool (*Table);
620 *Table = NULL;
621 }
622 return Status;
623 }
624
625 /** Free any resources allocated for constructing the MADT
626
627 @param [in] This Pointer to the table generator.
628 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.
629 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
630 Protocol Interface.
631 @param [in, out] Table Pointer to the ACPI Table.
632
633 @retval EFI_SUCCESS The resources were freed successfully.
634 @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
635 **/
636 STATIC
637 EFI_STATUS
638 FreeMadtTableResources (
639 IN CONST ACPI_TABLE_GENERATOR * CONST This,
640 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,
641 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
642 IN OUT EFI_ACPI_DESCRIPTION_HEADER ** CONST Table
643 )
644 {
645 ASSERT (This != NULL);
646 ASSERT (AcpiTableInfo != NULL);
647 ASSERT (CfgMgrProtocol != NULL);
648 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
649 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
650
651 if ((Table == NULL) || (*Table == NULL)) {
652 DEBUG ((DEBUG_ERROR, "ERROR: MADT: Invalid Table Pointer\n"));
653 ASSERT ((Table != NULL) && (*Table != NULL));
654 return EFI_INVALID_PARAMETER;
655 }
656
657 FreePool (*Table);
658 *Table = NULL;
659 return EFI_SUCCESS;
660 }
661
662 /** The MADT Table Generator revision.
663 */
664 #define MADT_GENERATOR_REVISION CREATE_REVISION (1, 0)
665
666 /** The interface for the MADT Table Generator.
667 */
668 STATIC
669 CONST
670 ACPI_TABLE_GENERATOR MadtGenerator = {
671 // Generator ID
672 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdMadt),
673 // Generator Description
674 L"ACPI.STD.MADT.GENERATOR",
675 // ACPI Table Signature
676 EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE,
677 // ACPI Table Revision supported by this Generator
678 EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION,
679 // Minimum supported ACPI Table Revision
680 EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION,
681 // Creator ID
682 TABLE_GENERATOR_CREATOR_ID_ARM,
683 // Creator Revision
684 MADT_GENERATOR_REVISION,
685 // Build Table function
686 BuildMadtTable,
687 // Free Resource function
688 FreeMadtTableResources,
689 // Extended build function not needed
690 NULL,
691 // Extended build function not implemented by the generator.
692 // Hence extended free resource function is not required.
693 NULL
694 };
695
696 /** Register the Generator with the ACPI Table Factory.
697
698 @param [in] ImageHandle The handle to the image.
699 @param [in] SystemTable Pointer to the System Table.
700
701 @retval EFI_SUCCESS The Generator is registered.
702 @retval EFI_INVALID_PARAMETER A parameter is invalid.
703 @retval EFI_ALREADY_STARTED The Generator for the Table ID
704 is already registered.
705 **/
706 EFI_STATUS
707 EFIAPI
708 AcpiMadtLibConstructor (
709 IN CONST EFI_HANDLE ImageHandle,
710 IN EFI_SYSTEM_TABLE * CONST SystemTable
711 )
712 {
713 EFI_STATUS Status;
714 Status = RegisterAcpiTableGenerator (&MadtGenerator);
715 DEBUG ((DEBUG_INFO, "MADT: Register Generator. Status = %r\n", Status));
716 ASSERT_EFI_ERROR (Status);
717 return Status;
718 }
719
720 /** Deregister the Generator from the ACPI Table Factory.
721
722 @param [in] ImageHandle The handle to the image.
723 @param [in] SystemTable Pointer to the System Table.
724
725 @retval EFI_SUCCESS The Generator is deregistered.
726 @retval EFI_INVALID_PARAMETER A parameter is invalid.
727 @retval EFI_NOT_FOUND The Generator is not registered.
728 **/
729 EFI_STATUS
730 EFIAPI
731 AcpiMadtLibDestructor (
732 IN CONST EFI_HANDLE ImageHandle,
733 IN EFI_SYSTEM_TABLE * CONST SystemTable
734 )
735 {
736 EFI_STATUS Status;
737 Status = DeregisterAcpiTableGenerator (&MadtGenerator);
738 DEBUG ((DEBUG_INFO, "MADT: Deregister Generator. Status = %r\n", Status));
739 ASSERT_EFI_ERROR (Status);
740 return Status;
741 }