DxeCheckPci.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. /** @file
  2. Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
  3. SPDX-License-Identifier: BSD-2-Clause-Patent
  4. **/
  5. #include <Uefi.h>
  6. #include <PiDxe.h>
  7. #include <Library/TestPointCheckLib.h>
  8. #include <Library/TestPointLib.h>
  9. #include <Library/DebugLib.h>
  10. #include <Library/MemoryAllocationLib.h>
  11. #include <Library/UefiBootServicesTableLib.h>
  12. #include <Protocol/PciIo.h>
  13. #include <Protocol/PciRootBridgeIo.h>
  14. #include <Library/PciSegmentLib.h>
  15. #include <Library/PciSegmentInfoLib.h>
  16. #include <IndustryStandard/Pci.h>
  17. #pragma pack(1)
  18. //
  19. // Data region after PCI configuration header(for cardbus bridge)
  20. //
  21. typedef struct {
  22. UINT16 SubVendorId; // Subsystem Vendor ID
  23. UINT16 SubSystemId; // Subsystem ID
  24. UINT32 LegacyBase; // Optional 16-Bit PC Card Legacy
  25. // Mode Base Address
  26. //
  27. UINT32 Data[46];
  28. } PCI_CARDBUS_DATA;
  29. typedef union {
  30. PCI_DEVICE_HEADER_TYPE_REGION Device;
  31. PCI_BRIDGE_CONTROL_REGISTER Bridge;
  32. PCI_CARDBUS_CONTROL_REGISTER CardBus;
  33. } NON_COMMON_UNION;
  34. typedef struct {
  35. PCI_DEVICE_INDEPENDENT_REGION Common;
  36. NON_COMMON_UNION NonCommon;
  37. UINT32 Data[48];
  38. } PCI_CONFIG_SPACE;
  39. #pragma pack()
  40. VOID
  41. DumpPciDevice (
  42. IN UINT8 Bus,
  43. IN UINT8 Device,
  44. IN UINT8 Function,
  45. IN PCI_TYPE00 *PciData
  46. )
  47. {
  48. //DEBUG ((DEBUG_INFO, " 00/00/00 : [0000][0000] [00|00|00] 00000000 00000000 00000000 00000000 00000000 00000000 0000\n"));
  49. DEBUG ((DEBUG_INFO, " %02x/%02x/%02x :",
  50. Bus,
  51. Device,
  52. Function
  53. ));
  54. DEBUG ((DEBUG_INFO, " [%04x][%04x]",
  55. PciData->Hdr.VendorId,
  56. PciData->Hdr.DeviceId
  57. ));
  58. DEBUG ((DEBUG_INFO, " [%02x|%02x|%02x]",
  59. PciData->Hdr.ClassCode[2],
  60. PciData->Hdr.ClassCode[1],
  61. PciData->Hdr.ClassCode[0]
  62. ));
  63. DEBUG ((DEBUG_INFO, " %08x %08x %08x %08x %08x %08x",
  64. PciData->Device.Bar[0],
  65. PciData->Device.Bar[1],
  66. PciData->Device.Bar[2],
  67. PciData->Device.Bar[3],
  68. PciData->Device.Bar[4],
  69. PciData->Device.Bar[5]
  70. ));
  71. DEBUG ((DEBUG_INFO, " %04x\n",
  72. PciData->Hdr.Command
  73. ));
  74. }
  75. VOID
  76. DumpPciBridge (
  77. IN UINT8 Bus,
  78. IN UINT8 Device,
  79. IN UINT8 Function,
  80. IN PCI_TYPE01 *PciData
  81. )
  82. {
  83. //DEBUG ((DEBUG_INFO, " 00/00/00*: [0000][0000] [00|00|00] 00000000 00000000 [00|00|00] [00:00] [0000:0000] [0000:0000] [00000000:00000000] [0000:0000] 0000 0000\n"));
  84. DEBUG ((DEBUG_INFO, " %02x/%02x/%02x*:",
  85. Bus,
  86. Device,
  87. Function
  88. ));
  89. DEBUG ((DEBUG_INFO, " [%04x][%04x]",
  90. PciData->Hdr.VendorId,
  91. PciData->Hdr.DeviceId
  92. ));
  93. DEBUG ((DEBUG_INFO, " [%02x|%02x|%02x]",
  94. PciData->Hdr.ClassCode[2],
  95. PciData->Hdr.ClassCode[1],
  96. PciData->Hdr.ClassCode[0]
  97. ));
  98. DEBUG ((DEBUG_INFO, " %08x %08x",
  99. PciData->Bridge.Bar[0],
  100. PciData->Bridge.Bar[1]
  101. ));
  102. DEBUG ((DEBUG_INFO, " [%02x|%02x|%02x]",
  103. PciData->Bridge.PrimaryBus,
  104. PciData->Bridge.SecondaryBus,
  105. PciData->Bridge.SubordinateBus
  106. ));
  107. DEBUG ((DEBUG_INFO, " [00:00] [0000:0000] [0000:0000]",
  108. PciData->Bridge.IoBase,
  109. PciData->Bridge.IoLimit,
  110. PciData->Bridge.MemoryBase,
  111. PciData->Bridge.MemoryLimit,
  112. PciData->Bridge.PrefetchableMemoryBase,
  113. PciData->Bridge.PrefetchableMemoryLimit
  114. ));
  115. DEBUG ((DEBUG_INFO, " [00000000:00000000] [0000:0000]",
  116. PciData->Bridge.PrefetchableBaseUpper32,
  117. PciData->Bridge.PrefetchableLimitUpper32,
  118. PciData->Bridge.IoBaseUpper16,
  119. PciData->Bridge.IoLimitUpper16
  120. ));
  121. DEBUG ((DEBUG_INFO, " %04x ",
  122. PciData->Bridge.BridgeControl
  123. ));
  124. DEBUG ((DEBUG_INFO, " %04x\n",
  125. PciData->Hdr.Command
  126. ));
  127. }
  128. /**
  129. This function gets the protocol interface from the given handle, and
  130. obtains its address space descriptors.
  131. @param[in] Handle The PCI_ROOT_BRIDIGE_IO_PROTOCOL handle.
  132. @param[out] IoDev Handle used to access configuration space of PCI device.
  133. @param[out] Descriptors Points to the address space descriptors.
  134. @retval EFI_SUCCESS The command completed successfully
  135. **/
  136. EFI_STATUS
  137. PciGetProtocolAndResource (
  138. IN EFI_HANDLE Handle,
  139. OUT EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL **IoDev,
  140. OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors
  141. )
  142. {
  143. EFI_STATUS Status;
  144. //
  145. // Get inferface from protocol
  146. //
  147. Status = gBS->HandleProtocol (
  148. Handle,
  149. &gEfiPciRootBridgeIoProtocolGuid,
  150. (VOID**)IoDev
  151. );
  152. if (EFI_ERROR (Status)) {
  153. return Status;
  154. }
  155. //
  156. // Call Configuration() to get address space descriptors
  157. //
  158. Status = (*IoDev)->Configuration (*IoDev, (VOID**)Descriptors);
  159. if (Status == EFI_UNSUPPORTED) {
  160. *Descriptors = NULL;
  161. return EFI_SUCCESS;
  162. } else {
  163. return Status;
  164. }
  165. }
  166. /**
  167. This function get the next bus range of given address space descriptors.
  168. It also moves the pointer backward a node, to get prepared to be called
  169. again.
  170. @param[in, out] Descriptors Points to current position of a serial of address space
  171. descriptors.
  172. @param[out] MinBus The lower range of bus number.
  173. @param[out] MaxBus The upper range of bus number.
  174. @param[out] IsEnd Meet end of the serial of descriptors.
  175. @retval EFI_SUCCESS The command completed successfully.
  176. **/
  177. EFI_STATUS
  178. PciGetNextBusRange (
  179. IN OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,
  180. OUT UINT16 *MinBus,
  181. OUT UINT16 *MaxBus,
  182. OUT BOOLEAN *IsEnd
  183. )
  184. {
  185. *IsEnd = FALSE;
  186. //
  187. // When *Descriptors is NULL, Configuration() is not implemented, so assume
  188. // range is 0~PCI_MAX_BUS
  189. //
  190. if ((*Descriptors) == NULL) {
  191. *MinBus = 0;
  192. *MaxBus = PCI_MAX_BUS;
  193. return EFI_SUCCESS;
  194. }
  195. //
  196. // *Descriptors points to one or more address space descriptors, which
  197. // ends with a end tagged descriptor. Examine each of the descriptors,
  198. // if a bus typed one is found and its bus range covers bus, this handle
  199. // is the handle we are looking for.
  200. //
  201. while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {
  202. if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
  203. *MinBus = (UINT16) (*Descriptors)->AddrRangeMin;
  204. *MaxBus = (UINT16) (*Descriptors)->AddrRangeMax;
  205. (*Descriptors)++;
  206. return (EFI_SUCCESS);
  207. }
  208. (*Descriptors)++;
  209. }
  210. if ((*Descriptors)->Desc == ACPI_END_TAG_DESCRIPTOR) {
  211. *IsEnd = TRUE;
  212. }
  213. return EFI_SUCCESS;
  214. }
  215. EFI_STATUS
  216. TestPointCheckPciResource (
  217. VOID
  218. )
  219. {
  220. UINT16 Bus;
  221. UINT16 Device;
  222. UINT16 Func;
  223. UINT64 Address;
  224. EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev;
  225. EFI_STATUS Status;
  226. PCI_TYPE00 PciData;
  227. UINTN Index;
  228. EFI_HANDLE *HandleBuf;
  229. UINTN HandleCount;
  230. EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
  231. UINT16 MinBus;
  232. UINT16 MaxBus;
  233. BOOLEAN IsEnd;
  234. DEBUG ((DEBUG_INFO, "==== TestPointCheckPciResource - Enter\n"));
  235. HandleBuf = NULL;
  236. Status = gBS->LocateHandleBuffer (
  237. ByProtocol,
  238. &gEfiPciRootBridgeIoProtocolGuid,
  239. NULL,
  240. &HandleCount,
  241. &HandleBuf
  242. );
  243. if (EFI_ERROR (Status)) {
  244. goto Done ;
  245. }
  246. DEBUG ((DEBUG_INFO, " B D F* VID DID Class[CSP] Bar0 Bar1 Bus[PSS] Io[BL] Memory[BL]"));
  247. DEBUG ((DEBUG_INFO, " PMemory[BL] PMemoryU[BL] IoU[BL] BriCtl Command\n"));
  248. DEBUG ((DEBUG_INFO, " B D F VID DID Class[CSP] Bar0 Bar1 Bar2 Bar3 Bar4 Bar5 Command\n"));
  249. for (Index = 0; Index < HandleCount; Index++) {
  250. Status = PciGetProtocolAndResource (
  251. HandleBuf[Index],
  252. &IoDev,
  253. &Descriptors
  254. );
  255. while (TRUE) {
  256. Status = PciGetNextBusRange (&Descriptors, &MinBus, &MaxBus, &IsEnd);
  257. if (EFI_ERROR (Status)) {
  258. goto Done;
  259. }
  260. if (IsEnd) {
  261. break;
  262. }
  263. for (Bus = MinBus; Bus <= MaxBus; Bus++) {
  264. //
  265. // For each devices, enumerate all functions it contains
  266. //
  267. for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
  268. //
  269. // For each function, read its configuration space and print summary
  270. //
  271. for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
  272. Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
  273. IoDev->Pci.Read (
  274. IoDev,
  275. EfiPciWidthUint16,
  276. Address,
  277. 1,
  278. &PciData.Hdr.VendorId
  279. );
  280. //
  281. // If VendorId = 0xffff, there does not exist a device at this
  282. // location. For each device, if there is any function on it,
  283. // there must be 1 function at Function 0. So if Func = 0, there
  284. // will be no more functions in the same device, so we can break
  285. // loop to deal with the next device.
  286. //
  287. if (PciData.Hdr.VendorId == 0xffff && Func == 0) {
  288. break;
  289. }
  290. if (PciData.Hdr.VendorId != 0xffff) {
  291. IoDev->Pci.Read (
  292. IoDev,
  293. EfiPciWidthUint32,
  294. Address,
  295. sizeof (PciData) / sizeof (UINT32),
  296. &PciData
  297. );
  298. if (IS_PCI_BRIDGE(&PciData)) {
  299. // Bridge
  300. DumpPciBridge ((UINT8)Bus, (UINT8)Device, (UINT8)Func, (PCI_TYPE01 *)&PciData);
  301. } else if (IS_CARDBUS_BRIDGE(&PciData)) {
  302. // CardBus Bridge
  303. } else {
  304. // Device
  305. DumpPciDevice ((UINT8)Bus, (UINT8)Device, (UINT8)Func, &PciData);
  306. }
  307. //
  308. // If this is not a multi-function device, we can leave the loop
  309. // to deal with the next device.
  310. //
  311. if (Func == 0 && ((PciData.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x00)) {
  312. break;
  313. }
  314. }
  315. }
  316. }
  317. }
  318. //
  319. // If Descriptor is NULL, Configuration() returns EFI_UNSUPPRORED,
  320. // we assume the bus range is 0~PCI_MAX_BUS. After enumerated all
  321. // devices on all bus, we can leave loop.
  322. //
  323. if (Descriptors == NULL) {
  324. break;
  325. }
  326. }
  327. }
  328. Done:
  329. if (HandleBuf != NULL) {
  330. FreePool (HandleBuf);
  331. }
  332. DEBUG ((DEBUG_INFO, "==== TestPointCheckPciResource - Exit\n"));
  333. if (EFI_ERROR(Status)) {
  334. TestPointLibAppendErrorString (
  335. PLATFORM_TEST_POINT_ROLE_PLATFORM_IBV,
  336. NULL,
  337. TEST_POINT_BYTE3_PCI_ENUMERATION_DONE_RESOURCE_ALLOCATED_ERROR_CODE \
  338. TEST_POINT_PCI_ENUMERATION_DONE \
  339. TEST_POINT_BYTE3_PCI_ENUMERATION_DONE_RESOURCE_ALLOCATED_ERROR_STRING
  340. );
  341. }
  342. return Status;
  343. }
  344. EFI_STATUS
  345. TestPointCheckPciBusMaster (
  346. VOID
  347. )
  348. {
  349. UINTN Segment;
  350. UINTN SegmentCount;
  351. UINTN Bus;
  352. UINTN Device;
  353. UINTN Function;
  354. UINT16 VendorId;
  355. UINT16 Command;
  356. UINT8 HeaderType;
  357. EFI_STATUS Status;
  358. PCI_SEGMENT_INFO *PciSegmentInfo;
  359. PciSegmentInfo = GetPciSegmentInfo (&SegmentCount);
  360. if (PciSegmentInfo == NULL) {
  361. return EFI_OUT_OF_RESOURCES;
  362. }
  363. Status = EFI_SUCCESS;
  364. for (Segment = 0; Segment < SegmentCount; Segment++) {
  365. for (Bus = PciSegmentInfo[Segment].StartBusNumber; Bus <= PciSegmentInfo[Segment].EndBusNumber; Bus++) {
  366. for (Device = 0; Device <= 0x1F; Device++) {
  367. for (Function = 0; Function <= 0x7; Function++) {
  368. VendorId = PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS(PciSegmentInfo[Segment].SegmentNumber, Bus, Device, Function, PCI_VENDOR_ID_OFFSET));
  369. //
  370. // If VendorId = 0xffff, there does not exist a device at this
  371. // location. For each device, if there is any function on it,
  372. // there must be 1 function at Function 0. So if Func = 0, there
  373. // will be no more functions in the same device, so we can break
  374. // loop to deal with the next device.
  375. //
  376. if (VendorId == 0xffff && Function == 0) {
  377. break;
  378. }
  379. if (VendorId != 0xffff) {
  380. Command = PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus, Device, Function, PCI_COMMAND_OFFSET));
  381. if ((Command & EFI_PCI_COMMAND_BUS_MASTER) != 0) {
  382. DEBUG ((DEBUG_INFO, "PCI BME enabled (S%04x.B%02x.D%02x.F%x - %04x)\n", Segment, Bus, Device, Function, Command));
  383. TestPointLibAppendErrorString (
  384. PLATFORM_TEST_POINT_ROLE_PLATFORM_IBV,
  385. NULL,
  386. TEST_POINT_BYTE3_PCI_ENUMERATION_DONE_BUS_MASTER_DISABLED_ERROR_CODE \
  387. TEST_POINT_PCI_ENUMERATION_DONE \
  388. TEST_POINT_BYTE3_PCI_ENUMERATION_DONE_BUS_MASTER_DISABLED_ERROR_STRING
  389. );
  390. Status = EFI_INVALID_PARAMETER;
  391. }
  392. //
  393. // If this is not a multi-function device, we can leave the loop
  394. // to deal with the next device.
  395. //
  396. HeaderType = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus, Device, Function, PCI_HEADER_TYPE_OFFSET));
  397. if (Function == 0 && ((HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x00)) {
  398. break;
  399. }
  400. }
  401. }
  402. }
  403. }
  404. }
  405. return Status;
  406. }