BoardAcpiDxe.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. /** @file
  2. ACPI Platform Driver
  3. Copyright (c) 2017, 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. VOID
  37. UpdateDsdt (
  38. IN VOID *Table
  39. );
  40. //
  41. // Function implementations
  42. //
  43. /**
  44. Locate the first instance of a protocol. If the protocol requested is an
  45. FV protocol, then it will return the first FV that contains the ACPI table
  46. storage file.
  47. @param[in] Protocol The protocol to find.
  48. @param[in] Instance Return pointer to the first instance of the protocol.
  49. @param[in] Type TRUE if the desired protocol is a FV protocol.
  50. @retval EFI_SUCCESS The function completed successfully.
  51. @retval EFI_NOT_FOUND The protocol could not be located.
  52. @retval EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.
  53. **/
  54. EFI_STATUS
  55. LocateSupportProtocol (
  56. IN EFI_GUID *Protocol,
  57. IN EFI_GUID *gEfiAcpiMultiTableStorageGuid,
  58. OUT VOID **Instance,
  59. IN BOOLEAN Type
  60. )
  61. {
  62. EFI_STATUS Status;
  63. EFI_HANDLE *HandleBuffer;
  64. UINTN NumberOfHandles;
  65. EFI_FV_FILETYPE FileType;
  66. UINT32 FvStatus;
  67. EFI_FV_FILE_ATTRIBUTES Attributes;
  68. UINTN Size;
  69. UINTN Index;
  70. //
  71. // Locate protocol.
  72. //
  73. Status = gBS->LocateHandleBuffer (
  74. ByProtocol,
  75. Protocol,
  76. NULL,
  77. &NumberOfHandles,
  78. &HandleBuffer
  79. );
  80. if (EFI_ERROR (Status)) {
  81. //
  82. // Defined errors at this time are not found and out of resources.
  83. //
  84. return Status;
  85. }
  86. //
  87. // Looking for FV with ACPI storage file
  88. //
  89. for (Index = 0; Index < NumberOfHandles; Index++) {
  90. //
  91. // Get the protocol on this handle
  92. // This should not fail because of LocateHandleBuffer
  93. //
  94. Status = gBS->HandleProtocol (
  95. HandleBuffer[Index],
  96. Protocol,
  97. Instance
  98. );
  99. ASSERT_EFI_ERROR (Status);
  100. if (!Type) {
  101. //
  102. // Not looking for the FV protocol, so find the first instance of the
  103. // protocol. There should not be any errors because our handle buffer
  104. // should always contain at least one or LocateHandleBuffer would have
  105. // returned not found.
  106. //
  107. break;
  108. }
  109. //
  110. // See if it has the ACPI storage file
  111. //
  112. Size = 0;
  113. FvStatus = 0;
  114. Status = ((EFI_FIRMWARE_VOLUME2_PROTOCOL *) (*Instance))->ReadFile (
  115. *Instance,
  116. gEfiAcpiMultiTableStorageGuid,
  117. NULL,
  118. &Size,
  119. &FileType,
  120. &Attributes,
  121. &FvStatus
  122. );
  123. //
  124. // If we found it, then we are done
  125. //
  126. if (Status == EFI_SUCCESS) {
  127. break;
  128. }
  129. }
  130. //
  131. // Our exit status is determined by the success of the previous operations
  132. // If the protocol was found, Instance already points to it.
  133. //
  134. //
  135. // Free any allocated buffers
  136. //
  137. FreePool (HandleBuffer);
  138. return Status;
  139. }
  140. EFI_STATUS
  141. PublishAcpiTablesFromFv (
  142. IN EFI_GUID *gEfiAcpiMultiTableStorageGuid
  143. )
  144. {
  145. EFI_STATUS Status;
  146. EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
  147. EFI_ACPI_COMMON_HEADER *CurrentTable;
  148. UINT32 FvStatus;
  149. UINTN Size;
  150. EFI_ACPI_TABLE_VERSION Version;
  151. UINTN TableHandle;
  152. INTN Instance;
  153. EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
  154. Instance = 0;
  155. TableHandle = 0;
  156. CurrentTable = NULL;
  157. FwVol = NULL;
  158. //
  159. // Find the AcpiSupport protocol
  160. //
  161. Status = LocateSupportProtocol (
  162. &gEfiAcpiTableProtocolGuid,
  163. gEfiAcpiMultiTableStorageGuid,
  164. (VOID **) &AcpiTable,
  165. FALSE
  166. );
  167. ASSERT_EFI_ERROR (Status);
  168. //
  169. // Locate the firmware volume protocol
  170. //
  171. Status = LocateSupportProtocol (
  172. &gEfiFirmwareVolume2ProtocolGuid,
  173. gEfiAcpiMultiTableStorageGuid,
  174. (VOID **) &FwVol,
  175. TRUE
  176. );
  177. //
  178. // Read tables from the storage file.
  179. //
  180. while (Status == EFI_SUCCESS) {
  181. Status = FwVol->ReadSection (
  182. FwVol,
  183. gEfiAcpiMultiTableStorageGuid,
  184. EFI_SECTION_RAW,
  185. Instance,
  186. (VOID **) &CurrentTable,
  187. &Size,
  188. &FvStatus
  189. );
  190. if (!EFI_ERROR (Status)) {
  191. //
  192. // Perform any table specific updates.
  193. //
  194. if (CurrentTable->Signature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
  195. UpdateDsdt (CurrentTable);
  196. }
  197. BoardUpdateAcpiTable (CurrentTable, &Version);
  198. //
  199. // Add the table
  200. //
  201. TableHandle = 0;
  202. if (Version != EFI_ACPI_TABLE_VERSION_NONE) {
  203. Status = AcpiTable->InstallAcpiTable (
  204. AcpiTable,
  205. CurrentTable,
  206. CurrentTable->Length,
  207. &TableHandle
  208. );
  209. }
  210. ASSERT_EFI_ERROR (Status);
  211. //
  212. // Increment the instance
  213. //
  214. Instance++;
  215. CurrentTable = NULL;
  216. }
  217. }
  218. //
  219. // Finished
  220. //
  221. return EFI_SUCCESS;
  222. }
  223. /**
  224. ACPI Platform driver installation function.
  225. @param[in] ImageHandle Handle for this drivers loaded image protocol.
  226. @param[in] SystemTable EFI system table.
  227. @retval EFI_SUCCESS The driver installed without error.
  228. @retval EFI_ABORTED The driver encountered an error and could not complete installation of
  229. the ACPI tables.
  230. **/
  231. EFI_STATUS
  232. EFIAPI
  233. InstallAcpiBoard (
  234. IN EFI_HANDLE ImageHandle,
  235. IN EFI_SYSTEM_TABLE *SystemTable
  236. )
  237. {
  238. EFI_STATUS Status;
  239. EFI_HANDLE Handle;
  240. AcpiGnvsInit((VOID **) &mGlobalNvsArea.Area);
  241. //
  242. // This PCD set must be done before PublishAcpiTablesFromFv.
  243. // The PCD data will be used there.
  244. //
  245. PcdSet64S (PcdAcpiGnvsAddress, (UINT64)(UINTN)mGlobalNvsArea.Area);
  246. //
  247. // Platform ACPI Tables
  248. //
  249. PublishAcpiTablesFromFv (&gEfiCallerIdGuid);
  250. //
  251. // This protocol publish must be done after PublishAcpiTablesFromFv.
  252. // The NVS data is be updated there.
  253. //
  254. Handle = NULL;
  255. Status = gBS->InstallMultipleProtocolInterfaces (
  256. &Handle,
  257. &gEfiGlobalNvsAreaProtocolGuid,
  258. &mGlobalNvsArea,
  259. NULL
  260. );
  261. ASSERT_EFI_ERROR (Status);
  262. return EFI_SUCCESS;
  263. }