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