AcpiTable.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /** @file
  2. Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
  3. SPDX-License-Identifier: BSD-2-Clause-Patent
  4. **/
  5. #include "UefiPayloadEntry.h"
  6. /**
  7. Find the board related info from ACPI table
  8. @param AcpiTableBase ACPI table start address in memory
  9. @param AcpiBoardInfo Pointer to the acpi board info strucutre
  10. @retval RETURN_SUCCESS Successfully find out all the required information.
  11. @retval RETURN_NOT_FOUND Failed to find the required info.
  12. **/
  13. RETURN_STATUS
  14. ParseAcpiInfo (
  15. IN UINT64 AcpiTableBase,
  16. OUT ACPI_BOARD_INFO *AcpiBoardInfo
  17. )
  18. {
  19. EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
  20. EFI_ACPI_DESCRIPTION_HEADER *Rsdt;
  21. UINT32 *Entry32;
  22. UINTN Entry32Num;
  23. EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt;
  24. EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
  25. UINT64 *Entry64;
  26. UINTN Entry64Num;
  27. UINTN Idx;
  28. UINT32 *Signature;
  29. EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER *MmCfgHdr;
  30. EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *MmCfgBase;
  31. Rsdp = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)(UINTN)AcpiTableBase;
  32. DEBUG ((DEBUG_INFO, "Rsdp at 0x%p\n", Rsdp));
  33. DEBUG ((DEBUG_INFO, "Rsdt at 0x%x, Xsdt at 0x%lx\n", Rsdp->RsdtAddress, Rsdp->XsdtAddress));
  34. //
  35. // Search Rsdt First
  36. //
  37. Fadt = NULL;
  38. MmCfgHdr = NULL;
  39. Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(Rsdp->RsdtAddress);
  40. if (Rsdt != NULL) {
  41. Entry32 = (UINT32 *)(Rsdt + 1);
  42. Entry32Num = (Rsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) >> 2;
  43. for (Idx = 0; Idx < Entry32Num; Idx++) {
  44. Signature = (UINT32 *)(UINTN)Entry32[Idx];
  45. if (*Signature == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
  46. Fadt = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)Signature;
  47. DEBUG ((DEBUG_INFO, "Found Fadt in Rsdt\n"));
  48. }
  49. if (*Signature == EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE) {
  50. MmCfgHdr = (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER *)Signature;
  51. DEBUG ((DEBUG_INFO, "Found MM config address in Rsdt\n"));
  52. }
  53. if ((Fadt != NULL) && (MmCfgHdr != NULL)) {
  54. goto Done;
  55. }
  56. }
  57. }
  58. //
  59. // Search Xsdt Second
  60. //
  61. Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(Rsdp->XsdtAddress);
  62. if (Xsdt != NULL) {
  63. Entry64 = (UINT64 *)(Xsdt + 1);
  64. Entry64Num = (Xsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) >> 3;
  65. for (Idx = 0; Idx < Entry64Num; Idx++) {
  66. Signature = (UINT32 *)(UINTN)Entry64[Idx];
  67. if (*Signature == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
  68. Fadt = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)Signature;
  69. DEBUG ((DEBUG_INFO, "Found Fadt in Xsdt\n"));
  70. }
  71. if (*Signature == EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE) {
  72. MmCfgHdr = (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER *)Signature;
  73. DEBUG ((DEBUG_INFO, "Found MM config address in Xsdt\n"));
  74. }
  75. if ((Fadt != NULL) && (MmCfgHdr != NULL)) {
  76. goto Done;
  77. }
  78. }
  79. }
  80. if (Fadt == NULL) {
  81. return RETURN_NOT_FOUND;
  82. }
  83. Done:
  84. AcpiBoardInfo->PmCtrlRegBase = Fadt->Pm1aCntBlk;
  85. AcpiBoardInfo->PmTimerRegBase = Fadt->PmTmrBlk;
  86. AcpiBoardInfo->ResetRegAddress = Fadt->ResetReg.Address;
  87. AcpiBoardInfo->ResetValue = Fadt->ResetValue;
  88. AcpiBoardInfo->PmEvtBase = Fadt->Pm1aEvtBlk;
  89. AcpiBoardInfo->PmGpeEnBase = Fadt->Gpe0Blk + Fadt->Gpe0BlkLen / 2;
  90. if (MmCfgHdr != NULL) {
  91. MmCfgBase = (EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *)((UINT8 *)MmCfgHdr + sizeof (*MmCfgHdr));
  92. AcpiBoardInfo->PcieBaseAddress = MmCfgBase->BaseAddress;
  93. AcpiBoardInfo->PcieBaseSize = (MmCfgBase->EndBusNumber + 1 - MmCfgBase->StartBusNumber) * 4096 * 32 * 8;
  94. } else {
  95. AcpiBoardInfo->PcieBaseAddress = 0;
  96. AcpiBoardInfo->PcieBaseSize = 0;
  97. }
  98. DEBUG ((DEBUG_INFO, "PmCtrl Reg 0x%lx\n", AcpiBoardInfo->PmCtrlRegBase));
  99. DEBUG ((DEBUG_INFO, "PmTimer Reg 0x%lx\n", AcpiBoardInfo->PmTimerRegBase));
  100. DEBUG ((DEBUG_INFO, "Reset Reg 0x%lx\n", AcpiBoardInfo->ResetRegAddress));
  101. DEBUG ((DEBUG_INFO, "Reset Value 0x%x\n", AcpiBoardInfo->ResetValue));
  102. DEBUG ((DEBUG_INFO, "PmEvt Reg 0x%lx\n", AcpiBoardInfo->PmEvtBase));
  103. DEBUG ((DEBUG_INFO, "PmGpeEn Reg 0x%lx\n", AcpiBoardInfo->PmGpeEnBase));
  104. DEBUG ((DEBUG_INFO, "PcieBaseAddr 0x%lx\n", AcpiBoardInfo->PcieBaseAddress));
  105. DEBUG ((DEBUG_INFO, "PcieBaseSize 0x%lx\n", AcpiBoardInfo->PcieBaseSize));
  106. //
  107. // Verify values for proper operation
  108. //
  109. ASSERT (Fadt->Pm1aCntBlk != 0);
  110. ASSERT (Fadt->PmTmrBlk != 0);
  111. ASSERT (Fadt->ResetReg.Address != 0);
  112. ASSERT (Fadt->Pm1aEvtBlk != 0);
  113. ASSERT (Fadt->Gpe0Blk != 0);
  114. DEBUG_CODE_BEGIN ();
  115. BOOLEAN SciEnabled;
  116. //
  117. // Check the consistency of SCI enabling
  118. //
  119. //
  120. // Get SCI_EN value
  121. //
  122. if (Fadt->Pm1CntLen == 4) {
  123. SciEnabled = (IoRead32 (Fadt->Pm1aCntBlk) & BIT0) ? TRUE : FALSE;
  124. } else {
  125. //
  126. // if (Pm1CntLen == 2), use 16 bit IO read;
  127. // if (Pm1CntLen != 2 && Pm1CntLen != 4), use 16 bit IO read as a fallback
  128. //
  129. SciEnabled = (IoRead16 (Fadt->Pm1aCntBlk) & BIT0) ? TRUE : FALSE;
  130. }
  131. if (!(Fadt->Flags & EFI_ACPI_5_0_HW_REDUCED_ACPI) &&
  132. (Fadt->SmiCmd == 0) &&
  133. !SciEnabled)
  134. {
  135. //
  136. // The ACPI enabling status is inconsistent: SCI is not enabled but ACPI
  137. // table does not provide a means to enable it through FADT->SmiCmd
  138. //
  139. DEBUG ((
  140. DEBUG_ERROR,
  141. "ERROR: The ACPI enabling status is inconsistent: SCI is not"
  142. " enabled but the ACPI table does not provide a means to enable it through FADT->SmiCmd."
  143. " This may cause issues in OS.\n"
  144. ));
  145. }
  146. DEBUG_CODE_END ();
  147. return RETURN_SUCCESS;
  148. }
  149. /**
  150. Build ACPI board info HOB using infomation from ACPI table
  151. @param AcpiTableBase ACPI table start address in memory
  152. @retval A pointer to ACPI board HOB ACPI_BOARD_INFO. Null if build HOB failure.
  153. **/
  154. ACPI_BOARD_INFO *
  155. BuildHobFromAcpi (
  156. IN UINT64 AcpiTableBase
  157. )
  158. {
  159. EFI_STATUS Status;
  160. ACPI_BOARD_INFO AcpiBoardInfo;
  161. ACPI_BOARD_INFO *NewAcpiBoardInfo;
  162. NewAcpiBoardInfo = NULL;
  163. Status = ParseAcpiInfo (AcpiTableBase, &AcpiBoardInfo);
  164. ASSERT_EFI_ERROR (Status);
  165. if (!EFI_ERROR (Status)) {
  166. NewAcpiBoardInfo = BuildGuidHob (&gUefiAcpiBoardInfoGuid, sizeof (ACPI_BOARD_INFO));
  167. ASSERT (NewAcpiBoardInfo != NULL);
  168. CopyMem (NewAcpiBoardInfo, &AcpiBoardInfo, sizeof (ACPI_BOARD_INFO));
  169. DEBUG ((DEBUG_INFO, "Create acpi board info guid hob\n"));
  170. }
  171. return NewAcpiBoardInfo;
  172. }