AhciPei.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /** @file
  2. The AhciPei driver is used to manage ATA hard disk device working under AHCI
  3. mode at PEI phase.
  4. Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include "AhciPei.h"
  8. EFI_PEI_PPI_DESCRIPTOR mAhciAtaPassThruPpiListTemplate = {
  9. (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
  10. &gEdkiiPeiAtaPassThruPpiGuid,
  11. NULL
  12. };
  13. EFI_PEI_PPI_DESCRIPTOR mAhciStorageSecurityPpiListTemplate = {
  14. (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
  15. &gEdkiiPeiStorageSecurityCommandPpiGuid,
  16. NULL
  17. };
  18. EFI_PEI_NOTIFY_DESCRIPTOR mAhciEndOfPeiNotifyListTemplate = {
  19. (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
  20. &gEfiEndOfPeiSignalPpiGuid,
  21. AhciPeimEndOfPei
  22. };
  23. /**
  24. Free the DMA resources allocated by an ATA AHCI controller.
  25. @param[in] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA data
  26. structure.
  27. **/
  28. VOID
  29. AhciFreeDmaResource (
  30. IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private
  31. )
  32. {
  33. EFI_AHCI_REGISTERS *AhciRegisters;
  34. ASSERT (Private != NULL);
  35. AhciRegisters = &Private->AhciRegisters;
  36. if (AhciRegisters->AhciRFisMap != NULL) {
  37. IoMmuFreeBuffer (
  38. EFI_SIZE_TO_PAGES (AhciRegisters->MaxRFisSize),
  39. AhciRegisters->AhciRFis,
  40. AhciRegisters->AhciRFisMap
  41. );
  42. }
  43. if (AhciRegisters->AhciCmdListMap != NULL) {
  44. IoMmuFreeBuffer (
  45. EFI_SIZE_TO_PAGES (AhciRegisters->MaxCmdListSize),
  46. AhciRegisters->AhciCmdList,
  47. AhciRegisters->AhciCmdListMap
  48. );
  49. }
  50. if (AhciRegisters->AhciCmdTableMap != NULL) {
  51. IoMmuFreeBuffer (
  52. EFI_SIZE_TO_PAGES (AhciRegisters->MaxCmdTableSize),
  53. AhciRegisters->AhciCmdTable,
  54. AhciRegisters->AhciCmdTableMap
  55. );
  56. }
  57. }
  58. /**
  59. One notified function to cleanup the allocated DMA buffers at EndOfPei.
  60. @param[in] PeiServices Pointer to PEI Services Table.
  61. @param[in] NotifyDescriptor Pointer to the descriptor for the Notification
  62. event that caused this function to execute.
  63. @param[in] Ppi Pointer to the PPI data associated with this function.
  64. @retval EFI_SUCCESS The function completes successfully
  65. **/
  66. EFI_STATUS
  67. EFIAPI
  68. AhciPeimEndOfPei (
  69. IN EFI_PEI_SERVICES **PeiServices,
  70. IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
  71. IN VOID *Ppi
  72. )
  73. {
  74. PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private;
  75. Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY (NotifyDescriptor);
  76. AhciFreeDmaResource (Private);
  77. return EFI_SUCCESS;
  78. }
  79. /**
  80. Entry point of the PEIM.
  81. @param[in] FileHandle Handle of the file being invoked.
  82. @param[in] PeiServices Describes the list of possible PEI Services.
  83. @retval EFI_SUCCESS PPI successfully installed.
  84. **/
  85. EFI_STATUS
  86. EFIAPI
  87. AtaAhciPeimEntry (
  88. IN EFI_PEI_FILE_HANDLE FileHandle,
  89. IN CONST EFI_PEI_SERVICES **PeiServices
  90. )
  91. {
  92. EFI_STATUS Status;
  93. EFI_BOOT_MODE BootMode;
  94. EDKII_ATA_AHCI_HOST_CONTROLLER_PPI *AhciHcPpi;
  95. UINT8 Controller;
  96. UINTN MmioBase;
  97. UINTN DevicePathLength;
  98. EFI_DEVICE_PATH_PROTOCOL *DevicePath;
  99. UINT32 PortBitMap;
  100. PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private;
  101. UINT8 NumberOfPorts;
  102. DEBUG ((DEBUG_INFO, "%a: Enters.\n", __FUNCTION__));
  103. //
  104. // Get the current boot mode.
  105. //
  106. Status = PeiServicesGetBootMode (&BootMode);
  107. if (EFI_ERROR (Status)) {
  108. DEBUG ((DEBUG_ERROR, "%a: Fail to get the current boot mode.\n", __FUNCTION__));
  109. return Status;
  110. }
  111. //
  112. // Locate the ATA AHCI host controller PPI.
  113. //
  114. Status = PeiServicesLocatePpi (
  115. &gEdkiiPeiAtaAhciHostControllerPpiGuid,
  116. 0,
  117. NULL,
  118. (VOID **) &AhciHcPpi
  119. );
  120. if (EFI_ERROR (Status)) {
  121. DEBUG ((DEBUG_ERROR, "%a: Failed to locate AtaAhciHostControllerPpi.\n", __FUNCTION__));
  122. return EFI_UNSUPPORTED;
  123. }
  124. Controller = 0;
  125. MmioBase = 0;
  126. while (TRUE) {
  127. Status = AhciHcPpi->GetAhciHcMmioBar (
  128. AhciHcPpi,
  129. Controller,
  130. &MmioBase
  131. );
  132. //
  133. // When status is error, meant no controller is found.
  134. //
  135. if (EFI_ERROR (Status)) {
  136. break;
  137. }
  138. Status = AhciHcPpi->GetAhciHcDevicePath (
  139. AhciHcPpi,
  140. Controller,
  141. &DevicePathLength,
  142. &DevicePath
  143. );
  144. if (EFI_ERROR (Status)) {
  145. DEBUG ((
  146. DEBUG_ERROR, "%a: Fail to allocate get the device path for Controller %d.\n",
  147. __FUNCTION__, Controller
  148. ));
  149. return Status;
  150. }
  151. //
  152. // Check validity of the device path of the ATA AHCI controller.
  153. //
  154. Status = AhciIsHcDevicePathValid (DevicePath, DevicePathLength);
  155. if (EFI_ERROR (Status)) {
  156. DEBUG ((
  157. DEBUG_ERROR, "%a: The device path is invalid for Controller %d.\n",
  158. __FUNCTION__, Controller
  159. ));
  160. Controller++;
  161. continue;
  162. }
  163. //
  164. // For S3 resume performance consideration, not all ports on an ATA AHCI
  165. // controller will be enumerated/initialized. The driver consumes the
  166. // content within S3StorageDeviceInitList LockBox to get the ports that
  167. // will be enumerated/initialized during S3 resume.
  168. //
  169. if (BootMode == BOOT_ON_S3_RESUME) {
  170. NumberOfPorts = AhciS3GetEumeratePorts (DevicePath, DevicePathLength, &PortBitMap);
  171. if (NumberOfPorts == 0) {
  172. //
  173. // No ports need to be enumerated for this controller.
  174. //
  175. Controller++;
  176. continue;
  177. }
  178. } else {
  179. PortBitMap = MAX_UINT32;
  180. }
  181. //
  182. // Memory allocation for controller private data.
  183. //
  184. Private = AllocateZeroPool (sizeof (PEI_AHCI_CONTROLLER_PRIVATE_DATA));
  185. if (Private == NULL) {
  186. DEBUG ((
  187. DEBUG_ERROR, "%a: Fail to allocate private data for Controller %d.\n",
  188. __FUNCTION__, Controller
  189. ));
  190. return EFI_OUT_OF_RESOURCES;
  191. }
  192. //
  193. // Initialize controller private data.
  194. //
  195. Private->Signature = AHCI_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE;
  196. Private->MmioBase = MmioBase;
  197. Private->DevicePathLength = DevicePathLength;
  198. Private->DevicePath = DevicePath;
  199. Private->PortBitMap = PortBitMap;
  200. InitializeListHead (&Private->DeviceList);
  201. Status = AhciModeInitialization (Private);
  202. if (EFI_ERROR (Status)) {
  203. DEBUG ((
  204. DEBUG_ERROR,
  205. "%a: Controller initialization fail for Controller %d with Status - %r.\n",
  206. __FUNCTION__,
  207. Controller,
  208. Status
  209. ));
  210. Controller++;
  211. continue;
  212. }
  213. Private->AtaPassThruMode.Attributes = EFI_ATA_PASS_THRU_ATTRIBUTES_PHYSICAL |
  214. EFI_ATA_PASS_THRU_ATTRIBUTES_LOGICAL;
  215. Private->AtaPassThruMode.IoAlign = sizeof (UINTN);
  216. Private->AtaPassThruPpi.Revision = EDKII_PEI_ATA_PASS_THRU_PPI_REVISION;
  217. Private->AtaPassThruPpi.Mode = &Private->AtaPassThruMode;
  218. Private->AtaPassThruPpi.PassThru = AhciAtaPassThruPassThru;
  219. Private->AtaPassThruPpi.GetNextPort = AhciAtaPassThruGetNextPort;
  220. Private->AtaPassThruPpi.GetNextDevice = AhciAtaPassThruGetNextDevice;
  221. Private->AtaPassThruPpi.GetDevicePath = AhciAtaPassThruGetDevicePath;
  222. CopyMem (
  223. &Private->AtaPassThruPpiList,
  224. &mAhciAtaPassThruPpiListTemplate,
  225. sizeof (EFI_PEI_PPI_DESCRIPTOR)
  226. );
  227. Private->AtaPassThruPpiList.Ppi = &Private->AtaPassThruPpi;
  228. PeiServicesInstallPpi (&Private->AtaPassThruPpiList);
  229. if (Private->TrustComputingDevices != 0) {
  230. DEBUG ((
  231. DEBUG_INFO,
  232. "%a: Security Security Command PPI will be produced for Controller %d.\n",
  233. __FUNCTION__, Controller
  234. ));
  235. Private->StorageSecurityPpi.Revision = EDKII_STORAGE_SECURITY_PPI_REVISION;
  236. Private->StorageSecurityPpi.GetNumberofDevices = AhciStorageSecurityGetDeviceNo;
  237. Private->StorageSecurityPpi.GetDevicePath = AhciStorageSecurityGetDevicePath;
  238. Private->StorageSecurityPpi.ReceiveData = AhciStorageSecurityReceiveData;
  239. Private->StorageSecurityPpi.SendData = AhciStorageSecuritySendData;
  240. CopyMem (
  241. &Private->StorageSecurityPpiList,
  242. &mAhciStorageSecurityPpiListTemplate,
  243. sizeof (EFI_PEI_PPI_DESCRIPTOR)
  244. );
  245. Private->StorageSecurityPpiList.Ppi = &Private->StorageSecurityPpi;
  246. PeiServicesInstallPpi (&Private->StorageSecurityPpiList);
  247. }
  248. CopyMem (
  249. &Private->EndOfPeiNotifyList,
  250. &mAhciEndOfPeiNotifyListTemplate,
  251. sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)
  252. );
  253. PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);
  254. DEBUG ((
  255. DEBUG_INFO, "%a: Controller %d has been successfully initialized.\n",
  256. __FUNCTION__, Controller
  257. ));
  258. Controller++;
  259. }
  260. return EFI_SUCCESS;
  261. }