FwBlockServiceDxe.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /**@file
  2. Functions related to the Firmware Volume Block service whose
  3. implementation is specific to the runtime DXE driver build.
  4. Copyright (C) 2015, Red Hat, Inc.
  5. Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
  6. SPDX-License-Identifier: BSD-2-Clause-Patent
  7. **/
  8. #include <Guid/EventGroup.h>
  9. #include <Library/DebugLib.h>
  10. #include <Library/DevicePathLib.h>
  11. #include <Library/DxeServicesTableLib.h>
  12. #include <Library/MemEncryptSevLib.h>
  13. #include <Library/PcdLib.h>
  14. #include <Library/UefiBootServicesTableLib.h>
  15. #include <Library/UefiRuntimeLib.h>
  16. #include <Protocol/DevicePath.h>
  17. #include <Protocol/FirmwareVolumeBlock.h>
  18. #include "FwBlockService.h"
  19. #include "QemuFlash.h"
  20. VOID
  21. InstallProtocolInterfaces (
  22. IN EFI_FW_VOL_BLOCK_DEVICE *FvbDevice
  23. )
  24. {
  25. EFI_STATUS Status;
  26. EFI_HANDLE FwbHandle;
  27. EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *OldFwbInterface;
  28. ASSERT (!FeaturePcdGet (PcdSmmSmramRequire));
  29. //
  30. // Find a handle with a matching device path that has supports FW Block
  31. // protocol
  32. //
  33. Status = gBS->LocateDevicePath (
  34. &gEfiFirmwareVolumeBlockProtocolGuid,
  35. &FvbDevice->DevicePath,
  36. &FwbHandle
  37. );
  38. if (EFI_ERROR (Status)) {
  39. //
  40. // LocateDevicePath fails so install a new interface and device path
  41. //
  42. FwbHandle = NULL;
  43. DEBUG ((DEBUG_INFO, "Installing QEMU flash FVB\n"));
  44. Status = gBS->InstallMultipleProtocolInterfaces (
  45. &FwbHandle,
  46. &gEfiFirmwareVolumeBlockProtocolGuid,
  47. &FvbDevice->FwVolBlockInstance,
  48. &gEfiDevicePathProtocolGuid,
  49. FvbDevice->DevicePath,
  50. NULL
  51. );
  52. ASSERT_EFI_ERROR (Status);
  53. } else if (IsDevicePathEnd (FvbDevice->DevicePath)) {
  54. //
  55. // Device already exists, so reinstall the FVB protocol
  56. //
  57. Status = gBS->HandleProtocol (
  58. FwbHandle,
  59. &gEfiFirmwareVolumeBlockProtocolGuid,
  60. (VOID **)&OldFwbInterface
  61. );
  62. ASSERT_EFI_ERROR (Status);
  63. DEBUG ((DEBUG_INFO, "Reinstalling FVB for QEMU flash region\n"));
  64. Status = gBS->ReinstallProtocolInterface (
  65. FwbHandle,
  66. &gEfiFirmwareVolumeBlockProtocolGuid,
  67. OldFwbInterface,
  68. &FvbDevice->FwVolBlockInstance
  69. );
  70. ASSERT_EFI_ERROR (Status);
  71. } else {
  72. //
  73. // There was a FVB protocol on an End Device Path node
  74. //
  75. ASSERT (FALSE);
  76. }
  77. }
  78. STATIC
  79. VOID
  80. EFIAPI
  81. FvbVirtualAddressChangeEvent (
  82. IN EFI_EVENT Event,
  83. IN VOID *Context
  84. )
  85. /*++
  86. Routine Description:
  87. Fixup internal data so that EFI and SAL can be call in virtual mode.
  88. Call the passed in Child Notify event and convert the mFvbModuleGlobal
  89. date items to there virtual address.
  90. Arguments:
  91. (Standard EFI notify event - EFI_EVENT_NOTIFY)
  92. Returns:
  93. None
  94. --*/
  95. {
  96. EFI_FW_VOL_INSTANCE *FwhInstance;
  97. UINTN Index;
  98. FwhInstance = mFvbModuleGlobal->FvInstance;
  99. EfiConvertPointer (0x0, (VOID **)&mFvbModuleGlobal->FvInstance);
  100. //
  101. // Convert the base address of all the instances
  102. //
  103. Index = 0;
  104. while (Index < mFvbModuleGlobal->NumFv) {
  105. EfiConvertPointer (0x0, (VOID **)&FwhInstance->FvBase);
  106. FwhInstance = (EFI_FW_VOL_INSTANCE *)
  107. (
  108. (UINTN)((UINT8 *)FwhInstance) +
  109. FwhInstance->VolumeHeader.HeaderLength +
  110. (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))
  111. );
  112. Index++;
  113. }
  114. EfiConvertPointer (0x0, (VOID **)&mFvbModuleGlobal);
  115. QemuFlashConvertPointers ();
  116. }
  117. VOID
  118. InstallVirtualAddressChangeHandler (
  119. VOID
  120. )
  121. {
  122. EFI_STATUS Status;
  123. EFI_EVENT VirtualAddressChangeEvent;
  124. Status = gBS->CreateEventEx (
  125. EVT_NOTIFY_SIGNAL,
  126. TPL_NOTIFY,
  127. FvbVirtualAddressChangeEvent,
  128. NULL,
  129. &gEfiEventVirtualAddressChangeGuid,
  130. &VirtualAddressChangeEvent
  131. );
  132. ASSERT_EFI_ERROR (Status);
  133. }
  134. EFI_STATUS
  135. MarkIoMemoryRangeForRuntimeAccess (
  136. IN EFI_PHYSICAL_ADDRESS BaseAddress,
  137. IN UINTN Length
  138. )
  139. {
  140. EFI_STATUS Status;
  141. EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
  142. //
  143. // Mark flash region as runtime memory
  144. //
  145. Status = gDS->RemoveMemorySpace (
  146. BaseAddress,
  147. Length
  148. );
  149. Status = gDS->AddMemorySpace (
  150. EfiGcdMemoryTypeMemoryMappedIo,
  151. BaseAddress,
  152. Length,
  153. EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
  154. );
  155. ASSERT_EFI_ERROR (Status);
  156. Status = gDS->AllocateMemorySpace (
  157. EfiGcdAllocateAddress,
  158. EfiGcdMemoryTypeMemoryMappedIo,
  159. 0,
  160. Length,
  161. &BaseAddress,
  162. gImageHandle,
  163. NULL
  164. );
  165. ASSERT_EFI_ERROR (Status);
  166. Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdDescriptor);
  167. ASSERT_EFI_ERROR (Status);
  168. Status = gDS->SetMemorySpaceAttributes (
  169. BaseAddress,
  170. Length,
  171. GcdDescriptor.Attributes | EFI_MEMORY_RUNTIME
  172. );
  173. ASSERT_EFI_ERROR (Status);
  174. //
  175. // When SEV is active, AmdSevDxe mapped the BaseAddress with C=0 but
  176. // SetMemorySpaceAttributes() remaps the range with C=1. Let's restore
  177. // the mapping so that both guest and hyervisor can access the flash
  178. // memory range.
  179. //
  180. if (MemEncryptSevIsEnabled ()) {
  181. Status = MemEncryptSevClearMmioPageEncMask (
  182. 0,
  183. BaseAddress,
  184. EFI_SIZE_TO_PAGES (Length)
  185. );
  186. ASSERT_EFI_ERROR (Status);
  187. }
  188. return Status;
  189. }
  190. VOID
  191. SetPcdFlashNvStorageBaseAddresses (
  192. VOID
  193. )
  194. {
  195. RETURN_STATUS PcdStatus;
  196. //
  197. // Set several PCD values to point to flash
  198. //
  199. PcdStatus = PcdSet64S (
  200. PcdFlashNvStorageVariableBase64,
  201. (UINTN)PcdGet32 (PcdOvmfFlashNvStorageVariableBase)
  202. );
  203. ASSERT_RETURN_ERROR (PcdStatus);
  204. PcdStatus = PcdSet32S (
  205. PcdFlashNvStorageFtwWorkingBase,
  206. PcdGet32 (PcdOvmfFlashNvStorageFtwWorkingBase)
  207. );
  208. ASSERT_RETURN_ERROR (PcdStatus);
  209. PcdStatus = PcdSet32S (
  210. PcdFlashNvStorageFtwSpareBase,
  211. PcdGet32 (PcdOvmfFlashNvStorageFtwSpareBase)
  212. );
  213. ASSERT_RETURN_ERROR (PcdStatus);
  214. }