Snp.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865
  1. /** @file
  2. Implementation of driver entry point and driver binding protocol.
  3. Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
  4. Copyright (c) Microsoft Corporation.<BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include "Snp.h"
  8. /**
  9. One notified function to stop UNDI device when gBS->ExitBootServices() called.
  10. @param Event Pointer to this event
  11. @param Context Event handler private data
  12. **/
  13. VOID
  14. EFIAPI
  15. SnpNotifyExitBootServices (
  16. EFI_EVENT Event,
  17. VOID *Context
  18. )
  19. {
  20. SNP_DRIVER *Snp;
  21. Snp = (SNP_DRIVER *)Context;
  22. //
  23. // Shutdown and stop UNDI driver
  24. //
  25. PxeShutdown (Snp);
  26. PxeStop (Snp);
  27. }
  28. /**
  29. Send command to UNDI. It does nothing currently.
  30. @param Cdb command to be sent to UNDI.
  31. @retval EFI_INVALID_PARAMETER The command is 0.
  32. @retval EFI_UNSUPPORTED Default return status because it's not
  33. supported currently.
  34. **/
  35. EFI_STATUS
  36. EFIAPI
  37. IssueHwUndiCommand (
  38. UINT64 Cdb
  39. )
  40. {
  41. DEBUG ((DEBUG_ERROR, "\nIssueHwUndiCommand() - This should not be called!"));
  42. if (Cdb == 0) {
  43. return EFI_INVALID_PARAMETER;
  44. }
  45. //
  46. // %%TBD - For now, nothing is done.
  47. //
  48. return EFI_UNSUPPORTED;
  49. }
  50. /**
  51. Compute 8-bit checksum of a buffer.
  52. @param Buffer Pointer to buffer.
  53. @param Length Length of buffer in bytes.
  54. @return 8-bit checksum of all bytes in buffer, or zero if ptr is NULL or len
  55. is zero.
  56. **/
  57. UINT8
  58. Calc8BitCksum (
  59. VOID *Buffer,
  60. UINTN Length
  61. )
  62. {
  63. UINT8 *Ptr;
  64. UINT8 Cksum;
  65. Ptr = Buffer;
  66. Cksum = 0;
  67. if ((Ptr == NULL) || (Length == 0)) {
  68. return 0;
  69. }
  70. while (Length-- != 0) {
  71. Cksum = (UINT8)(Cksum + *Ptr++);
  72. }
  73. return Cksum;
  74. }
  75. /**
  76. Test to see if this driver supports ControllerHandle. This service
  77. is called by the EFI boot service ConnectController(). In
  78. order to make drivers as small as possible, there are a few calling
  79. restrictions for this service. ConnectController() must
  80. follow these calling restrictions. If any other agent wishes to call
  81. Supported() it must also follow these calling restrictions.
  82. @param This Protocol instance pointer.
  83. @param ControllerHandle Handle of device to test.
  84. @param RemainingDevicePath Optional parameter use to pick a specific child
  85. device to start.
  86. @retval EFI_SUCCESS This driver supports this device.
  87. @retval EFI_ALREADY_STARTED This driver is already running on this device.
  88. @retval other This driver does not support this device.
  89. **/
  90. EFI_STATUS
  91. EFIAPI
  92. SimpleNetworkDriverSupported (
  93. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  94. IN EFI_HANDLE Controller,
  95. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
  96. )
  97. {
  98. EFI_STATUS Status;
  99. EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NiiProtocol;
  100. PXE_UNDI *Pxe;
  101. Status = gBS->OpenProtocol (
  102. Controller,
  103. &gEfiDevicePathProtocolGuid,
  104. NULL,
  105. This->DriverBindingHandle,
  106. Controller,
  107. EFI_OPEN_PROTOCOL_TEST_PROTOCOL
  108. );
  109. if (EFI_ERROR (Status)) {
  110. return Status;
  111. }
  112. Status = gBS->OpenProtocol (
  113. Controller,
  114. &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
  115. (VOID **)&NiiProtocol,
  116. This->DriverBindingHandle,
  117. Controller,
  118. EFI_OPEN_PROTOCOL_BY_DRIVER
  119. );
  120. if (EFI_ERROR (Status)) {
  121. if (Status == EFI_ALREADY_STARTED) {
  122. DEBUG ((DEBUG_INFO, "Support(): Already Started. on handle %p\n", Controller));
  123. }
  124. return Status;
  125. }
  126. DEBUG ((DEBUG_INFO, "Support(): UNDI3.1 found on handle %p\n", Controller));
  127. //
  128. // check the version, we don't want to connect to the undi16
  129. //
  130. if (NiiProtocol->Type != EfiNetworkInterfaceUndi) {
  131. Status = EFI_UNSUPPORTED;
  132. goto Done;
  133. }
  134. //
  135. // Check to see if !PXE structure is valid. Paragraph alignment of !PXE structure is required.
  136. //
  137. if ((NiiProtocol->Id & 0x0F) != 0) {
  138. DEBUG ((DEBUG_NET, "\n!PXE structure is not paragraph aligned.\n"));
  139. Status = EFI_UNSUPPORTED;
  140. goto Done;
  141. }
  142. Pxe = (PXE_UNDI *)(UINTN)(NiiProtocol->Id);
  143. //
  144. // Verify !PXE revisions.
  145. //
  146. if (Pxe->hw.Signature != PXE_ROMID_SIGNATURE) {
  147. DEBUG ((DEBUG_NET, "\n!PXE signature is not valid.\n"));
  148. Status = EFI_UNSUPPORTED;
  149. goto Done;
  150. }
  151. if (Pxe->hw.Rev < PXE_ROMID_REV) {
  152. DEBUG ((DEBUG_NET, "\n!PXE.Rev is not supported.\n"));
  153. Status = EFI_UNSUPPORTED;
  154. goto Done;
  155. }
  156. if (Pxe->hw.MajorVer < PXE_ROMID_MAJORVER) {
  157. DEBUG ((DEBUG_NET, "\n!PXE.MajorVer is not supported.\n"));
  158. Status = EFI_UNSUPPORTED;
  159. goto Done;
  160. } else if ((Pxe->hw.MajorVer == PXE_ROMID_MAJORVER) && (Pxe->hw.MinorVer < PXE_ROMID_MINORVER)) {
  161. DEBUG ((DEBUG_NET, "\n!PXE.MinorVer is not supported."));
  162. Status = EFI_UNSUPPORTED;
  163. goto Done;
  164. }
  165. //
  166. // Do S/W UNDI specific checks.
  167. //
  168. if ((Pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) == 0) {
  169. if (Pxe->sw.EntryPoint < Pxe->sw.Len) {
  170. DEBUG ((DEBUG_NET, "\n!PXE S/W entry point is not valid."));
  171. Status = EFI_UNSUPPORTED;
  172. goto Done;
  173. }
  174. if (Pxe->sw.BusCnt == 0) {
  175. DEBUG ((DEBUG_NET, "\n!PXE.BusCnt is zero."));
  176. Status = EFI_UNSUPPORTED;
  177. goto Done;
  178. }
  179. }
  180. Status = EFI_SUCCESS;
  181. DEBUG ((DEBUG_INFO, "Support(): supported on %p\n", Controller));
  182. Done:
  183. gBS->CloseProtocol (
  184. Controller,
  185. &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
  186. This->DriverBindingHandle,
  187. Controller
  188. );
  189. return Status;
  190. }
  191. /**
  192. Start this driver on ControllerHandle. This service is called by the
  193. EFI boot service ConnectController(). In order to make
  194. drivers as small as possible, there are a few calling restrictions for
  195. this service. ConnectController() must follow these
  196. calling restrictions. If any other agent wishes to call Start() it
  197. must also follow these calling restrictions.
  198. @param This Protocol instance pointer.
  199. @param ControllerHandle Handle of device to bind driver to.
  200. @param RemainingDevicePath Optional parameter use to pick a specific child
  201. device to start.
  202. @retval EFI_SUCCESS This driver is added to ControllerHandle
  203. @retval EFI_DEVICE_ERROR This driver could not be started due to a device error
  204. @retval other This driver does not support this device
  205. **/
  206. EFI_STATUS
  207. EFIAPI
  208. SimpleNetworkDriverStart (
  209. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  210. IN EFI_HANDLE Controller,
  211. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
  212. )
  213. {
  214. EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *Nii;
  215. EFI_DEVICE_PATH_PROTOCOL *NiiDevicePath;
  216. EFI_STATUS Status;
  217. PXE_UNDI *Pxe;
  218. SNP_DRIVER *Snp;
  219. VOID *Address;
  220. EFI_HANDLE Handle;
  221. UINT8 BarIndex;
  222. PXE_STATFLAGS InitStatFlags;
  223. EFI_PCI_IO_PROTOCOL *PciIo;
  224. EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc;
  225. BOOLEAN FoundIoBar;
  226. BOOLEAN FoundMemoryBar;
  227. DEBUG ((DEBUG_NET, "\nSnpNotifyNetworkInterfaceIdentifier() "));
  228. Status = gBS->OpenProtocol (
  229. Controller,
  230. &gEfiDevicePathProtocolGuid,
  231. (VOID **)&NiiDevicePath,
  232. This->DriverBindingHandle,
  233. Controller,
  234. EFI_OPEN_PROTOCOL_BY_DRIVER
  235. );
  236. if (EFI_ERROR (Status)) {
  237. return Status;
  238. }
  239. Status = gBS->LocateDevicePath (
  240. &gEfiPciIoProtocolGuid,
  241. &NiiDevicePath,
  242. &Handle
  243. );
  244. if (EFI_ERROR (Status)) {
  245. return Status;
  246. }
  247. Status = gBS->OpenProtocol (
  248. Handle,
  249. &gEfiPciIoProtocolGuid,
  250. (VOID **)&PciIo,
  251. This->DriverBindingHandle,
  252. Controller,
  253. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  254. );
  255. if (EFI_ERROR (Status)) {
  256. return Status;
  257. }
  258. //
  259. // Get the NII interface.
  260. //
  261. Status = gBS->OpenProtocol (
  262. Controller,
  263. &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
  264. (VOID **)&Nii,
  265. This->DriverBindingHandle,
  266. Controller,
  267. EFI_OPEN_PROTOCOL_BY_DRIVER
  268. );
  269. if (EFI_ERROR (Status)) {
  270. gBS->CloseProtocol (
  271. Controller,
  272. &gEfiDevicePathProtocolGuid,
  273. This->DriverBindingHandle,
  274. Controller
  275. );
  276. return Status;
  277. }
  278. DEBUG ((DEBUG_INFO, "Start(): UNDI3.1 found\n"));
  279. Pxe = (PXE_UNDI *)(UINTN)(Nii->Id);
  280. if (Calc8BitCksum (Pxe, Pxe->hw.Len) != 0) {
  281. DEBUG ((DEBUG_NET, "\n!PXE checksum is not correct.\n"));
  282. goto NiiError;
  283. }
  284. if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {
  285. //
  286. // We can get any packets.
  287. //
  288. } else if ((Pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {
  289. //
  290. // We need to be able to get broadcast packets for DHCP.
  291. // If we do not have promiscuous support, we must at least have
  292. // broadcast support or we cannot do DHCP!
  293. //
  294. } else {
  295. DEBUG ((DEBUG_NET, "\nUNDI does not have promiscuous or broadcast support."));
  296. goto NiiError;
  297. }
  298. //
  299. // OK, we like this UNDI, and we know snp is not already there on this handle
  300. // Allocate and initialize a new simple network protocol structure.
  301. //
  302. Status = PciIo->AllocateBuffer (
  303. PciIo,
  304. AllocateAnyPages,
  305. EfiBootServicesData,
  306. SNP_MEM_PAGES (sizeof (SNP_DRIVER)),
  307. &Address,
  308. 0
  309. );
  310. if (Status != EFI_SUCCESS) {
  311. DEBUG ((DEBUG_NET, "\nCould not allocate SNP_DRIVER structure.\n"));
  312. goto NiiError;
  313. }
  314. Snp = (SNP_DRIVER *)(UINTN)Address;
  315. ZeroMem (Snp, sizeof (SNP_DRIVER));
  316. Snp->PciIo = PciIo;
  317. Snp->Signature = SNP_DRIVER_SIGNATURE;
  318. EfiInitializeLock (&Snp->Lock, TPL_NOTIFY);
  319. Snp->Snp.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
  320. Snp->Snp.Start = SnpUndi32Start;
  321. Snp->Snp.Stop = SnpUndi32Stop;
  322. Snp->Snp.Initialize = SnpUndi32Initialize;
  323. Snp->Snp.Reset = SnpUndi32Reset;
  324. Snp->Snp.Shutdown = SnpUndi32Shutdown;
  325. Snp->Snp.ReceiveFilters = SnpUndi32ReceiveFilters;
  326. Snp->Snp.StationAddress = SnpUndi32StationAddress;
  327. Snp->Snp.Statistics = SnpUndi32Statistics;
  328. Snp->Snp.MCastIpToMac = SnpUndi32McastIpToMac;
  329. Snp->Snp.NvData = SnpUndi32NvData;
  330. Snp->Snp.GetStatus = SnpUndi32GetStatus;
  331. Snp->Snp.Transmit = SnpUndi32Transmit;
  332. Snp->Snp.Receive = SnpUndi32Receive;
  333. Snp->Snp.WaitForPacket = NULL;
  334. Snp->Snp.Mode = &Snp->Mode;
  335. Snp->TxRxBufferSize = 0;
  336. Snp->TxRxBuffer = NULL;
  337. Snp->RecycledTxBuf = AllocatePool (sizeof (UINT64) * SNP_TX_BUFFER_INCREASEMENT);
  338. if (Snp->RecycledTxBuf == NULL) {
  339. Status = EFI_OUT_OF_RESOURCES;
  340. goto Error_DeleteSNP;
  341. }
  342. Snp->MaxRecycledTxBuf = SNP_TX_BUFFER_INCREASEMENT;
  343. Snp->RecycledTxBufCount = 0;
  344. if (Nii->Revision >= EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION) {
  345. Snp->IfNum = Nii->IfNum;
  346. } else {
  347. Snp->IfNum = (UINT8)(Nii->IfNum & 0xFF);
  348. }
  349. if ((Pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) != 0) {
  350. Snp->IsSwUndi = FALSE;
  351. Snp->IssueUndi32Command = &IssueHwUndiCommand;
  352. } else {
  353. Snp->IsSwUndi = TRUE;
  354. if ((Pxe->sw.Implementation & PXE_ROMID_IMP_SW_VIRT_ADDR) != 0) {
  355. Snp->IssueUndi32Command = (ISSUE_UNDI32_COMMAND)(UINTN)Pxe->sw.EntryPoint;
  356. } else {
  357. Snp->IssueUndi32Command = (ISSUE_UNDI32_COMMAND)(UINTN)((UINT8)(UINTN)Pxe + Pxe->sw.EntryPoint);
  358. }
  359. }
  360. //
  361. // Allocate a global CPB and DB buffer for this UNDI interface.
  362. // we do this because:
  363. //
  364. // -UNDI 3.0 wants all the addresses passed to it (even the cpb and db) to be
  365. // within 2GB limit, create them here and map them so that when undi calls
  366. // v2p callback to check if the physical address is < 2gb, we will pass.
  367. //
  368. // -This is not a requirement for 3.1 or later UNDIs but the code looks
  369. // simpler if we use the same cpb, db variables for both old and new undi
  370. // interfaces from all the SNP interface calls (we don't map the buffers
  371. // for the newer undi interfaces though)
  372. // .
  373. // -it is OK to allocate one global set of CPB, DB pair for each UNDI
  374. // interface as EFI does not multi-task and so SNP will not be re-entered!
  375. //
  376. Status = PciIo->AllocateBuffer (
  377. PciIo,
  378. AllocateAnyPages,
  379. EfiBootServicesData,
  380. SNP_MEM_PAGES (4096),
  381. &Address,
  382. 0
  383. );
  384. if (Status != EFI_SUCCESS) {
  385. DEBUG ((DEBUG_NET, "\nCould not allocate CPB and DB structures.\n"));
  386. goto Error_DeleteSNP;
  387. }
  388. Snp->Cpb = (VOID *)(UINTN)Address;
  389. Snp->Db = (VOID *)((UINTN)Address + 2048);
  390. //
  391. // Find the correct BAR to do IO.
  392. //
  393. // Enumerate through the PCI BARs for the device to determine which one is
  394. // the IO BAR. Save the index of the BAR into the adapter info structure.
  395. // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped
  396. //
  397. Snp->MemoryBarIndex = PCI_MAX_BAR;
  398. Snp->IoBarIndex = PCI_MAX_BAR;
  399. FoundMemoryBar = FALSE;
  400. FoundIoBar = FALSE;
  401. for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex++) {
  402. Status = PciIo->GetBarAttributes (
  403. PciIo,
  404. BarIndex,
  405. NULL,
  406. (VOID **)&BarDesc
  407. );
  408. if (Status == EFI_UNSUPPORTED) {
  409. continue;
  410. } else if (EFI_ERROR (Status)) {
  411. goto Error_DeleteSNP;
  412. }
  413. if ((!FoundMemoryBar) && (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM)) {
  414. Snp->MemoryBarIndex = BarIndex;
  415. FoundMemoryBar = TRUE;
  416. } else if ((!FoundIoBar) && (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_IO)) {
  417. Snp->IoBarIndex = BarIndex;
  418. FoundIoBar = TRUE;
  419. }
  420. FreePool (BarDesc);
  421. if (FoundMemoryBar && FoundIoBar) {
  422. break;
  423. }
  424. }
  425. Status = PxeStart (Snp);
  426. if (Status != EFI_SUCCESS) {
  427. goto Error_DeleteSNP;
  428. }
  429. Snp->Cdb.OpCode = PXE_OPCODE_GET_INIT_INFO;
  430. Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
  431. Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
  432. Snp->Cdb.CPBaddr = PXE_DBADDR_NOT_USED;
  433. Snp->Cdb.DBsize = (UINT16)sizeof (Snp->InitInfo);
  434. Snp->Cdb.DBaddr = (UINT64)(UINTN)(&Snp->InitInfo);
  435. Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;
  436. Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
  437. Snp->Cdb.IFnum = Snp->IfNum;
  438. Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
  439. DEBUG ((DEBUG_NET, "\nSnp->undi.get_init_info() "));
  440. (*Snp->IssueUndi32Command)((UINT64)(UINTN)&Snp->Cdb);
  441. //
  442. // Save the INIT Stat Code...
  443. //
  444. InitStatFlags = Snp->Cdb.StatFlags;
  445. if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {
  446. DEBUG ((DEBUG_NET, "\nSnp->undi.init_info() %xh:%xh\n", Snp->Cdb.StatFlags, Snp->Cdb.StatCode));
  447. PxeStop (Snp);
  448. goto Error_DeleteSNP;
  449. }
  450. //
  451. // Initialize simple network protocol mode structure
  452. //
  453. Snp->Mode.State = EfiSimpleNetworkStopped;
  454. Snp->Mode.HwAddressSize = Snp->InitInfo.HWaddrLen;
  455. Snp->Mode.MediaHeaderSize = Snp->InitInfo.MediaHeaderLen;
  456. Snp->Mode.MaxPacketSize = Snp->InitInfo.FrameDataLen;
  457. Snp->Mode.NvRamAccessSize = Snp->InitInfo.NvWidth;
  458. Snp->Mode.NvRamSize = Snp->InitInfo.NvCount * Snp->Mode.NvRamAccessSize;
  459. Snp->Mode.IfType = Snp->InitInfo.IFtype;
  460. Snp->Mode.MaxMCastFilterCount = Snp->InitInfo.MCastFilterCnt;
  461. Snp->Mode.MCastFilterCount = 0;
  462. switch (InitStatFlags & PXE_STATFLAGS_CABLE_DETECT_MASK) {
  463. case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED:
  464. Snp->CableDetectSupported = TRUE;
  465. break;
  466. case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED:
  467. default:
  468. Snp->CableDetectSupported = FALSE;
  469. }
  470. switch (InitStatFlags & PXE_STATFLAGS_GET_STATUS_NO_MEDIA_MASK) {
  471. case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED:
  472. Snp->MediaStatusSupported = TRUE;
  473. break;
  474. case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_NOT_SUPPORTED:
  475. default:
  476. Snp->MediaStatusSupported = FALSE;
  477. }
  478. if (Snp->CableDetectSupported || Snp->MediaStatusSupported) {
  479. Snp->Mode.MediaPresentSupported = TRUE;
  480. }
  481. if ((Pxe->hw.Implementation & PXE_ROMID_IMP_STATION_ADDR_SETTABLE) != 0) {
  482. Snp->Mode.MacAddressChangeable = TRUE;
  483. } else {
  484. Snp->Mode.MacAddressChangeable = FALSE;
  485. }
  486. if ((Pxe->hw.Implementation & PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED) != 0) {
  487. Snp->Mode.MultipleTxSupported = TRUE;
  488. } else {
  489. Snp->Mode.MultipleTxSupported = FALSE;
  490. }
  491. Snp->Mode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
  492. if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) {
  493. Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
  494. }
  495. if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {
  496. Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
  497. }
  498. if ((Pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {
  499. Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
  500. }
  501. if ((Pxe->hw.Implementation & PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED) != 0) {
  502. Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;
  503. }
  504. if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) {
  505. Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
  506. }
  507. Snp->Mode.ReceiveFilterSetting = 0;
  508. //
  509. // need to get the station address to save in the mode structure. we need to
  510. // initialize the UNDI first for this.
  511. //
  512. Snp->TxRxBufferSize = Snp->InitInfo.MemoryRequired;
  513. Status = PxeInit (Snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE);
  514. if (EFI_ERROR (Status)) {
  515. PxeStop (Snp);
  516. goto Error_DeleteSNP;
  517. }
  518. Status = PxeGetStnAddr (Snp);
  519. if (Status != EFI_SUCCESS) {
  520. DEBUG ((DEBUG_ERROR, "\nSnp->undi.get_station_addr() failed.\n"));
  521. PxeShutdown (Snp);
  522. PxeStop (Snp);
  523. goto Error_DeleteSNP;
  524. }
  525. Snp->Mode.MediaPresent = FALSE;
  526. //
  527. // We should not leave UNDI started and initialized here. this DriverStart()
  528. // routine must only find and attach the SNP interface to UNDI layer that it
  529. // finds on the given handle!
  530. // The UNDI layer will be started when upper layers call Snp->start.
  531. // How ever, this DriverStart() must fill up the snp mode structure which
  532. // contains the MAC address of the NIC. For this reason we started and
  533. // initialized UNDI here, now we are done, do a shutdown and stop of the
  534. // UNDI interface!
  535. //
  536. PxeShutdown (Snp);
  537. PxeStop (Snp);
  538. if (PcdGetBool (PcdSnpCreateExitBootServicesEvent)) {
  539. //
  540. // Create EXIT_BOOT_SERIVES Event
  541. //
  542. Status = gBS->CreateEventEx (
  543. EVT_NOTIFY_SIGNAL,
  544. TPL_CALLBACK,
  545. SnpNotifyExitBootServices,
  546. Snp,
  547. &gEfiEventExitBootServicesGuid,
  548. &Snp->ExitBootServicesEvent
  549. );
  550. if (EFI_ERROR (Status)) {
  551. goto Error_DeleteSNP;
  552. }
  553. }
  554. //
  555. // add SNP to the undi handle
  556. //
  557. Status = gBS->InstallProtocolInterface (
  558. &Controller,
  559. &gEfiSimpleNetworkProtocolGuid,
  560. EFI_NATIVE_INTERFACE,
  561. &(Snp->Snp)
  562. );
  563. if (!EFI_ERROR (Status)) {
  564. return Status;
  565. }
  566. PciIo->FreeBuffer (
  567. PciIo,
  568. SNP_MEM_PAGES (4096),
  569. Snp->Cpb
  570. );
  571. Error_DeleteSNP:
  572. if (Snp->RecycledTxBuf != NULL) {
  573. FreePool (Snp->RecycledTxBuf);
  574. }
  575. PciIo->FreeBuffer (
  576. PciIo,
  577. SNP_MEM_PAGES (sizeof (SNP_DRIVER)),
  578. Snp
  579. );
  580. NiiError:
  581. gBS->CloseProtocol (
  582. Controller,
  583. &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
  584. This->DriverBindingHandle,
  585. Controller
  586. );
  587. gBS->CloseProtocol (
  588. Controller,
  589. &gEfiDevicePathProtocolGuid,
  590. This->DriverBindingHandle,
  591. Controller
  592. );
  593. //
  594. // If we got here that means we are in error state.
  595. //
  596. if (!EFI_ERROR (Status)) {
  597. Status = EFI_DEVICE_ERROR;
  598. }
  599. return Status;
  600. }
  601. /**
  602. Stop this driver on ControllerHandle. This service is called by the
  603. EFI boot service DisconnectController(). In order to
  604. make drivers as small as possible, there are a few calling
  605. restrictions for this service. DisconnectController()
  606. must follow these calling restrictions. If any other agent wishes
  607. to call Stop() it must also follow these calling restrictions.
  608. @param This Protocol instance pointer.
  609. @param ControllerHandle Handle of device to stop driver on
  610. @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
  611. children is zero stop the entire bus driver.
  612. @param ChildHandleBuffer List of Child Handles to Stop.
  613. @retval EFI_SUCCESS This driver is removed ControllerHandle
  614. @retval other This driver was not removed from this device
  615. **/
  616. EFI_STATUS
  617. EFIAPI
  618. SimpleNetworkDriverStop (
  619. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  620. IN EFI_HANDLE Controller,
  621. IN UINTN NumberOfChildren,
  622. IN EFI_HANDLE *ChildHandleBuffer
  623. )
  624. {
  625. EFI_STATUS Status;
  626. EFI_SIMPLE_NETWORK_PROTOCOL *SnpProtocol;
  627. SNP_DRIVER *Snp;
  628. EFI_PCI_IO_PROTOCOL *PciIo;
  629. //
  630. // Get our context back.
  631. //
  632. Status = gBS->OpenProtocol (
  633. Controller,
  634. &gEfiSimpleNetworkProtocolGuid,
  635. (VOID **)&SnpProtocol,
  636. This->DriverBindingHandle,
  637. Controller,
  638. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  639. );
  640. if (EFI_ERROR (Status)) {
  641. return EFI_UNSUPPORTED;
  642. }
  643. Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SnpProtocol);
  644. Status = gBS->UninstallProtocolInterface (
  645. Controller,
  646. &gEfiSimpleNetworkProtocolGuid,
  647. &Snp->Snp
  648. );
  649. if (EFI_ERROR (Status)) {
  650. return Status;
  651. }
  652. if (PcdGetBool (PcdSnpCreateExitBootServicesEvent)) {
  653. //
  654. // Close EXIT_BOOT_SERVICES Event
  655. //
  656. gBS->CloseEvent (Snp->ExitBootServicesEvent);
  657. }
  658. Status = gBS->CloseProtocol (
  659. Controller,
  660. &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
  661. This->DriverBindingHandle,
  662. Controller
  663. );
  664. Status = gBS->CloseProtocol (
  665. Controller,
  666. &gEfiDevicePathProtocolGuid,
  667. This->DriverBindingHandle,
  668. Controller
  669. );
  670. PxeShutdown (Snp);
  671. PxeStop (Snp);
  672. FreePool (Snp->RecycledTxBuf);
  673. PciIo = Snp->PciIo;
  674. PciIo->FreeBuffer (
  675. PciIo,
  676. SNP_MEM_PAGES (4096),
  677. Snp->Cpb
  678. );
  679. PciIo->FreeBuffer (
  680. PciIo,
  681. SNP_MEM_PAGES (sizeof (SNP_DRIVER)),
  682. Snp
  683. );
  684. return Status;
  685. }
  686. //
  687. // Simple Network Protocol Driver Global Variables
  688. //
  689. EFI_DRIVER_BINDING_PROTOCOL gSimpleNetworkDriverBinding = {
  690. SimpleNetworkDriverSupported,
  691. SimpleNetworkDriverStart,
  692. SimpleNetworkDriverStop,
  693. 0xa,
  694. NULL,
  695. NULL
  696. };
  697. /**
  698. The SNP driver entry point.
  699. @param ImageHandle The driver image handle.
  700. @param SystemTable The system table.
  701. @retval EFI_SUCCESS Initialization routine has found UNDI hardware,
  702. loaded it's ROM, and installed a notify event for
  703. the Network Identifier Interface Protocol
  704. successfully.
  705. @retval Other Return value from HandleProtocol for
  706. DeviceIoProtocol or LoadedImageProtocol
  707. **/
  708. EFI_STATUS
  709. EFIAPI
  710. InitializeSnpNiiDriver (
  711. IN EFI_HANDLE ImageHandle,
  712. IN EFI_SYSTEM_TABLE *SystemTable
  713. )
  714. {
  715. return EfiLibInstallDriverBindingComponentName2 (
  716. ImageHandle,
  717. SystemTable,
  718. &gSimpleNetworkDriverBinding,
  719. ImageHandle,
  720. &gSimpleNetworkComponentName,
  721. &gSimpleNetworkComponentName2
  722. );
  723. }