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