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