AcpiPlatform.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /** @file
  2. bhyve ACPI Platform Driver
  3. Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
  4. Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include "AcpiPlatform.h"
  8. EFI_STATUS
  9. EFIAPI
  10. InstallAcpiTable (
  11. IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,
  12. IN VOID *AcpiTableBuffer,
  13. IN UINTN AcpiTableBufferSize,
  14. OUT UINTN *TableKey
  15. )
  16. {
  17. return AcpiProtocol->InstallAcpiTable (
  18. AcpiProtocol,
  19. AcpiTableBuffer,
  20. AcpiTableBufferSize,
  21. TableKey
  22. );
  23. }
  24. /**
  25. Locate the first instance of a protocol. If the protocol requested is an
  26. FV protocol, then it will return the first FV that contains the ACPI table
  27. storage file.
  28. @param Instance Return pointer to the first instance of the protocol
  29. @return EFI_SUCCESS The function completed successfully.
  30. @return EFI_NOT_FOUND The protocol could not be located.
  31. @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.
  32. **/
  33. EFI_STATUS
  34. LocateFvInstanceWithTables (
  35. OUT EFI_FIRMWARE_VOLUME2_PROTOCOL **Instance
  36. )
  37. {
  38. EFI_STATUS Status;
  39. EFI_HANDLE *HandleBuffer;
  40. UINTN NumberOfHandles;
  41. EFI_FV_FILETYPE FileType;
  42. UINT32 FvStatus;
  43. EFI_FV_FILE_ATTRIBUTES Attributes;
  44. UINTN Size;
  45. UINTN Index;
  46. EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance;
  47. FvStatus = 0;
  48. //
  49. // Locate protocol.
  50. //
  51. Status = gBS->LocateHandleBuffer (
  52. ByProtocol,
  53. &gEfiFirmwareVolume2ProtocolGuid,
  54. NULL,
  55. &NumberOfHandles,
  56. &HandleBuffer
  57. );
  58. if (EFI_ERROR (Status)) {
  59. //
  60. // Defined errors at this time are not found and out of resources.
  61. //
  62. return Status;
  63. }
  64. //
  65. // Looking for FV with ACPI storage file
  66. //
  67. for (Index = 0; Index < NumberOfHandles; Index++) {
  68. //
  69. // Get the protocol on this handle
  70. // This should not fail because of LocateHandleBuffer
  71. //
  72. Status = gBS->HandleProtocol (
  73. HandleBuffer[Index],
  74. &gEfiFirmwareVolume2ProtocolGuid,
  75. (VOID **)&FvInstance
  76. );
  77. ASSERT_EFI_ERROR (Status);
  78. //
  79. // See if it has the ACPI storage file
  80. //
  81. Status = FvInstance->ReadFile (
  82. FvInstance,
  83. (EFI_GUID *)PcdGetPtr (PcdAcpiTableStorageFile),
  84. NULL,
  85. &Size,
  86. &FileType,
  87. &Attributes,
  88. &FvStatus
  89. );
  90. //
  91. // If we found it, then we are done
  92. //
  93. if (Status == EFI_SUCCESS) {
  94. *Instance = FvInstance;
  95. break;
  96. }
  97. }
  98. //
  99. // Our exit status is determined by the success of the previous operations
  100. // If the protocol was found, Instance already points to it.
  101. //
  102. //
  103. // Free any allocated buffers
  104. //
  105. gBS->FreePool (HandleBuffer);
  106. return Status;
  107. }
  108. /**
  109. Find ACPI tables in an FV and install them.
  110. This is now a fall-back path. Normally, we will search for tables provided
  111. by the VMM first.
  112. If that fails, we use this function to load the ACPI tables from an FV. The
  113. sources for the FV based tables is located under OvmfPkg/Bhyve/AcpiTables.
  114. @param AcpiTable Protocol instance pointer
  115. **/
  116. EFI_STATUS
  117. EFIAPI
  118. InstallOvmfFvTables (
  119. IN EFI_ACPI_TABLE_PROTOCOL *AcpiTable
  120. )
  121. {
  122. EFI_STATUS Status;
  123. EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
  124. INTN Instance;
  125. EFI_ACPI_COMMON_HEADER *CurrentTable;
  126. UINTN TableHandle;
  127. UINT32 FvStatus;
  128. UINTN TableSize;
  129. UINTN Size;
  130. EFI_ACPI_TABLE_INSTALL_ACPI_TABLE TableInstallFunction;
  131. Instance = 0;
  132. CurrentTable = NULL;
  133. TableHandle = 0;
  134. TableInstallFunction = BhyveInstallAcpiTable;
  135. //
  136. // set FwVol (and use an ASSERT() below) to suppress incorrect
  137. // compiler/analyzer warnings
  138. //
  139. FwVol = NULL;
  140. //
  141. // Locate the firmware volume protocol
  142. //
  143. Status = LocateFvInstanceWithTables (&FwVol);
  144. if (EFI_ERROR (Status)) {
  145. return EFI_ABORTED;
  146. }
  147. ASSERT (FwVol != NULL);
  148. //
  149. // Read tables from the storage file.
  150. //
  151. while (Status == EFI_SUCCESS) {
  152. Status = FwVol->ReadSection (
  153. FwVol,
  154. (EFI_GUID *)PcdGetPtr (PcdAcpiTableStorageFile),
  155. EFI_SECTION_RAW,
  156. Instance,
  157. (VOID **)&CurrentTable,
  158. &Size,
  159. &FvStatus
  160. );
  161. if (!EFI_ERROR (Status)) {
  162. //
  163. // Add the table
  164. //
  165. TableHandle = 0;
  166. TableSize = ((EFI_ACPI_DESCRIPTION_HEADER *)CurrentTable)->Length;
  167. ASSERT (Size >= TableSize);
  168. //
  169. // Install ACPI table
  170. //
  171. Status = TableInstallFunction (
  172. AcpiTable,
  173. CurrentTable,
  174. TableSize,
  175. &TableHandle
  176. );
  177. //
  178. // Free memory allocated by ReadSection
  179. //
  180. gBS->FreePool (CurrentTable);
  181. if (EFI_ERROR (Status)) {
  182. return EFI_ABORTED;
  183. }
  184. //
  185. // Increment the instance
  186. //
  187. Instance++;
  188. CurrentTable = NULL;
  189. }
  190. }
  191. return EFI_SUCCESS;
  192. }
  193. /**
  194. Effective entrypoint of Acpi Platform driver.
  195. @param ImageHandle
  196. @param SystemTable
  197. @return EFI_SUCCESS
  198. @return EFI_LOAD_ERROR
  199. @return EFI_OUT_OF_RESOURCES
  200. **/
  201. EFI_STATUS
  202. EFIAPI
  203. InstallAcpiTables (
  204. IN EFI_ACPI_TABLE_PROTOCOL *AcpiTable
  205. )
  206. {
  207. EFI_STATUS Status;
  208. Status = InstallOvmfFvTables (AcpiTable);
  209. return Status;
  210. }