BoardAcpiDxe.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /** @file
  2. ACPI Platform Driver
  3. Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <Base.h>
  7. #include <Uefi.h>
  8. #include <IndustryStandard/Acpi.h>
  9. #include <Library/UefiLib.h>
  10. #include <Library/UefiBootServicesTableLib.h>
  11. #include <Library/UefiRuntimeServicesTableLib.h>
  12. #include <Library/DebugLib.h>
  13. #include <Library/BaseMemoryLib.h>
  14. #include <Library/IoLib.h>
  15. #include <Library/PcdLib.h>
  16. #include <Library/PciLib.h>
  17. #include <Library/BoardAcpiTableLib.h>
  18. #include <Library/MemoryAllocationLib.h>
  19. #include <Library/AslUpdateLib.h>
  20. #include <Protocol/GlobalNvsArea.h>
  21. #include <Protocol/FirmwareVolume2.h>
  22. #include <Protocol/AcpiTable.h>
  23. GLOBAL_REMOVE_IF_UNREFERENCED EFI_GLOBAL_NVS_AREA_PROTOCOL mGlobalNvsArea;
  24. /**
  25. @brief
  26. Global NVS initialize.
  27. @param[in] GlobalNvs - Pointer of Global NVS area
  28. @retval EFI_SUCCESS - Allocate Global NVS completed.
  29. @retval EFI_OUT_OF_RESOURCES - Failed to allocate required page for GNVS.
  30. **/
  31. EFI_STATUS
  32. EFIAPI
  33. AcpiGnvsInit (
  34. IN OUT VOID **GlobalNvs
  35. );
  36. //
  37. // Function implementations
  38. //
  39. /**
  40. Locate the first instance of a protocol. If the protocol requested is an
  41. FV protocol, then it will return the first FV that contains the ACPI table
  42. storage file.
  43. @param[in] Protocol The protocol to find.
  44. @param[in] Instance Return pointer to the first instance of the protocol.
  45. @param[in] Type TRUE if the desired protocol is a FV protocol.
  46. @retval EFI_SUCCESS The function completed successfully.
  47. @retval EFI_NOT_FOUND The protocol could not be located.
  48. @retval EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.
  49. **/
  50. EFI_STATUS
  51. LocateSupportProtocol (
  52. IN EFI_GUID *Protocol,
  53. IN EFI_GUID *gEfiAcpiMultiTableStorageGuid,
  54. OUT VOID **Instance,
  55. IN BOOLEAN Type
  56. )
  57. {
  58. EFI_STATUS Status;
  59. EFI_HANDLE *HandleBuffer;
  60. UINTN NumberOfHandles;
  61. EFI_FV_FILETYPE FileType;
  62. UINT32 FvStatus;
  63. EFI_FV_FILE_ATTRIBUTES Attributes;
  64. UINTN Size;
  65. UINTN Index;
  66. //
  67. // Locate protocol.
  68. //
  69. Status = gBS->LocateHandleBuffer (
  70. ByProtocol,
  71. Protocol,
  72. NULL,
  73. &NumberOfHandles,
  74. &HandleBuffer
  75. );
  76. if (EFI_ERROR (Status)) {
  77. //
  78. // Defined errors at this time are not found and out of resources.
  79. //
  80. return Status;
  81. }
  82. //
  83. // Looking for FV with ACPI storage file
  84. //
  85. for (Index = 0; Index < NumberOfHandles; Index++) {
  86. //
  87. // Get the protocol on this handle
  88. // This should not fail because of LocateHandleBuffer
  89. //
  90. Status = gBS->HandleProtocol (
  91. HandleBuffer[Index],
  92. Protocol,
  93. Instance
  94. );
  95. ASSERT_EFI_ERROR (Status);
  96. if (!Type) {
  97. //
  98. // Not looking for the FV protocol, so find the first instance of the
  99. // protocol. There should not be any errors because our handle buffer
  100. // should always contain at least one or LocateHandleBuffer would have
  101. // returned not found.
  102. //
  103. break;
  104. }
  105. //
  106. // See if it has the ACPI storage file
  107. //
  108. Size = 0;
  109. FvStatus = 0;
  110. Status = ((EFI_FIRMWARE_VOLUME2_PROTOCOL *) (*Instance))->ReadFile (
  111. *Instance,
  112. gEfiAcpiMultiTableStorageGuid,
  113. NULL,
  114. &Size,
  115. &FileType,
  116. &Attributes,
  117. &FvStatus
  118. );
  119. //
  120. // If we found it, then we are done
  121. //
  122. if (Status == EFI_SUCCESS) {
  123. break;
  124. }
  125. }
  126. //
  127. // Our exit status is determined by the success of the previous operations
  128. // If the protocol was found, Instance already points to it.
  129. //
  130. //
  131. // Free any allocated buffers
  132. //
  133. FreePool (HandleBuffer);
  134. return Status;
  135. }
  136. EFI_STATUS
  137. PublishAcpiTablesFromFv (
  138. IN EFI_GUID *gEfiAcpiMultiTableStorageGuid
  139. )
  140. {
  141. EFI_STATUS Status;
  142. EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
  143. EFI_ACPI_COMMON_HEADER *CurrentTable;
  144. UINT32 FvStatus;
  145. UINTN Size;
  146. UINTN TableHandle;
  147. INTN Instance;
  148. EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
  149. Instance = 0;
  150. TableHandle = 0;
  151. CurrentTable = NULL;
  152. FwVol = NULL;
  153. //
  154. // Find the AcpiSupport protocol
  155. //
  156. Status = LocateSupportProtocol (
  157. &gEfiAcpiTableProtocolGuid,
  158. gEfiAcpiMultiTableStorageGuid,
  159. (VOID **) &AcpiTable,
  160. FALSE
  161. );
  162. ASSERT_EFI_ERROR (Status);
  163. //
  164. // Locate the firmware volume protocol
  165. //
  166. Status = LocateSupportProtocol (
  167. &gEfiFirmwareVolume2ProtocolGuid,
  168. gEfiAcpiMultiTableStorageGuid,
  169. (VOID **) &FwVol,
  170. TRUE
  171. );
  172. //
  173. // Read tables from the storage file.
  174. //
  175. while (Status == EFI_SUCCESS) {
  176. Status = FwVol->ReadSection (
  177. FwVol,
  178. gEfiAcpiMultiTableStorageGuid,
  179. EFI_SECTION_RAW,
  180. Instance,
  181. (VOID **) &CurrentTable,
  182. &Size,
  183. &FvStatus
  184. );
  185. if (!EFI_ERROR (Status)) {
  186. //
  187. // Add the table
  188. //
  189. TableHandle = 0;
  190. Status = AcpiTable->InstallAcpiTable (
  191. AcpiTable,
  192. CurrentTable,
  193. CurrentTable->Length,
  194. &TableHandle
  195. );
  196. ASSERT_EFI_ERROR (Status);
  197. //
  198. // Increment the instance
  199. //
  200. Instance++;
  201. CurrentTable = NULL;
  202. }
  203. }
  204. //
  205. // Finished
  206. //
  207. return EFI_SUCCESS;
  208. }
  209. /**
  210. ACPI Platform driver installation function.
  211. @param[in] ImageHandle Handle for this drivers loaded image protocol.
  212. @param[in] SystemTable EFI system table.
  213. @retval EFI_SUCCESS The driver installed without error.
  214. @retval EFI_ABORTED The driver encountered an error and could not complete installation of
  215. the ACPI tables.
  216. **/
  217. EFI_STATUS
  218. EFIAPI
  219. InstallAcpiBoard (
  220. IN EFI_HANDLE ImageHandle,
  221. IN EFI_SYSTEM_TABLE *SystemTable
  222. )
  223. {
  224. EFI_STATUS Status;
  225. EFI_HANDLE Handle;
  226. AcpiGnvsInit((VOID **) &mGlobalNvsArea.Area);
  227. //
  228. // This PCD set must be done before PublishAcpiTablesFromFv.
  229. // The PCD data will be used there.
  230. //
  231. PcdSet64S (PcdAcpiGnvsAddress, (UINT64)(UINTN)mGlobalNvsArea.Area);
  232. //
  233. // Platform ACPI Tables
  234. //
  235. PublishAcpiTablesFromFv (&gEfiCallerIdGuid);
  236. //
  237. // This protocol publish must be done after PublishAcpiTablesFromFv.
  238. // The NVS data is be updated there.
  239. //
  240. Handle = NULL;
  241. Status = gBS->InstallMultipleProtocolInterfaces (
  242. &Handle,
  243. &gEfiGlobalNvsAreaProtocolGuid,
  244. &mGlobalNvsArea,
  245. NULL
  246. );
  247. ASSERT_EFI_ERROR (Status);
  248. return EFI_SUCCESS;
  249. }