]> git.proxmox.com Git - mirror_edk2.git/blame - DynamicTablesPkg/Library/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerator.c
DynamicTablesPkg: Add OEM Info
[mirror_edk2.git] / DynamicTablesPkg / Library / Acpi / Arm / AcpiGtdtLibArm / GtdtGenerator.c
CommitLineData
9c720258
SM
1/** @file\r
2 GTDT 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 GTDT Generator\r
31\r
32Requirements:\r
33 The following Configuration Manager Object(s) are required by\r
34 this Generator:\r
35 - EArmObjGenericTimerInfo\r
36 - EArmObjPlatformGenericWatchdogInfo (OPTIONAL)\r
37 - EArmObjPlatformGTBlockInfo (OPTIONAL)\r
38 - EArmObjGTBlockTimerFrameInfo (OPTIONAL)\r
39*/\r
40\r
41/** This macro expands to a function that retrieves the Generic\r
42 Timer Information from the Configuration Manager.\r
43*/\r
44GET_OBJECT_LIST (\r
45 EObjNameSpaceArm,\r
46 EArmObjGenericTimerInfo,\r
47 CM_ARM_GENERIC_TIMER_INFO\r
48 );\r
49\r
50/** This macro expands to a function that retrieves the SBSA Generic\r
51 Watchdog Timer Information from the Configuration Manager.\r
52*/\r
53GET_OBJECT_LIST (\r
54 EObjNameSpaceArm,\r
55 EArmObjPlatformGenericWatchdogInfo,\r
56 CM_ARM_GENERIC_WATCHDOG_INFO\r
57 );\r
58\r
59/** This macro expands to a function that retrieves the Platform Generic\r
60 Timer Block Information from the Configuration Manager.\r
61*/\r
62GET_OBJECT_LIST (\r
63 EObjNameSpaceArm,\r
64 EArmObjPlatformGTBlockInfo,\r
65 CM_ARM_GTBLOCK_INFO\r
66 );\r
67\r
68/** This macro expands to a function that retrieves the Generic\r
69 Timer Block Timer Frame Information from the Configuration Manager.\r
70*/\r
71GET_OBJECT_LIST (\r
72 EObjNameSpaceArm,\r
73 EArmObjGTBlockTimerFrameInfo,\r
74 CM_ARM_GTBLOCK_TIMER_FRAME_INFO\r
75 );\r
76\r
77/** Add the Generic Timer Information to the GTDT table.\r
78\r
79 Also update the Platform Timer offset information if the platform\r
80 implements platform timers.\r
81\r
82 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
83 Protocol Interface.\r
84 @param [in] Gtdt Pointer to the GTDT Table.\r
85 @param [in] PlatformTimerCount Platform timer count.\r
86\r
87 @retval EFI_SUCCESS Success.\r
88 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
89 @retval EFI_NOT_FOUND The required object was not found.\r
90 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration\r
91 Manager is less than the Object size for the\r
92 requested object.\r
93**/\r
94STATIC\r
95EFI_STATUS\r
96EFIAPI\r
97AddGenericTimerInfo (\r
98 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
99 IN EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE * CONST Gtdt,\r
100 IN CONST UINT32 PlatformTimerCount\r
101)\r
102{\r
103 EFI_STATUS Status;\r
104 CM_ARM_GENERIC_TIMER_INFO * GenericTimerInfo;\r
105\r
106 ASSERT (CfgMgrProtocol != NULL);\r
107 ASSERT (Gtdt != NULL);\r
108\r
109 Status = GetEArmObjGenericTimerInfo (\r
110 CfgMgrProtocol,\r
111 CM_NULL_TOKEN,\r
112 &GenericTimerInfo,\r
113 NULL\r
114 );\r
115\r
116 if (EFI_ERROR (Status)) {\r
117 DEBUG ((\r
118 DEBUG_ERROR,\r
119 "ERROR: GTDT: Failed to get GenericTimerInfo. Status = %r\n",\r
120 Status\r
121 ));\r
122 return Status;\r
123 }\r
124\r
125 Gtdt->CntControlBasePhysicalAddress =\r
126 GenericTimerInfo->CounterControlBaseAddress;\r
127 Gtdt->Reserved = EFI_ACPI_RESERVED_DWORD;\r
128 Gtdt->SecurePL1TimerGSIV = GenericTimerInfo->SecurePL1TimerGSIV;\r
129 Gtdt->SecurePL1TimerFlags = GenericTimerInfo->SecurePL1TimerFlags;\r
130 Gtdt->NonSecurePL1TimerGSIV = GenericTimerInfo->NonSecurePL1TimerGSIV;\r
131 Gtdt->NonSecurePL1TimerFlags = GenericTimerInfo->NonSecurePL1TimerFlags;\r
132 Gtdt->VirtualTimerGSIV = GenericTimerInfo->VirtualTimerGSIV;\r
133 Gtdt->VirtualTimerFlags = GenericTimerInfo->VirtualTimerFlags;\r
134 Gtdt->NonSecurePL2TimerGSIV = GenericTimerInfo->NonSecurePL2TimerGSIV;\r
135 Gtdt->NonSecurePL2TimerFlags = GenericTimerInfo->NonSecurePL2TimerFlags;\r
136 Gtdt->CntReadBasePhysicalAddress =\r
137 GenericTimerInfo->CounterReadBaseAddress;\r
138 Gtdt->PlatformTimerCount = PlatformTimerCount;\r
139 Gtdt->PlatformTimerOffset = (PlatformTimerCount == 0) ? 0 :\r
140 sizeof (EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE);\r
141\r
142 return EFI_SUCCESS;\r
143}\r
144\r
145/** Add the SBSA Generic Watchdog Timers to the GTDT table.\r
146\r
147 @param [in] Gtdt Pointer to the GTDT Table.\r
148 @param [in] WatchdogOffset Offset to the watchdog information in the\r
149 GTDT Table.\r
150 @param [in] WatchdogInfoList Pointer to the watchdog information list.\r
151 @param [in] WatchdogCount Platform timer count.\r
152**/\r
153STATIC\r
154VOID\r
155AddGenericWatchdogList (\r
156 IN EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE * CONST Gtdt,\r
157 IN CONST UINT32 WatchdogOffset,\r
158 IN CONST CM_ARM_GENERIC_WATCHDOG_INFO * WatchdogInfoList,\r
159 IN UINT32 WatchdogCount\r
160 )\r
161{\r
162 EFI_ACPI_6_2_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE * Watchdog;\r
163\r
164 ASSERT (Gtdt != NULL);\r
165 ASSERT (WatchdogInfoList != NULL);\r
166\r
167 Watchdog = (EFI_ACPI_6_2_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE *)\r
168 ((UINT8*)Gtdt + WatchdogOffset);\r
169\r
170 while (WatchdogCount-- != 0) {\r
171 // Add watchdog entry\r
172 DEBUG ((DEBUG_INFO, "GTDT: Watchdog = 0x%p\n", Watchdog));\r
173 Watchdog->Type = EFI_ACPI_6_2_GTDT_SBSA_GENERIC_WATCHDOG;\r
174 Watchdog->Length =\r
175 sizeof (EFI_ACPI_6_2_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE);\r
176 Watchdog->Reserved = EFI_ACPI_RESERVED_BYTE;\r
177 Watchdog->RefreshFramePhysicalAddress =\r
178 WatchdogInfoList->RefreshFrameAddress;\r
179 Watchdog->WatchdogControlFramePhysicalAddress =\r
180 WatchdogInfoList->ControlFrameAddress;\r
181 Watchdog->WatchdogTimerGSIV = WatchdogInfoList->TimerGSIV;\r
182 Watchdog->WatchdogTimerFlags = WatchdogInfoList->Flags;\r
183 Watchdog++;\r
184 WatchdogInfoList++;\r
185 } // for\r
186}\r
187\r
188/** Update the GT Block Timer Frame lists in the GTDT Table.\r
189\r
190 @param [in] GtBlockFrame Pointer to the GT Block Frames\r
191 list to be updated.\r
192 @param [in] GTBlockTimerFrameList Pointer to the GT Block Frame\r
193 Information List.\r
194 @param [in] GTBlockFrameCount Number of GT Block Frames.\r
195\r
196 @retval EFI_SUCCESS Table generated successfully.\r
197 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
198**/\r
199STATIC\r
200EFI_STATUS\r
201AddGTBlockTimerFrames (\r
202 IN EFI_ACPI_6_2_GTDT_GT_BLOCK_TIMER_STRUCTURE * GtBlockFrame,\r
203 IN CONST CM_ARM_GTBLOCK_TIMER_FRAME_INFO * GTBlockTimerFrameList,\r
204 IN UINT32 GTBlockFrameCount\r
205)\r
206{\r
207 ASSERT (GtBlockFrame != NULL);\r
208 ASSERT (GTBlockTimerFrameList != NULL);\r
209\r
210 if (GTBlockFrameCount > 8) {\r
211 DEBUG ((\r
212 DEBUG_ERROR,\r
213 "ERROR: GTDT: GT Block Frame Count %d is greater than 8\n",\r
214 GTBlockFrameCount\r
215 ));\r
216 ASSERT (GTBlockFrameCount <= 8);\r
217 return EFI_INVALID_PARAMETER;\r
218 }\r
219\r
220 while (GTBlockFrameCount-- != 0) {\r
221 DEBUG ((\r
222 DEBUG_INFO,\r
223 "GTDT: GtBlockFrame = 0x%p\n",\r
224 GtBlockFrame\r
225 ));\r
226\r
227 GtBlockFrame->GTFrameNumber = GTBlockTimerFrameList->FrameNumber;\r
228 GtBlockFrame->Reserved[0] = EFI_ACPI_RESERVED_BYTE;\r
229 GtBlockFrame->Reserved[1] = EFI_ACPI_RESERVED_BYTE;\r
230 GtBlockFrame->Reserved[2] = EFI_ACPI_RESERVED_BYTE;\r
231\r
232 GtBlockFrame->CntBaseX = GTBlockTimerFrameList->PhysicalAddressCntBase;\r
233 GtBlockFrame->CntEL0BaseX =\r
234 GTBlockTimerFrameList->PhysicalAddressCntEL0Base;\r
235\r
236 GtBlockFrame->GTxPhysicalTimerGSIV =\r
237 GTBlockTimerFrameList->PhysicalTimerGSIV;\r
238 GtBlockFrame->GTxPhysicalTimerFlags =\r
239 GTBlockTimerFrameList->PhysicalTimerFlags;\r
240\r
241 GtBlockFrame->GTxVirtualTimerGSIV = GTBlockTimerFrameList->VirtualTimerGSIV;\r
242 GtBlockFrame->GTxVirtualTimerFlags =\r
243 GTBlockTimerFrameList->VirtualTimerFlags;\r
244\r
245 GtBlockFrame->GTxCommonFlags = GTBlockTimerFrameList->CommonFlags;\r
246 GtBlockFrame++;\r
247 GTBlockTimerFrameList++;\r
248 } // for\r
249 return EFI_SUCCESS;\r
250}\r
251\r
252/** Add the GT Block Timers in the GTDT Table.\r
253\r
254 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
255 Protocol Interface.\r
256 @param [in] Gtdt Pointer to the GTDT Table.\r
257 @param [in] GTBlockOffset Offset of the GT Block\r
258 information in the GTDT Table.\r
259 @param [in] GTBlockInfo Pointer to the GT Block\r
260 Information List.\r
261 @param [in] BlockTimerCount Number of GT Block Timers.\r
262\r
263 @retval EFI_SUCCESS Table generated successfully.\r
264 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
265**/\r
266STATIC\r
267EFI_STATUS\r
268AddGTBlockList (\r
269 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
270 IN EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE * CONST Gtdt,\r
271 IN CONST UINT32 GTBlockOffset,\r
272 IN CONST CM_ARM_GTBLOCK_INFO * GTBlockInfo,\r
273 IN UINT32 BlockTimerCount\r
274)\r
275{\r
276 EFI_STATUS Status;\r
277 EFI_ACPI_6_2_GTDT_GT_BLOCK_STRUCTURE * GTBlock;\r
278 EFI_ACPI_6_2_GTDT_GT_BLOCK_TIMER_STRUCTURE * GtBlockFrame;\r
279 CM_ARM_GTBLOCK_TIMER_FRAME_INFO * GTBlockTimerFrameList;\r
280 UINT32 GTBlockTimerFrameCount;\r
281\r
282 ASSERT (Gtdt != NULL);\r
283 ASSERT (GTBlockInfo != NULL);\r
284\r
285 GTBlock = (EFI_ACPI_6_2_GTDT_GT_BLOCK_STRUCTURE *)((UINT8*)Gtdt +\r
286 GTBlockOffset);\r
287\r
288 while (BlockTimerCount-- != 0) {\r
289 DEBUG ((DEBUG_INFO, "GTDT: GTBlock = 0x%p\n", GTBlock));\r
290\r
291 Status = GetEArmObjGTBlockTimerFrameInfo (\r
292 CfgMgrProtocol,\r
293 GTBlockInfo->GTBlockTimerFrameToken,\r
294 &GTBlockTimerFrameList,\r
295 &GTBlockTimerFrameCount\r
296 );\r
297 if (EFI_ERROR (Status) ||\r
298 (GTBlockTimerFrameCount != GTBlockInfo->GTBlockTimerFrameCount)) {\r
299 DEBUG ((\r
300 DEBUG_ERROR,\r
301 "ERROR: GTDT: Failed to get Generic Timer Frames. Status = %r\n",\r
302 Status\r
303 ));\r
304 return Status;\r
305 }\r
306\r
307 GTBlock->Type = EFI_ACPI_6_2_GTDT_GT_BLOCK;\r
308 GTBlock->Length = sizeof (EFI_ACPI_6_2_GTDT_GT_BLOCK_STRUCTURE) +\r
309 (sizeof (EFI_ACPI_6_2_GTDT_GT_BLOCK_TIMER_STRUCTURE) *\r
310 GTBlockInfo->GTBlockTimerFrameCount);\r
311\r
312 GTBlock->Reserved = EFI_ACPI_RESERVED_BYTE;\r
313 GTBlock->CntCtlBase = GTBlockInfo->GTBlockPhysicalAddress;\r
314 GTBlock->GTBlockTimerCount = GTBlockInfo->GTBlockTimerFrameCount;\r
315 GTBlock->GTBlockTimerOffset =\r
316 sizeof (EFI_ACPI_6_2_GTDT_GT_BLOCK_STRUCTURE);\r
317\r
318 GtBlockFrame = (EFI_ACPI_6_2_GTDT_GT_BLOCK_TIMER_STRUCTURE*)\r
319 ((UINT8*)GTBlock + GTBlock->GTBlockTimerOffset);\r
320\r
321 // Add GT Block Timer frames\r
322 Status = AddGTBlockTimerFrames (\r
323 GtBlockFrame,\r
324 GTBlockTimerFrameList,\r
325 GTBlockTimerFrameCount\r
326 );\r
327 if (EFI_ERROR (Status)) {\r
328 DEBUG ((\r
329 DEBUG_ERROR,\r
330 "ERROR: GTDT: Failed to add Generic Timer Frames. Status = %r\n",\r
331 Status\r
332 ));\r
333 return Status;\r
334 }\r
335\r
336 // Next GTBlock\r
337 GTBlock = (EFI_ACPI_6_2_GTDT_GT_BLOCK_STRUCTURE *)((UINT8*)GTBlock +\r
338 GTBlock->Length);\r
339 GTBlockInfo++;\r
340 }// for\r
341 return EFI_SUCCESS;\r
342}\r
343\r
344/** Construct the GTDT ACPI table.\r
345\r
346 Called by the Dynamic Table Manager, this function invokes the\r
347 Configuration Manager protocol interface to get the required hardware\r
348 information for generating the ACPI table.\r
349\r
350 If this function allocates any resources then they must be freed\r
351 in the FreeXXXXTableResources function.\r
352\r
353 @param [in] This Pointer to the table generator.\r
354 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.\r
355 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
356 Protocol Interface.\r
357 @param [out] Table Pointer to the constructed ACPI Table.\r
358\r
359 @retval EFI_SUCCESS Table generated successfully.\r
360 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
361 @retval EFI_NOT_FOUND The required object was not found.\r
362 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration\r
363 Manager is less than the Object size for the\r
364 requested object.\r
365 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
366**/\r
367STATIC\r
368EFI_STATUS\r
369EFIAPI\r
370BuildGtdtTable (\r
371 IN CONST ACPI_TABLE_GENERATOR * CONST This,\r
372 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,\r
373 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
374 OUT EFI_ACPI_DESCRIPTION_HEADER ** CONST Table\r
375 )\r
376{\r
377 EFI_STATUS Status;\r
378 UINT32 TableSize;\r
379 UINT32 PlatformTimerCount;\r
380 UINT32 WatchdogCount;\r
381 UINT32 BlockTimerCount;\r
382 CM_ARM_GENERIC_WATCHDOG_INFO * WatchdogInfoList;\r
383 CM_ARM_GTBLOCK_INFO * GTBlockInfo;\r
384 EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE * Gtdt;\r
385 UINT32 Idx;\r
386 UINT32 GTBlockOffset;\r
387 UINT32 WatchdogOffset;\r
388\r
389 ASSERT (This != NULL);\r
390 ASSERT (AcpiTableInfo != NULL);\r
391 ASSERT (CfgMgrProtocol != NULL);\r
392 ASSERT (Table != NULL);\r
393 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);\r
394 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);\r
395\r
396 if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) ||\r
397 (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) {\r
398 DEBUG ((\r
399 DEBUG_ERROR,\r
400 "ERROR: GTDT: Requested table revision = %d, is not supported."\r
401 "Supported table revision: Minimum = %d, Maximum = %d\n",\r
402 AcpiTableInfo->AcpiTableRevision,\r
403 This->MinAcpiTableRevision,\r
404 This->AcpiTableRevision\r
405 ));\r
406 return EFI_INVALID_PARAMETER;\r
407 }\r
408\r
409 *Table = NULL;\r
410 Status = GetEArmObjPlatformGTBlockInfo (\r
411 CfgMgrProtocol,\r
412 CM_NULL_TOKEN,\r
413 &GTBlockInfo,\r
414 &BlockTimerCount\r
415 );\r
416 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
417 DEBUG ((\r
418 DEBUG_ERROR,\r
419 "ERROR: GTDT: Failed to Get Platform GT Block Information." \\r
420 " Status = %r\n",\r
421 Status\r
422 ));\r
423 goto error_handler;\r
424 }\r
425\r
426 Status = GetEArmObjPlatformGenericWatchdogInfo (\r
427 CfgMgrProtocol,\r
428 CM_NULL_TOKEN,\r
429 &WatchdogInfoList,\r
430 &WatchdogCount\r
431 );\r
432 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
433 DEBUG ((\r
434 DEBUG_ERROR,\r
435 "ERROR: GTDT: Failed to Get Platform Generic Watchdog Information." \\r
436 " Status = %r\n",\r
437 Status\r
438 ));\r
439 goto error_handler;\r
440 }\r
441\r
442 DEBUG ((\r
443 DEBUG_INFO,\r
444 "GTDT: BlockTimerCount = %d, WatchdogCount = %d\n",\r
445 BlockTimerCount,\r
446 WatchdogCount\r
447 ));\r
448\r
449 // Calculate the GTDT Table Size\r
450 PlatformTimerCount = 0;\r
451 TableSize = sizeof (EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE);\r
452 if (BlockTimerCount != 0) {\r
453 GTBlockOffset = TableSize;\r
454 PlatformTimerCount += BlockTimerCount;\r
455 TableSize += (sizeof (EFI_ACPI_6_2_GTDT_GT_BLOCK_STRUCTURE) *\r
456 BlockTimerCount);\r
457\r
458 for (Idx = 0; Idx < BlockTimerCount; Idx++) {\r
459 if (GTBlockInfo[Idx].GTBlockTimerFrameCount > 8) {\r
460 Status = EFI_INVALID_PARAMETER;\r
461 DEBUG ((\r
462 DEBUG_ERROR,\r
463 "GTDT: GTBockFrameCount cannot be more than 8." \\r
464 " GTBockFrameCount = %d, Status = %r\n",\r
465 GTBlockInfo[Idx].GTBlockTimerFrameCount,\r
466 Status\r
467 ));\r
468 goto error_handler;\r
469 }\r
470 TableSize += (sizeof (EFI_ACPI_6_2_GTDT_GT_BLOCK_TIMER_STRUCTURE) *\r
471 GTBlockInfo[Idx].GTBlockTimerFrameCount);\r
472 }\r
473\r
474 DEBUG ((\r
475 DEBUG_INFO,\r
476 "GTDT: GTBockOffset = 0x%x, PLATFORM_TIMER_COUNT = %d\n",\r
477 GTBlockOffset,\r
478 PlatformTimerCount\r
479 ));\r
480 }\r
481\r
482 WatchdogOffset = 0;\r
483 if (WatchdogCount != 0) {\r
484 WatchdogOffset = TableSize;\r
485 PlatformTimerCount += WatchdogCount;\r
486 TableSize += (sizeof (EFI_ACPI_6_2_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE) *\r
487 WatchdogCount);\r
488 DEBUG ((\r
489 DEBUG_INFO,\r
490 "GTDT: WatchdogOffset = 0x%x, PLATFORM_TIMER_COUNT = %d\n",\r
491 WatchdogOffset,\r
492 PlatformTimerCount\r
493 ));\r
494 }\r
495\r
496 *Table = (EFI_ACPI_DESCRIPTION_HEADER*)AllocateZeroPool (TableSize);\r
497 if (*Table == NULL) {\r
498 Status = EFI_OUT_OF_RESOURCES;\r
499 DEBUG ((\r
500 DEBUG_ERROR,\r
501 "ERROR: GTDT: Failed to allocate memory for GTDT Table, Size = %d," \\r
502 " Status = %r\n",\r
503 TableSize,\r
504 Status\r
505 ));\r
506 goto error_handler;\r
507 }\r
508\r
509 Gtdt = (EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE*)*Table;\r
510 DEBUG ((\r
511 DEBUG_INFO,\r
512 "GTDT: Gtdt = 0x%p TableSize = 0x%x\n",\r
513 Gtdt,\r
514 TableSize\r
515 ));\r
516\r
517 Status = AddAcpiHeader (\r
518 CfgMgrProtocol,\r
519 This,\r
520 &Gtdt->Header,\r
e12bdeb1 521 AcpiTableInfo,\r
9c720258
SM
522 TableSize\r
523 );\r
524 if (EFI_ERROR (Status)) {\r
525 DEBUG ((\r
526 DEBUG_ERROR,\r
527 "ERROR: GTDT: Failed to add ACPI header. Status = %r\n",\r
528 Status\r
529 ));\r
530 goto error_handler;\r
531 }\r
532\r
533 Status = AddGenericTimerInfo (\r
534 CfgMgrProtocol,\r
535 Gtdt,\r
536 PlatformTimerCount\r
537 );\r
538 if (EFI_ERROR (Status)) {\r
539 DEBUG ((\r
540 DEBUG_ERROR,\r
541 "ERROR: GTDT: Failed to add Generic Timer Info. Status = %r\n",\r
542 Status\r
543 ));\r
544 goto error_handler;\r
545 }\r
546\r
547 if (BlockTimerCount != 0) {\r
548 Status = AddGTBlockList (\r
549 CfgMgrProtocol,\r
550 Gtdt,\r
551 GTBlockOffset,\r
552 GTBlockInfo,\r
553 BlockTimerCount\r
554 );\r
555 if (EFI_ERROR (Status)) {\r
556 DEBUG ((\r
557 DEBUG_ERROR,\r
558 "ERROR: GTDT: Failed to add GT Block timers. Status = %r\n",\r
559 Status\r
560 ));\r
561 goto error_handler;\r
562 }\r
563 }\r
564\r
565 if (WatchdogCount != 0) {\r
566 AddGenericWatchdogList (\r
567 Gtdt,\r
568 WatchdogOffset,\r
569 WatchdogInfoList,\r
570 WatchdogCount\r
571 );\r
572 }\r
573\r
574 return Status;\r
575\r
576error_handler:\r
577 if (*Table != NULL) {\r
578 FreePool (*Table);\r
579 *Table = NULL;\r
580 }\r
581 return Status;\r
582}\r
583\r
584/** Free any resources allocated for constructing the GTDT.\r
585\r
586 @param [in] This Pointer to the table generator.\r
587 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.\r
588 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
589 Protocol Interface.\r
590 @param [in, out] Table Pointer to the ACPI Table.\r
591\r
592 @retval EFI_SUCCESS The resources were freed successfully.\r
593 @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.\r
594**/\r
595STATIC\r
596EFI_STATUS\r
597FreeGtdtTableResources (\r
598 IN CONST ACPI_TABLE_GENERATOR * CONST This,\r
599 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,\r
600 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
601 IN OUT EFI_ACPI_DESCRIPTION_HEADER ** CONST Table\r
602)\r
603{\r
604 ASSERT (This != NULL);\r
605 ASSERT (AcpiTableInfo != NULL);\r
606 ASSERT (CfgMgrProtocol != NULL);\r
607 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);\r
608 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);\r
609\r
610 if ((Table == NULL) || (*Table == NULL)) {\r
611 DEBUG ((DEBUG_ERROR, "ERROR: GTDT: Invalid Table Pointer\n"));\r
612 ASSERT ((Table != NULL) && (*Table != NULL));\r
613 return EFI_INVALID_PARAMETER;\r
614 }\r
615\r
616 FreePool (*Table);\r
617 *Table = NULL;\r
618 return EFI_SUCCESS;\r
619}\r
620\r
621/** This macro defines the GTDT Table Generator revision.\r
622*/\r
623#define GTDT_GENERATOR_REVISION CREATE_REVISION (1, 0)\r
624\r
625/** The interface for the GTDT Table Generator.\r
626*/\r
627STATIC\r
628CONST\r
629ACPI_TABLE_GENERATOR GtdtGenerator = {\r
630 // Generator ID\r
631 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdGtdt),\r
632 // Generator Description\r
633 L"ACPI.STD.GTDT.GENERATOR",\r
634 // ACPI Table Signature\r
635 EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE,\r
636 // ACPI Table Revision supported by this Generator\r
637 EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_REVISION,\r
638 // Minimum ACPI Table Revision supported by this Generator\r
639 EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_REVISION,\r
640 // Creator ID\r
641 TABLE_GENERATOR_CREATOR_ID_ARM,\r
642 // Creator Revision\r
643 GTDT_GENERATOR_REVISION,\r
644 // Build Table function\r
645 BuildGtdtTable,\r
646 // Free Resource function\r
647 FreeGtdtTableResources,\r
648 // Extended build function not needed\r
649 NULL,\r
650 // Extended build function not implemented by the generator.\r
651 // Hence extended free resource function is not required.\r
652 NULL\r
653};\r
654\r
655/** Register the Generator with the ACPI Table Factory.\r
656\r
657 @param [in] ImageHandle The handle to the image.\r
658 @param [in] SystemTable Pointer to the System Table.\r
659\r
660 @retval EFI_SUCCESS The Generator is registered.\r
661 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
662 @retval EFI_ALREADY_STARTED The Generator for the Table ID\r
663 is already registered.\r
664**/\r
665EFI_STATUS\r
666EFIAPI\r
667AcpiGtdtLibConstructor (\r
668 IN CONST EFI_HANDLE ImageHandle,\r
669 IN EFI_SYSTEM_TABLE * CONST SystemTable\r
670 )\r
671{\r
672 EFI_STATUS Status;\r
673 Status = RegisterAcpiTableGenerator (&GtdtGenerator);\r
674 DEBUG ((DEBUG_INFO, "GTDT: Register Generator. Status = %r\n", Status));\r
675 ASSERT_EFI_ERROR (Status);\r
676 return Status;\r
677}\r
678\r
679/** Deregister the Generator from the ACPI Table Factory.\r
680\r
681 @param [in] ImageHandle The handle to the image.\r
682 @param [in] SystemTable Pointer to the System Table.\r
683\r
684 @retval EFI_SUCCESS The Generator is deregistered.\r
685 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
686 @retval EFI_NOT_FOUND The Generator is not registered.\r
687**/\r
688EFI_STATUS\r
689EFIAPI\r
690AcpiGtdtLibDestructor (\r
691 IN CONST EFI_HANDLE ImageHandle,\r
692 IN EFI_SYSTEM_TABLE * CONST SystemTable\r
693 )\r
694{\r
695 EFI_STATUS Status;\r
696 Status = DeregisterAcpiTableGenerator (&GtdtGenerator);\r
697 DEBUG ((DEBUG_INFO, "GTDT: Deregister Generator. Status = %r\n", Status));\r
698 ASSERT_EFI_ERROR (Status);\r
699 return Status;\r
700}\r