Init.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051
  1. /** @file
  2. Initialization functions for EFI UNDI32 driver.
  3. Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "Undi32.h"
  7. //
  8. // Global Variables
  9. //
  10. PXE_SW_UNDI *pxe_31 = NULL; // 3.1 entry
  11. UNDI32_DEV *UNDI32DeviceList[MAX_NIC_INTERFACES];
  12. UNDI_CONFIG_TABLE *UndiDataPointer = NULL;
  13. //
  14. // UNDI Class Driver Global Variables
  15. //
  16. EFI_DRIVER_BINDING_PROTOCOL gUndiDriverBinding = {
  17. UndiDriverSupported,
  18. UndiDriverStart,
  19. UndiDriverStop,
  20. 0xa,
  21. NULL,
  22. NULL
  23. };
  24. /**
  25. When address mapping changes to virtual this should make the appropriate
  26. address conversions.
  27. (Standard Event handler)
  28. @return None
  29. **/
  30. VOID
  31. EFIAPI
  32. UndiNotifyVirtual (
  33. EFI_EVENT Event,
  34. VOID *Context
  35. )
  36. {
  37. UINT16 Index;
  38. VOID *Pxe31Pointer;
  39. if (pxe_31 != NULL) {
  40. Pxe31Pointer = (VOID *) pxe_31;
  41. EfiConvertPointer (
  42. EFI_OPTIONAL_PTR,
  43. (VOID **) &Pxe31Pointer
  44. );
  45. //
  46. // UNDI32DeviceList is an array of pointers
  47. //
  48. for (Index = 0; Index < (pxe_31->IFcnt | pxe_31->IFcntExt << 8); Index++) {
  49. UNDI32DeviceList[Index]->NIIProtocol_31.Id = (UINT64) (UINTN) Pxe31Pointer;
  50. EfiConvertPointer (
  51. EFI_OPTIONAL_PTR,
  52. (VOID **) &(UNDI32DeviceList[Index])
  53. );
  54. }
  55. EfiConvertPointer (
  56. EFI_OPTIONAL_PTR,
  57. (VOID **) &(pxe_31->EntryPoint)
  58. );
  59. pxe_31 = Pxe31Pointer;
  60. }
  61. for (Index = 0; Index <= PXE_OPCODE_LAST_VALID; Index++) {
  62. EfiConvertPointer (
  63. EFI_OPTIONAL_PTR,
  64. (VOID **) &api_table[Index].api_ptr
  65. );
  66. }
  67. }
  68. /**
  69. When EFI is shuting down the boot services, we need to install a
  70. configuration table for UNDI to work at runtime!
  71. (Standard Event handler)
  72. @return None
  73. **/
  74. VOID
  75. EFIAPI
  76. UndiNotifyReadyToBoot (
  77. EFI_EVENT Event,
  78. VOID *Context
  79. )
  80. {
  81. InstallConfigTable ();
  82. }
  83. /**
  84. Test to see if this driver supports ControllerHandle. Any ControllerHandle
  85. than contains a DevicePath, PciIo protocol, Class code of 2, Vendor ID of 0x8086,
  86. and DeviceId of (D100_DEVICE_ID || D102_DEVICE_ID || ICH3_DEVICE_ID_1 ||
  87. ICH3_DEVICE_ID_2 || ICH3_DEVICE_ID_3 || ICH3_DEVICE_ID_4 || ICH3_DEVICE_ID_5 ||
  88. ICH3_DEVICE_ID_6 || ICH3_DEVICE_ID_7 || ICH3_DEVICE_ID_8) can be supported.
  89. @param This Protocol instance pointer.
  90. @param Controller Handle of device to test.
  91. @param RemainingDevicePath Not used.
  92. @retval EFI_SUCCESS This driver supports this device.
  93. @retval other This driver does not support this device.
  94. **/
  95. EFI_STATUS
  96. EFIAPI
  97. UndiDriverSupported (
  98. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  99. IN EFI_HANDLE Controller,
  100. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
  101. )
  102. {
  103. EFI_STATUS Status;
  104. EFI_PCI_IO_PROTOCOL *PciIo;
  105. PCI_TYPE00 Pci;
  106. Status = gBS->OpenProtocol (
  107. Controller,
  108. &gEfiDevicePathProtocolGuid,
  109. NULL,
  110. This->DriverBindingHandle,
  111. Controller,
  112. EFI_OPEN_PROTOCOL_TEST_PROTOCOL
  113. );
  114. if (EFI_ERROR (Status)) {
  115. return Status;
  116. }
  117. Status = gBS->OpenProtocol (
  118. Controller,
  119. &gEfiPciIoProtocolGuid,
  120. (VOID **) &PciIo,
  121. This->DriverBindingHandle,
  122. Controller,
  123. EFI_OPEN_PROTOCOL_BY_DRIVER
  124. );
  125. if (EFI_ERROR (Status)) {
  126. return Status;
  127. }
  128. Status = PciIo->Pci.Read (
  129. PciIo,
  130. EfiPciIoWidthUint8,
  131. 0,
  132. sizeof (PCI_CONFIG_HEADER),
  133. &Pci
  134. );
  135. if (!EFI_ERROR (Status)) {
  136. Status = EFI_UNSUPPORTED;
  137. if (Pci.Hdr.ClassCode[2] == 0x02 && Pci.Hdr.VendorId == PCI_VENDOR_ID_INTEL) {
  138. switch (Pci.Hdr.DeviceId) {
  139. case D100_DEVICE_ID:
  140. case D102_DEVICE_ID:
  141. case ICH3_DEVICE_ID_1:
  142. case ICH3_DEVICE_ID_2:
  143. case ICH3_DEVICE_ID_3:
  144. case ICH3_DEVICE_ID_4:
  145. case ICH3_DEVICE_ID_5:
  146. case ICH3_DEVICE_ID_6:
  147. case ICH3_DEVICE_ID_7:
  148. case ICH3_DEVICE_ID_8:
  149. case 0x1039:
  150. case 0x103A:
  151. case 0x103B:
  152. case 0x103C:
  153. case 0x103D:
  154. case 0x103E:
  155. case 0x1050:
  156. case 0x1051:
  157. case 0x1052:
  158. case 0x1053:
  159. case 0x1054:
  160. case 0x1055:
  161. case 0x1056:
  162. case 0x1057:
  163. case 0x1059:
  164. case 0x1064:
  165. Status = EFI_SUCCESS;
  166. }
  167. }
  168. }
  169. gBS->CloseProtocol (
  170. Controller,
  171. &gEfiPciIoProtocolGuid,
  172. This->DriverBindingHandle,
  173. Controller
  174. );
  175. return Status;
  176. }
  177. /**
  178. Start this driver on Controller by opening PciIo and DevicePath protocol.
  179. Initialize PXE structures, create a copy of the Controller Device Path with the
  180. NIC's MAC address appended to it, install the NetworkInterfaceIdentifier protocol
  181. on the newly created Device Path.
  182. @param This Protocol instance pointer.
  183. @param Controller Handle of device to work with.
  184. @param RemainingDevicePath Not used, always produce all possible children.
  185. @retval EFI_SUCCESS This driver is added to Controller.
  186. @retval other This driver does not support this device.
  187. **/
  188. EFI_STATUS
  189. EFIAPI
  190. UndiDriverStart (
  191. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  192. IN EFI_HANDLE Controller,
  193. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
  194. )
  195. {
  196. EFI_STATUS Status;
  197. EFI_DEVICE_PATH_PROTOCOL *UndiDevicePath;
  198. PCI_CONFIG_HEADER *CfgHdr;
  199. UNDI32_DEV *UNDI32Device;
  200. UINT16 NewCommand;
  201. UINT8 *TmpPxePointer;
  202. EFI_PCI_IO_PROTOCOL *PciIoFncs;
  203. UINTN Len;
  204. UINT64 Supports;
  205. BOOLEAN PciAttributesSaved;
  206. Status = gBS->OpenProtocol (
  207. Controller,
  208. &gEfiPciIoProtocolGuid,
  209. (VOID **) &PciIoFncs,
  210. This->DriverBindingHandle,
  211. Controller,
  212. EFI_OPEN_PROTOCOL_BY_DRIVER
  213. );
  214. if (EFI_ERROR (Status)) {
  215. return Status;
  216. }
  217. Status = gBS->OpenProtocol (
  218. Controller,
  219. &gEfiDevicePathProtocolGuid,
  220. (VOID **) &UndiDevicePath,
  221. This->DriverBindingHandle,
  222. Controller,
  223. EFI_OPEN_PROTOCOL_BY_DRIVER
  224. );
  225. if (EFI_ERROR (Status)) {
  226. gBS->CloseProtocol (
  227. Controller,
  228. &gEfiPciIoProtocolGuid,
  229. This->DriverBindingHandle,
  230. Controller
  231. );
  232. return Status;
  233. }
  234. PciAttributesSaved = FALSE;
  235. Status = gBS->AllocatePool (
  236. EfiRuntimeServicesData,
  237. sizeof (UNDI32_DEV),
  238. (VOID **) &UNDI32Device
  239. );
  240. if (EFI_ERROR (Status)) {
  241. goto UndiError;
  242. }
  243. ZeroMem ((CHAR8 *) UNDI32Device, sizeof (UNDI32_DEV));
  244. //
  245. // Get original PCI attributes
  246. //
  247. Status = PciIoFncs->Attributes (
  248. PciIoFncs,
  249. EfiPciIoAttributeOperationGet,
  250. 0,
  251. &UNDI32Device->NicInfo.OriginalPciAttributes
  252. );
  253. if (EFI_ERROR (Status)) {
  254. goto UndiErrorDeleteDevice;
  255. }
  256. PciAttributesSaved = TRUE;
  257. //
  258. // allocate and initialize both (old and new) the !pxe structures here,
  259. // there should only be one copy of each of these structure for any number
  260. // of NICs this undi supports. Also, these structures need to be on a
  261. // paragraph boundary as per the spec. so, while allocating space for these,
  262. // make sure that there is space for 2 !pxe structures (old and new) and a
  263. // 32 bytes padding for alignment adjustment (in case)
  264. //
  265. TmpPxePointer = NULL;
  266. if (pxe_31 == NULL) {
  267. Status = gBS->AllocatePool (
  268. EfiRuntimeServicesData,
  269. (sizeof (PXE_SW_UNDI) + sizeof (PXE_SW_UNDI) + 32),
  270. (VOID **) &TmpPxePointer
  271. );
  272. if (EFI_ERROR (Status)) {
  273. goto UndiErrorDeleteDevice;
  274. }
  275. ZeroMem (
  276. TmpPxePointer,
  277. sizeof (PXE_SW_UNDI) + sizeof (PXE_SW_UNDI) + 32
  278. );
  279. //
  280. // check for paragraph alignment here, assuming that the pointer is
  281. // already 8 byte aligned.
  282. //
  283. if (((UINTN) TmpPxePointer & 0x0F) != 0) {
  284. pxe_31 = (PXE_SW_UNDI *) ((UINTN) (TmpPxePointer + 8));
  285. } else {
  286. pxe_31 = (PXE_SW_UNDI *) TmpPxePointer;
  287. }
  288. PxeStructInit (pxe_31);
  289. }
  290. UNDI32Device->NIIProtocol_31.Id = (UINT64) (UINTN) (pxe_31);
  291. Status = PciIoFncs->Attributes (
  292. PciIoFncs,
  293. EfiPciIoAttributeOperationSupported,
  294. 0,
  295. &Supports
  296. );
  297. if (!EFI_ERROR (Status)) {
  298. Supports &= EFI_PCI_DEVICE_ENABLE;
  299. Status = PciIoFncs->Attributes (
  300. PciIoFncs,
  301. EfiPciIoAttributeOperationEnable,
  302. Supports,
  303. NULL
  304. );
  305. }
  306. //
  307. // Read all the registers from device's PCI Configuration space
  308. //
  309. Status = PciIoFncs->Pci.Read (
  310. PciIoFncs,
  311. EfiPciIoWidthUint32,
  312. 0,
  313. MAX_PCI_CONFIG_LEN,
  314. &UNDI32Device->NicInfo.Config
  315. );
  316. CfgHdr = (PCI_CONFIG_HEADER *) &(UNDI32Device->NicInfo.Config[0]);
  317. //
  318. // make sure that this device is a PCI bus master
  319. //
  320. NewCommand = (UINT16) (CfgHdr->Command | PCI_COMMAND_MASTER | PCI_COMMAND_IO);
  321. if (CfgHdr->Command != NewCommand) {
  322. PciIoFncs->Pci.Write (
  323. PciIoFncs,
  324. EfiPciIoWidthUint16,
  325. PCI_COMMAND,
  326. 1,
  327. &NewCommand
  328. );
  329. CfgHdr->Command = NewCommand;
  330. }
  331. //
  332. // make sure that the latency timer is at least 32
  333. //
  334. if (CfgHdr->LatencyTimer < 32) {
  335. CfgHdr->LatencyTimer = 32;
  336. PciIoFncs->Pci.Write (
  337. PciIoFncs,
  338. EfiPciIoWidthUint8,
  339. PCI_LATENCY_TIMER,
  340. 1,
  341. &CfgHdr->LatencyTimer
  342. );
  343. }
  344. //
  345. // the IfNum index for the current interface will be the total number
  346. // of interfaces initialized so far
  347. //
  348. UNDI32Device->NIIProtocol_31.IfNum = pxe_31->IFcnt | pxe_31->IFcntExt << 8;
  349. PxeUpdate (&UNDI32Device->NicInfo, pxe_31);
  350. UNDI32Device->NicInfo.Io_Function = PciIoFncs;
  351. UNDI32DeviceList[UNDI32Device->NIIProtocol_31.IfNum] = UNDI32Device;
  352. UNDI32Device->Undi32BaseDevPath = UndiDevicePath;
  353. Status = AppendMac2DevPath (
  354. &UNDI32Device->Undi32DevPath,
  355. UNDI32Device->Undi32BaseDevPath,
  356. &UNDI32Device->NicInfo
  357. );
  358. if (Status != 0) {
  359. goto UndiErrorDeletePxe;
  360. }
  361. UNDI32Device->Signature = UNDI_DEV_SIGNATURE;
  362. UNDI32Device->NIIProtocol_31.Revision = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION_31;
  363. UNDI32Device->NIIProtocol_31.Type = EfiNetworkInterfaceUndi;
  364. UNDI32Device->NIIProtocol_31.MajorVer = PXE_ROMID_MAJORVER;
  365. UNDI32Device->NIIProtocol_31.MinorVer = PXE_ROMID_MINORVER_31;
  366. UNDI32Device->NIIProtocol_31.ImageSize = 0;
  367. UNDI32Device->NIIProtocol_31.ImageAddr = 0;
  368. UNDI32Device->NIIProtocol_31.Ipv6Supported = TRUE;
  369. UNDI32Device->NIIProtocol_31.StringId[0] = 'U';
  370. UNDI32Device->NIIProtocol_31.StringId[1] = 'N';
  371. UNDI32Device->NIIProtocol_31.StringId[2] = 'D';
  372. UNDI32Device->NIIProtocol_31.StringId[3] = 'I';
  373. UNDI32Device->DeviceHandle = NULL;
  374. UNDI32Device->Aip.GetInformation = UndiAipGetInfo;
  375. UNDI32Device->Aip.SetInformation = UndiAipSetInfo;
  376. UNDI32Device->Aip.GetSupportedTypes = UndiAipGetSupportedTypes;
  377. //
  378. // install both the 3.0 and 3.1 NII protocols.
  379. //
  380. Status = gBS->InstallMultipleProtocolInterfaces (
  381. &UNDI32Device->DeviceHandle,
  382. &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
  383. &UNDI32Device->NIIProtocol_31,
  384. &gEfiDevicePathProtocolGuid,
  385. UNDI32Device->Undi32DevPath,
  386. &gEfiAdapterInformationProtocolGuid,
  387. &UNDI32Device->Aip,
  388. NULL
  389. );
  390. if (EFI_ERROR (Status)) {
  391. goto UndiErrorDeleteDevicePath;
  392. }
  393. //
  394. // if the table exists, free it and alloc again, or alloc it directly
  395. //
  396. if (UndiDataPointer != NULL) {
  397. Status = gBS->FreePool(UndiDataPointer);
  398. }
  399. if (EFI_ERROR (Status)) {
  400. goto UndiErrorDeleteDevicePath;
  401. }
  402. Len = ((pxe_31->IFcnt|pxe_31->IFcntExt << 8)* sizeof (UndiDataPointer->NII_entry)) + sizeof (UndiDataPointer);
  403. Status = gBS->AllocatePool (EfiRuntimeServicesData, Len, (VOID **) &UndiDataPointer);
  404. if (EFI_ERROR (Status)) {
  405. goto UndiErrorAllocDataPointer;
  406. }
  407. //
  408. // Open For Child Device
  409. //
  410. Status = gBS->OpenProtocol (
  411. Controller,
  412. &gEfiPciIoProtocolGuid,
  413. (VOID **) &PciIoFncs,
  414. This->DriverBindingHandle,
  415. UNDI32Device->DeviceHandle,
  416. EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
  417. );
  418. return EFI_SUCCESS;
  419. UndiErrorAllocDataPointer:
  420. gBS->UninstallMultipleProtocolInterfaces (
  421. &UNDI32Device->DeviceHandle,
  422. &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
  423. &UNDI32Device->NIIProtocol_31,
  424. &gEfiDevicePathProtocolGuid,
  425. UNDI32Device->Undi32DevPath,
  426. &gEfiAdapterInformationProtocolGuid,
  427. &UNDI32Device->Aip,
  428. NULL
  429. );
  430. UndiErrorDeleteDevicePath:
  431. UNDI32DeviceList[UNDI32Device->NIIProtocol_31.IfNum] = NULL;
  432. gBS->FreePool (UNDI32Device->Undi32DevPath);
  433. UndiErrorDeletePxe:
  434. PxeUpdate (NULL, pxe_31);
  435. if (TmpPxePointer != NULL) {
  436. gBS->FreePool (TmpPxePointer);
  437. }
  438. UndiErrorDeleteDevice:
  439. if (PciAttributesSaved) {
  440. //
  441. // Restore original PCI attributes
  442. //
  443. PciIoFncs->Attributes (
  444. PciIoFncs,
  445. EfiPciIoAttributeOperationSet,
  446. UNDI32Device->NicInfo.OriginalPciAttributes,
  447. NULL
  448. );
  449. }
  450. gBS->FreePool (UNDI32Device);
  451. UndiError:
  452. gBS->CloseProtocol (
  453. Controller,
  454. &gEfiDevicePathProtocolGuid,
  455. This->DriverBindingHandle,
  456. Controller
  457. );
  458. gBS->CloseProtocol (
  459. Controller,
  460. &gEfiPciIoProtocolGuid,
  461. This->DriverBindingHandle,
  462. Controller
  463. );
  464. return Status;
  465. }
  466. /**
  467. Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and
  468. closing the DevicePath and PciIo protocols on Controller.
  469. @param This Protocol instance pointer.
  470. @param Controller Handle of device to stop driver on.
  471. @param NumberOfChildren How many children need to be stopped.
  472. @param ChildHandleBuffer Not used.
  473. @retval EFI_SUCCESS This driver is removed Controller.
  474. @retval other This driver was not removed from this device.
  475. **/
  476. // TODO: EFI_DEVICE_ERROR - add return value to function comment
  477. EFI_STATUS
  478. EFIAPI
  479. UndiDriverStop (
  480. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  481. IN EFI_HANDLE Controller,
  482. IN UINTN NumberOfChildren,
  483. IN EFI_HANDLE *ChildHandleBuffer
  484. )
  485. {
  486. EFI_STATUS Status;
  487. BOOLEAN AllChildrenStopped;
  488. UINTN Index;
  489. UNDI32_DEV *UNDI32Device;
  490. EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NIIProtocol;
  491. //
  492. // Complete all outstanding transactions to Controller.
  493. // Don't allow any new transaction to Controller to be started.
  494. //
  495. if (NumberOfChildren == 0) {
  496. //
  497. // Close the bus driver
  498. //
  499. Status = gBS->CloseProtocol (
  500. Controller,
  501. &gEfiDevicePathProtocolGuid,
  502. This->DriverBindingHandle,
  503. Controller
  504. );
  505. Status = gBS->CloseProtocol (
  506. Controller,
  507. &gEfiPciIoProtocolGuid,
  508. This->DriverBindingHandle,
  509. Controller
  510. );
  511. return Status;
  512. }
  513. AllChildrenStopped = TRUE;
  514. for (Index = 0; Index < NumberOfChildren; Index++) {
  515. Status = gBS->OpenProtocol (
  516. ChildHandleBuffer[Index],
  517. &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
  518. (VOID **) &NIIProtocol,
  519. This->DriverBindingHandle,
  520. Controller,
  521. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  522. );
  523. if (!EFI_ERROR (Status)) {
  524. UNDI32Device = UNDI_DEV_FROM_THIS (NIIProtocol);
  525. Status = gBS->CloseProtocol (
  526. Controller,
  527. &gEfiPciIoProtocolGuid,
  528. This->DriverBindingHandle,
  529. ChildHandleBuffer[Index]
  530. );
  531. if (!EFI_ERROR (Status)) {
  532. Status = gBS->UninstallMultipleProtocolInterfaces (
  533. ChildHandleBuffer[Index],
  534. &gEfiDevicePathProtocolGuid,
  535. UNDI32Device->Undi32DevPath,
  536. &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
  537. &UNDI32Device->NIIProtocol_31,
  538. NULL
  539. );
  540. if (!EFI_ERROR (Status)) {
  541. //
  542. // Restore original PCI attributes
  543. //
  544. Status = UNDI32Device->NicInfo.Io_Function->Attributes (
  545. UNDI32Device->NicInfo.Io_Function,
  546. EfiPciIoAttributeOperationSet,
  547. UNDI32Device->NicInfo.OriginalPciAttributes,
  548. NULL
  549. );
  550. ASSERT_EFI_ERROR (Status);
  551. gBS->FreePool (UNDI32Device->Undi32DevPath);
  552. gBS->FreePool (UNDI32Device);
  553. }
  554. }
  555. }
  556. if (EFI_ERROR (Status)) {
  557. AllChildrenStopped = FALSE;
  558. }
  559. }
  560. if (!AllChildrenStopped) {
  561. return EFI_DEVICE_ERROR;
  562. }
  563. return EFI_SUCCESS;
  564. }
  565. /**
  566. Use the EFI boot services to produce a pause. This is also the routine which
  567. gets replaced during RunTime by the O/S in the NIC_DATA_INSTANCE so it can
  568. do it's own pause.
  569. @param UnqId Runtime O/S routine might use this, this temp
  570. routine does not use it
  571. @param MicroSeconds Determines the length of pause.
  572. @return none
  573. **/
  574. VOID
  575. TmpDelay (
  576. IN UINT64 UnqId,
  577. IN UINTN MicroSeconds
  578. )
  579. {
  580. gBS->Stall ((UINT32) MicroSeconds);
  581. }
  582. /**
  583. Use the PCI IO abstraction to issue memory or I/O reads and writes. This is also the routine which
  584. gets replaced during RunTime by the O/S in the NIC_DATA_INSTANCE so it can do it's own I/O abstractions.
  585. @param UnqId Runtime O/S routine may use this field, this temp
  586. routine does not.
  587. @param ReadWrite Determine if it is an I/O or Memory Read/Write
  588. Operation.
  589. @param Len Determines the width of the data operation.
  590. @param Port What port to Read/Write from.
  591. @param BuffAddr Address to read to or write from.
  592. @return none
  593. **/
  594. VOID
  595. TmpMemIo (
  596. IN UINT64 UnqId,
  597. IN UINT8 ReadWrite,
  598. IN UINT8 Len,
  599. IN UINT64 Port,
  600. IN UINT64 BuffAddr
  601. )
  602. {
  603. EFI_PCI_IO_PROTOCOL_WIDTH Width;
  604. NIC_DATA_INSTANCE *AdapterInfo;
  605. Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 0;
  606. AdapterInfo = (NIC_DATA_INSTANCE *) (UINTN) UnqId;
  607. switch (Len) {
  608. case 2:
  609. Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 1;
  610. break;
  611. case 4:
  612. Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 2;
  613. break;
  614. case 8:
  615. Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 3;
  616. break;
  617. }
  618. switch (ReadWrite) {
  619. case PXE_IO_READ:
  620. AdapterInfo->Io_Function->Io.Read (
  621. AdapterInfo->Io_Function,
  622. Width,
  623. 1,
  624. Port,
  625. 1,
  626. (VOID *) (UINTN) (BuffAddr)
  627. );
  628. break;
  629. case PXE_IO_WRITE:
  630. AdapterInfo->Io_Function->Io.Write (
  631. AdapterInfo->Io_Function,
  632. Width,
  633. 1,
  634. Port,
  635. 1,
  636. (VOID *) (UINTN) (BuffAddr)
  637. );
  638. break;
  639. case PXE_MEM_READ:
  640. AdapterInfo->Io_Function->Mem.Read (
  641. AdapterInfo->Io_Function,
  642. Width,
  643. 0,
  644. Port,
  645. 1,
  646. (VOID *) (UINTN) (BuffAddr)
  647. );
  648. break;
  649. case PXE_MEM_WRITE:
  650. AdapterInfo->Io_Function->Mem.Write (
  651. AdapterInfo->Io_Function,
  652. Width,
  653. 0,
  654. Port,
  655. 1,
  656. (VOID *) (UINTN) (BuffAddr)
  657. );
  658. break;
  659. }
  660. return ;
  661. }
  662. /**
  663. Using the NIC data structure information, read the EEPROM to get the MAC address and then allocate space
  664. for a new devicepath (**DevPtr) which will contain the original device path the NIC was found on (*BaseDevPtr)
  665. and an added MAC node.
  666. @param DevPtr Pointer which will point to the newly created device
  667. path with the MAC node attached.
  668. @param BaseDevPtr Pointer to the device path which the UNDI device
  669. driver is latching on to.
  670. @param AdapterInfo Pointer to the NIC data structure information which
  671. the UNDI driver is layering on..
  672. @retval EFI_SUCCESS A MAC address was successfully appended to the Base
  673. Device Path.
  674. @retval other Not enough resources available to create new Device
  675. Path node.
  676. **/
  677. EFI_STATUS
  678. AppendMac2DevPath (
  679. IN OUT EFI_DEVICE_PATH_PROTOCOL **DevPtr,
  680. IN EFI_DEVICE_PATH_PROTOCOL *BaseDevPtr,
  681. IN NIC_DATA_INSTANCE *AdapterInfo
  682. )
  683. {
  684. EFI_MAC_ADDRESS MACAddress;
  685. PCI_CONFIG_HEADER *CfgHdr;
  686. INT32 Val;
  687. INT32 Index;
  688. INT32 Index2;
  689. UINT8 AddrLen;
  690. MAC_ADDR_DEVICE_PATH MacAddrNode;
  691. EFI_DEVICE_PATH_PROTOCOL *EndNode;
  692. UINT8 *DevicePtr;
  693. UINT16 TotalPathLen;
  694. UINT16 BasePathLen;
  695. EFI_STATUS Status;
  696. //
  697. // set the environment ready (similar to UNDI_Start call) so that we can
  698. // execute the other UNDI_ calls to get the mac address
  699. // we are using undi 3.1 style
  700. //
  701. AdapterInfo->Delay = TmpDelay;
  702. AdapterInfo->Virt2Phys = (VOID *) 0;
  703. AdapterInfo->Block = (VOID *) 0;
  704. AdapterInfo->Map_Mem = (VOID *) 0;
  705. AdapterInfo->UnMap_Mem = (VOID *) 0;
  706. AdapterInfo->Sync_Mem = (VOID *) 0;
  707. AdapterInfo->Mem_Io = TmpMemIo;
  708. //
  709. // these tmp call-backs follow 3.1 undi style
  710. // i.e. they have the unique_id parameter.
  711. //
  712. AdapterInfo->VersionFlag = 0x31;
  713. AdapterInfo->Unique_ID = (UINT64) (UINTN) AdapterInfo;
  714. //
  715. // undi init portion
  716. //
  717. CfgHdr = (PCI_CONFIG_HEADER *) &(AdapterInfo->Config[0]);
  718. AdapterInfo->ioaddr = 0;
  719. AdapterInfo->RevID = CfgHdr->RevID;
  720. AddrLen = E100bGetEepromAddrLen (AdapterInfo);
  721. for (Index = 0, Index2 = 0; Index < 3; Index++) {
  722. Val = E100bReadEeprom (AdapterInfo, Index, AddrLen);
  723. MACAddress.Addr[Index2++] = (UINT8) Val;
  724. MACAddress.Addr[Index2++] = (UINT8) (Val >> 8);
  725. }
  726. SetMem (MACAddress.Addr + Index2, sizeof (EFI_MAC_ADDRESS) - Index2, 0);
  727. //for (; Index2 < sizeof (EFI_MAC_ADDRESS); Index2++) {
  728. // MACAddress.Addr[Index2] = 0;
  729. //}
  730. //
  731. // stop undi
  732. //
  733. AdapterInfo->Delay = (VOID *) 0;
  734. AdapterInfo->Mem_Io = (VOID *) 0;
  735. //
  736. // fill the mac address node first
  737. //
  738. ZeroMem ((CHAR8 *) &MacAddrNode, sizeof MacAddrNode);
  739. CopyMem (
  740. (CHAR8 *) &MacAddrNode.MacAddress,
  741. (CHAR8 *) &MACAddress,
  742. sizeof (EFI_MAC_ADDRESS)
  743. );
  744. MacAddrNode.Header.Type = MESSAGING_DEVICE_PATH;
  745. MacAddrNode.Header.SubType = MSG_MAC_ADDR_DP;
  746. MacAddrNode.Header.Length[0] = (UINT8) sizeof (MacAddrNode);
  747. MacAddrNode.Header.Length[1] = 0;
  748. //
  749. // find the size of the base dev path.
  750. //
  751. EndNode = BaseDevPtr;
  752. while (!IsDevicePathEnd (EndNode)) {
  753. EndNode = NextDevicePathNode (EndNode);
  754. }
  755. BasePathLen = (UINT16) ((UINTN) (EndNode) - (UINTN) (BaseDevPtr));
  756. //
  757. // create space for full dev path
  758. //
  759. TotalPathLen = (UINT16) (BasePathLen + sizeof (MacAddrNode) + sizeof (EFI_DEVICE_PATH_PROTOCOL));
  760. Status = gBS->AllocatePool (
  761. EfiRuntimeServicesData,
  762. TotalPathLen,
  763. (VOID **) &DevicePtr
  764. );
  765. if (Status != EFI_SUCCESS) {
  766. return Status;
  767. }
  768. //
  769. // copy the base path, mac addr and end_dev_path nodes
  770. //
  771. *DevPtr = (EFI_DEVICE_PATH_PROTOCOL *) DevicePtr;
  772. CopyMem (DevicePtr, (CHAR8 *) BaseDevPtr, BasePathLen);
  773. DevicePtr += BasePathLen;
  774. CopyMem (DevicePtr, (CHAR8 *) &MacAddrNode, sizeof (MacAddrNode));
  775. DevicePtr += sizeof (MacAddrNode);
  776. CopyMem (DevicePtr, (CHAR8 *) EndNode, sizeof (EFI_DEVICE_PATH_PROTOCOL));
  777. return EFI_SUCCESS;
  778. }
  779. /**
  780. Install a GUID/Pointer pair into the system's configuration table.
  781. none
  782. @retval EFI_SUCCESS Install a GUID/Pointer pair into the system's
  783. configuration table.
  784. @retval other Did not successfully install the GUID/Pointer pair
  785. into the configuration table.
  786. **/
  787. // TODO: VOID - add argument and description to function comment
  788. EFI_STATUS
  789. InstallConfigTable (
  790. IN VOID
  791. )
  792. {
  793. EFI_STATUS Status;
  794. EFI_CONFIGURATION_TABLE *CfgPtr;
  795. UNDI_CONFIG_TABLE *TmpData;
  796. UINT16 Index;
  797. UNDI_CONFIG_TABLE *UndiData;
  798. if (pxe_31 == NULL) {
  799. return EFI_SUCCESS;
  800. }
  801. if(UndiDataPointer == NULL) {
  802. return EFI_SUCCESS;
  803. }
  804. UndiData = (UNDI_CONFIG_TABLE *)UndiDataPointer;
  805. UndiData->NumberOfInterfaces = (pxe_31->IFcnt | pxe_31->IFcntExt << 8);
  806. UndiData->nextlink = NULL;
  807. for (Index = 0; Index < (pxe_31->IFcnt | pxe_31->IFcntExt << 8); Index++) {
  808. UndiData->NII_entry[Index].NII_InterfacePointer = &UNDI32DeviceList[Index]->NIIProtocol_31;
  809. UndiData->NII_entry[Index].DevicePathPointer = UNDI32DeviceList[Index]->Undi32DevPath;
  810. }
  811. //
  812. // see if there is an entry in the config table already
  813. //
  814. CfgPtr = gST->ConfigurationTable;
  815. for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
  816. Status = CompareGuid (
  817. &CfgPtr->VendorGuid,
  818. &gEfiNetworkInterfaceIdentifierProtocolGuid_31
  819. );
  820. if (Status != EFI_SUCCESS) {
  821. break;
  822. }
  823. CfgPtr++;
  824. }
  825. if (Index < gST->NumberOfTableEntries) {
  826. TmpData = (UNDI_CONFIG_TABLE *) CfgPtr->VendorTable;
  827. //
  828. // go to the last link
  829. //
  830. while (TmpData->nextlink != NULL) {
  831. TmpData = TmpData->nextlink;
  832. }
  833. TmpData->nextlink = UndiData;
  834. //
  835. // 1st one in chain
  836. //
  837. UndiData = (UNDI_CONFIG_TABLE *) CfgPtr->VendorTable;
  838. }
  839. //
  840. // create an entry in the configuration table for our GUID
  841. //
  842. Status = gBS->InstallConfigurationTable (
  843. &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
  844. UndiData
  845. );
  846. return Status;
  847. }
  848. /**
  849. **/
  850. EFI_STATUS
  851. EFIAPI
  852. InitializeUndi(
  853. IN EFI_HANDLE ImageHandle,
  854. IN EFI_SYSTEM_TABLE *SystemTable
  855. )
  856. {
  857. EFI_EVENT Event;
  858. EFI_STATUS Status;
  859. Status = EfiLibInstallDriverBindingComponentName2 (
  860. ImageHandle,
  861. SystemTable,
  862. &gUndiDriverBinding,
  863. ImageHandle,
  864. &gUndiComponentName,
  865. &gUndiComponentName2
  866. );
  867. ASSERT_EFI_ERROR (Status);
  868. Status = gBS->CreateEventEx (
  869. EVT_NOTIFY_SIGNAL,
  870. TPL_NOTIFY,
  871. UndiNotifyReadyToBoot,
  872. NULL,
  873. &gEfiEventReadyToBootGuid,
  874. &Event
  875. );
  876. ASSERT_EFI_ERROR (Status);
  877. Status = gBS->CreateEventEx (
  878. EVT_NOTIFY_SIGNAL,
  879. TPL_NOTIFY,
  880. UndiNotifyVirtual,
  881. NULL,
  882. &gEfiEventVirtualAddressChangeGuid,
  883. &Event
  884. );
  885. ASSERT_EFI_ERROR (Status);
  886. return Status;
  887. }