SsdtCpuTopologyGenerator.c 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362
  1. /** @file
  2. SSDT Cpu Topology Table Generator.
  3. Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. @par Reference(s):
  6. - ACPI 6.3 Specification - January 2019 - s8.4 Declaring Processors
  7. **/
  8. #include <Library/AcpiLib.h>
  9. #include <Library/BaseLib.h>
  10. #include <Library/BaseMemoryLib.h>
  11. #include <Library/DebugLib.h>
  12. #include <Library/MemoryAllocationLib.h>
  13. #include <Protocol/AcpiTable.h>
  14. // Module specific include files.
  15. #include <AcpiTableGenerator.h>
  16. #include <ConfigurationManagerObject.h>
  17. #include <ConfigurationManagerHelper.h>
  18. #include <Library/AcpiHelperLib.h>
  19. #include <Library/TableHelperLib.h>
  20. #include <Library/AmlLib/AmlLib.h>
  21. #include <Protocol/ConfigurationManagerProtocol.h>
  22. #include "SsdtCpuTopologyGenerator.h"
  23. /** ARM standard SSDT Cpu Topology Table Generator.
  24. Requirements:
  25. The following Configuration Manager Object(s) are required by
  26. this Generator:
  27. - EArmObjGicCInfo
  28. - EArmObjProcHierarchyInfo (OPTIONAL) along with
  29. - EArmObjCmRef (OPTIONAL)
  30. - EArmObjLpiInfo (OPTIONAL)
  31. */
  32. /** This macro expands to a function that retrieves the GIC
  33. CPU interface Information from the Configuration Manager.
  34. */
  35. GET_OBJECT_LIST (
  36. EObjNameSpaceArm,
  37. EArmObjGicCInfo,
  38. CM_ARM_GICC_INFO
  39. );
  40. /**
  41. This macro expands to a function that retrieves the Processor Hierarchy
  42. information from the Configuration Manager.
  43. */
  44. GET_OBJECT_LIST (
  45. EObjNameSpaceArm,
  46. EArmObjProcHierarchyInfo,
  47. CM_ARM_PROC_HIERARCHY_INFO
  48. );
  49. /**
  50. This macro expands to a function that retrieves the cross-CM-object-
  51. reference information from the Configuration Manager.
  52. */
  53. GET_OBJECT_LIST (
  54. EObjNameSpaceArm,
  55. EArmObjCmRef,
  56. CM_ARM_OBJ_REF
  57. );
  58. /**
  59. This macro expands to a function that retrieves the Lpi
  60. information from the Configuration Manager.
  61. */
  62. GET_OBJECT_LIST (
  63. EObjNameSpaceArm,
  64. EArmObjLpiInfo,
  65. CM_ARM_LPI_INFO
  66. );
  67. /**
  68. This macro expands to a function that retrieves the CPC
  69. information from the Configuration Manager.
  70. */
  71. GET_OBJECT_LIST (
  72. EObjNameSpaceArm,
  73. EArmObjCpcInfo,
  74. CM_ARM_CPC_INFO
  75. );
  76. /** Initialize the TokenTable.
  77. One entry should be allocated for each CM_ARM_PROC_HIERARCHY_INFO
  78. structure of the platform. The TokenTable allows to have a mapping:
  79. Index <-> CM_OBJECT_TOKEN (to CM_ARM_LPI_INFO structures).
  80. There will always be less sets of Lpi states (CM_ARM_OBJ_REF)
  81. than the number of cpus/clusters (CM_ARM_PROC_HIERARCHY_INFO).
  82. @param [in] Generator The SSDT Cpu Topology generator.
  83. @param [in] Count Number of entries to allocate in the TokenTable.
  84. @retval EFI_SUCCESS Success.
  85. @retval EFI_INVALID_PARAMETER Invalid parameter.
  86. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
  87. **/
  88. STATIC
  89. EFI_STATUS
  90. EFIAPI
  91. TokenTableInitialize (
  92. IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
  93. IN UINT32 Count
  94. )
  95. {
  96. CM_OBJECT_TOKEN *Table;
  97. if ((Generator == NULL) ||
  98. (Count == 0) ||
  99. (Count >= MAX_NODE_COUNT))
  100. {
  101. ASSERT (0);
  102. return EFI_INVALID_PARAMETER;
  103. }
  104. Table = AllocateZeroPool (sizeof (CM_OBJECT_TOKEN) * Count);
  105. if (Table == NULL) {
  106. ASSERT (0);
  107. return EFI_OUT_OF_RESOURCES;
  108. }
  109. Generator->TokenTable.Table = Table;
  110. return EFI_SUCCESS;
  111. }
  112. /** Free the TokenTable.
  113. @param [in] Generator The SSDT Cpu Topology generator.
  114. **/
  115. STATIC
  116. VOID
  117. EFIAPI
  118. TokenTableFree (
  119. IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator
  120. )
  121. {
  122. ASSERT (Generator != NULL);
  123. ASSERT (Generator->TokenTable.Table != NULL);
  124. if (Generator->TokenTable.Table != NULL) {
  125. FreePool (Generator->TokenTable.Table);
  126. }
  127. }
  128. /** Add a new entry to the TokenTable and return its index.
  129. If an entry with Token is already available in the table,
  130. return its index without adding a new entry.
  131. @param [in] Generator The SSDT Cpu Topology generator.
  132. @param [in] Token New Token entry to add.
  133. @retval The index of the token entry in the TokenTable.
  134. **/
  135. STATIC
  136. UINT32
  137. EFIAPI
  138. TokenTableAdd (
  139. IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
  140. IN CM_OBJECT_TOKEN Token
  141. )
  142. {
  143. CM_OBJECT_TOKEN *Table;
  144. UINT32 Index;
  145. UINT32 LastIndex;
  146. ASSERT (Generator != NULL);
  147. ASSERT (Generator->TokenTable.Table != NULL);
  148. Table = Generator->TokenTable.Table;
  149. LastIndex = Generator->TokenTable.LastIndex;
  150. // Search if there is already an entry with this Token.
  151. for (Index = 0; Index < LastIndex; Index++) {
  152. if (Table[Index] == Token) {
  153. return Index;
  154. }
  155. }
  156. ASSERT (LastIndex < MAX_NODE_COUNT);
  157. ASSERT (LastIndex < Generator->ProcNodeCount);
  158. // If no, create a new entry.
  159. Table[LastIndex] = Token;
  160. return Generator->TokenTable.LastIndex++;
  161. }
  162. /** Write a string 'Xxxx\0' in AslName (5 bytes long),
  163. with 'X' being the leading char of the name, and
  164. with 'xxx' being Value in hexadecimal.
  165. As 'xxx' in hexadecimal represents a number on 12 bits,
  166. we have Value < (1 << 12).
  167. @param [in] LeadChar Leading char of the name.
  168. @param [in] Value Hex value of the name.
  169. Must be lower than (2 << 12).
  170. @param [in, out] AslName Pointer to write the 'Xxxx' string to.
  171. Must be at least 5 bytes long.
  172. @retval EFI_SUCCESS Success.
  173. @retval EFI_INVALID_PARAMETER Invalid parameter.
  174. **/
  175. STATIC
  176. EFI_STATUS
  177. EFIAPI
  178. WriteAslName (
  179. IN CHAR8 LeadChar,
  180. IN UINT32 Value,
  181. IN OUT CHAR8 *AslName
  182. )
  183. {
  184. UINT8 Index;
  185. if ((Value >= MAX_NODE_COUNT) ||
  186. (AslName == NULL))
  187. {
  188. ASSERT (0);
  189. return EFI_INVALID_PARAMETER;
  190. }
  191. AslName[0] = LeadChar;
  192. AslName[AML_NAME_SEG_SIZE] = '\0';
  193. for (Index = 0; Index < AML_NAME_SEG_SIZE - 1; Index++) {
  194. AslName[AML_NAME_SEG_SIZE - Index - 1] =
  195. AsciiFromHex (((Value >> (4 * Index)) & 0xF));
  196. }
  197. return EFI_SUCCESS;
  198. }
  199. /** Create and add an _CPC Node to Cpu Node.
  200. For instance, transform an AML node from:
  201. Device (C002)
  202. {
  203. Name (_UID, 2)
  204. Name (_HID, "ACPI0007")
  205. }
  206. To:
  207. Device (C002)
  208. {
  209. Name (_UID, 2)
  210. Name (_HID, "ACPI0007")
  211. Name(_CPC, Package()
  212. {
  213. NumEntries, // Integer
  214. Revision, // Integer
  215. HighestPerformance, // Integer or Buffer (Resource Descriptor)
  216. NominalPerformance, // Integer or Buffer (Resource Descriptor)
  217. LowestNonlinearPerformance, // Integer or Buffer (Resource Descriptor)
  218. LowestPerformance, // Integer or Buffer (Resource Descriptor)
  219. GuaranteedPerformanceRegister, // Buffer (Resource Descriptor)
  220. DesiredPerformanceRegister , // Buffer (Resource Descriptor)
  221. MinimumPerformanceRegister , // Buffer (Resource Descriptor)
  222. MaximumPerformanceRegister , // Buffer (Resource Descriptor)
  223. PerformanceReductionToleranceRegister, // Buffer (Resource Descriptor)
  224. TimeWindowRegister, // Buffer (Resource Descriptor)
  225. CounterWraparoundTime, // Integer or Buffer (Resource Descriptor)
  226. ReferencePerformanceCounterRegister, // Buffer (Resource Descriptor)
  227. DeliveredPerformanceCounterRegister, // Buffer (Resource Descriptor)
  228. PerformanceLimitedRegister, // Buffer (Resource Descriptor)
  229. CPPCEnableRegister // Buffer (Resource Descriptor)
  230. AutonomousSelectionEnable, // Integer or Buffer (Resource Descriptor)
  231. AutonomousActivityWindowRegister, // Buffer (Resource Descriptor)
  232. EnergyPerformancePreferenceRegister, // Buffer (Resource Descriptor)
  233. ReferencePerformance // Integer or Buffer (Resource Descriptor)
  234. LowestFrequency, // Integer or Buffer (Resource Descriptor)
  235. NominalFrequency // Integer or Buffer (Resource Descriptor)
  236. })
  237. }
  238. @param [in] Generator The SSDT Cpu Topology generator.
  239. @param [in] CfgMgrProtocol Pointer to the Configuration Manager
  240. Protocol Interface.
  241. @param [in] GicCInfo Pointer to the CM_ARM_GICC_INFO object
  242. describing the Cpu.
  243. @param [in] Node CPU Node to which the _CPC node is
  244. attached.
  245. @retval EFI_SUCCESS The function completed successfully.
  246. @retval EFI_INVALID_PARAMETER Invalid parameter.
  247. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
  248. **/
  249. STATIC
  250. EFI_STATUS
  251. EFIAPI
  252. CreateAmlCpcNode (
  253. IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
  254. IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
  255. IN CM_ARM_GICC_INFO *GicCInfo,
  256. IN AML_OBJECT_NODE_HANDLE *Node
  257. )
  258. {
  259. EFI_STATUS Status;
  260. CM_ARM_CPC_INFO *CpcInfo;
  261. Status = GetEArmObjCpcInfo (
  262. CfgMgrProtocol,
  263. GicCInfo->CpcToken,
  264. &CpcInfo,
  265. NULL
  266. );
  267. if (EFI_ERROR (Status)) {
  268. ASSERT (0);
  269. return Status;
  270. }
  271. Status = AmlCreateCpcNode (
  272. CpcInfo,
  273. Node,
  274. NULL
  275. );
  276. ASSERT_EFI_ERROR (Status);
  277. return Status;
  278. }
  279. /** Create and add an _LPI method to Cpu/Cluster Node.
  280. For instance, transform an AML node from:
  281. Device (C002)
  282. {
  283. Name (_UID, 2)
  284. Name (_HID, "ACPI0007")
  285. }
  286. To:
  287. Device (C002)
  288. {
  289. Name (_UID, 2)
  290. Name (_HID, "ACPI0007")
  291. Method (_LPI, 0, NotSerialized)
  292. {
  293. Return (\_SB.L003)
  294. }
  295. }
  296. @param [in] Generator The SSDT Cpu Topology generator.
  297. @param [in] ProcHierarchyNodeInfo CM_ARM_PROC_HIERARCHY_INFO describing
  298. the Cpu.
  299. @param [in] Node Node to which the _LPI method is
  300. attached. Can represent a Cpu or a
  301. Cluster.
  302. @retval EFI_SUCCESS The function completed successfully.
  303. @retval EFI_INVALID_PARAMETER Invalid parameter.
  304. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
  305. **/
  306. STATIC
  307. EFI_STATUS
  308. EFIAPI
  309. CreateAmlLpiMethod (
  310. IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
  311. IN CM_ARM_PROC_HIERARCHY_INFO *ProcHierarchyNodeInfo,
  312. IN AML_OBJECT_NODE_HANDLE *Node
  313. )
  314. {
  315. EFI_STATUS Status;
  316. UINT32 TokenIndex;
  317. CHAR8 AslName[SB_SCOPE_PREFIX_SIZE + AML_NAME_SEG_SIZE];
  318. ASSERT (Generator != NULL);
  319. ASSERT (ProcHierarchyNodeInfo != NULL);
  320. ASSERT (ProcHierarchyNodeInfo->LpiToken != CM_NULL_TOKEN);
  321. ASSERT (Node != NULL);
  322. TokenIndex = TokenTableAdd (Generator, ProcHierarchyNodeInfo->LpiToken);
  323. CopyMem (AslName, SB_SCOPE_PREFIX, SB_SCOPE_PREFIX_SIZE);
  324. Status = WriteAslName (
  325. 'L',
  326. TokenIndex,
  327. AslName + SB_SCOPE_PREFIX_SIZE - 1
  328. );
  329. if (EFI_ERROR (Status)) {
  330. ASSERT (0);
  331. return Status;
  332. }
  333. // ASL:
  334. // Method (_LPI, 0) {
  335. // Return ([AslName])
  336. // }
  337. Status = AmlCodeGenMethodRetNameString (
  338. "_LPI",
  339. AslName,
  340. 0,
  341. FALSE,
  342. 0,
  343. Node,
  344. NULL
  345. );
  346. if (EFI_ERROR (Status)) {
  347. ASSERT (0);
  348. }
  349. return Status;
  350. }
  351. /** Generate all the Lpi states under the '_SB' scope.
  352. This function generates the following ASL code:
  353. Scope (\_SB) {
  354. Name (L000, Package() {
  355. 0, // Version
  356. 0, // Level Index
  357. X, // Count
  358. Package() {
  359. [An Lpi state]
  360. },
  361. Package() {
  362. [Another Lpi state]
  363. },
  364. } // Name L000
  365. Name (L001, Package() {
  366. ...
  367. } // Name L001
  368. ...
  369. } // Scope /_SB
  370. The Lpi states are fetched from the Configuration Manager.
  371. The names of the Lpi states are generated from the TokenTable.
  372. @param [in] Generator The SSDT Cpu Topology generator.
  373. @param [in] CfgMgrProtocol Pointer to the Configuration Manager
  374. Protocol Interface.
  375. @param [in] ScopeNode Scope node handle ('\_SB' scope).
  376. @retval EFI_SUCCESS Success.
  377. @retval EFI_INVALID_PARAMETER Invalid parameter.
  378. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
  379. **/
  380. STATIC
  381. EFI_STATUS
  382. EFIAPI
  383. GenerateLpiStates (
  384. IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
  385. IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
  386. IN AML_OBJECT_NODE_HANDLE ScopeNode
  387. )
  388. {
  389. EFI_STATUS Status;
  390. UINT32 Index;
  391. UINT32 LastIndex;
  392. AML_OBJECT_NODE_HANDLE LpiNode;
  393. CM_ARM_OBJ_REF *LpiRefInfo;
  394. UINT32 LpiRefInfoCount;
  395. UINT32 LpiRefIndex;
  396. CM_ARM_LPI_INFO *LpiInfo;
  397. CHAR8 AslName[AML_NAME_SEG_SIZE + 1];
  398. ASSERT (Generator != NULL);
  399. ASSERT (Generator->TokenTable.Table != NULL);
  400. ASSERT (CfgMgrProtocol != NULL);
  401. ASSERT (ScopeNode != NULL);
  402. LastIndex = Generator->TokenTable.LastIndex;
  403. // For each entry in the TokenTable, create a name in the AML namespace
  404. // under SB_SCOPE, to store the Lpi states associated with the LpiToken.
  405. for (Index = 0; Index < LastIndex; Index++) {
  406. Status = WriteAslName ('L', Index, AslName);
  407. if (EFI_ERROR (Status)) {
  408. ASSERT (0);
  409. return Status;
  410. }
  411. // We do not support the LevelId field for now, let it to 0.
  412. Status = AmlCreateLpiNode (AslName, 1, 0, ScopeNode, &LpiNode);
  413. if (EFI_ERROR (Status)) {
  414. ASSERT (0);
  415. return Status;
  416. }
  417. // Fetch the LPI objects referenced by the token.
  418. Status = GetEArmObjCmRef (
  419. CfgMgrProtocol,
  420. Generator->TokenTable.Table[Index],
  421. &LpiRefInfo,
  422. &LpiRefInfoCount
  423. );
  424. if (EFI_ERROR (Status)) {
  425. ASSERT (0);
  426. return Status;
  427. }
  428. for (LpiRefIndex = 0; LpiRefIndex < LpiRefInfoCount; LpiRefIndex++) {
  429. // For each CM_ARM_LPI_INFO referenced by the token, add an Lpi state.
  430. Status = GetEArmObjLpiInfo (
  431. CfgMgrProtocol,
  432. LpiRefInfo[LpiRefIndex].ReferenceToken,
  433. &LpiInfo,
  434. NULL
  435. );
  436. if (EFI_ERROR (Status)) {
  437. ASSERT (0);
  438. return Status;
  439. }
  440. Status = AmlAddLpiState (
  441. LpiInfo->MinResidency,
  442. LpiInfo->WorstCaseWakeLatency,
  443. LpiInfo->Flags,
  444. LpiInfo->ArchFlags,
  445. LpiInfo->ResCntFreq,
  446. LpiInfo->EnableParentState,
  447. LpiInfo->IsInteger ?
  448. NULL :
  449. &LpiInfo->RegisterEntryMethod,
  450. LpiInfo->IsInteger ?
  451. LpiInfo->IntegerEntryMethod :
  452. 0,
  453. &LpiInfo->ResidencyCounterRegister,
  454. &LpiInfo->UsageCounterRegister,
  455. LpiInfo->StateName,
  456. LpiNode
  457. );
  458. if (EFI_ERROR (Status)) {
  459. ASSERT (0);
  460. return Status;
  461. }
  462. } // for LpiRefIndex
  463. } // for Index
  464. return EFI_SUCCESS;
  465. }
  466. /** Create a Cpu in the AML namespace.
  467. This generates the following ASL code:
  468. Device (C002)
  469. {
  470. Name (_UID, 2)
  471. Name (_HID, "ACPI0007")
  472. }
  473. @param [in] Generator The SSDT Cpu Topology generator.
  474. @param [in] ParentNode Parent node to attach the Cpu node to.
  475. @param [in] GicCInfo CM_ARM_GICC_INFO object used to create the node.
  476. @param [in] CpuIndex Index used to generate the node name.
  477. @param [out] CpuNodePtr If not NULL, return the created Cpu node.
  478. @retval EFI_SUCCESS Success.
  479. @retval EFI_INVALID_PARAMETER Invalid parameter.
  480. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
  481. **/
  482. STATIC
  483. EFI_STATUS
  484. EFIAPI
  485. CreateAmlCpu (
  486. IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
  487. IN AML_NODE_HANDLE ParentNode,
  488. IN CM_ARM_GICC_INFO *GicCInfo,
  489. IN UINT32 CpuIndex,
  490. OUT AML_OBJECT_NODE_HANDLE *CpuNodePtr OPTIONAL
  491. )
  492. {
  493. EFI_STATUS Status;
  494. AML_OBJECT_NODE_HANDLE CpuNode;
  495. CHAR8 AslName[AML_NAME_SEG_SIZE + 1];
  496. ASSERT (Generator != NULL);
  497. ASSERT (ParentNode != NULL);
  498. ASSERT (GicCInfo != NULL);
  499. Status = WriteAslName ('C', CpuIndex, AslName);
  500. if (EFI_ERROR (Status)) {
  501. ASSERT (0);
  502. return Status;
  503. }
  504. Status = AmlCodeGenDevice (AslName, ParentNode, &CpuNode);
  505. if (EFI_ERROR (Status)) {
  506. ASSERT (0);
  507. return Status;
  508. }
  509. Status = AmlCodeGenNameInteger (
  510. "_UID",
  511. GicCInfo->AcpiProcessorUid,
  512. CpuNode,
  513. NULL
  514. );
  515. if (EFI_ERROR (Status)) {
  516. ASSERT (0);
  517. return Status;
  518. }
  519. Status = AmlCodeGenNameString (
  520. "_HID",
  521. ACPI_HID_PROCESSOR_DEVICE,
  522. CpuNode,
  523. NULL
  524. );
  525. if (EFI_ERROR (Status)) {
  526. ASSERT (0);
  527. return Status;
  528. }
  529. // If requested, return the handle to the CpuNode.
  530. if (CpuNodePtr != NULL) {
  531. *CpuNodePtr = CpuNode;
  532. }
  533. return Status;
  534. }
  535. /** Create a Cpu in the AML namespace from a CM_ARM_PROC_HIERARCHY_INFO
  536. CM object.
  537. @param [in] Generator The SSDT Cpu Topology generator.
  538. @param [in] CfgMgrProtocol Pointer to the Configuration Manager
  539. Protocol Interface.
  540. @param [in] ParentNode Parent node to attach the Cpu node to.
  541. @param [in] CpuIndex Index used to generate the node name.
  542. @param [in] ProcHierarchyNodeInfo CM_ARM_PROC_HIERARCHY_INFO describing
  543. the Cpu.
  544. @retval EFI_SUCCESS Success.
  545. @retval EFI_INVALID_PARAMETER Invalid parameter.
  546. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
  547. **/
  548. STATIC
  549. EFI_STATUS
  550. EFIAPI
  551. CreateAmlCpuFromProcHierarchy (
  552. IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
  553. IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
  554. IN AML_NODE_HANDLE ParentNode,
  555. IN UINT32 CpuIndex,
  556. IN CM_ARM_PROC_HIERARCHY_INFO *ProcHierarchyNodeInfo
  557. )
  558. {
  559. EFI_STATUS Status;
  560. CM_ARM_GICC_INFO *GicCInfo;
  561. AML_OBJECT_NODE_HANDLE CpuNode;
  562. ASSERT (Generator != NULL);
  563. ASSERT (CfgMgrProtocol != NULL);
  564. ASSERT (ParentNode != NULL);
  565. ASSERT (ProcHierarchyNodeInfo != NULL);
  566. ASSERT (ProcHierarchyNodeInfo->GicCToken != CM_NULL_TOKEN);
  567. Status = GetEArmObjGicCInfo (
  568. CfgMgrProtocol,
  569. ProcHierarchyNodeInfo->GicCToken,
  570. &GicCInfo,
  571. NULL
  572. );
  573. if (EFI_ERROR (Status)) {
  574. ASSERT (0);
  575. return Status;
  576. }
  577. Status = CreateAmlCpu (Generator, ParentNode, GicCInfo, CpuIndex, &CpuNode);
  578. if (EFI_ERROR (Status)) {
  579. ASSERT (0);
  580. return Status;
  581. }
  582. // If a set of Lpi states is associated with the
  583. // CM_ARM_PROC_HIERARCHY_INFO, create an _LPI method returning them.
  584. if (ProcHierarchyNodeInfo->LpiToken != CM_NULL_TOKEN) {
  585. Status = CreateAmlLpiMethod (Generator, ProcHierarchyNodeInfo, CpuNode);
  586. if (EFI_ERROR (Status)) {
  587. ASSERT_EFI_ERROR (Status);
  588. return Status;
  589. }
  590. }
  591. // If a CPC info is associated with the
  592. // GicCinfo, create an _CPC method returning them.
  593. if (GicCInfo->CpcToken != CM_NULL_TOKEN) {
  594. Status = CreateAmlCpcNode (Generator, CfgMgrProtocol, GicCInfo, CpuNode);
  595. if (EFI_ERROR (Status)) {
  596. ASSERT_EFI_ERROR (Status);
  597. return Status;
  598. }
  599. }
  600. return Status;
  601. }
  602. /** Create a Processor Container in the AML namespace.
  603. Any CM_ARM_PROC_HIERARCHY_INFO object with the following flags is
  604. assumed to be a processor container:
  605. - EFI_ACPI_6_3_PPTT_PACKAGE_NOT_PHYSICAL
  606. - EFI_ACPI_6_3_PPTT_PROCESSOR_ID_INVALID
  607. - EFI_ACPI_6_3_PPTT_NODE_IS_NOT_LEAF
  608. This generates the following ASL code:
  609. Device (C002)
  610. {
  611. Name (_UID, 2)
  612. Name (_HID, "ACPI0010")
  613. }
  614. @param [in] Generator The SSDT Cpu Topology generator.
  615. @param [in] CfgMgrProtocol Pointer to the Configuration Manager
  616. Protocol Interface.
  617. @param [in] ParentNode Parent node to attach the processor
  618. container node to.
  619. @param [in] ProcHierarchyNodeInfo CM_ARM_PROC_HIERARCHY_INFO object used
  620. to create the node.
  621. @param [in] ProcContainerIndex Index used to generate the node name.
  622. @param [out] ProcContainerNodePtr If success, contains the created processor
  623. container node.
  624. @retval EFI_SUCCESS Success.
  625. @retval EFI_INVALID_PARAMETER Invalid parameter.
  626. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
  627. **/
  628. STATIC
  629. EFI_STATUS
  630. EFIAPI
  631. CreateAmlProcessorContainer (
  632. IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
  633. IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
  634. IN AML_NODE_HANDLE ParentNode,
  635. IN CM_ARM_PROC_HIERARCHY_INFO *ProcHierarchyNodeInfo,
  636. IN UINT32 ProcContainerIndex,
  637. OUT AML_OBJECT_NODE_HANDLE *ProcContainerNodePtr
  638. )
  639. {
  640. EFI_STATUS Status;
  641. AML_OBJECT_NODE_HANDLE ProcContainerNode;
  642. CHAR8 AslNameProcContainer[AML_NAME_SEG_SIZE + 1];
  643. ASSERT (Generator != NULL);
  644. ASSERT (CfgMgrProtocol != NULL);
  645. ASSERT (ParentNode != NULL);
  646. ASSERT (ProcHierarchyNodeInfo != NULL);
  647. ASSERT (ProcContainerNodePtr != NULL);
  648. Status = WriteAslName ('C', ProcContainerIndex, AslNameProcContainer);
  649. if (EFI_ERROR (Status)) {
  650. ASSERT (0);
  651. return Status;
  652. }
  653. Status = AmlCodeGenDevice (AslNameProcContainer, ParentNode, &ProcContainerNode);
  654. if (EFI_ERROR (Status)) {
  655. ASSERT (0);
  656. return Status;
  657. }
  658. // Use the ProcContainerIndex for the _UID value as there is no AcpiProcessorUid
  659. // and EFI_ACPI_6_3_PPTT_PROCESSOR_ID_INVALID is set for non-Cpus.
  660. Status = AmlCodeGenNameInteger (
  661. "_UID",
  662. ProcContainerIndex,
  663. ProcContainerNode,
  664. NULL
  665. );
  666. if (EFI_ERROR (Status)) {
  667. ASSERT (0);
  668. return Status;
  669. }
  670. Status = AmlCodeGenNameString (
  671. "_HID",
  672. ACPI_HID_PROCESSOR_CONTAINER_DEVICE,
  673. ProcContainerNode,
  674. NULL
  675. );
  676. if (EFI_ERROR (Status)) {
  677. ASSERT (0);
  678. return Status;
  679. }
  680. // If a set of Lpi states are associated with the
  681. // CM_ARM_PROC_HIERARCHY_INFO, create an _LPI method returning them.
  682. if (ProcHierarchyNodeInfo->LpiToken != CM_NULL_TOKEN) {
  683. Status = CreateAmlLpiMethod (
  684. Generator,
  685. ProcHierarchyNodeInfo,
  686. ProcContainerNode
  687. );
  688. if (EFI_ERROR (Status)) {
  689. ASSERT (0);
  690. return Status;
  691. }
  692. }
  693. *ProcContainerNodePtr = ProcContainerNode;
  694. return Status;
  695. }
  696. /** Create an AML representation of the Cpu topology.
  697. A processor container is by extension any non-leave device in the cpu topology.
  698. @param [in] Generator The SSDT Cpu Topology generator.
  699. @param [in] CfgMgrProtocol Pointer to the Configuration Manager
  700. Protocol Interface.
  701. @param [in] NodeToken Token of the CM_ARM_PROC_HIERARCHY_INFO
  702. currently handled.
  703. Cannot be CM_NULL_TOKEN.
  704. @param [in] ParentNode Parent node to attach the created
  705. node to.
  706. @param [in,out] ProcContainerIndex Pointer to the current processor container
  707. index to be used as UID.
  708. @retval EFI_SUCCESS Success.
  709. @retval EFI_INVALID_PARAMETER Invalid parameter.
  710. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
  711. **/
  712. STATIC
  713. EFI_STATUS
  714. EFIAPI
  715. CreateAmlCpuTopologyTree (
  716. IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
  717. IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
  718. IN CM_OBJECT_TOKEN NodeToken,
  719. IN AML_NODE_HANDLE ParentNode,
  720. IN OUT UINT32 *ProcContainerIndex
  721. )
  722. {
  723. EFI_STATUS Status;
  724. UINT32 Index;
  725. UINT32 CpuIndex;
  726. AML_OBJECT_NODE_HANDLE ProcContainerNode;
  727. ASSERT (Generator != NULL);
  728. ASSERT (Generator->ProcNodeList != NULL);
  729. ASSERT (Generator->ProcNodeCount != 0);
  730. ASSERT (CfgMgrProtocol != NULL);
  731. ASSERT (NodeToken != CM_NULL_TOKEN);
  732. ASSERT (ParentNode != NULL);
  733. ASSERT (ProcContainerIndex != NULL);
  734. CpuIndex = 0;
  735. for (Index = 0; Index < Generator->ProcNodeCount; Index++) {
  736. // Find the children of the CM_ARM_PROC_HIERARCHY_INFO
  737. // currently being handled (i.e. ParentToken == NodeToken).
  738. if (Generator->ProcNodeList[Index].ParentToken == NodeToken) {
  739. // Only Cpus (leaf nodes in this tree) have a GicCToken.
  740. // Create a Cpu node.
  741. if (Generator->ProcNodeList[Index].GicCToken != CM_NULL_TOKEN) {
  742. if ((Generator->ProcNodeList[Index].Flags & PPTT_PROCESSOR_MASK) !=
  743. PPTT_CPU_PROCESSOR_MASK)
  744. {
  745. DEBUG ((
  746. DEBUG_ERROR,
  747. "ERROR: SSDT-CPU-TOPOLOGY: Invalid flags for cpu: 0x%x.\n",
  748. Generator->ProcNodeList[Index].Flags
  749. ));
  750. ASSERT (0);
  751. return EFI_INVALID_PARAMETER;
  752. }
  753. Status = CreateAmlCpuFromProcHierarchy (
  754. Generator,
  755. CfgMgrProtocol,
  756. ParentNode,
  757. CpuIndex,
  758. &Generator->ProcNodeList[Index]
  759. );
  760. if (EFI_ERROR (Status)) {
  761. ASSERT (0);
  762. return Status;
  763. }
  764. CpuIndex++;
  765. } else {
  766. // If this is not a Cpu, then this is a processor container.
  767. // Acpi processor Id for clusters is not handled.
  768. if ((Generator->ProcNodeList[Index].Flags & PPTT_PROCESSOR_MASK) !=
  769. PPTT_CLUSTER_PROCESSOR_MASK)
  770. {
  771. DEBUG ((
  772. DEBUG_ERROR,
  773. "ERROR: SSDT-CPU-TOPOLOGY: Invalid flags for cluster: 0x%x.\n",
  774. Generator->ProcNodeList[Index].Flags
  775. ));
  776. ASSERT (0);
  777. return EFI_INVALID_PARAMETER;
  778. }
  779. Status = CreateAmlProcessorContainer (
  780. Generator,
  781. CfgMgrProtocol,
  782. ParentNode,
  783. &Generator->ProcNodeList[Index],
  784. *ProcContainerIndex,
  785. &ProcContainerNode
  786. );
  787. if (EFI_ERROR (Status)) {
  788. ASSERT (0);
  789. return Status;
  790. }
  791. // Nodes must have a unique name in the ASL namespace.
  792. // Reset the Cpu index whenever we create a new processor container.
  793. (*ProcContainerIndex)++;
  794. CpuIndex = 0;
  795. // Recursively continue creating an AML tree.
  796. Status = CreateAmlCpuTopologyTree (
  797. Generator,
  798. CfgMgrProtocol,
  799. Generator->ProcNodeList[Index].Token,
  800. ProcContainerNode,
  801. ProcContainerIndex
  802. );
  803. if (EFI_ERROR (Status)) {
  804. ASSERT (0);
  805. return Status;
  806. }
  807. }
  808. } // if ParentToken == NodeToken
  809. } // for
  810. return EFI_SUCCESS;
  811. }
  812. /** Create the processor hierarchy AML tree from CM_ARM_PROC_HIERARCHY_INFO
  813. CM objects.
  814. @param [in] Generator The SSDT Cpu Topology generator.
  815. @param [in] CfgMgrProtocol Pointer to the Configuration Manager
  816. Protocol Interface.
  817. @param [in] ScopeNode Scope node handle ('\_SB' scope).
  818. @retval EFI_SUCCESS Success.
  819. @retval EFI_INVALID_PARAMETER Invalid parameter.
  820. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
  821. **/
  822. STATIC
  823. EFI_STATUS
  824. EFIAPI
  825. CreateTopologyFromProcHierarchy (
  826. IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
  827. IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
  828. IN AML_OBJECT_NODE_HANDLE ScopeNode
  829. )
  830. {
  831. EFI_STATUS Status;
  832. UINT32 Index;
  833. UINT32 TopLevelProcNodeIndex;
  834. UINT32 ProcContainerIndex;
  835. ASSERT (Generator != NULL);
  836. ASSERT (Generator->ProcNodeCount != 0);
  837. ASSERT (Generator->ProcNodeList != NULL);
  838. ASSERT (CfgMgrProtocol != NULL);
  839. ASSERT (ScopeNode != NULL);
  840. TopLevelProcNodeIndex = MAX_UINT32;
  841. ProcContainerIndex = 0;
  842. Status = TokenTableInitialize (Generator, Generator->ProcNodeCount);
  843. if (EFI_ERROR (Status)) {
  844. ASSERT (0);
  845. return Status;
  846. }
  847. // It is assumed that there is one unique CM_ARM_PROC_HIERARCHY_INFO
  848. // structure with no ParentToken and the EFI_ACPI_6_3_PPTT_PACKAGE_PHYSICAL
  849. // flag set. All other CM_ARM_PROC_HIERARCHY_INFO are non-physical and
  850. // have a ParentToken.
  851. for (Index = 0; Index < Generator->ProcNodeCount; Index++) {
  852. if ((Generator->ProcNodeList[Index].ParentToken == CM_NULL_TOKEN) &&
  853. (Generator->ProcNodeList[Index].Flags &
  854. EFI_ACPI_6_3_PPTT_PACKAGE_PHYSICAL))
  855. {
  856. if (TopLevelProcNodeIndex != MAX_UINT32) {
  857. DEBUG ((
  858. DEBUG_ERROR,
  859. "ERROR: SSDT-CPU-TOPOLOGY: Top level CM_ARM_PROC_HIERARCHY_INFO "
  860. "must be unique\n"
  861. ));
  862. ASSERT (0);
  863. goto exit_handler;
  864. }
  865. TopLevelProcNodeIndex = Index;
  866. }
  867. } // for
  868. Status = CreateAmlCpuTopologyTree (
  869. Generator,
  870. CfgMgrProtocol,
  871. Generator->ProcNodeList[TopLevelProcNodeIndex].Token,
  872. ScopeNode,
  873. &ProcContainerIndex
  874. );
  875. if (EFI_ERROR (Status)) {
  876. ASSERT (0);
  877. goto exit_handler;
  878. }
  879. Status = GenerateLpiStates (Generator, CfgMgrProtocol, ScopeNode);
  880. if (EFI_ERROR (Status)) {
  881. ASSERT (0);
  882. goto exit_handler;
  883. }
  884. exit_handler:
  885. TokenTableFree (Generator);
  886. return Status;
  887. }
  888. /** Create the processor hierarchy AML tree from CM_ARM_GICC_INFO
  889. CM objects.
  890. A processor container is by extension any non-leave device in the cpu topology.
  891. @param [in] Generator The SSDT Cpu Topology generator.
  892. @param [in] CfgMgrProtocol Pointer to the Configuration Manager
  893. Protocol Interface.
  894. @param [in] ScopeNode Scope node handle ('\_SB' scope).
  895. @retval EFI_SUCCESS Success.
  896. @retval EFI_INVALID_PARAMETER Invalid parameter.
  897. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
  898. **/
  899. STATIC
  900. EFI_STATUS
  901. EFIAPI
  902. CreateTopologyFromGicC (
  903. IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
  904. IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
  905. IN AML_OBJECT_NODE_HANDLE ScopeNode
  906. )
  907. {
  908. EFI_STATUS Status;
  909. CM_ARM_GICC_INFO *GicCInfo;
  910. UINT32 GicCInfoCount;
  911. UINT32 Index;
  912. AML_OBJECT_NODE_HANDLE CpuNode;
  913. ASSERT (Generator != NULL);
  914. ASSERT (CfgMgrProtocol != NULL);
  915. ASSERT (ScopeNode != NULL);
  916. Status = GetEArmObjGicCInfo (
  917. CfgMgrProtocol,
  918. CM_NULL_TOKEN,
  919. &GicCInfo,
  920. &GicCInfoCount
  921. );
  922. if (EFI_ERROR (Status)) {
  923. ASSERT (0);
  924. return Status;
  925. }
  926. // For each CM_ARM_GICC_INFO object, create an AML node.
  927. for (Index = 0; Index < GicCInfoCount; Index++) {
  928. Status = CreateAmlCpu (
  929. Generator,
  930. ScopeNode,
  931. &GicCInfo[Index],
  932. Index,
  933. &CpuNode
  934. );
  935. if (EFI_ERROR (Status)) {
  936. ASSERT (0);
  937. break;
  938. }
  939. // If a CPC info is associated with the
  940. // GicCinfo, create an _CPC method returning them.
  941. if (GicCInfo->CpcToken != CM_NULL_TOKEN) {
  942. Status = CreateAmlCpcNode (Generator, CfgMgrProtocol, &GicCInfo[Index], CpuNode);
  943. if (EFI_ERROR (Status)) {
  944. ASSERT_EFI_ERROR (Status);
  945. break;
  946. }
  947. }
  948. } // for
  949. return Status;
  950. }
  951. /** Construct the SSDT Cpu Topology ACPI table.
  952. This function invokes the Configuration Manager protocol interface
  953. to get the required hardware information for generating the ACPI
  954. table.
  955. If this function allocates any resources then they must be freed
  956. in the FreeXXXXTableResources function.
  957. @param [in] This Pointer to the table generator.
  958. @param [in] AcpiTableInfo Pointer to the ACPI Table Info.
  959. @param [in] CfgMgrProtocol Pointer to the Configuration Manager
  960. Protocol Interface.
  961. @param [out] Table Pointer to the constructed ACPI Table.
  962. @retval EFI_SUCCESS Table generated successfully.
  963. @retval EFI_INVALID_PARAMETER A parameter is invalid.
  964. @retval EFI_NOT_FOUND The required object was not found.
  965. @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
  966. Manager is less than the Object size for the
  967. requested object.
  968. **/
  969. STATIC
  970. EFI_STATUS
  971. EFIAPI
  972. BuildSsdtCpuTopologyTable (
  973. IN CONST ACPI_TABLE_GENERATOR *CONST This,
  974. IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,
  975. IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
  976. OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table
  977. )
  978. {
  979. EFI_STATUS Status;
  980. AML_ROOT_NODE_HANDLE RootNode;
  981. AML_OBJECT_NODE_HANDLE ScopeNode;
  982. CM_ARM_PROC_HIERARCHY_INFO *ProcHierarchyNodeList;
  983. UINT32 ProcHierarchyNodeCount;
  984. ACPI_CPU_TOPOLOGY_GENERATOR *Generator;
  985. ASSERT (This != NULL);
  986. ASSERT (AcpiTableInfo != NULL);
  987. ASSERT (CfgMgrProtocol != NULL);
  988. ASSERT (Table != NULL);
  989. ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
  990. ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
  991. Generator = (ACPI_CPU_TOPOLOGY_GENERATOR *)This;
  992. Status = AddSsdtAcpiHeader (
  993. CfgMgrProtocol,
  994. This,
  995. AcpiTableInfo,
  996. &RootNode
  997. );
  998. if (EFI_ERROR (Status)) {
  999. return Status;
  1000. }
  1001. Status = AmlCodeGenScope (SB_SCOPE, RootNode, &ScopeNode);
  1002. if (EFI_ERROR (Status)) {
  1003. goto exit_handler;
  1004. }
  1005. // Get the processor hierarchy info and update the processor topology
  1006. // structure count with Processor Hierarchy Nodes (Type 0)
  1007. Status = GetEArmObjProcHierarchyInfo (
  1008. CfgMgrProtocol,
  1009. CM_NULL_TOKEN,
  1010. &ProcHierarchyNodeList,
  1011. &ProcHierarchyNodeCount
  1012. );
  1013. if (EFI_ERROR (Status) &&
  1014. (Status != EFI_NOT_FOUND))
  1015. {
  1016. goto exit_handler;
  1017. }
  1018. if (Status == EFI_NOT_FOUND) {
  1019. // If hierarchy information is not found generate a flat topology
  1020. // using CM_ARM_GICC_INFO objects.
  1021. Status = CreateTopologyFromGicC (
  1022. Generator,
  1023. CfgMgrProtocol,
  1024. ScopeNode
  1025. );
  1026. if (EFI_ERROR (Status)) {
  1027. goto exit_handler;
  1028. }
  1029. } else {
  1030. // Generate the topology from CM_ARM_PROC_HIERARCHY_INFO objects.
  1031. Generator->ProcNodeList = ProcHierarchyNodeList;
  1032. Generator->ProcNodeCount = ProcHierarchyNodeCount;
  1033. Status = CreateTopologyFromProcHierarchy (
  1034. Generator,
  1035. CfgMgrProtocol,
  1036. ScopeNode
  1037. );
  1038. if (EFI_ERROR (Status)) {
  1039. goto exit_handler;
  1040. }
  1041. }
  1042. Status = AmlSerializeDefinitionBlock (
  1043. RootNode,
  1044. Table
  1045. );
  1046. if (EFI_ERROR (Status)) {
  1047. DEBUG ((
  1048. DEBUG_ERROR,
  1049. "ERROR: SSDT-CPU-TOPOLOGY: Failed to Serialize SSDT Table Data."
  1050. " Status = %r\n",
  1051. Status
  1052. ));
  1053. goto exit_handler;
  1054. }
  1055. exit_handler:
  1056. // Delete the RootNode and its attached children.
  1057. return AmlDeleteTree (RootNode);
  1058. }
  1059. /** Free any resources allocated for constructing the
  1060. SSDT Cpu Topology ACPI table.
  1061. @param [in] This Pointer to the table generator.
  1062. @param [in] AcpiTableInfo Pointer to the ACPI Table Info.
  1063. @param [in] CfgMgrProtocol Pointer to the Configuration Manager
  1064. Protocol Interface.
  1065. @param [in, out] Table Pointer to the ACPI Table.
  1066. @retval EFI_SUCCESS The resources were freed successfully.
  1067. @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
  1068. **/
  1069. STATIC
  1070. EFI_STATUS
  1071. FreeSsdtCpuTopologyTableResources (
  1072. IN CONST ACPI_TABLE_GENERATOR *CONST This,
  1073. IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,
  1074. IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
  1075. IN OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table
  1076. )
  1077. {
  1078. ASSERT (This != NULL);
  1079. ASSERT (AcpiTableInfo != NULL);
  1080. ASSERT (CfgMgrProtocol != NULL);
  1081. ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
  1082. ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
  1083. if ((Table == NULL) || (*Table == NULL)) {
  1084. DEBUG ((DEBUG_ERROR, "ERROR: SSDT-CPU-TOPOLOGY: Invalid Table Pointer\n"));
  1085. ASSERT ((Table != NULL) && (*Table != NULL));
  1086. return EFI_INVALID_PARAMETER;
  1087. }
  1088. FreePool (*Table);
  1089. *Table = NULL;
  1090. return EFI_SUCCESS;
  1091. }
  1092. /** This macro defines the SSDT Cpu Topology Table Generator revision.
  1093. */
  1094. #define SSDT_CPU_TOPOLOGY_GENERATOR_REVISION CREATE_REVISION (1, 0)
  1095. /** The interface for the SSDT Cpu Topology Table Generator.
  1096. */
  1097. STATIC
  1098. ACPI_CPU_TOPOLOGY_GENERATOR SsdtCpuTopologyGenerator = {
  1099. // ACPI table generator header
  1100. {
  1101. // Generator ID
  1102. CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtCpuTopology),
  1103. // Generator Description
  1104. L"ACPI.STD.SSDT.CPU.TOPOLOGY.GENERATOR",
  1105. // ACPI Table Signature
  1106. EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
  1107. // ACPI Table Revision - Unused
  1108. 0,
  1109. // Minimum ACPI Table Revision - Unused
  1110. 0,
  1111. // Creator ID
  1112. TABLE_GENERATOR_CREATOR_ID_ARM,
  1113. // Creator Revision
  1114. SSDT_CPU_TOPOLOGY_GENERATOR_REVISION,
  1115. // Build Table function
  1116. BuildSsdtCpuTopologyTable,
  1117. // Free Resource function
  1118. FreeSsdtCpuTopologyTableResources,
  1119. // Extended build function not needed
  1120. NULL,
  1121. // Extended build function not implemented by the generator.
  1122. // Hence extended free resource function is not required.
  1123. NULL
  1124. },
  1125. // Private fields are defined from here.
  1126. // TokenTable
  1127. {
  1128. // Table
  1129. NULL,
  1130. // LastIndex
  1131. 0
  1132. },
  1133. // ProcNodeList
  1134. NULL,
  1135. // ProcNodeCount
  1136. 0
  1137. };
  1138. /** Register the Generator with the ACPI Table Factory.
  1139. @param [in] ImageHandle The handle to the image.
  1140. @param [in] SystemTable Pointer to the System Table.
  1141. @retval EFI_SUCCESS The Generator is registered.
  1142. @retval EFI_INVALID_PARAMETER A parameter is invalid.
  1143. @retval EFI_ALREADY_STARTED The Generator for the Table ID
  1144. is already registered.
  1145. **/
  1146. EFI_STATUS
  1147. EFIAPI
  1148. AcpiSsdtCpuTopologyLibConstructor (
  1149. IN EFI_HANDLE ImageHandle,
  1150. IN EFI_SYSTEM_TABLE *SystemTable
  1151. )
  1152. {
  1153. EFI_STATUS Status;
  1154. Status = RegisterAcpiTableGenerator (&SsdtCpuTopologyGenerator.Header);
  1155. DEBUG ((
  1156. DEBUG_INFO,
  1157. "SSDT-CPU-TOPOLOGY: Register Generator. Status = %r\n",
  1158. Status
  1159. ));
  1160. ASSERT_EFI_ERROR (Status);
  1161. return Status;
  1162. }
  1163. /** Deregister the Generator from the ACPI Table Factory.
  1164. @param [in] ImageHandle The handle to the image.
  1165. @param [in] SystemTable Pointer to the System Table.
  1166. @retval EFI_SUCCESS The Generator is deregistered.
  1167. @retval EFI_INVALID_PARAMETER A parameter is invalid.
  1168. @retval EFI_NOT_FOUND The Generator is not registered.
  1169. **/
  1170. EFI_STATUS
  1171. EFIAPI
  1172. AcpiSsdtCpuTopologyLibDestructor (
  1173. IN EFI_HANDLE ImageHandle,
  1174. IN EFI_SYSTEM_TABLE *SystemTable
  1175. )
  1176. {
  1177. EFI_STATUS Status;
  1178. Status = DeregisterAcpiTableGenerator (&SsdtCpuTopologyGenerator.Header);
  1179. DEBUG ((
  1180. DEBUG_INFO,
  1181. "SSDT-CPU-TOPOLOGY: Deregister Generator. Status = %r\n",
  1182. Status
  1183. ));
  1184. ASSERT_EFI_ERROR (Status);
  1185. return Status;
  1186. }