PciEnumeratorSupport.c 83 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892
  1. /** @file
  2. PCI emumeration support functions implementation for PCI Bus module.
  3. Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
  4. (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
  5. Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
  6. SPDX-License-Identifier: BSD-2-Clause-Patent
  7. **/
  8. #include "PciBus.h"
  9. extern CHAR16 *mBarTypeStr[];
  10. extern EDKII_DEVICE_SECURITY_PROTOCOL *mDeviceSecurityProtocol;
  11. #define OLD_ALIGN 0xFFFFFFFFFFFFFFFFULL
  12. #define EVEN_ALIGN 0xFFFFFFFFFFFFFFFEULL
  13. #define SQUAD_ALIGN 0xFFFFFFFFFFFFFFFDULL
  14. #define DQUAD_ALIGN 0xFFFFFFFFFFFFFFFCULL
  15. /**
  16. This routine is used to check whether the pci device is present.
  17. @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
  18. @param Pci Output buffer for PCI device configuration space.
  19. @param Bus PCI bus NO.
  20. @param Device PCI device NO.
  21. @param Func PCI Func NO.
  22. @retval EFI_NOT_FOUND PCI device not present.
  23. @retval EFI_SUCCESS PCI device is found.
  24. **/
  25. EFI_STATUS
  26. PciDevicePresent (
  27. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
  28. OUT PCI_TYPE00 *Pci,
  29. IN UINT8 Bus,
  30. IN UINT8 Device,
  31. IN UINT8 Func
  32. )
  33. {
  34. UINT64 Address;
  35. EFI_STATUS Status;
  36. //
  37. // Create PCI address map in terms of Bus, Device and Func
  38. //
  39. Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
  40. //
  41. // Read the Vendor ID register
  42. //
  43. Status = PciRootBridgeIo->Pci.Read (
  44. PciRootBridgeIo,
  45. EfiPciWidthUint32,
  46. Address,
  47. 1,
  48. Pci
  49. );
  50. if (!EFI_ERROR (Status) && ((Pci->Hdr).VendorId != 0xffff)) {
  51. //
  52. // Read the entire config header for the device
  53. //
  54. Status = PciRootBridgeIo->Pci.Read (
  55. PciRootBridgeIo,
  56. EfiPciWidthUint32,
  57. Address,
  58. sizeof (PCI_TYPE00) / sizeof (UINT32),
  59. Pci
  60. );
  61. return EFI_SUCCESS;
  62. }
  63. return EFI_NOT_FOUND;
  64. }
  65. /**
  66. Collect all the resource information under this root bridge.
  67. A database that records all the information about pci device subject to this
  68. root bridge will then be created.
  69. @param Bridge Parent bridge instance.
  70. @param StartBusNumber Bus number of beginning.
  71. @retval EFI_SUCCESS PCI device is found.
  72. @retval other Some error occurred when reading PCI bridge information.
  73. **/
  74. EFI_STATUS
  75. PciPciDeviceInfoCollector (
  76. IN PCI_IO_DEVICE *Bridge,
  77. IN UINT8 StartBusNumber
  78. )
  79. {
  80. EFI_STATUS Status;
  81. PCI_TYPE00 Pci;
  82. UINT8 Device;
  83. UINT8 Func;
  84. UINT8 SecBus;
  85. PCI_IO_DEVICE *PciIoDevice;
  86. EFI_PCI_IO_PROTOCOL *PciIo;
  87. Status = EFI_SUCCESS;
  88. SecBus = 0;
  89. for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
  90. for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
  91. //
  92. // Check to see whether PCI device is present
  93. //
  94. Status = PciDevicePresent (
  95. Bridge->PciRootBridgeIo,
  96. &Pci,
  97. (UINT8)StartBusNumber,
  98. (UINT8)Device,
  99. (UINT8)Func
  100. );
  101. if (EFI_ERROR (Status) && (Func == 0)) {
  102. //
  103. // go to next device if there is no Function 0
  104. //
  105. break;
  106. }
  107. if (!EFI_ERROR (Status)) {
  108. //
  109. // Call back to host bridge function
  110. //
  111. PreprocessController (Bridge, (UINT8)StartBusNumber, Device, Func, EfiPciBeforeResourceCollection);
  112. //
  113. // Collect all the information about the PCI device discovered
  114. //
  115. Status = PciSearchDevice (
  116. Bridge,
  117. &Pci,
  118. (UINT8)StartBusNumber,
  119. Device,
  120. Func,
  121. &PciIoDevice
  122. );
  123. //
  124. // Recursively scan PCI busses on the other side of PCI-PCI bridges
  125. //
  126. //
  127. if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {
  128. //
  129. // If it is PPB, we need to get the secondary bus to continue the enumeration
  130. //
  131. PciIo = &(PciIoDevice->PciIo);
  132. Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, 1, &SecBus);
  133. if (EFI_ERROR (Status)) {
  134. return Status;
  135. }
  136. //
  137. // Ensure secondary bus number is greater than the primary bus number to avoid
  138. // any potential dead loop when PcdPciDisableBusEnumeration is set to TRUE
  139. //
  140. if (SecBus <= StartBusNumber) {
  141. break;
  142. }
  143. //
  144. // Get resource padding for PPB
  145. //
  146. GetResourcePaddingPpb (PciIoDevice);
  147. //
  148. // Deep enumerate the next level bus
  149. //
  150. Status = PciPciDeviceInfoCollector (
  151. PciIoDevice,
  152. (UINT8)(SecBus)
  153. );
  154. }
  155. if ((Func == 0) && !IS_PCI_MULTI_FUNC (&Pci)) {
  156. //
  157. // Skip sub functions, this is not a multi function device
  158. //
  159. Func = PCI_MAX_FUNC;
  160. }
  161. }
  162. }
  163. }
  164. return EFI_SUCCESS;
  165. }
  166. /**
  167. Search required device and create PCI device instance.
  168. @param Bridge Parent bridge instance.
  169. @param Pci Input PCI device information block.
  170. @param Bus PCI bus NO.
  171. @param Device PCI device NO.
  172. @param Func PCI func NO.
  173. @param PciDevice Output of searched PCI device instance.
  174. @retval EFI_SUCCESS Successfully created PCI device instance.
  175. @retval EFI_OUT_OF_RESOURCES Cannot get PCI device information.
  176. **/
  177. EFI_STATUS
  178. PciSearchDevice (
  179. IN PCI_IO_DEVICE *Bridge,
  180. IN PCI_TYPE00 *Pci,
  181. IN UINT8 Bus,
  182. IN UINT8 Device,
  183. IN UINT8 Func,
  184. OUT PCI_IO_DEVICE **PciDevice
  185. )
  186. {
  187. PCI_IO_DEVICE *PciIoDevice;
  188. BOOLEAN IgnoreOptionRom;
  189. PciIoDevice = NULL;
  190. IgnoreOptionRom = FALSE;
  191. DEBUG ((
  192. DEBUG_INFO,
  193. "PciBus: Discovered %s @ [%02x|%02x|%02x] [VID = 0x%x, DID = 0x%0x]\n",
  194. IS_PCI_BRIDGE (Pci) ? L"PPB" :
  195. IS_CARDBUS_BRIDGE (Pci) ? L"P2C" :
  196. L"PCI",
  197. Bus,
  198. Device,
  199. Func,
  200. Pci->Hdr.VendorId,
  201. Pci->Hdr.DeviceId
  202. ));
  203. if (!IS_PCI_BRIDGE (Pci)) {
  204. if (IS_CARDBUS_BRIDGE (Pci)) {
  205. PciIoDevice = GatherP2CInfo (
  206. Bridge,
  207. Pci,
  208. Bus,
  209. Device,
  210. Func
  211. );
  212. if ((PciIoDevice != NULL) && gFullEnumeration) {
  213. InitializeP2C (PciIoDevice);
  214. }
  215. } else {
  216. //
  217. // Create private data for Pci Device
  218. //
  219. PciIoDevice = GatherDeviceInfo (
  220. Bridge,
  221. Pci,
  222. Bus,
  223. Device,
  224. Func
  225. );
  226. }
  227. } else {
  228. //
  229. // Create private data for PPB
  230. //
  231. PciIoDevice = GatherPpbInfo (
  232. Bridge,
  233. Pci,
  234. Bus,
  235. Device,
  236. Func
  237. );
  238. //
  239. // Special initialization for PPB including making the PPB quiet
  240. //
  241. if ((PciIoDevice != NULL) && gFullEnumeration) {
  242. InitializePpb (PciIoDevice);
  243. }
  244. }
  245. if (PciIoDevice == NULL) {
  246. return EFI_OUT_OF_RESOURCES;
  247. }
  248. //
  249. // Update the bar information for this PCI device so as to support some specific device
  250. //
  251. UpdatePciInfo (PciIoDevice, &IgnoreOptionRom);
  252. if (PciIoDevice->DevicePath == NULL) {
  253. return EFI_OUT_OF_RESOURCES;
  254. }
  255. //
  256. // Detect this function has option rom
  257. //
  258. if (gFullEnumeration) {
  259. if (!IS_CARDBUS_BRIDGE (Pci) && !IgnoreOptionRom) {
  260. GetOpRomInfo (PciIoDevice);
  261. }
  262. ResetPowerManagementFeature (PciIoDevice);
  263. }
  264. //
  265. // Insert it into a global tree for future reference
  266. //
  267. InsertPciDevice (Bridge, PciIoDevice);
  268. //
  269. // Determine PCI device attributes
  270. //
  271. if (PciDevice != NULL) {
  272. *PciDevice = PciIoDevice;
  273. }
  274. return EFI_SUCCESS;
  275. }
  276. /**
  277. Dump the PPB padding resource information.
  278. @param PciIoDevice PCI IO instance.
  279. @param ResourceType The desired resource type to dump.
  280. PciBarTypeUnknown means to dump all types of resources.
  281. **/
  282. VOID
  283. DumpPpbPaddingResource (
  284. IN PCI_IO_DEVICE *PciIoDevice,
  285. IN PCI_BAR_TYPE ResourceType
  286. )
  287. {
  288. EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
  289. PCI_BAR_TYPE Type;
  290. if (PciIoDevice->ResourcePaddingDescriptors == NULL) {
  291. return;
  292. }
  293. if ((ResourceType == PciBarTypeIo16) || (ResourceType == PciBarTypeIo32)) {
  294. ResourceType = PciBarTypeIo;
  295. }
  296. for (Descriptor = PciIoDevice->ResourcePaddingDescriptors; Descriptor->Desc != ACPI_END_TAG_DESCRIPTOR; Descriptor++) {
  297. Type = PciBarTypeUnknown;
  298. if ((Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) && (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_IO)) {
  299. Type = PciBarTypeIo;
  300. } else if ((Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) && (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM)) {
  301. if (Descriptor->AddrSpaceGranularity == 32) {
  302. //
  303. // prefetchable
  304. //
  305. if (Descriptor->SpecificFlag == EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) {
  306. Type = PciBarTypePMem32;
  307. }
  308. //
  309. // Non-prefetchable
  310. //
  311. if (Descriptor->SpecificFlag == 0) {
  312. Type = PciBarTypeMem32;
  313. }
  314. }
  315. if (Descriptor->AddrSpaceGranularity == 64) {
  316. //
  317. // prefetchable
  318. //
  319. if (Descriptor->SpecificFlag == EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) {
  320. Type = PciBarTypePMem64;
  321. }
  322. //
  323. // Non-prefetchable
  324. //
  325. if (Descriptor->SpecificFlag == 0) {
  326. Type = PciBarTypeMem64;
  327. }
  328. }
  329. }
  330. if ((Type != PciBarTypeUnknown) && ((ResourceType == PciBarTypeUnknown) || (ResourceType == Type))) {
  331. DEBUG ((
  332. DEBUG_INFO,
  333. " Padding: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx\n",
  334. mBarTypeStr[Type],
  335. Descriptor->AddrRangeMax,
  336. Descriptor->AddrLen
  337. ));
  338. }
  339. }
  340. }
  341. /**
  342. Dump the PCI BAR information.
  343. @param PciIoDevice PCI IO instance.
  344. **/
  345. VOID
  346. DumpPciBars (
  347. IN PCI_IO_DEVICE *PciIoDevice
  348. )
  349. {
  350. UINTN Index;
  351. for (Index = 0; Index < PCI_MAX_BAR; Index++) {
  352. if (PciIoDevice->PciBar[Index].BarType == PciBarTypeUnknown) {
  353. continue;
  354. }
  355. DEBUG ((
  356. DEBUG_INFO,
  357. " BAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",
  358. Index,
  359. mBarTypeStr[MIN (PciIoDevice->PciBar[Index].BarType, PciBarTypeMaxType)],
  360. PciIoDevice->PciBar[Index].Alignment,
  361. PciIoDevice->PciBar[Index].Length,
  362. PciIoDevice->PciBar[Index].Offset
  363. ));
  364. }
  365. for (Index = 0; Index < PCI_MAX_BAR; Index++) {
  366. if ((PciIoDevice->VfPciBar[Index].BarType == PciBarTypeUnknown) && (PciIoDevice->VfPciBar[Index].Length == 0)) {
  367. continue;
  368. }
  369. DEBUG ((
  370. DEBUG_INFO,
  371. " VFBAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",
  372. Index,
  373. mBarTypeStr[MIN (PciIoDevice->VfPciBar[Index].BarType, PciBarTypeMaxType)],
  374. PciIoDevice->VfPciBar[Index].Alignment,
  375. PciIoDevice->VfPciBar[Index].Length,
  376. PciIoDevice->VfPciBar[Index].Offset
  377. ));
  378. }
  379. DEBUG ((DEBUG_INFO, "\n"));
  380. }
  381. /**
  382. Create PCI device instance for PCI device.
  383. @param Bridge Parent bridge instance.
  384. @param Pci Input PCI device information block.
  385. @param Bus PCI device Bus NO.
  386. @param Device PCI device Device NO.
  387. @param Func PCI device's func NO.
  388. @return Created PCI device instance.
  389. **/
  390. PCI_IO_DEVICE *
  391. GatherDeviceInfo (
  392. IN PCI_IO_DEVICE *Bridge,
  393. IN PCI_TYPE00 *Pci,
  394. IN UINT8 Bus,
  395. IN UINT8 Device,
  396. IN UINT8 Func
  397. )
  398. {
  399. UINTN Offset;
  400. UINTN BarIndex;
  401. PCI_IO_DEVICE *PciIoDevice;
  402. PciIoDevice = CreatePciIoDevice (
  403. Bridge,
  404. Pci,
  405. Bus,
  406. Device,
  407. Func
  408. );
  409. if (PciIoDevice == NULL) {
  410. return NULL;
  411. }
  412. //
  413. // If it is a full enumeration, disconnect the device in advance
  414. //
  415. if (gFullEnumeration) {
  416. PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
  417. }
  418. //
  419. // Start to parse the bars
  420. //
  421. for (Offset = 0x10, BarIndex = 0; Offset <= 0x24 && BarIndex < PCI_MAX_BAR; BarIndex++) {
  422. Offset = PciParseBar (PciIoDevice, Offset, BarIndex);
  423. }
  424. //
  425. // Parse the SR-IOV VF bars
  426. //
  427. if (PcdGetBool (PcdSrIovSupport) && (PciIoDevice->SrIovCapabilityOffset != 0)) {
  428. for (Offset = PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_BAR0, BarIndex = 0;
  429. Offset <= PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_BAR5;
  430. BarIndex++)
  431. {
  432. ASSERT (BarIndex < PCI_MAX_BAR);
  433. Offset = PciIovParseVfBar (PciIoDevice, Offset, BarIndex);
  434. }
  435. }
  436. DEBUG_CODE (
  437. DumpPciBars (PciIoDevice);
  438. );
  439. return PciIoDevice;
  440. }
  441. /**
  442. Create PCI device instance for PCI-PCI bridge.
  443. @param Bridge Parent bridge instance.
  444. @param Pci Input PCI device information block.
  445. @param Bus PCI device Bus NO.
  446. @param Device PCI device Device NO.
  447. @param Func PCI device's func NO.
  448. @return Created PCI device instance.
  449. **/
  450. PCI_IO_DEVICE *
  451. GatherPpbInfo (
  452. IN PCI_IO_DEVICE *Bridge,
  453. IN PCI_TYPE00 *Pci,
  454. IN UINT8 Bus,
  455. IN UINT8 Device,
  456. IN UINT8 Func
  457. )
  458. {
  459. PCI_IO_DEVICE *PciIoDevice;
  460. EFI_STATUS Status;
  461. UINT8 Value;
  462. EFI_PCI_IO_PROTOCOL *PciIo;
  463. UINT8 Temp;
  464. UINT32 PMemBaseLimit;
  465. UINT16 PrefetchableMemoryBase;
  466. UINT16 PrefetchableMemoryLimit;
  467. PciIoDevice = CreatePciIoDevice (
  468. Bridge,
  469. Pci,
  470. Bus,
  471. Device,
  472. Func
  473. );
  474. if (PciIoDevice == NULL) {
  475. return NULL;
  476. }
  477. if (gFullEnumeration) {
  478. PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
  479. //
  480. // Initialize the bridge control register
  481. //
  482. PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED);
  483. }
  484. //
  485. // PPB can have two BARs
  486. //
  487. if (PciParseBar (PciIoDevice, 0x10, PPB_BAR_0) == 0x14) {
  488. //
  489. // Not 64-bit bar
  490. //
  491. PciParseBar (PciIoDevice, 0x14, PPB_BAR_1);
  492. }
  493. PciIo = &PciIoDevice->PciIo;
  494. //
  495. // Test whether it support 32 decode or not
  496. //
  497. PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
  498. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
  499. PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
  500. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
  501. if (Value != 0) {
  502. if ((Value & 0x01) != 0) {
  503. PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED;
  504. } else {
  505. PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
  506. }
  507. }
  508. //
  509. // if PcdPciBridgeIoAlignmentProbe is TRUE, PCI bus driver probes
  510. // PCI bridge supporting non-standard I/O window alignment less than 4K.
  511. //
  512. PciIoDevice->BridgeIoAlignment = 0xFFF;
  513. if (FeaturePcdGet (PcdPciBridgeIoAlignmentProbe)) {
  514. //
  515. // Check any bits of bit 3-1 of I/O Base Register are writable.
  516. // if so, it is assumed non-standard I/O window alignment is supported by this bridge.
  517. // Per spec, bit 3-1 of I/O Base Register are reserved bits, so its content can't be assumed.
  518. //
  519. Value = (UINT8)(Temp ^ (BIT3 | BIT2 | BIT1));
  520. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
  521. PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
  522. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
  523. Value = (UINT8)((Value ^ Temp) & (BIT3 | BIT2 | BIT1));
  524. switch (Value) {
  525. case BIT3:
  526. PciIoDevice->BridgeIoAlignment = 0x7FF;
  527. break;
  528. case BIT3 | BIT2:
  529. PciIoDevice->BridgeIoAlignment = 0x3FF;
  530. break;
  531. case BIT3 | BIT2 | BIT1:
  532. PciIoDevice->BridgeIoAlignment = 0x1FF;
  533. break;
  534. }
  535. }
  536. Status = BarExisted (
  537. PciIoDevice,
  538. 0x24,
  539. NULL,
  540. &PMemBaseLimit
  541. );
  542. //
  543. // Test if it supports 64 memory or not
  544. //
  545. // The bottom 4 bits of both the Prefetchable Memory Base and Prefetchable Memory Limit
  546. // registers:
  547. // 0 - the bridge supports only 32 bit addresses.
  548. // 1 - the bridge supports 64-bit addresses.
  549. //
  550. PrefetchableMemoryBase = (UINT16)(PMemBaseLimit & 0xffff);
  551. PrefetchableMemoryLimit = (UINT16)(PMemBaseLimit >> 16);
  552. if (!EFI_ERROR (Status) &&
  553. ((PrefetchableMemoryBase & 0x000f) == 0x0001) &&
  554. ((PrefetchableMemoryLimit & 0x000f) == 0x0001))
  555. {
  556. Status = BarExisted (
  557. PciIoDevice,
  558. 0x28,
  559. NULL,
  560. NULL
  561. );
  562. if (!EFI_ERROR (Status)) {
  563. PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
  564. PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;
  565. } else {
  566. PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
  567. }
  568. }
  569. //
  570. // Memory 32 code is required for ppb
  571. //
  572. PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
  573. GetResourcePaddingPpb (PciIoDevice);
  574. DEBUG_CODE (
  575. DumpPpbPaddingResource (PciIoDevice, PciBarTypeUnknown);
  576. DumpPciBars (PciIoDevice);
  577. );
  578. return PciIoDevice;
  579. }
  580. /**
  581. Create PCI device instance for PCI Card bridge device.
  582. @param Bridge Parent bridge instance.
  583. @param Pci Input PCI device information block.
  584. @param Bus PCI device Bus NO.
  585. @param Device PCI device Device NO.
  586. @param Func PCI device's func NO.
  587. @return Created PCI device instance.
  588. **/
  589. PCI_IO_DEVICE *
  590. GatherP2CInfo (
  591. IN PCI_IO_DEVICE *Bridge,
  592. IN PCI_TYPE00 *Pci,
  593. IN UINT8 Bus,
  594. IN UINT8 Device,
  595. IN UINT8 Func
  596. )
  597. {
  598. PCI_IO_DEVICE *PciIoDevice;
  599. PciIoDevice = CreatePciIoDevice (
  600. Bridge,
  601. Pci,
  602. Bus,
  603. Device,
  604. Func
  605. );
  606. if (PciIoDevice == NULL) {
  607. return NULL;
  608. }
  609. if (gFullEnumeration) {
  610. PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
  611. //
  612. // Initialize the bridge control register
  613. //
  614. PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED);
  615. }
  616. //
  617. // P2C only has one bar that is in 0x10
  618. //
  619. PciParseBar (PciIoDevice, 0x10, P2C_BAR_0);
  620. //
  621. // Read PciBar information from the bar register
  622. //
  623. GetBackPcCardBar (PciIoDevice);
  624. PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED |
  625. EFI_BRIDGE_PMEM32_DECODE_SUPPORTED |
  626. EFI_BRIDGE_IO32_DECODE_SUPPORTED;
  627. DEBUG_CODE (
  628. DumpPciBars (PciIoDevice);
  629. );
  630. return PciIoDevice;
  631. }
  632. /**
  633. Create device path for pci device.
  634. @param ParentDevicePath Parent bridge's path.
  635. @param PciIoDevice Pci device instance.
  636. @return Device path protocol instance for specific pci device.
  637. **/
  638. EFI_DEVICE_PATH_PROTOCOL *
  639. CreatePciDevicePath (
  640. IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
  641. IN PCI_IO_DEVICE *PciIoDevice
  642. )
  643. {
  644. PCI_DEVICE_PATH PciNode;
  645. //
  646. // Create PCI device path
  647. //
  648. PciNode.Header.Type = HARDWARE_DEVICE_PATH;
  649. PciNode.Header.SubType = HW_PCI_DP;
  650. SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
  651. PciNode.Device = PciIoDevice->DeviceNumber;
  652. PciNode.Function = PciIoDevice->FunctionNumber;
  653. PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header);
  654. return PciIoDevice->DevicePath;
  655. }
  656. /**
  657. Check whether the PCI IOV VF bar is existed or not.
  658. @param PciIoDevice A pointer to the PCI_IO_DEVICE.
  659. @param Offset The offset.
  660. @param BarLengthValue The bar length value returned.
  661. @param OriginalBarValue The original bar value returned.
  662. @retval EFI_NOT_FOUND The bar doesn't exist.
  663. @retval EFI_SUCCESS The bar exist.
  664. **/
  665. EFI_STATUS
  666. VfBarExisted (
  667. IN PCI_IO_DEVICE *PciIoDevice,
  668. IN UINTN Offset,
  669. OUT UINT32 *BarLengthValue,
  670. OUT UINT32 *OriginalBarValue
  671. )
  672. {
  673. EFI_PCI_IO_PROTOCOL *PciIo;
  674. UINT32 OriginalValue;
  675. UINT32 Value;
  676. EFI_TPL OldTpl;
  677. //
  678. // Ensure it is called properly
  679. //
  680. ASSERT (PciIoDevice->SrIovCapabilityOffset != 0);
  681. if (PciIoDevice->SrIovCapabilityOffset == 0) {
  682. return EFI_NOT_FOUND;
  683. }
  684. PciIo = &PciIoDevice->PciIo;
  685. //
  686. // Preserve the original value
  687. //
  688. PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &OriginalValue);
  689. //
  690. // Raise TPL to high level to disable timer interrupt while the BAR is probed
  691. //
  692. OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
  693. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &gAllOne);
  694. PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &Value);
  695. //
  696. // Write back the original value
  697. //
  698. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &OriginalValue);
  699. //
  700. // Restore TPL to its original level
  701. //
  702. gBS->RestoreTPL (OldTpl);
  703. if (BarLengthValue != NULL) {
  704. *BarLengthValue = Value;
  705. }
  706. if (OriginalBarValue != NULL) {
  707. *OriginalBarValue = OriginalValue;
  708. }
  709. if (Value == 0) {
  710. return EFI_NOT_FOUND;
  711. } else {
  712. return EFI_SUCCESS;
  713. }
  714. }
  715. /**
  716. Check whether the bar is existed or not.
  717. @param PciIoDevice A pointer to the PCI_IO_DEVICE.
  718. @param Offset The offset.
  719. @param BarLengthValue The bar length value returned.
  720. @param OriginalBarValue The original bar value returned.
  721. @retval EFI_NOT_FOUND The bar doesn't exist.
  722. @retval EFI_SUCCESS The bar exist.
  723. **/
  724. EFI_STATUS
  725. BarExisted (
  726. IN PCI_IO_DEVICE *PciIoDevice,
  727. IN UINTN Offset,
  728. OUT UINT32 *BarLengthValue,
  729. OUT UINT32 *OriginalBarValue
  730. )
  731. {
  732. EFI_PCI_IO_PROTOCOL *PciIo;
  733. UINT32 OriginalValue;
  734. UINT32 Value;
  735. EFI_TPL OldTpl;
  736. PciIo = &PciIoDevice->PciIo;
  737. //
  738. // Preserve the original value
  739. //
  740. PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8)Offset, 1, &OriginalValue);
  741. //
  742. // Raise TPL to high level to disable timer interrupt while the BAR is probed
  743. //
  744. OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
  745. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8)Offset, 1, &gAllOne);
  746. PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8)Offset, 1, &Value);
  747. //
  748. // Write back the original value
  749. //
  750. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8)Offset, 1, &OriginalValue);
  751. //
  752. // Restore TPL to its original level
  753. //
  754. gBS->RestoreTPL (OldTpl);
  755. if (BarLengthValue != NULL) {
  756. *BarLengthValue = Value;
  757. }
  758. if (OriginalBarValue != NULL) {
  759. *OriginalBarValue = OriginalValue;
  760. }
  761. if (Value == 0) {
  762. return EFI_NOT_FOUND;
  763. } else {
  764. return EFI_SUCCESS;
  765. }
  766. }
  767. /**
  768. Test whether the device can support given attributes.
  769. @param PciIoDevice Pci device instance.
  770. @param Command Input command register value, and
  771. returned supported register value.
  772. @param BridgeControl Input bridge control value for PPB or P2C, and
  773. returned supported bridge control value.
  774. @param OldCommand Returned and stored old command register offset.
  775. @param OldBridgeControl Returned and stored old Bridge control value for PPB or P2C.
  776. **/
  777. VOID
  778. PciTestSupportedAttribute (
  779. IN PCI_IO_DEVICE *PciIoDevice,
  780. IN OUT UINT16 *Command,
  781. IN OUT UINT16 *BridgeControl,
  782. OUT UINT16 *OldCommand,
  783. OUT UINT16 *OldBridgeControl
  784. )
  785. {
  786. EFI_TPL OldTpl;
  787. UINT16 CommandValue;
  788. //
  789. // Preserve the original value
  790. //
  791. PCI_READ_COMMAND_REGISTER (PciIoDevice, OldCommand);
  792. //
  793. // Raise TPL to high level to disable timer interrupt while the BAR is probed
  794. //
  795. OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
  796. CommandValue = *Command | *OldCommand;
  797. PCI_SET_COMMAND_REGISTER (PciIoDevice, CommandValue);
  798. PCI_READ_COMMAND_REGISTER (PciIoDevice, &CommandValue);
  799. *Command = *Command & CommandValue;
  800. //
  801. // Write back the original value
  802. //
  803. PCI_SET_COMMAND_REGISTER (PciIoDevice, *OldCommand);
  804. //
  805. // Restore TPL to its original level
  806. //
  807. gBS->RestoreTPL (OldTpl);
  808. if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
  809. //
  810. // Preserve the original value
  811. //
  812. PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice, OldBridgeControl);
  813. //
  814. // Raise TPL to high level to disable timer interrupt while the BAR is probed
  815. //
  816. OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
  817. PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice, *BridgeControl);
  818. PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice, BridgeControl);
  819. //
  820. // Write back the original value
  821. //
  822. PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice, *OldBridgeControl);
  823. //
  824. // Restore TPL to its original level
  825. //
  826. gBS->RestoreTPL (OldTpl);
  827. } else {
  828. *OldBridgeControl = 0;
  829. *BridgeControl = 0;
  830. }
  831. }
  832. /**
  833. Set the supported or current attributes of a PCI device.
  834. @param PciIoDevice Structure pointer for PCI device.
  835. @param Command Command register value.
  836. @param BridgeControl Bridge control value for PPB or P2C.
  837. @param Option Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.
  838. **/
  839. VOID
  840. PciSetDeviceAttribute (
  841. IN PCI_IO_DEVICE *PciIoDevice,
  842. IN UINT16 Command,
  843. IN UINT16 BridgeControl,
  844. IN UINTN Option
  845. )
  846. {
  847. UINT64 Attributes;
  848. Attributes = 0;
  849. if ((Command & EFI_PCI_COMMAND_IO_SPACE) != 0) {
  850. Attributes |= EFI_PCI_IO_ATTRIBUTE_IO;
  851. }
  852. if ((Command & EFI_PCI_COMMAND_MEMORY_SPACE) != 0) {
  853. Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY;
  854. }
  855. if ((Command & EFI_PCI_COMMAND_BUS_MASTER) != 0) {
  856. Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;
  857. }
  858. if ((Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) {
  859. Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
  860. }
  861. if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) != 0) {
  862. Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;
  863. }
  864. if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) != 0) {
  865. Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;
  866. Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
  867. Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
  868. }
  869. if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16) != 0) {
  870. Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO_16;
  871. Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16;
  872. }
  873. if (Option == EFI_SET_SUPPORTS) {
  874. Attributes |= (UINT64)(EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE |
  875. EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED |
  876. EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE |
  877. EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE |
  878. EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM |
  879. EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE);
  880. if (IS_PCI_LPC (&PciIoDevice->Pci)) {
  881. Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;
  882. Attributes |= (mReserveIsaAliases ? (UINT64)EFI_PCI_IO_ATTRIBUTE_ISA_IO : \
  883. (UINT64)EFI_PCI_IO_ATTRIBUTE_ISA_IO_16);
  884. }
  885. if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
  886. //
  887. // For bridge, it should support IDE attributes
  888. //
  889. Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;
  890. Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;
  891. if (mReserveVgaAliases) {
  892. Attributes &= ~(UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 | \
  893. EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16);
  894. } else {
  895. Attributes &= ~(UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO | \
  896. EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO);
  897. }
  898. } else {
  899. if (IS_PCI_IDE (&PciIoDevice->Pci)) {
  900. Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;
  901. Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;
  902. }
  903. if (IS_PCI_VGA (&PciIoDevice->Pci)) {
  904. Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
  905. Attributes |= (mReserveVgaAliases ? (UINT64)EFI_PCI_IO_ATTRIBUTE_VGA_IO : \
  906. (UINT64)EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);
  907. }
  908. }
  909. PciIoDevice->Supports = Attributes;
  910. PciIoDevice->Supports &= ((PciIoDevice->Parent->Supports) | \
  911. EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | \
  912. EFI_PCI_IO_ATTRIBUTE_BUS_MASTER);
  913. } else {
  914. //
  915. // When this attribute is clear, the RomImage and RomSize fields in the PCI IO were
  916. // initialized based on the PCI option ROM found through the ROM BAR of the PCI controller.
  917. // When this attribute is set, the PCI option ROM described by the RomImage and RomSize
  918. // fields is not from the the ROM BAR of the PCI controller.
  919. //
  920. if (!PciIoDevice->EmbeddedRom) {
  921. Attributes |= EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM;
  922. }
  923. PciIoDevice->Attributes = Attributes;
  924. }
  925. }
  926. /**
  927. Determine if the device can support Fast Back to Back attribute.
  928. @param PciIoDevice Pci device instance.
  929. @param StatusIndex Status register value.
  930. @retval EFI_SUCCESS This device support Fast Back to Back attribute.
  931. @retval EFI_UNSUPPORTED This device doesn't support Fast Back to Back attribute.
  932. **/
  933. EFI_STATUS
  934. GetFastBackToBackSupport (
  935. IN PCI_IO_DEVICE *PciIoDevice,
  936. IN UINT8 StatusIndex
  937. )
  938. {
  939. EFI_PCI_IO_PROTOCOL *PciIo;
  940. EFI_STATUS Status;
  941. UINT32 StatusRegister;
  942. //
  943. // Read the status register
  944. //
  945. PciIo = &PciIoDevice->PciIo;
  946. Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, StatusIndex, 1, &StatusRegister);
  947. if (EFI_ERROR (Status)) {
  948. return EFI_UNSUPPORTED;
  949. }
  950. //
  951. // Check the Fast B2B bit
  952. //
  953. if ((StatusRegister & EFI_PCI_FAST_BACK_TO_BACK_CAPABLE) != 0) {
  954. return EFI_SUCCESS;
  955. } else {
  956. return EFI_UNSUPPORTED;
  957. }
  958. }
  959. /**
  960. Process the option ROM for all the children of the specified parent PCI device.
  961. It can only be used after the first full Option ROM process.
  962. @param PciIoDevice Pci device instance.
  963. **/
  964. VOID
  965. ProcessOptionRomLight (
  966. IN PCI_IO_DEVICE *PciIoDevice
  967. )
  968. {
  969. PCI_IO_DEVICE *Temp;
  970. LIST_ENTRY *CurrentLink;
  971. //
  972. // For RootBridge, PPB , P2C, go recursively to traverse all its children
  973. //
  974. CurrentLink = PciIoDevice->ChildList.ForwardLink;
  975. while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {
  976. Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
  977. if (!IsListEmpty (&Temp->ChildList)) {
  978. ProcessOptionRomLight (Temp);
  979. }
  980. Temp->AllOpRomProcessed = PciRomGetImageMapping (Temp);
  981. CurrentLink = CurrentLink->ForwardLink;
  982. }
  983. }
  984. /**
  985. Determine the related attributes of all devices under a Root Bridge.
  986. @param PciIoDevice PCI device instance.
  987. **/
  988. EFI_STATUS
  989. DetermineDeviceAttribute (
  990. IN PCI_IO_DEVICE *PciIoDevice
  991. )
  992. {
  993. UINT16 Command;
  994. UINT16 BridgeControl;
  995. UINT16 OldCommand;
  996. UINT16 OldBridgeControl;
  997. BOOLEAN FastB2BSupport;
  998. PCI_IO_DEVICE *Temp;
  999. LIST_ENTRY *CurrentLink;
  1000. EFI_STATUS Status;
  1001. //
  1002. // For Root Bridge, just copy it by RootBridgeIo protocol
  1003. // so as to keep consistent with the actual attribute
  1004. //
  1005. if (PciIoDevice->Parent == NULL) {
  1006. Status = PciIoDevice->PciRootBridgeIo->GetAttributes (
  1007. PciIoDevice->PciRootBridgeIo,
  1008. &PciIoDevice->Supports,
  1009. &PciIoDevice->Attributes
  1010. );
  1011. if (EFI_ERROR (Status)) {
  1012. return Status;
  1013. }
  1014. //
  1015. // Assume the PCI Root Bridge supports DAC
  1016. //
  1017. PciIoDevice->Supports |= (UINT64)(EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE |
  1018. EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM |
  1019. EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE);
  1020. } else {
  1021. //
  1022. // Set the attributes to be checked for common PCI devices and PPB or P2C
  1023. // Since some devices only support part of them, it is better to set the
  1024. // attribute according to its command or bridge control register
  1025. //
  1026. Command = EFI_PCI_COMMAND_IO_SPACE |
  1027. EFI_PCI_COMMAND_MEMORY_SPACE |
  1028. EFI_PCI_COMMAND_BUS_MASTER |
  1029. EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
  1030. BridgeControl = EFI_PCI_BRIDGE_CONTROL_ISA | EFI_PCI_BRIDGE_CONTROL_VGA | EFI_PCI_BRIDGE_CONTROL_VGA_16;
  1031. //
  1032. // Test whether the device can support attributes above
  1033. //
  1034. PciTestSupportedAttribute (PciIoDevice, &Command, &BridgeControl, &OldCommand, &OldBridgeControl);
  1035. //
  1036. // Set the supported attributes for specified PCI device
  1037. //
  1038. PciSetDeviceAttribute (PciIoDevice, Command, BridgeControl, EFI_SET_SUPPORTS);
  1039. //
  1040. // Set the current attributes for specified PCI device
  1041. //
  1042. PciSetDeviceAttribute (PciIoDevice, OldCommand, OldBridgeControl, EFI_SET_ATTRIBUTES);
  1043. //
  1044. // Enable other PCI supported attributes but not defined in PCI_IO_PROTOCOL
  1045. // For PCI Express devices, Memory Write and Invalidate is hardwired to 0b so only enable it for PCI devices.
  1046. if (!PciIoDevice->IsPciExp) {
  1047. PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE);
  1048. }
  1049. }
  1050. FastB2BSupport = TRUE;
  1051. //
  1052. // P2C can not support FB2B on the secondary side
  1053. //
  1054. if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
  1055. FastB2BSupport = FALSE;
  1056. }
  1057. //
  1058. // For RootBridge, PPB , P2C, go recursively to traverse all its children
  1059. //
  1060. CurrentLink = PciIoDevice->ChildList.ForwardLink;
  1061. while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {
  1062. Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
  1063. Status = DetermineDeviceAttribute (Temp);
  1064. if (EFI_ERROR (Status)) {
  1065. return Status;
  1066. }
  1067. //
  1068. // Detect Fast Back to Back support for the device under the bridge
  1069. //
  1070. Status = GetFastBackToBackSupport (Temp, PCI_PRIMARY_STATUS_OFFSET);
  1071. if (FastB2BSupport && EFI_ERROR (Status)) {
  1072. FastB2BSupport = FALSE;
  1073. }
  1074. CurrentLink = CurrentLink->ForwardLink;
  1075. }
  1076. //
  1077. // Set or clear Fast Back to Back bit for the whole bridge
  1078. //
  1079. if (!IsListEmpty (&PciIoDevice->ChildList)) {
  1080. if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
  1081. Status = GetFastBackToBackSupport (PciIoDevice, PCI_BRIDGE_STATUS_REGISTER_OFFSET);
  1082. if (EFI_ERROR (Status) || (!FastB2BSupport)) {
  1083. FastB2BSupport = FALSE;
  1084. PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);
  1085. } else {
  1086. PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);
  1087. }
  1088. }
  1089. CurrentLink = PciIoDevice->ChildList.ForwardLink;
  1090. while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {
  1091. Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
  1092. if (FastB2BSupport) {
  1093. PCI_ENABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);
  1094. } else {
  1095. PCI_DISABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);
  1096. }
  1097. CurrentLink = CurrentLink->ForwardLink;
  1098. }
  1099. }
  1100. //
  1101. // End for IsListEmpty
  1102. //
  1103. return EFI_SUCCESS;
  1104. }
  1105. /**
  1106. This routine is used to update the bar information for those incompatible PCI device.
  1107. @param PciIoDevice Input Pci device instance. Output Pci device instance with updated
  1108. Bar information.
  1109. @param IgnoreOptionRom Output If the option rom of incompatible device need to be ignored.
  1110. @retval EFI_SUCCESS Successfully updated bar information.
  1111. @retval EFI_UNSUPPORTED Given PCI device doesn't belong to incompatible PCI device list.
  1112. **/
  1113. EFI_STATUS
  1114. UpdatePciInfo (
  1115. IN OUT PCI_IO_DEVICE *PciIoDevice,
  1116. OUT BOOLEAN *IgnoreOptionRom
  1117. )
  1118. {
  1119. EFI_STATUS Status;
  1120. UINTN BarIndex;
  1121. BOOLEAN SetFlag;
  1122. VOID *Configuration;
  1123. EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
  1124. Configuration = NULL;
  1125. Status = EFI_SUCCESS;
  1126. if (gIncompatiblePciDeviceSupport == NULL) {
  1127. //
  1128. // It can only be supported after the Incompatible PCI Device
  1129. // Support Protocol has been installed
  1130. //
  1131. Status = gBS->LocateProtocol (
  1132. &gEfiIncompatiblePciDeviceSupportProtocolGuid,
  1133. NULL,
  1134. (VOID **)&gIncompatiblePciDeviceSupport
  1135. );
  1136. }
  1137. if (Status == EFI_SUCCESS) {
  1138. //
  1139. // Check whether the device belongs to incompatible devices from protocol or not
  1140. // If it is , then get its special requirement in the ACPI table
  1141. //
  1142. Status = gIncompatiblePciDeviceSupport->CheckDevice (
  1143. gIncompatiblePciDeviceSupport,
  1144. PciIoDevice->Pci.Hdr.VendorId,
  1145. PciIoDevice->Pci.Hdr.DeviceId,
  1146. PciIoDevice->Pci.Hdr.RevisionID,
  1147. PciIoDevice->Pci.Device.SubsystemVendorID,
  1148. PciIoDevice->Pci.Device.SubsystemID,
  1149. &Configuration
  1150. );
  1151. }
  1152. if (EFI_ERROR (Status) || (Configuration == NULL)) {
  1153. return EFI_UNSUPPORTED;
  1154. }
  1155. //
  1156. // Update PCI device information from the ACPI table
  1157. //
  1158. Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Configuration;
  1159. while (Ptr->Desc != ACPI_END_TAG_DESCRIPTOR) {
  1160. if (Ptr->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
  1161. //
  1162. // The format is not support
  1163. //
  1164. break;
  1165. }
  1166. //
  1167. // According to "Table 20. ACPI 2.0 & 3.0 QWORD Address Space Descriptor Usage"
  1168. // in PI Spec 1.7, Type-specific flags can be set to 0 when Address Translation
  1169. // Offset == 6 to skip device option ROM (do not probe option rom BAR).
  1170. //
  1171. if (((Ptr->AddrTranslationOffset == PCI_MAX_BAR) && (Ptr->SpecificFlag == 0))) {
  1172. *IgnoreOptionRom = TRUE;
  1173. Ptr++;
  1174. continue;
  1175. }
  1176. for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex++) {
  1177. if ((Ptr->AddrTranslationOffset != MAX_UINT64) &&
  1178. (Ptr->AddrTranslationOffset != MAX_UINT8) &&
  1179. (Ptr->AddrTranslationOffset != BarIndex)
  1180. )
  1181. {
  1182. //
  1183. // Skip updating when AddrTranslationOffset is not MAX_UINT64 or MAX_UINT8 (wide match).
  1184. // Skip updating when current BarIndex doesn't equal to AddrTranslationOffset.
  1185. // Comparing against MAX_UINT8 is to keep backward compatibility.
  1186. //
  1187. continue;
  1188. }
  1189. SetFlag = FALSE;
  1190. switch (Ptr->ResType) {
  1191. case ACPI_ADDRESS_SPACE_TYPE_MEM:
  1192. //
  1193. // Make sure the bar is memory type
  1194. //
  1195. if (CheckBarType (PciIoDevice, (UINT8)BarIndex, PciBarTypeMem)) {
  1196. SetFlag = TRUE;
  1197. //
  1198. // Ignored if granularity is 0.
  1199. // Ignored if PCI BAR is I/O or 32-bit memory.
  1200. // If PCI BAR is 64-bit memory and granularity is 32, then
  1201. // the PCI BAR resource is allocated below 4GB.
  1202. // If PCI BAR is 64-bit memory and granularity is 64, then
  1203. // the PCI BAR resource is allocated above 4GB.
  1204. //
  1205. if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeMem64) {
  1206. switch (Ptr->AddrSpaceGranularity) {
  1207. case 32:
  1208. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;
  1209. case 64:
  1210. PciIoDevice->PciBar[BarIndex].BarTypeFixed = TRUE;
  1211. break;
  1212. default:
  1213. break;
  1214. }
  1215. }
  1216. if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypePMem64) {
  1217. switch (Ptr->AddrSpaceGranularity) {
  1218. case 32:
  1219. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;
  1220. case 64:
  1221. PciIoDevice->PciBar[BarIndex].BarTypeFixed = TRUE;
  1222. break;
  1223. default:
  1224. break;
  1225. }
  1226. }
  1227. }
  1228. break;
  1229. case ACPI_ADDRESS_SPACE_TYPE_IO:
  1230. //
  1231. // Make sure the bar is IO type
  1232. //
  1233. if (CheckBarType (PciIoDevice, (UINT8)BarIndex, PciBarTypeIo)) {
  1234. SetFlag = TRUE;
  1235. }
  1236. break;
  1237. }
  1238. if (SetFlag) {
  1239. //
  1240. // Update the new alignment for the device
  1241. //
  1242. SetNewAlign (&(PciIoDevice->PciBar[BarIndex].Alignment), Ptr->AddrRangeMax);
  1243. //
  1244. // Update the new length for the device
  1245. //
  1246. if (Ptr->AddrLen != 0) {
  1247. PciIoDevice->PciBar[BarIndex].Length = Ptr->AddrLen;
  1248. }
  1249. }
  1250. }
  1251. Ptr++;
  1252. }
  1253. FreePool (Configuration);
  1254. return EFI_SUCCESS;
  1255. }
  1256. /**
  1257. This routine will update the alignment with the new alignment.
  1258. Compare with OLD_ALIGN/EVEN_ALIGN/SQUAD_ALIGN/DQUAD_ALIGN is to keep
  1259. backward compatibility.
  1260. @param Alignment Input Old alignment. Output updated alignment.
  1261. @param NewAlignment New alignment.
  1262. **/
  1263. VOID
  1264. SetNewAlign (
  1265. IN OUT UINT64 *Alignment,
  1266. IN UINT64 NewAlignment
  1267. )
  1268. {
  1269. UINT64 OldAlignment;
  1270. UINTN ShiftBit;
  1271. //
  1272. // The new alignment is the same as the original,
  1273. // so skip it
  1274. //
  1275. if ((NewAlignment == 0) || (NewAlignment == OLD_ALIGN)) {
  1276. return;
  1277. }
  1278. //
  1279. // Check the validity of the parameter
  1280. //
  1281. if ((NewAlignment != EVEN_ALIGN) &&
  1282. (NewAlignment != SQUAD_ALIGN) &&
  1283. (NewAlignment != DQUAD_ALIGN))
  1284. {
  1285. *Alignment = NewAlignment;
  1286. return;
  1287. }
  1288. OldAlignment = (*Alignment) + 1;
  1289. ShiftBit = 0;
  1290. //
  1291. // Get the first non-zero hex value of the length
  1292. //
  1293. while ((OldAlignment & 0x0F) == 0x00) {
  1294. OldAlignment = RShiftU64 (OldAlignment, 4);
  1295. ShiftBit += 4;
  1296. }
  1297. //
  1298. // Adjust the alignment to even, quad or double quad boundary
  1299. //
  1300. if (NewAlignment == EVEN_ALIGN) {
  1301. if ((OldAlignment & 0x01) != 0) {
  1302. OldAlignment = OldAlignment + 2 - (OldAlignment & 0x01);
  1303. }
  1304. } else if (NewAlignment == SQUAD_ALIGN) {
  1305. if ((OldAlignment & 0x03) != 0) {
  1306. OldAlignment = OldAlignment + 4 - (OldAlignment & 0x03);
  1307. }
  1308. } else if (NewAlignment == DQUAD_ALIGN) {
  1309. if ((OldAlignment & 0x07) != 0) {
  1310. OldAlignment = OldAlignment + 8 - (OldAlignment & 0x07);
  1311. }
  1312. }
  1313. //
  1314. // Update the old value
  1315. //
  1316. NewAlignment = LShiftU64 (OldAlignment, ShiftBit) - 1;
  1317. *Alignment = NewAlignment;
  1318. return;
  1319. }
  1320. /**
  1321. Parse PCI IOV VF bar information and fill them into PCI device instance.
  1322. @param PciIoDevice Pci device instance.
  1323. @param Offset Bar offset.
  1324. @param BarIndex Bar index.
  1325. @return Next bar offset.
  1326. **/
  1327. UINTN
  1328. PciIovParseVfBar (
  1329. IN PCI_IO_DEVICE *PciIoDevice,
  1330. IN UINTN Offset,
  1331. IN UINTN BarIndex
  1332. )
  1333. {
  1334. UINT32 Value;
  1335. UINT32 OriginalValue;
  1336. UINT32 Mask;
  1337. EFI_STATUS Status;
  1338. //
  1339. // Ensure it is called properly
  1340. //
  1341. ASSERT (PciIoDevice->SrIovCapabilityOffset != 0);
  1342. if (PciIoDevice->SrIovCapabilityOffset == 0) {
  1343. return 0;
  1344. }
  1345. OriginalValue = 0;
  1346. Value = 0;
  1347. Status = VfBarExisted (
  1348. PciIoDevice,
  1349. Offset,
  1350. &Value,
  1351. &OriginalValue
  1352. );
  1353. if (EFI_ERROR (Status)) {
  1354. PciIoDevice->VfPciBar[BarIndex].BaseAddress = 0;
  1355. PciIoDevice->VfPciBar[BarIndex].Length = 0;
  1356. PciIoDevice->VfPciBar[BarIndex].Alignment = 0;
  1357. //
  1358. // Scan all the BARs anyway
  1359. //
  1360. PciIoDevice->VfPciBar[BarIndex].Offset = (UINT16)Offset;
  1361. return Offset + 4;
  1362. }
  1363. PciIoDevice->VfPciBar[BarIndex].Offset = (UINT16)Offset;
  1364. if ((Value & 0x01) != 0) {
  1365. //
  1366. // Device I/Os. Impossible
  1367. //
  1368. ASSERT (FALSE);
  1369. return Offset + 4;
  1370. } else {
  1371. Mask = 0xfffffff0;
  1372. PciIoDevice->VfPciBar[BarIndex].BaseAddress = OriginalValue & Mask;
  1373. switch (Value & 0x07) {
  1374. //
  1375. // memory space; anywhere in 32 bit address space
  1376. //
  1377. case 0x00:
  1378. if ((Value & 0x08) != 0) {
  1379. PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem32;
  1380. } else {
  1381. PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem32;
  1382. }
  1383. PciIoDevice->VfPciBar[BarIndex].Length = (~(Value & Mask)) + 1;
  1384. PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;
  1385. //
  1386. // Adjust Length
  1387. //
  1388. PciIoDevice->VfPciBar[BarIndex].Length = MultU64x32 (PciIoDevice->VfPciBar[BarIndex].Length, PciIoDevice->InitialVFs);
  1389. //
  1390. // Adjust Alignment
  1391. //
  1392. if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {
  1393. PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;
  1394. }
  1395. break;
  1396. //
  1397. // memory space; anywhere in 64 bit address space
  1398. //
  1399. case 0x04:
  1400. if ((Value & 0x08) != 0) {
  1401. PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem64;
  1402. } else {
  1403. PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem64;
  1404. }
  1405. //
  1406. // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
  1407. // is regarded as an extension for the first bar. As a result
  1408. // the sizing will be conducted on combined 64 bit value
  1409. // Here just store the masked first 32bit value for future size
  1410. // calculation
  1411. //
  1412. PciIoDevice->VfPciBar[BarIndex].Length = Value & Mask;
  1413. PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;
  1414. if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {
  1415. PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;
  1416. }
  1417. //
  1418. // Increment the offset to point to next DWORD
  1419. //
  1420. Offset += 4;
  1421. Status = VfBarExisted (
  1422. PciIoDevice,
  1423. Offset,
  1424. &Value,
  1425. &OriginalValue
  1426. );
  1427. if (EFI_ERROR (Status)) {
  1428. PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeUnknown;
  1429. return Offset + 4;
  1430. }
  1431. //
  1432. // Fix the length to support some special 64 bit BAR
  1433. //
  1434. Value |= ((UINT32)-1 << HighBitSet32 (Value));
  1435. //
  1436. // Calculate the size of 64bit bar
  1437. //
  1438. PciIoDevice->VfPciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64)OriginalValue, 32);
  1439. PciIoDevice->VfPciBar[BarIndex].Length = PciIoDevice->VfPciBar[BarIndex].Length | LShiftU64 ((UINT64)Value, 32);
  1440. PciIoDevice->VfPciBar[BarIndex].Length = (~(PciIoDevice->VfPciBar[BarIndex].Length)) + 1;
  1441. PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;
  1442. //
  1443. // Adjust Length
  1444. //
  1445. PciIoDevice->VfPciBar[BarIndex].Length = MultU64x32 (PciIoDevice->VfPciBar[BarIndex].Length, PciIoDevice->InitialVFs);
  1446. //
  1447. // Adjust Alignment
  1448. //
  1449. if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {
  1450. PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;
  1451. }
  1452. break;
  1453. //
  1454. // reserved
  1455. //
  1456. default:
  1457. PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeUnknown;
  1458. PciIoDevice->VfPciBar[BarIndex].Length = (~(Value & Mask)) + 1;
  1459. PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;
  1460. if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {
  1461. PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;
  1462. }
  1463. break;
  1464. }
  1465. }
  1466. //
  1467. // Check the length again so as to keep compatible with some special bars
  1468. //
  1469. if (PciIoDevice->VfPciBar[BarIndex].Length == 0) {
  1470. PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeUnknown;
  1471. PciIoDevice->VfPciBar[BarIndex].BaseAddress = 0;
  1472. PciIoDevice->VfPciBar[BarIndex].Alignment = 0;
  1473. }
  1474. //
  1475. // Increment number of bar
  1476. //
  1477. return Offset + 4;
  1478. }
  1479. /**
  1480. Parse PCI bar information and fill them into PCI device instance.
  1481. @param PciIoDevice Pci device instance.
  1482. @param Offset Bar offset.
  1483. @param BarIndex Bar index.
  1484. @return Next bar offset.
  1485. **/
  1486. UINTN
  1487. PciParseBar (
  1488. IN PCI_IO_DEVICE *PciIoDevice,
  1489. IN UINTN Offset,
  1490. IN UINTN BarIndex
  1491. )
  1492. {
  1493. UINT32 Value;
  1494. UINT32 OriginalValue;
  1495. UINT32 Mask;
  1496. EFI_STATUS Status;
  1497. OriginalValue = 0;
  1498. Value = 0;
  1499. Status = BarExisted (
  1500. PciIoDevice,
  1501. Offset,
  1502. &Value,
  1503. &OriginalValue
  1504. );
  1505. if (EFI_ERROR (Status)) {
  1506. PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
  1507. PciIoDevice->PciBar[BarIndex].Length = 0;
  1508. PciIoDevice->PciBar[BarIndex].Alignment = 0;
  1509. //
  1510. // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
  1511. //
  1512. PciIoDevice->PciBar[BarIndex].Offset = (UINT8)Offset;
  1513. return Offset + 4;
  1514. }
  1515. PciIoDevice->PciBar[BarIndex].BarTypeFixed = FALSE;
  1516. PciIoDevice->PciBar[BarIndex].Offset = (UINT8)Offset;
  1517. if ((Value & 0x01) != 0) {
  1518. //
  1519. // Device I/Os
  1520. //
  1521. Mask = 0xfffffffc;
  1522. if ((Value & 0xFFFF0000) != 0) {
  1523. //
  1524. // It is a IO32 bar
  1525. //
  1526. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo32;
  1527. PciIoDevice->PciBar[BarIndex].Length = ((~(Value & Mask)) + 1);
  1528. PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
  1529. } else {
  1530. //
  1531. // It is a IO16 bar
  1532. //
  1533. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo16;
  1534. PciIoDevice->PciBar[BarIndex].Length = 0x0000FFFF & ((~(Value & Mask)) + 1);
  1535. PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
  1536. }
  1537. //
  1538. // Workaround. Some platforms implement IO bar with 0 length
  1539. // Need to treat it as no-bar
  1540. //
  1541. if (PciIoDevice->PciBar[BarIndex].Length == 0) {
  1542. PciIoDevice->PciBar[BarIndex].BarType = (PCI_BAR_TYPE)0;
  1543. }
  1544. PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
  1545. } else {
  1546. Mask = 0xfffffff0;
  1547. PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
  1548. switch (Value & 0x07) {
  1549. //
  1550. // memory space; anywhere in 32 bit address space
  1551. //
  1552. case 0x00:
  1553. if ((Value & 0x08) != 0) {
  1554. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;
  1555. } else {
  1556. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;
  1557. }
  1558. PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;
  1559. if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {
  1560. //
  1561. // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
  1562. //
  1563. PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);
  1564. } else {
  1565. PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
  1566. }
  1567. break;
  1568. //
  1569. // memory space; anywhere in 64 bit address space
  1570. //
  1571. case 0x04:
  1572. if ((Value & 0x08) != 0) {
  1573. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;
  1574. } else {
  1575. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;
  1576. }
  1577. //
  1578. // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
  1579. // is regarded as an extension for the first bar. As a result
  1580. // the sizing will be conducted on combined 64 bit value
  1581. // Here just store the masked first 32bit value for future size
  1582. // calculation
  1583. //
  1584. PciIoDevice->PciBar[BarIndex].Length = Value & Mask;
  1585. PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
  1586. //
  1587. // Increment the offset to point to next DWORD
  1588. //
  1589. Offset += 4;
  1590. Status = BarExisted (
  1591. PciIoDevice,
  1592. Offset,
  1593. &Value,
  1594. &OriginalValue
  1595. );
  1596. if (EFI_ERROR (Status)) {
  1597. //
  1598. // the high 32 bit does not claim any BAR, we need to re-check the low 32 bit BAR again
  1599. //
  1600. if (PciIoDevice->PciBar[BarIndex].Length == 0) {
  1601. //
  1602. // some device implement MMIO bar with 0 length, need to treat it as no-bar
  1603. //
  1604. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
  1605. return Offset + 4;
  1606. }
  1607. }
  1608. //
  1609. // Fix the length to support some special 64 bit BAR
  1610. //
  1611. if (Value == 0) {
  1612. DEBUG ((DEBUG_INFO, "[PciBus]BAR probing for upper 32bit of MEM64 BAR returns 0, change to 0xFFFFFFFF.\n"));
  1613. Value = (UINT32)-1;
  1614. } else {
  1615. Value |= ((UINT32)(-1) << HighBitSet32 (Value));
  1616. }
  1617. //
  1618. // Calculate the size of 64bit bar
  1619. //
  1620. PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64)OriginalValue, 32);
  1621. PciIoDevice->PciBar[BarIndex].Length = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64)Value, 32);
  1622. PciIoDevice->PciBar[BarIndex].Length = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;
  1623. if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {
  1624. //
  1625. // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
  1626. //
  1627. PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);
  1628. } else {
  1629. PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
  1630. }
  1631. break;
  1632. //
  1633. // reserved
  1634. //
  1635. default:
  1636. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
  1637. PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;
  1638. if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {
  1639. //
  1640. // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
  1641. //
  1642. PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);
  1643. } else {
  1644. PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
  1645. }
  1646. break;
  1647. }
  1648. }
  1649. //
  1650. // Check the length again so as to keep compatible with some special bars
  1651. //
  1652. if (PciIoDevice->PciBar[BarIndex].Length == 0) {
  1653. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
  1654. PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
  1655. PciIoDevice->PciBar[BarIndex].Alignment = 0;
  1656. }
  1657. //
  1658. // Increment number of bar
  1659. //
  1660. return Offset + 4;
  1661. }
  1662. /**
  1663. This routine is used to initialize the bar of a PCI device.
  1664. @param PciIoDevice Pci device instance.
  1665. @note It can be called typically when a device is going to be rejected.
  1666. **/
  1667. VOID
  1668. InitializePciDevice (
  1669. IN PCI_IO_DEVICE *PciIoDevice
  1670. )
  1671. {
  1672. EFI_PCI_IO_PROTOCOL *PciIo;
  1673. UINT8 Offset;
  1674. PciIo = &(PciIoDevice->PciIo);
  1675. //
  1676. // Put all the resource apertures
  1677. // Resource base is set to all ones so as to indicate its resource
  1678. // has not been allocated
  1679. //
  1680. for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {
  1681. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllOne);
  1682. }
  1683. }
  1684. /**
  1685. This routine is used to initialize the bar of a PCI-PCI Bridge device.
  1686. @param PciIoDevice PCI-PCI bridge device instance.
  1687. **/
  1688. VOID
  1689. InitializePpb (
  1690. IN PCI_IO_DEVICE *PciIoDevice
  1691. )
  1692. {
  1693. EFI_PCI_IO_PROTOCOL *PciIo;
  1694. PciIo = &(PciIoDevice->PciIo);
  1695. //
  1696. // Put all the resource apertures including IO16
  1697. // Io32, pMem32, pMem64 to quiescent state
  1698. // Resource base all ones, Resource limit all zeros
  1699. //
  1700. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
  1701. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero);
  1702. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne);
  1703. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero);
  1704. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne);
  1705. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero);
  1706. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne);
  1707. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero);
  1708. //
  1709. // Don't support use io32 as for now
  1710. //
  1711. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne);
  1712. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero);
  1713. //
  1714. // Force Interrupt line to zero for cards that come up randomly
  1715. //
  1716. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);
  1717. }
  1718. /**
  1719. This routine is used to initialize the bar of a PCI Card Bridge device.
  1720. @param PciIoDevice PCI Card bridge device.
  1721. **/
  1722. VOID
  1723. InitializeP2C (
  1724. IN PCI_IO_DEVICE *PciIoDevice
  1725. )
  1726. {
  1727. EFI_PCI_IO_PROTOCOL *PciIo;
  1728. PciIo = &(PciIoDevice->PciIo);
  1729. //
  1730. // Put all the resource apertures including IO16
  1731. // Io32, pMem32, pMem64 to quiescent state(
  1732. // Resource base all ones, Resource limit all zeros
  1733. //
  1734. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne);
  1735. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero);
  1736. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne);
  1737. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero);
  1738. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne);
  1739. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero);
  1740. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne);
  1741. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero);
  1742. //
  1743. // Force Interrupt line to zero for cards that come up randomly
  1744. //
  1745. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);
  1746. }
  1747. /**
  1748. Authenticate the PCI device by using DeviceSecurityProtocol.
  1749. @param PciIoDevice PCI device.
  1750. @retval EFI_SUCCESS The device passes the authentication.
  1751. @return not EFI_SUCCESS The device failes the authentication or
  1752. unexpected error happen during authentication.
  1753. **/
  1754. EFI_STATUS
  1755. AuthenticatePciDevice (
  1756. IN PCI_IO_DEVICE *PciIoDevice
  1757. )
  1758. {
  1759. EDKII_DEVICE_IDENTIFIER DeviceIdentifier;
  1760. EFI_STATUS Status;
  1761. if (mDeviceSecurityProtocol != NULL) {
  1762. //
  1763. // Prepare the parameter
  1764. //
  1765. DeviceIdentifier.Version = EDKII_DEVICE_IDENTIFIER_REVISION;
  1766. CopyGuid (&DeviceIdentifier.DeviceType, &gEdkiiDeviceIdentifierTypePciGuid);
  1767. DeviceIdentifier.DeviceHandle = NULL;
  1768. Status = gBS->InstallMultipleProtocolInterfaces (
  1769. &DeviceIdentifier.DeviceHandle,
  1770. &gEfiDevicePathProtocolGuid,
  1771. PciIoDevice->DevicePath,
  1772. &gEdkiiDeviceIdentifierTypePciGuid,
  1773. &PciIoDevice->PciIo,
  1774. NULL
  1775. );
  1776. if (EFI_ERROR (Status)) {
  1777. return Status;
  1778. }
  1779. //
  1780. // Do DeviceAuthentication
  1781. //
  1782. Status = mDeviceSecurityProtocol->DeviceAuthenticate (mDeviceSecurityProtocol, &DeviceIdentifier);
  1783. //
  1784. // Always uninstall, because they are only for Authentication.
  1785. // No need to check return Status.
  1786. //
  1787. gBS->UninstallMultipleProtocolInterfaces (
  1788. DeviceIdentifier.DeviceHandle,
  1789. &gEfiDevicePathProtocolGuid,
  1790. PciIoDevice->DevicePath,
  1791. &gEdkiiDeviceIdentifierTypePciGuid,
  1792. &PciIoDevice->PciIo,
  1793. NULL
  1794. );
  1795. return Status;
  1796. }
  1797. //
  1798. // Device Security Protocol is not found, just return success
  1799. //
  1800. return EFI_SUCCESS;
  1801. }
  1802. /**
  1803. Checks if PCI device is Root Bridge.
  1804. @param PciIoDevice Instance of PCI device
  1805. @retval TRUE Device is Root Bridge
  1806. @retval FALSE Device is not Root Bridge
  1807. **/
  1808. BOOLEAN
  1809. IsRootBridge (
  1810. IN PCI_IO_DEVICE *PciIoDevice
  1811. )
  1812. {
  1813. if (PciIoDevice->Parent == NULL) {
  1814. return TRUE;
  1815. } else {
  1816. return FALSE;
  1817. }
  1818. }
  1819. /**
  1820. Create and initialize general PCI I/O device instance for
  1821. PCI device/bridge device/hotplug bridge device.
  1822. @param Bridge Parent bridge instance.
  1823. @param Pci Input Pci information block.
  1824. @param Bus Device Bus NO.
  1825. @param Device Device device NO.
  1826. @param Func Device func NO.
  1827. @return Instance of PCI device. NULL means no instance created.
  1828. **/
  1829. PCI_IO_DEVICE *
  1830. CreatePciIoDevice (
  1831. IN PCI_IO_DEVICE *Bridge,
  1832. IN PCI_TYPE00 *Pci,
  1833. IN UINT8 Bus,
  1834. IN UINT8 Device,
  1835. IN UINT8 Func
  1836. )
  1837. {
  1838. PCI_IO_DEVICE *PciIoDevice;
  1839. EFI_PCI_IO_PROTOCOL *PciIo;
  1840. EFI_STATUS Status;
  1841. PciIoDevice = AllocateZeroPool (sizeof (PCI_IO_DEVICE));
  1842. if (PciIoDevice == NULL) {
  1843. return NULL;
  1844. }
  1845. PciIoDevice->Signature = PCI_IO_DEVICE_SIGNATURE;
  1846. PciIoDevice->Handle = NULL;
  1847. PciIoDevice->PciRootBridgeIo = Bridge->PciRootBridgeIo;
  1848. PciIoDevice->DevicePath = NULL;
  1849. PciIoDevice->BusNumber = Bus;
  1850. PciIoDevice->DeviceNumber = Device;
  1851. PciIoDevice->FunctionNumber = Func;
  1852. PciIoDevice->Decodes = 0;
  1853. if (gFullEnumeration) {
  1854. PciIoDevice->Allocated = FALSE;
  1855. } else {
  1856. PciIoDevice->Allocated = TRUE;
  1857. }
  1858. PciIoDevice->Registered = FALSE;
  1859. PciIoDevice->Attributes = 0;
  1860. PciIoDevice->Supports = 0;
  1861. PciIoDevice->BusOverride = FALSE;
  1862. PciIoDevice->AllOpRomProcessed = FALSE;
  1863. PciIoDevice->IsPciExp = FALSE;
  1864. CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01));
  1865. //
  1866. // Initialize the PCI I/O instance structure
  1867. //
  1868. InitializePciIoInstance (PciIoDevice);
  1869. InitializePciDriverOverrideInstance (PciIoDevice);
  1870. InitializePciLoadFile2 (PciIoDevice);
  1871. PciIo = &PciIoDevice->PciIo;
  1872. //
  1873. // Create a device path for this PCI device and store it into its private data
  1874. //
  1875. CreatePciDevicePath (
  1876. Bridge->DevicePath,
  1877. PciIoDevice
  1878. );
  1879. //
  1880. // Detect if PCI Express Device
  1881. //
  1882. PciIoDevice->PciExpressCapabilityOffset = 0;
  1883. Status = LocateCapabilityRegBlock (
  1884. PciIoDevice,
  1885. EFI_PCI_CAPABILITY_ID_PCIEXP,
  1886. &PciIoDevice->PciExpressCapabilityOffset,
  1887. NULL
  1888. );
  1889. if (!EFI_ERROR (Status)) {
  1890. PciIoDevice->IsPciExp = TRUE;
  1891. }
  1892. //
  1893. // Now we can do the authentication check for the device.
  1894. //
  1895. Status = AuthenticatePciDevice (PciIoDevice);
  1896. //
  1897. // If authentication fails, skip this device.
  1898. //
  1899. if (EFI_ERROR (Status)) {
  1900. if (PciIoDevice->DevicePath != NULL) {
  1901. FreePool (PciIoDevice->DevicePath);
  1902. }
  1903. FreePool (PciIoDevice);
  1904. return NULL;
  1905. }
  1906. //
  1907. // Check if device's parent is not Root Bridge
  1908. //
  1909. if (PcdGetBool (PcdAriSupport) && !IsRootBridge (Bridge)) {
  1910. //
  1911. // Check if the device is an ARI device.
  1912. //
  1913. Status = LocatePciExpressCapabilityRegBlock (
  1914. PciIoDevice,
  1915. EFI_PCIE_CAPABILITY_ID_ARI,
  1916. &PciIoDevice->AriCapabilityOffset,
  1917. NULL
  1918. );
  1919. if (!EFI_ERROR (Status)) {
  1920. //
  1921. // We need to enable ARI feature before calculate BusReservation,
  1922. // because FirstVFOffset and VFStride may change after that.
  1923. //
  1924. EFI_PCI_IO_PROTOCOL *ParentPciIo;
  1925. UINT32 Data32;
  1926. //
  1927. // Check if its parent supports ARI forwarding.
  1928. //
  1929. ParentPciIo = &Bridge->PciIo;
  1930. ParentPciIo->Pci.Read (
  1931. ParentPciIo,
  1932. EfiPciIoWidthUint32,
  1933. Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET,
  1934. 1,
  1935. &Data32
  1936. );
  1937. if ((Data32 & EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_ARI_FORWARDING) != 0) {
  1938. PciIoDevice->IsAriEnabled = TRUE;
  1939. //
  1940. // ARI forward support in bridge, so enable it.
  1941. //
  1942. ParentPciIo->Pci.Read (
  1943. ParentPciIo,
  1944. EfiPciIoWidthUint32,
  1945. Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET,
  1946. 1,
  1947. &Data32
  1948. );
  1949. if ((Data32 & EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING) == 0) {
  1950. Data32 |= EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING;
  1951. ParentPciIo->Pci.Write (
  1952. ParentPciIo,
  1953. EfiPciIoWidthUint32,
  1954. Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET,
  1955. 1,
  1956. &Data32
  1957. );
  1958. DEBUG ((
  1959. DEBUG_INFO,
  1960. " ARI: forwarding enabled for PPB[%02x:%02x:%02x]\n",
  1961. Bridge->BusNumber,
  1962. Bridge->DeviceNumber,
  1963. Bridge->FunctionNumber
  1964. ));
  1965. }
  1966. }
  1967. DEBUG ((DEBUG_INFO, " ARI: CapOffset = 0x%x\n", PciIoDevice->AriCapabilityOffset));
  1968. }
  1969. }
  1970. //
  1971. // Initialization for SR-IOV
  1972. //
  1973. if (PcdGetBool (PcdSrIovSupport)) {
  1974. Status = LocatePciExpressCapabilityRegBlock (
  1975. PciIoDevice,
  1976. EFI_PCIE_CAPABILITY_ID_SRIOV,
  1977. &PciIoDevice->SrIovCapabilityOffset,
  1978. NULL
  1979. );
  1980. if (!EFI_ERROR (Status)) {
  1981. UINT32 SupportedPageSize;
  1982. UINT16 VFStride;
  1983. UINT16 FirstVFOffset;
  1984. UINT16 Data16;
  1985. UINT32 PFRid;
  1986. UINT32 LastVF;
  1987. //
  1988. // If the SR-IOV device is an ARI device, then Set ARI Capable Hierarchy for the device.
  1989. //
  1990. if (PcdGetBool (PcdAriSupport) && (PciIoDevice->AriCapabilityOffset != 0)) {
  1991. PciIo->Pci.Read (
  1992. PciIo,
  1993. EfiPciIoWidthUint16,
  1994. PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL,
  1995. 1,
  1996. &Data16
  1997. );
  1998. Data16 |= EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL_ARI_HIERARCHY;
  1999. PciIo->Pci.Write (
  2000. PciIo,
  2001. EfiPciIoWidthUint16,
  2002. PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL,
  2003. 1,
  2004. &Data16
  2005. );
  2006. }
  2007. //
  2008. // Calculate SystemPageSize
  2009. //
  2010. PciIo->Pci.Read (
  2011. PciIo,
  2012. EfiPciIoWidthUint32,
  2013. PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SUPPORTED_PAGE_SIZE,
  2014. 1,
  2015. &SupportedPageSize
  2016. );
  2017. PciIoDevice->SystemPageSize = (PcdGet32 (PcdSrIovSystemPageSize) & SupportedPageSize);
  2018. ASSERT (PciIoDevice->SystemPageSize != 0);
  2019. PciIo->Pci.Write (
  2020. PciIo,
  2021. EfiPciIoWidthUint32,
  2022. PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SYSTEM_PAGE_SIZE,
  2023. 1,
  2024. &PciIoDevice->SystemPageSize
  2025. );
  2026. //
  2027. // Adjust SystemPageSize for Alignment usage later
  2028. //
  2029. PciIoDevice->SystemPageSize <<= 12;
  2030. //
  2031. // Calculate BusReservation for PCI IOV
  2032. //
  2033. //
  2034. // Read First FirstVFOffset, InitialVFs, and VFStride
  2035. //
  2036. PciIo->Pci.Read (
  2037. PciIo,
  2038. EfiPciIoWidthUint16,
  2039. PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_FIRSTVF,
  2040. 1,
  2041. &FirstVFOffset
  2042. );
  2043. PciIo->Pci.Read (
  2044. PciIo,
  2045. EfiPciIoWidthUint16,
  2046. PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_INITIALVFS,
  2047. 1,
  2048. &PciIoDevice->InitialVFs
  2049. );
  2050. PciIo->Pci.Read (
  2051. PciIo,
  2052. EfiPciIoWidthUint16,
  2053. PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_VFSTRIDE,
  2054. 1,
  2055. &VFStride
  2056. );
  2057. //
  2058. // Calculate LastVF
  2059. //
  2060. if (PciIoDevice->InitialVFs == 0) {
  2061. PciIoDevice->ReservedBusNum = 0;
  2062. } else {
  2063. PFRid = EFI_PCI_RID (Bus, Device, Func);
  2064. LastVF = PFRid + FirstVFOffset + (PciIoDevice->InitialVFs - 1) * VFStride;
  2065. //
  2066. // Calculate ReservedBusNum for this PF
  2067. //
  2068. PciIoDevice->ReservedBusNum = (UINT16)(EFI_PCI_BUS_OF_RID (LastVF) - Bus);
  2069. }
  2070. DEBUG ((
  2071. DEBUG_INFO,
  2072. " SR-IOV: SupportedPageSize = 0x%x; SystemPageSize = 0x%x; FirstVFOffset = 0x%x;\n",
  2073. SupportedPageSize,
  2074. PciIoDevice->SystemPageSize >> 12,
  2075. FirstVFOffset
  2076. ));
  2077. DEBUG ((
  2078. DEBUG_INFO,
  2079. " InitialVFs = 0x%x; ReservedBusNum = 0x%x; CapOffset = 0x%x\n",
  2080. PciIoDevice->InitialVFs,
  2081. PciIoDevice->ReservedBusNum,
  2082. PciIoDevice->SrIovCapabilityOffset
  2083. ));
  2084. }
  2085. }
  2086. if (PcdGetBool (PcdMrIovSupport)) {
  2087. Status = LocatePciExpressCapabilityRegBlock (
  2088. PciIoDevice,
  2089. EFI_PCIE_CAPABILITY_ID_MRIOV,
  2090. &PciIoDevice->MrIovCapabilityOffset,
  2091. NULL
  2092. );
  2093. if (!EFI_ERROR (Status)) {
  2094. DEBUG ((DEBUG_INFO, " MR-IOV: CapOffset = 0x%x\n", PciIoDevice->MrIovCapabilityOffset));
  2095. }
  2096. }
  2097. PciIoDevice->ResizableBarOffset = 0;
  2098. if (PcdGetBool (PcdPcieResizableBarSupport)) {
  2099. Status = LocatePciExpressCapabilityRegBlock (
  2100. PciIoDevice,
  2101. PCI_EXPRESS_EXTENDED_CAPABILITY_RESIZABLE_BAR_ID,
  2102. &PciIoDevice->ResizableBarOffset,
  2103. NULL
  2104. );
  2105. if (!EFI_ERROR (Status)) {
  2106. PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CONTROL ResizableBarControl;
  2107. UINT32 Offset;
  2108. Offset = PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER)
  2109. + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CAPABILITY),
  2110. PciIo->Pci.Read (
  2111. PciIo,
  2112. EfiPciIoWidthUint8,
  2113. Offset,
  2114. sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CONTROL),
  2115. &ResizableBarControl
  2116. );
  2117. PciIoDevice->ResizableBarNumber = ResizableBarControl.Bits.ResizableBarNumber;
  2118. PciProgramResizableBar (PciIoDevice, PciResizableBarMax);
  2119. }
  2120. }
  2121. //
  2122. // Initialize the reserved resource list
  2123. //
  2124. InitializeListHead (&PciIoDevice->ReservedResourceList);
  2125. //
  2126. // Initialize the driver list
  2127. //
  2128. InitializeListHead (&PciIoDevice->OptionRomDriverList);
  2129. //
  2130. // Initialize the child list
  2131. //
  2132. InitializeListHead (&PciIoDevice->ChildList);
  2133. return PciIoDevice;
  2134. }
  2135. /**
  2136. This routine is used to enumerate entire pci bus system
  2137. in a given platform.
  2138. It is only called on the second start on the same Root Bridge.
  2139. @param Controller Parent bridge handler.
  2140. @retval EFI_SUCCESS PCI enumeration finished successfully.
  2141. @retval other Some error occurred when enumerating the pci bus system.
  2142. **/
  2143. EFI_STATUS
  2144. PciEnumeratorLight (
  2145. IN EFI_HANDLE Controller
  2146. )
  2147. {
  2148. EFI_STATUS Status;
  2149. EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
  2150. PCI_IO_DEVICE *RootBridgeDev;
  2151. UINT16 MinBus;
  2152. UINT16 MaxBus;
  2153. EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
  2154. MinBus = 0;
  2155. MaxBus = PCI_MAX_BUS;
  2156. Descriptors = NULL;
  2157. //
  2158. // If this root bridge has been already enumerated, then return successfully
  2159. //
  2160. if (GetRootBridgeByHandle (Controller) != NULL) {
  2161. return EFI_SUCCESS;
  2162. }
  2163. //
  2164. // Open pci root bridge io protocol
  2165. //
  2166. Status = gBS->OpenProtocol (
  2167. Controller,
  2168. &gEfiPciRootBridgeIoProtocolGuid,
  2169. (VOID **)&PciRootBridgeIo,
  2170. gPciBusDriverBinding.DriverBindingHandle,
  2171. Controller,
  2172. EFI_OPEN_PROTOCOL_BY_DRIVER
  2173. );
  2174. if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
  2175. return Status;
  2176. }
  2177. Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **)&Descriptors);
  2178. if (EFI_ERROR (Status)) {
  2179. return Status;
  2180. }
  2181. while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) {
  2182. //
  2183. // Create a device node for root bridge device with a NULL host bridge controller handle
  2184. //
  2185. RootBridgeDev = CreateRootBridge (Controller);
  2186. if (RootBridgeDev == NULL) {
  2187. Descriptors++;
  2188. continue;
  2189. }
  2190. //
  2191. // Record the root bridge-io protocol
  2192. //
  2193. RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;
  2194. Status = PciPciDeviceInfoCollector (
  2195. RootBridgeDev,
  2196. (UINT8)MinBus
  2197. );
  2198. if (!EFI_ERROR (Status)) {
  2199. //
  2200. // Remove those PCI devices which are rejected when full enumeration
  2201. //
  2202. RemoveRejectedPciDevices (RootBridgeDev->Handle, RootBridgeDev);
  2203. //
  2204. // Process option rom light
  2205. //
  2206. ProcessOptionRomLight (RootBridgeDev);
  2207. //
  2208. // Determine attributes for all devices under this root bridge
  2209. //
  2210. DetermineDeviceAttribute (RootBridgeDev);
  2211. //
  2212. // If successfully, insert the node into device pool
  2213. //
  2214. InsertRootBridge (RootBridgeDev);
  2215. } else {
  2216. //
  2217. // If unsuccessfully, destroy the entire node
  2218. //
  2219. DestroyRootBridge (RootBridgeDev);
  2220. }
  2221. Descriptors++;
  2222. }
  2223. return EFI_SUCCESS;
  2224. }
  2225. /**
  2226. Get bus range from PCI resource descriptor list.
  2227. @param Descriptors A pointer to the address space descriptor.
  2228. @param MinBus The min bus returned.
  2229. @param MaxBus The max bus returned.
  2230. @param BusRange The bus range returned.
  2231. @retval EFI_SUCCESS Successfully got bus range.
  2232. @retval EFI_NOT_FOUND Can not find the specific bus.
  2233. **/
  2234. EFI_STATUS
  2235. PciGetBusRange (
  2236. IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,
  2237. OUT UINT16 *MinBus,
  2238. OUT UINT16 *MaxBus,
  2239. OUT UINT16 *BusRange
  2240. )
  2241. {
  2242. while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {
  2243. if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
  2244. if (MinBus != NULL) {
  2245. *MinBus = (UINT16)(*Descriptors)->AddrRangeMin;
  2246. }
  2247. if (MaxBus != NULL) {
  2248. *MaxBus = (UINT16)(*Descriptors)->AddrRangeMax;
  2249. }
  2250. if (BusRange != NULL) {
  2251. *BusRange = (UINT16)(*Descriptors)->AddrLen;
  2252. }
  2253. return EFI_SUCCESS;
  2254. }
  2255. (*Descriptors)++;
  2256. }
  2257. return EFI_NOT_FOUND;
  2258. }
  2259. /**
  2260. This routine can be used to start the root bridge.
  2261. @param RootBridgeDev Pci device instance.
  2262. @retval EFI_SUCCESS This device started.
  2263. @retval other Failed to get PCI Root Bridge I/O protocol.
  2264. **/
  2265. EFI_STATUS
  2266. StartManagingRootBridge (
  2267. IN PCI_IO_DEVICE *RootBridgeDev
  2268. )
  2269. {
  2270. EFI_HANDLE RootBridgeHandle;
  2271. EFI_STATUS Status;
  2272. EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
  2273. //
  2274. // Get the root bridge handle
  2275. //
  2276. RootBridgeHandle = RootBridgeDev->Handle;
  2277. PciRootBridgeIo = NULL;
  2278. //
  2279. // Get the pci root bridge io protocol
  2280. //
  2281. Status = gBS->OpenProtocol (
  2282. RootBridgeHandle,
  2283. &gEfiPciRootBridgeIoProtocolGuid,
  2284. (VOID **)&PciRootBridgeIo,
  2285. gPciBusDriverBinding.DriverBindingHandle,
  2286. RootBridgeHandle,
  2287. EFI_OPEN_PROTOCOL_BY_DRIVER
  2288. );
  2289. if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
  2290. return Status;
  2291. }
  2292. //
  2293. // Store the PciRootBridgeIo protocol into root bridge private data
  2294. //
  2295. RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;
  2296. return EFI_SUCCESS;
  2297. }
  2298. /**
  2299. This routine can be used to check whether a PCI device should be rejected when light enumeration.
  2300. @param PciIoDevice Pci device instance.
  2301. @retval TRUE This device should be rejected.
  2302. @retval FALSE This device shouldn't be rejected.
  2303. **/
  2304. BOOLEAN
  2305. IsPciDeviceRejected (
  2306. IN PCI_IO_DEVICE *PciIoDevice
  2307. )
  2308. {
  2309. EFI_STATUS Status;
  2310. UINT32 TestValue;
  2311. UINT32 OldValue;
  2312. UINT32 Mask;
  2313. UINT8 BarOffset;
  2314. //
  2315. // PPB should be skip!
  2316. //
  2317. if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
  2318. return FALSE;
  2319. }
  2320. if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
  2321. //
  2322. // Only test base registers for P2C
  2323. //
  2324. for (BarOffset = 0x1C; BarOffset <= 0x38; BarOffset += 2 * sizeof (UINT32)) {
  2325. Mask = (BarOffset < 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;
  2326. Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
  2327. if (EFI_ERROR (Status)) {
  2328. continue;
  2329. }
  2330. TestValue = TestValue & Mask;
  2331. if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
  2332. //
  2333. // The bar isn't programed, so it should be rejected
  2334. //
  2335. return TRUE;
  2336. }
  2337. }
  2338. return FALSE;
  2339. }
  2340. for (BarOffset = 0x14; BarOffset <= 0x24; BarOffset += sizeof (UINT32)) {
  2341. //
  2342. // Test PCI devices
  2343. //
  2344. Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
  2345. if (EFI_ERROR (Status)) {
  2346. continue;
  2347. }
  2348. if ((TestValue & 0x01) != 0) {
  2349. //
  2350. // IO Bar
  2351. //
  2352. Mask = 0xFFFFFFFC;
  2353. TestValue = TestValue & Mask;
  2354. if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
  2355. return TRUE;
  2356. }
  2357. } else {
  2358. //
  2359. // Mem Bar
  2360. //
  2361. Mask = 0xFFFFFFF0;
  2362. TestValue = TestValue & Mask;
  2363. if ((TestValue & 0x07) == 0x04) {
  2364. //
  2365. // Mem64 or PMem64
  2366. //
  2367. BarOffset += sizeof (UINT32);
  2368. if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
  2369. //
  2370. // Test its high 32-Bit BAR
  2371. //
  2372. Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
  2373. if (TestValue == OldValue) {
  2374. return TRUE;
  2375. }
  2376. }
  2377. } else {
  2378. //
  2379. // Mem32 or PMem32
  2380. //
  2381. if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
  2382. return TRUE;
  2383. }
  2384. }
  2385. }
  2386. }
  2387. return FALSE;
  2388. }
  2389. /**
  2390. Reset all bus number from specific bridge.
  2391. @param Bridge Parent specific bridge.
  2392. @param StartBusNumber Start bus number.
  2393. **/
  2394. VOID
  2395. ResetAllPpbBusNumber (
  2396. IN PCI_IO_DEVICE *Bridge,
  2397. IN UINT8 StartBusNumber
  2398. )
  2399. {
  2400. EFI_STATUS Status;
  2401. PCI_TYPE00 Pci;
  2402. UINT8 Device;
  2403. UINT32 Register;
  2404. UINT8 Func;
  2405. UINT64 Address;
  2406. UINT8 SecondaryBus;
  2407. EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
  2408. PciRootBridgeIo = Bridge->PciRootBridgeIo;
  2409. for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
  2410. for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
  2411. //
  2412. // Check to see whether a pci device is present
  2413. //
  2414. Status = PciDevicePresent (
  2415. PciRootBridgeIo,
  2416. &Pci,
  2417. StartBusNumber,
  2418. Device,
  2419. Func
  2420. );
  2421. if (EFI_ERROR (Status) && (Func == 0)) {
  2422. //
  2423. // go to next device if there is no Function 0
  2424. //
  2425. break;
  2426. }
  2427. if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci))) {
  2428. Register = 0;
  2429. Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
  2430. Status = PciRootBridgeIo->Pci.Read (
  2431. PciRootBridgeIo,
  2432. EfiPciWidthUint32,
  2433. Address,
  2434. 1,
  2435. &Register
  2436. );
  2437. SecondaryBus = (UINT8)(Register >> 8);
  2438. if (SecondaryBus != 0) {
  2439. ResetAllPpbBusNumber (Bridge, SecondaryBus);
  2440. }
  2441. //
  2442. // Reset register 18h, 19h, 1Ah on PCI Bridge
  2443. //
  2444. Register &= 0xFF000000;
  2445. Status = PciRootBridgeIo->Pci.Write (
  2446. PciRootBridgeIo,
  2447. EfiPciWidthUint32,
  2448. Address,
  2449. 1,
  2450. &Register
  2451. );
  2452. }
  2453. if ((Func == 0) && !IS_PCI_MULTI_FUNC (&Pci)) {
  2454. //
  2455. // Skip sub functions, this is not a multi function device
  2456. //
  2457. Func = PCI_MAX_FUNC;
  2458. }
  2459. }
  2460. }
  2461. }