PciPlatform.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. /** @file
  2. @copyright
  3. Copyright 2004 - 2021 Intel Corporation. <BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <PiDxe.h>
  7. #include "PciPlatform.h"
  8. #include <Library/PcdLib.h>
  9. #include <Library/PlatformOpromPolicyLib.h>
  10. #include <Protocol/DynamicSiLibraryProtocol.h>
  11. #include <Protocol/UbaCfgDb.h>
  12. #ifdef EFI_PCI_IOV_SUPPORT
  13. #include "PciIovPlatformPolicy.h"
  14. #endif
  15. #include <Library/UbaPlatLib.h>
  16. PCI_PLATFORM_PRIVATE_DATA mPciPrivateData;
  17. BOOLEAN FirstCall = TRUE;
  18. UINT8 sSataRaidLoadEfiDriverOption;
  19. UINT8 SataRaidLoadEfiDriverOption[PCH_MAX_SATA_CONTROLLERS];
  20. UINT8 BootNetworkOption;
  21. STATIC
  22. BOOLEAN
  23. InternalPlatformCheckPcieRootPort (
  24. IN UINTN Bus,
  25. IN UINT32 PcieSlotOpromBitMap
  26. )
  27. {
  28. EFI_STATUS Status;
  29. UBA_CONFIG_DATABASE_PROTOCOL *UbaConfigProtocol = NULL;
  30. UINTN DataLength = 0;
  31. PLATFORM_OPTION_ROM_UPDATE_DATA OptionRomUpdateTable;
  32. Status = gBS->LocateProtocol (
  33. &gUbaConfigDatabaseProtocolGuid,
  34. NULL,
  35. &UbaConfigProtocol
  36. );
  37. if (EFI_ERROR(Status)) {
  38. DEBUG ((DEBUG_INFO," InternalPlatformCheckPcieRootPort fail!\n"));
  39. return TRUE;
  40. }
  41. DataLength = sizeof (OptionRomUpdateTable);
  42. Status = UbaConfigProtocol->GetData (
  43. UbaConfigProtocol,
  44. &gPlatformOptionRomUpdateConfigDataGuid,
  45. &OptionRomUpdateTable,
  46. &DataLength
  47. );
  48. if (EFI_ERROR(Status)) {
  49. DEBUG ((DEBUG_INFO,"InternalPlatformCheckPcieRootPort fail!\n"));
  50. return TRUE;
  51. }
  52. ASSERT (OptionRomUpdateTable.Signature == PLATFORM_OPTION_ROM_UPDATE_SIGNATURE);
  53. ASSERT (OptionRomUpdateTable.Version == PLATFORM_OPTION_ROM_UPDATE_VERSION);
  54. return OptionRomUpdateTable.CallCheckRootPort (Bus, PcieSlotOpromBitMap);
  55. }
  56. STATIC
  57. EFI_STATUS
  58. InternalGetSystemBoardInfo (
  59. IN OUT DXE_SYSTEM_BOARD_INFO **SystemboardInfoTableBuffer
  60. )
  61. {
  62. EFI_STATUS Status;
  63. UBA_CONFIG_DATABASE_PROTOCOL *UbaConfigProtocol = NULL;
  64. UINTN DataLength = 0;
  65. SYSTEM_BOARD_INFO_DATA SystemBoardInfoData;
  66. Status = gBS->LocateProtocol (
  67. &gUbaConfigDatabaseProtocolGuid,
  68. NULL,
  69. &UbaConfigProtocol
  70. );
  71. if (EFI_ERROR(Status)) {
  72. DEBUG ((EFI_D_ERROR," [GetSystemBoardInfo] Locate UbaConfigProtocol fail!\n"));
  73. return Status;
  74. }
  75. DataLength = sizeof(SystemBoardInfoData);
  76. Status = UbaConfigProtocol->GetData (
  77. UbaConfigProtocol,
  78. &gSystemBoardInfoConfigDataGuid,
  79. &SystemBoardInfoData,
  80. &DataLength
  81. );
  82. if (EFI_ERROR(Status)) {
  83. DEBUG ((EFI_D_ERROR," [GetSystemBoardInfo] Get Data fail!\n"));
  84. return Status;
  85. }
  86. ASSERT (SystemBoardInfoData.Signature == SYSTEM_SYSTEM_BOARD_INFO_SIGNATURE);
  87. ASSERT (SystemBoardInfoData.Version == SYSTEM_SYSTEM_BOARD_INFO_VERSION);
  88. *SystemboardInfoTableBuffer = SystemBoardInfoData.CallUpdate ();
  89. return Status;
  90. }
  91. /**
  92. Set the PciPolicy as EFI_RESERVE_ISA_IO_NO_ALIAS | EFI_RESERVE_VGA_IO_NO_ALIAS.
  93. @param This - The pointer to the Protocol itself.
  94. PciPolicy - the returned Policy.
  95. @retval EFI_UNSUPPORTED - Function not supported.
  96. @retval EFI_INVALID_PARAMETER - Invalid PciPolicy value.
  97. **/
  98. EFI_STATUS
  99. EFIAPI
  100. GetPlatformPolicy (
  101. IN CONST EFI_PCI_PLATFORM_PROTOCOL *This,
  102. OUT EFI_PCI_PLATFORM_POLICY *PciPolicy
  103. )
  104. {
  105. if (PciPolicy == NULL) {
  106. return EFI_INVALID_PARAMETER;
  107. }
  108. return EFI_UNSUPPORTED;
  109. }
  110. /**
  111. Get an indicated image in raw sections.
  112. @param NameGuid - NameGuid of the image to get.
  113. @param Buffer - Buffer to store the image get.
  114. @param Size - size of the image get.
  115. @retval EFI_NOT_FOUND - Could not find the image.
  116. @retval EFI_LOAD_ERROR - Error occurred during image loading.
  117. @retval EFI_SUCCESS - Image has been successfully loaded.
  118. **/
  119. EFI_STATUS
  120. GetRawImage(
  121. IN EFI_GUID *NameGuid,
  122. IN OUT VOID **Buffer,
  123. IN OUT UINTN *Size
  124. ) {
  125. EFI_STATUS Status;
  126. EFI_HANDLE *HandleBuffer;
  127. UINTN HandleCount;
  128. UINTN Index;
  129. EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
  130. UINT32 AuthenticationStatus;
  131. Status = gBS->LocateHandleBuffer(
  132. ByProtocol,
  133. &gEfiFirmwareVolume2ProtocolGuid,
  134. NULL,
  135. &HandleCount,
  136. &HandleBuffer
  137. );
  138. if (EFI_ERROR(Status) || HandleCount == 0) {
  139. return EFI_NOT_FOUND;
  140. }
  141. //
  142. // Find desired image in all Fvs
  143. //
  144. for (Index = 0; Index < HandleCount; Index++) {
  145. Status = gBS->HandleProtocol(
  146. HandleBuffer[Index],
  147. &gEfiFirmwareVolume2ProtocolGuid,
  148. &Fv
  149. );
  150. if (EFI_ERROR(Status)) {
  151. return EFI_LOAD_ERROR;
  152. }
  153. //
  154. // Try a raw file
  155. //
  156. *Buffer = NULL;
  157. *Size = 0;
  158. Status = Fv->ReadSection(
  159. Fv,
  160. NameGuid,
  161. EFI_SECTION_RAW,
  162. 0,
  163. Buffer,
  164. Size,
  165. &AuthenticationStatus
  166. );
  167. if (!EFI_ERROR(Status)) {
  168. DEBUG((EFI_D_INFO, "Read the OROM successfully!\n"));
  169. break;
  170. }
  171. }
  172. if (Index >= HandleCount) {
  173. return EFI_NOT_FOUND;
  174. }
  175. return EFI_SUCCESS;
  176. }
  177. /**
  178. Return a PCI ROM image for the onboard device represented by PciHandle.
  179. @param This - Protocol instance pointer.
  180. PciHandle - PCI device to return the ROM image for.
  181. RomImage - PCI Rom Image for onboard device.
  182. RomSize - Size of RomImage in bytes.
  183. @retval EFI_SUCCESS - RomImage is valid.
  184. @retval EFI_NOT_FOUND - No RomImage.
  185. **/
  186. EFI_STATUS
  187. EFIAPI
  188. GetPciRom (
  189. IN CONST EFI_PCI_PLATFORM_PROTOCOL *This,
  190. IN EFI_HANDLE PciHandle,
  191. OUT VOID **RomImage,
  192. OUT UINTN *RomSize
  193. )
  194. {
  195. EFI_STATUS Status;
  196. EFI_PCI_IO_PROTOCOL *PciIo;
  197. UINTN Segment;
  198. UINTN Bus;
  199. UINTN Device;
  200. UINTN Function;
  201. UINT16 VendorId;
  202. UINT16 DeviceId;
  203. UINT16 DeviceClass;
  204. UINTN TableIndex;
  205. UINTN RomImageNumber;
  206. VOID *OpRomBase;
  207. UINTN OpRomSize;
  208. EFI_PCI_ROM_HEADER RomHeader;
  209. PCI_DATA_STRUCTURE *Pcir;
  210. OPROM_LOAD_POLICY OpromPolicy;
  211. BOOLEAN SlotOptionRomDisabled;
  212. DXE_SYSTEM_BOARD_INFO *SystemBoardInfo = NULL;
  213. UINT32 Index;
  214. DYNAMIC_SI_LIBARY_PROTOCOL *DynamicSiLibraryProtocol = NULL;
  215. OpRomBase = NULL;
  216. OpRomSize = 0;
  217. Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocolGuid, NULL, &DynamicSiLibraryProtocol);
  218. if (EFI_ERROR (Status)) {
  219. ASSERT_EFI_ERROR (Status);
  220. return Status;
  221. }
  222. //
  223. // Get System Board Info
  224. //
  225. Status = InternalGetSystemBoardInfo (&SystemBoardInfo);
  226. ASSERT_EFI_ERROR (Status);
  227. if (EFI_ERROR (Status)) {
  228. DEBUG ((EFI_D_ERROR, "[GetPciRom] Get system board info fail!\n"));
  229. return Status;
  230. }
  231. Status = gBS->HandleProtocol (
  232. PciHandle,
  233. &gEfiPciIoProtocolGuid,
  234. (VOID **) &PciIo
  235. );
  236. if (EFI_ERROR (Status)) {
  237. return EFI_NOT_FOUND;
  238. }
  239. if (FirstCall == TRUE) {
  240. Status = GetOptionData (&gEfiSetupVariableGuid, OFFSET_OF(SYSTEM_CONFIGURATION, BootNetwork), &BootNetworkOption, sizeof(BootNetworkOption));
  241. if (EFI_ERROR (Status)) {
  242. BootNetworkOption = 0;
  243. }
  244. Status = GetOptionData (&gPchSetupVariableGuid,
  245. OFFSET_OF(PCH_SETUP, SataRaidLoadEfiDriver),
  246. &SataRaidLoadEfiDriverOption,
  247. sizeof(SataRaidLoadEfiDriverOption) * PCH_MAX_SATA_CONTROLLERS);
  248. if (EFI_ERROR (Status)) {
  249. for (Index = 0; Index < DynamicSiLibraryProtocol->MaxSataControllerNum(); Index++) {
  250. SataRaidLoadEfiDriverOption[Index] = 0;
  251. }
  252. }
  253. FirstCall = FALSE;
  254. }
  255. PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
  256. PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, PCI_CLASSCODE_OFFSET + 1, 1, &DeviceClass);
  257. //
  258. // Run PXE ROM only if Boot network is enabled
  259. //
  260. if ((BootNetworkOption == 0) &&
  261. (DeviceClass == ((PCI_CLASS_NETWORK << 8) | PCI_CLASS_NETWORK_ETHERNET))
  262. ) {
  263. return EFI_NOT_FOUND;
  264. }
  265. //
  266. // Run each PCI-E slot ROM only if PCI-E Slot Oprom is enabled.
  267. //
  268. if ( Bus != 0 ) {
  269. SlotOptionRomDisabled = InternalPlatformCheckPcieRootPort (Bus, PcdGet32(PcdOemSkuPcieSlotOpromBitMap));
  270. if (SlotOptionRomDisabled) {
  271. return EFI_NOT_FOUND;
  272. }
  273. }
  274. PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, PCI_VENDOR_ID_OFFSET, 1, &VendorId);
  275. PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, PCI_DEVICE_ID_OFFSET, 1, &DeviceId);
  276. //DEBUG ((EFI_D_INFO, "GetPciRom - VenID:DevID: %04x:%04x\n", (UINTN)VendorId, (UINTN)DeviceId));
  277. //
  278. // Fix MS-HD5770 video adapter can not work:
  279. // This device is not a OPROM 3.0 and does not have device id list as well.
  280. // It only have 1 device id in OPROM.
  281. // Device Id in OpROM is not same with the value in PCI configuration space
  282. // it will cause VBIOS fails to start
  283. //
  284. if ((VendorId == 0x1002) && (DeviceId == 0x68BE)) {
  285. DEBUG ((DEBUG_INFO, "MS-HD5770 video adapter\n"));
  286. RomHeader.Raw = PciIo->RomImage;
  287. if (RomHeader.Raw != NULL) {
  288. Pcir = (PCI_DATA_STRUCTURE *)(RomHeader.Raw + RomHeader.Generic->PcirOffset);
  289. if ((Pcir->VendorId == 0x1002) && (Pcir->DeviceId == 0x68B8)) {
  290. //
  291. // Assign same device id in PCI configuration space
  292. //
  293. Pcir->DeviceId = DeviceId;
  294. }
  295. } else {
  296. DEBUG ((EFI_D_ERROR, "MS-HD5770 video adapter detected but PciIo->RomImage == NULL!\n"));
  297. }
  298. }
  299. //Check if user disables the option rom loading for this device.
  300. if (!PlatformOpromLoadDevicePolicy(PciIo)) {
  301. return EFI_NOT_FOUND;
  302. }
  303. // If setup value requested EFI, we don't load the RAID OROM.
  304. if (VendorId == V_SATA_CFG_VENDOR_ID) {
  305. for (Index = 0; Index < DynamicSiLibraryProtocol->MaxSataControllerNum(); Index++) {
  306. if (Bus == DEFAULT_PCI_BUS_NUMBER_PCH &&
  307. Device == DynamicSiLibraryProtocol->SataDevNumber (Index) &&
  308. Function == DynamicSiLibraryProtocol->SataFuncNumber (Index) &&
  309. SataRaidLoadEfiDriverOption[Index] == 1) {
  310. return EFI_NOT_FOUND;
  311. }
  312. }
  313. }
  314. //
  315. // Loop through table of video option rom descriptions
  316. //
  317. RomImageNumber = 0;
  318. for (TableIndex = 0; SystemBoardInfo->PciOptionRomTable[TableIndex].VendorId != 0xffff; TableIndex++) {
  319. //
  320. // See if the PCI device specified by PciHandle matches at device in mPciOptionRomTable
  321. //
  322. if (VendorId != SystemBoardInfo->PciOptionRomTable[TableIndex].VendorId ||
  323. DeviceId != SystemBoardInfo->PciOptionRomTable[TableIndex].DeviceId ||
  324. Device != SystemBoardInfo->PciOptionRomTable[TableIndex].Device ||
  325. Function != SystemBoardInfo->PciOptionRomTable[TableIndex].Function
  326. ) {
  327. continue;
  328. }
  329. //Check if user wants to exclusively run this option rom for the device.
  330. OpromPolicy = PlatformOpromLoadTypePolicy(PciHandle, TableIndex);
  331. if(OpromPolicy == DONT_LOAD) {
  332. continue;
  333. }
  334. Status = GetRawImage (
  335. &SystemBoardInfo->PciOptionRomTable[TableIndex].FileName,
  336. &OpRomBase,
  337. &OpRomSize
  338. );
  339. if (EFI_ERROR (Status)) {
  340. continue;
  341. } else {
  342. RomImageNumber++;
  343. if (RomImageNumber == PcdGet8(PcdMaxOptionRomNumber) || OpromPolicy == EXCLUSIVE_LOAD) {
  344. break;
  345. }
  346. }
  347. }
  348. if (RomImageNumber == 0) {
  349. return EFI_NOT_FOUND;
  350. } else {
  351. *RomImage = OpRomBase;
  352. *RomSize = OpRomSize;
  353. return EFI_SUCCESS;
  354. }
  355. }
  356. /**
  357. GC_TODO: Add function description
  358. @param This - GC_TODO: add argument description
  359. @param Function - GC_TODO: add argument description
  360. @param Phase - GC_TODO: add argument description
  361. @retval EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
  362. @retval EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
  363. @retval EFI_UNSUPPORTED - GC_TODO: Add description for return value
  364. @retval EFI_SUCCESS - GC_TODO: Add description for return value
  365. **/
  366. EFI_STATUS
  367. EFIAPI
  368. RegisterPciCallback (
  369. IN EFI_PCI_CALLBACK_PROTOCOL *This,
  370. IN EFI_PCI_CALLBACK_FUNC Function,
  371. IN EFI_PCI_ENUMERATION_PHASE Phase
  372. )
  373. {
  374. LIST_ENTRY *NodeEntry;
  375. PCI_CALLBACK_DATA *PciCallbackData;
  376. if (Function == NULL) {
  377. return EFI_INVALID_PARAMETER;
  378. }
  379. if ( (Phase & (EfiPciEnumerationDeviceScanning | EfiPciEnumerationBusNumberAssigned \
  380. | EfiPciEnumerationResourceAssigned)) == 0) {
  381. return EFI_INVALID_PARAMETER;
  382. }
  383. //
  384. // Check if the node has been added
  385. //
  386. NodeEntry = GetFirstNode (&mPciPrivateData.PciCallbackList);
  387. while (!IsNull (&mPciPrivateData.PciCallbackList, NodeEntry)) {
  388. PciCallbackData = PCI_CALLBACK_DATA_FROM_LINK (NodeEntry);
  389. if (PciCallbackData->Function == Function) {
  390. return EFI_UNSUPPORTED;
  391. }
  392. NodeEntry = GetNextNode (&mPciPrivateData.PciCallbackList, NodeEntry);
  393. }
  394. PciCallbackData = NULL;
  395. PciCallbackData = AllocateZeroPool (sizeof (PCI_CALLBACK_DATA));
  396. ASSERT (PciCallbackData != NULL);
  397. if(PciCallbackData != NULL){
  398. PciCallbackData->Signature = PCI_CALLBACK_DATA_SIGNATURE;
  399. PciCallbackData->Function = Function;
  400. PciCallbackData->Phase = Phase;
  401. InsertTailList (&mPciPrivateData.PciCallbackList, &PciCallbackData->Link);
  402. return EFI_SUCCESS;
  403. } else {
  404. return EFI_UNSUPPORTED;
  405. }
  406. }
  407. /**
  408. Main Entry point of the Pci Platform Driver.
  409. @param ImageHandle - Handle to the image.
  410. @param SystemTable - Handle to System Table.
  411. @retval EFI_STATUS - Status of the function calling.
  412. **/
  413. EFI_STATUS
  414. EFIAPI
  415. PciPlatformDriverEntry (
  416. IN EFI_HANDLE ImageHandle,
  417. IN EFI_SYSTEM_TABLE *SystemTable
  418. )
  419. {
  420. EFI_STATUS Status;
  421. EFI_HOB_GUID_TYPE *GuidHob;
  422. GuidHob = GetFirstGuidHob (&gEfiPlatformInfoGuid);
  423. ASSERT (GuidHob != NULL);
  424. if (GuidHob == NULL) {
  425. return EFI_NOT_FOUND;
  426. }
  427. mPciPrivateData.PlatformInfo = GET_GUID_HOB_DATA(GuidHob);
  428. //EDK2_TODO Check if clearing mPciPrivateData.PlatformInfo (got above) is intended.
  429. ZeroMem (&mPciPrivateData, sizeof (mPciPrivateData));
  430. InitializeListHead (&mPciPrivateData.PciCallbackList);
  431. mPciPrivateData.PciPlatform.PlatformNotify = PhaseNotify;
  432. mPciPrivateData.PciPlatform.PlatformPrepController = PlatformPrepController;
  433. mPciPrivateData.PciPlatform.GetPlatformPolicy = GetPlatformPolicy;
  434. mPciPrivateData.PciPlatform.GetPciRom = GetPciRom;
  435. mPciPrivateData.PciCallback.RegisterPciCallback = RegisterPciCallback;
  436. #ifdef EFI_PCI_IOV_SUPPORT
  437. mPciPrivateData.PciIovPlatform.GetSystemLowestPageSize = GetSystemLowestPageSize;
  438. mPciPrivateData.PciIovPlatform.GetPlatformPolicy = GetIovPlatformPolicy;
  439. #endif
  440. //
  441. // Install on a new handle
  442. //
  443. Status = gBS->InstallMultipleProtocolInterfaces (
  444. &mPciPrivateData.PciPlatformHandle,
  445. &gEfiPciPlatformProtocolGuid,
  446. &mPciPrivateData.PciPlatform,
  447. &gEfiPciCallbackProtocolGuid,
  448. &mPciPrivateData.PciCallback,
  449. #ifdef EFI_PCI_IOV_SUPPORT
  450. &gEfiPciIovPlatformProtocolGuid,
  451. &mPciPrivateData.PciIovPlatform,
  452. #endif
  453. NULL
  454. );
  455. return Status;
  456. }