PciHostBridgeLib.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /** @file
  2. PCI Host Bridge Library instance for Hisilicon D0x
  3. Copyright (c) 2018, Hisilicon Limited. All rights reserved.<BR>
  4. Copyright (c) 2017 - 2018, Linaro Ltd. All rights reserved.<BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include <PiDxe.h>
  8. #include <Library/BaseMemoryLib.h>
  9. #include <Library/DebugLib.h>
  10. #include <Library/DevicePathLib.h>
  11. #include <Library/IoLib.h>
  12. #include <Library/MemoryAllocationLib.h>
  13. #include <Library/OemMiscLib.h>
  14. #include <Library/PcdLib.h>
  15. #include <Library/PciHostBridgeLib.h>
  16. #include <Library/PlatformPciLib.h>
  17. #include <Protocol/PciHostBridgeResourceAllocation.h>
  18. #include <Protocol/PciRootBridgeIo.h>
  19. #pragma pack(1)
  20. typedef struct {
  21. ACPI_HID_DEVICE_PATH AcpiDevicePath;
  22. EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
  23. } EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
  24. #pragma pack ()
  25. STATIC EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath = {
  26. {
  27. {
  28. ACPI_DEVICE_PATH,
  29. ACPI_DP,
  30. {
  31. (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
  32. (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
  33. }
  34. },
  35. EISA_PNP_ID(0x0A03), // PCI
  36. 0
  37. }, {
  38. END_DEVICE_PATH_TYPE,
  39. END_ENTIRE_DEVICE_PATH_SUBTYPE,
  40. {
  41. END_DEVICE_PATH_LENGTH,
  42. 0
  43. }
  44. }
  45. };
  46. STATIC PCI_ROOT_BRIDGE mRootBridgeTemplate = {
  47. 0, // Segment
  48. 0, // Supports
  49. 0, // Attributes
  50. TRUE, // DmaAbove4G
  51. FALSE, // NoExtendedConfigSpace
  52. FALSE, // ResourceAssigned
  53. EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM | // AllocationAttributes
  54. EFI_PCI_HOST_BRIDGE_MEM64_DECODE,
  55. {
  56. // Bus
  57. 0,
  58. 0
  59. }, {
  60. // Io
  61. 0,
  62. 0,
  63. 0
  64. }, {
  65. // Mem
  66. MAX_UINT64,
  67. 0,
  68. 0
  69. }, {
  70. // MemAbove4G
  71. MAX_UINT64,
  72. 0,
  73. 0
  74. }, {
  75. // PMem
  76. MAX_UINT64,
  77. 0,
  78. 0
  79. }, {
  80. // PMemAbove4G
  81. MAX_UINT64,
  82. 0,
  83. 0
  84. },
  85. (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath
  86. };
  87. STATIC
  88. EFI_STATUS
  89. ConstructRootBridge (
  90. PCI_ROOT_BRIDGE *Bridge,
  91. PCI_ROOT_BRIDGE_RESOURCE_APPETURE *Appeture
  92. )
  93. {
  94. EFI_PCI_ROOT_BRIDGE_DEVICE_PATH *DevicePath;
  95. CopyMem (Bridge, &mRootBridgeTemplate, sizeof *Bridge);
  96. Bridge->Segment = Appeture->Segment;
  97. Bridge->Bus.Base = Appeture->BusBase;
  98. Bridge->Bus.Limit = Appeture->BusLimit;
  99. Bridge->Io.Base = Appeture->IoBase;
  100. // According to UEFI 2.7, device address = host address + translation
  101. Bridge->Io.Translation = Appeture->IoBase - Appeture->CpuIoRegionBase;
  102. // IoLimit is actually an address in CPU view
  103. // TODO: improve the definition of PCI_ROOT_BRIDGE_RESOURCE_APPETURE
  104. Bridge->Io.Limit = Appeture->IoLimit + Bridge->Io.Translation;
  105. if (Appeture->PciRegionBase > MAX_UINT32) {
  106. Bridge->MemAbove4G.Base = Appeture->PciRegionBase;
  107. Bridge->MemAbove4G.Limit = Appeture->PciRegionLimit;
  108. Bridge->MemAbove4G.Translation = Appeture->PciRegionBase - Appeture->CpuMemRegionBase;
  109. } else {
  110. Bridge->Mem.Base = Appeture->PciRegionBase;
  111. Bridge->Mem.Limit = Appeture->PciRegionLimit;
  112. Bridge->Mem.Translation = Appeture->PciRegionBase - Appeture->CpuMemRegionBase;
  113. }
  114. DevicePath = AllocateCopyPool(sizeof mEfiPciRootBridgeDevicePath, &mEfiPciRootBridgeDevicePath);
  115. if (DevicePath == NULL) {
  116. DEBUG ((DEBUG_ERROR, "[%a]:[%dL] AllocatePool failed!\n", __FUNCTION__, __LINE__));
  117. return EFI_OUT_OF_RESOURCES;
  118. }
  119. DevicePath->AcpiDevicePath.UID = Bridge->Segment;
  120. Bridge->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;
  121. return EFI_SUCCESS;
  122. }
  123. /**
  124. Return all the root bridge instances in an array.
  125. @param Count Return the count of root bridge instances.
  126. @return All the root bridge instances in an array.
  127. The array should be passed into PciHostBridgeFreeRootBridges()
  128. when it's not used.
  129. **/
  130. PCI_ROOT_BRIDGE *
  131. EFIAPI
  132. PciHostBridgeGetRootBridges (
  133. UINTN *Count
  134. )
  135. {
  136. EFI_STATUS Status;
  137. UINTN Loop1;
  138. UINTN Loop2;
  139. UINT32 PcieRootBridgeMask;
  140. UINTN RootBridgeCount = 0;
  141. PCI_ROOT_BRIDGE *Bridges;
  142. // Set default value to 0 in case we got any error.
  143. *Count = 0;
  144. if (!OemIsMpBoot())
  145. {
  146. PcieRootBridgeMask = PcdGet32(PcdPcieRootBridgeMask);
  147. }
  148. else
  149. {
  150. PcieRootBridgeMask = PcdGet32(PcdPcieRootBridgeMask2P);
  151. }
  152. for (Loop1 = 0; Loop1 < PCIE_MAX_HOSTBRIDGE; Loop1++) {
  153. if (((PcieRootBridgeMask >> (PCIE_MAX_ROOTBRIDGE * Loop1)) & 0xFF ) == 0) {
  154. continue;
  155. }
  156. for (Loop2 = 0; Loop2 < PCIE_MAX_ROOTBRIDGE; Loop2++) {
  157. if (!(((PcieRootBridgeMask >> (PCIE_MAX_ROOTBRIDGE * Loop1)) >> Loop2 ) & 0x01)) {
  158. continue;
  159. }
  160. RootBridgeCount++;
  161. }
  162. }
  163. Bridges = AllocatePool (RootBridgeCount * sizeof *Bridges);
  164. if (Bridges == NULL) {
  165. DEBUG ((DEBUG_ERROR, "[%a:%d] - AllocatePool failed!\n", __FUNCTION__, __LINE__));
  166. return NULL;
  167. }
  168. for (Loop1 = 0; Loop1 < PCIE_MAX_HOSTBRIDGE; Loop1++) {
  169. if (((PcieRootBridgeMask >> (PCIE_MAX_ROOTBRIDGE * Loop1)) & 0xFF ) == 0) {
  170. continue;
  171. }
  172. for (Loop2 = 0; Loop2 < PCIE_MAX_ROOTBRIDGE; Loop2++) {
  173. if (!(((PcieRootBridgeMask >> (PCIE_MAX_ROOTBRIDGE * Loop1)) >> Loop2 ) & 0x01)) {
  174. continue;
  175. }
  176. Status = ConstructRootBridge (&Bridges[*Count], &mResAppeture[Loop1][Loop2]);
  177. if (EFI_ERROR (Status)) {
  178. continue;
  179. }
  180. (*Count)++;
  181. }
  182. }
  183. if (*Count == 0) {
  184. FreePool (Bridges);
  185. return NULL;
  186. }
  187. return Bridges;
  188. }
  189. /**
  190. Free the root bridge instances array returned from PciHostBridgeGetRootBridges().
  191. @param Bridges The root bridge instances array.
  192. @param Count The count of the array.
  193. **/
  194. VOID
  195. EFIAPI
  196. PciHostBridgeFreeRootBridges (
  197. PCI_ROOT_BRIDGE *Bridges,
  198. UINTN Count
  199. )
  200. {
  201. UINTN Index;
  202. for (Index = 0; Index < Count; Index++) {
  203. FreePool (Bridges[Index].DevicePath);
  204. }
  205. if (Bridges != NULL) {
  206. FreePool (Bridges);
  207. }
  208. }
  209. #ifndef MDEPKG_NDEBUG
  210. STATIC CONST CHAR16 mPciHostBridgeLibAcpiAddressSpaceTypeStr[][4] = {
  211. L"Mem", L"I/O", L"Bus"
  212. };
  213. #endif
  214. /**
  215. Inform the platform that the resource conflict happens.
  216. @param HostBridgeHandle Handle of the Host Bridge.
  217. @param Configuration Pointer to PCI I/O and PCI memory resource
  218. descriptors. The Configuration contains the resources
  219. for all the root bridges. The resource for each root
  220. bridge is terminated with END descriptor and an
  221. additional END is appended indicating the end of the
  222. entire resources. The resource descriptor field
  223. values follow the description in
  224. EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
  225. .SubmitResources().
  226. **/
  227. VOID
  228. EFIAPI
  229. PciHostBridgeResourceConflict (
  230. EFI_HANDLE HostBridgeHandle,
  231. VOID *Configuration
  232. )
  233. {
  234. EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
  235. UINTN RootBridgeIndex;
  236. DEBUG ((DEBUG_ERROR, "PciHostBridge: Resource conflict happens!\n"));
  237. RootBridgeIndex = 0;
  238. Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
  239. while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
  240. DEBUG ((DEBUG_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));
  241. for (; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
  242. ASSERT (Descriptor->ResType <
  243. ARRAY_SIZE (mPciHostBridgeLibAcpiAddressSpaceTypeStr)
  244. );
  245. DEBUG ((DEBUG_ERROR, " %s: Length/Alignment = 0x%lx / 0x%lx\n",
  246. mPciHostBridgeLibAcpiAddressSpaceTypeStr[Descriptor->ResType],
  247. Descriptor->AddrLen, Descriptor->AddrRangeMax
  248. ));
  249. if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
  250. DEBUG ((DEBUG_ERROR, " Granularity/SpecificFlag = %ld / %02x%s\n",
  251. Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,
  252. ((Descriptor->SpecificFlag &
  253. EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
  254. ) != 0) ? L" (Prefetchable)" : L""
  255. ));
  256. }
  257. }
  258. //
  259. // Skip the END descriptor for root bridge
  260. //
  261. ASSERT (Descriptor->Desc == ACPI_END_TAG_DESCRIPTOR);
  262. Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(
  263. (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor + 1
  264. );
  265. }
  266. }