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