1 /** @file
2 
3 Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved.<BR>
4 
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions
7 of the BSD License which accompanies this distribution.  The
8 full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10 
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 
16 #include "BiosSnp16.h"
17 
18 
19 ///
20 /// EFI Driver Binding Protocol Instance
21 ///
22 EFI_DRIVER_BINDING_PROTOCOL gBiosSnp16DriverBinding = {
23   BiosSnp16DriverBindingSupported,
24   BiosSnp16DriverBindingStart,
25   BiosSnp16DriverBindingStop,
26   0x3,
27   NULL,
28   NULL
29 };
30 
31 ///
32 ///  This boolean is used to determine if we should release the cached vector during an error condition.
33 ///
34 BOOLEAN     mCachedInt1A = FALSE;
35 
36 //
37 // Private worker functions;
38 //
39 
40 /**
41   Start the UNDI interface.
42 
43   @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
44   @param Ax                  PCI address of Undi device.
45 
46   @retval EFI_DEVICE_ERROR Fail to start 16 bit UNDI ROM.
47   @retval Others           Status of start 16 bit UNDI ROM.
48 **/
49 EFI_STATUS
50 Undi16SimpleNetworkStartUndi (
51   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice,
52   UINT16                  Ax
53   );
54 
55 /**
56   Start the UNDI interface
57 
58   @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
59 
60   @retval EFI_DEVICE_ERROR Fail to start 16 bit UNDI ROM.
61   @retval Others           Status of start 16 bit UNDI ROM.
62 **/
63 EFI_STATUS
64 Undi16SimpleNetworkStopUndi (
65   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
66   );
67 
68 /**
69   Stop the UNDI interface
70 
71   @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
72 
73   @retval EFI_DEVICE_ERROR Fail to stop 16 bit UNDI ROM.
74   @retval Others           Status of stop 16 bit UNDI ROM.
75 **/
76 EFI_STATUS
77 Undi16SimpleNetworkCleanupUndi (
78   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
79   );
80 
81 /**
82   Get runtime information for Undi network interface
83 
84   @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
85 
86   @retval EFI_SUCCESS Sucess operation.
87   @retval Others      Fail to get runtime information for Undi network interface.
88 **/
89 EFI_STATUS
90 Undi16SimpleNetworkGetInformation (
91   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
92   );
93 
94 /**
95   Get NIC type
96 
97   @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
98 
99   @retval EFI_SUCCESS Sucess operation.
100   @retval Others      Fail to get NIC type.
101 **/
102 EFI_STATUS
103 Undi16SimpleNetworkGetNicType (
104   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
105   );
106 
107 /**
108   Get NDIS information
109 
110   @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
111 
112   @retval EFI_SUCCESS Sucess operation.
113   @retval Others      Fail to get NDIS information.
114 **/
115 EFI_STATUS
116 Undi16SimpleNetworkGetNdisInfo (
117   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
118   );
119 
120 /**
121   Signal handlers for ExitBootServices event.
122 
123   Clean up any Real-mode UNDI residue from the system
124 
125   @param Event      ExitBootServices event
126   @param Context
127 **/
128 VOID
129 EFIAPI
130 Undi16SimpleNetworkEvent (
131   IN EFI_EVENT  Event,
132   IN VOID       *Context
133   );
134 
135 /**
136   Loads the undi driver.
137 
138   @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
139 
140   @retval   EFI_SUCCESS   - Successfully loads undi driver.
141   @retval   EFI_NOT_FOUND - Doesn't find undi driver or undi driver load failure.
142 **/
143 EFI_STATUS
144 Undi16SimpleNetworkLoadUndi (
145   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
146   );
147 
148 /**
149   Unload 16 bit UNDI Option ROM from memory
150 
151   @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
152 
153   @return EFI_STATUS
154 **/
155 EFI_STATUS
156 Undi16SimpleNetworkUnloadUndi (
157   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
158   );
159 
160 /**
161   Entry point for EFI drivers.
162 
163   @param ImageHandle Handle that identifies the loaded image.
164   @param SystemTable System Table for this image.
165 
166   @return EFI_STATUS Return status from EfiLibInstallAllDriverProtocols.
167 **/
168 EFI_STATUS
169 EFIAPI
BiosSnp16DriverEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)170 BiosSnp16DriverEntryPoint (
171   IN EFI_HANDLE         ImageHandle,
172   IN EFI_SYSTEM_TABLE   *SystemTable
173   )
174 {
175   return EfiLibInstallDriverBindingComponentName2 (
176            ImageHandle,
177            SystemTable,
178            &gBiosSnp16DriverBinding,
179            ImageHandle,
180            &gBiosSnp16ComponentName,
181            &gBiosSnp16ComponentName2
182            );
183 }
184 
185 //
186 // EFI Driver Binding Protocol Functions
187 //
188 /**
189   Tests to see if this driver supports a given controller.
190 
191   @param This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
192   @param Controller           The handle of the controller to test.
193   @param RemainingDevicePath  A pointer to the remaining portion of a device path.
194 
195   @retval EFI_SUCCESS    The driver supports given controller.
196   @retval EFI_UNSUPPORT  The driver doesn't support given controller.
197   @retval Other          Other errors prevent driver finishing to test
198                          if the driver supports given controller.
199 **/
200 EFI_STATUS
201 EFIAPI
BiosSnp16DriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)202 BiosSnp16DriverBindingSupported (
203   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
204   IN EFI_HANDLE                   Controller,
205   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
206   )
207 {
208   EFI_STATUS                Status;
209   EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;
210   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
211   EFI_PCI_IO_PROTOCOL       *PciIo;
212   PCI_TYPE00                Pci;
213 
214   //
215   // See if the Legacy BIOS Protocol is available
216   //
217   Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
218   if (EFI_ERROR (Status)) {
219     return Status;
220   }
221   //
222   // Open the IO Abstraction(s) needed to perform the supported test
223   //
224   Status = gBS->OpenProtocol (
225                   Controller,
226                   &gEfiDevicePathProtocolGuid,
227                   (VOID **) &DevicePath,
228                   This->DriverBindingHandle,
229                   Controller,
230                   EFI_OPEN_PROTOCOL_BY_DRIVER
231                   );
232   if (EFI_ERROR (Status)) {
233     return Status;
234   }
235 
236   gBS->CloseProtocol (
237         Controller,
238         &gEfiDevicePathProtocolGuid,
239         This->DriverBindingHandle,
240         Controller
241         );
242 
243   //
244   // Open the IO Abstraction(s) needed to perform the supported test
245   //
246   Status = gBS->OpenProtocol (
247                   Controller,
248                   &gEfiPciIoProtocolGuid,
249                   (VOID **) &PciIo,
250                   This->DriverBindingHandle,
251                   Controller,
252                   EFI_OPEN_PROTOCOL_BY_DRIVER
253                   );
254   if (EFI_ERROR (Status)) {
255     return Status;
256   }
257   //
258   // See if this is a PCI Network Controller by looking at the Command register and
259   // Class Code Register
260   //
261   Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, sizeof (Pci) / sizeof (UINT32), &Pci);
262   if (EFI_ERROR (Status)) {
263     Status = EFI_UNSUPPORTED;
264     goto Done;
265   }
266 
267   Status = EFI_UNSUPPORTED;
268   if (Pci.Hdr.ClassCode[2] == PCI_CLASS_NETWORK) {
269     Status = EFI_SUCCESS;
270   }
271 
272 Done:
273   gBS->CloseProtocol (
274         Controller,
275         &gEfiPciIoProtocolGuid,
276         This->DriverBindingHandle,
277         Controller
278         );
279 
280   return Status;
281 }
282 
283 /**
284   Starts the Snp device controller
285 
286   @param This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
287   @param Controller           The handle of the controller to test.
288   @param RemainingDevicePath  A pointer to the remaining portion of a device path.
289 
290   @retval  EFI_SUCCESS          - The device was started.
291   @retval  EFI_DEVICE_ERROR     - The device could not be started due to a device error.
292   @retval  EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
293 **/
294 EFI_STATUS
295 EFIAPI
BiosSnp16DriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)296 BiosSnp16DriverBindingStart (
297   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
298   IN EFI_HANDLE                   Controller,
299   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
300   )
301 {
302   EFI_STATUS                Status;
303   EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;
304   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
305   EFI_PCI_IO_PROTOCOL       *PciIo;
306   EFI_SIMPLE_NETWORK_DEV    *SimpleNetworkDevice;
307   EFI_DEV_PATH              Node;
308   UINTN                     Index;
309   UINTN                     Index2;
310   UINTN                     Segment;
311   UINTN                     Bus;
312   UINTN                     Device;
313   UINTN                     Function;
314   UINTN                     Flags;
315   UINT64                    Supports;
316 
317   SimpleNetworkDevice = NULL;
318   PciIo               = NULL;
319 
320   //
321   // See if the Legacy BIOS Protocol is available
322   //
323   Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
324   if (EFI_ERROR (Status)) {
325     return Status;
326   }
327   //
328   // Open the IO Abstraction(s) needed
329   //
330   Status = gBS->OpenProtocol (
331                   Controller,
332                   &gEfiDevicePathProtocolGuid,
333                   (VOID **) &DevicePath,
334                   This->DriverBindingHandle,
335                   Controller,
336                   EFI_OPEN_PROTOCOL_BY_DRIVER
337                   );
338   if (EFI_ERROR (Status)) {
339     goto Done;
340   }
341 
342   Status = gBS->OpenProtocol (
343                   Controller,
344                   &gEfiPciIoProtocolGuid,
345                   (VOID **) &PciIo,
346                   This->DriverBindingHandle,
347                   Controller,
348                   EFI_OPEN_PROTOCOL_BY_DRIVER
349                   );
350   if (EFI_ERROR (Status)) {
351     goto Done;
352   }
353 
354   Status = PciIo->Attributes (
355                     PciIo,
356                     EfiPciIoAttributeOperationSupported,
357                     0,
358                     &Supports
359                     );
360   if (!EFI_ERROR (Status)) {
361     Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
362     Status = PciIo->Attributes (
363                       PciIo,
364                       EfiPciIoAttributeOperationEnable,
365                       Supports,
366                       NULL
367                       );
368   }
369 
370   if (EFI_ERROR (Status)) {
371     goto Done;
372   }
373   //
374   // Check to see if there is a legacy option ROM image associated with this PCI device
375   //
376   Status = LegacyBios->CheckPciRom (
377                          LegacyBios,
378                          Controller,
379                          NULL,
380                          NULL,
381                          &Flags
382                          );
383   if (EFI_ERROR (Status)) {
384     goto Done;
385   }
386   //
387   // Post the legacy option ROM if it is available.
388   //
389   Status = LegacyBios->InstallPciRom (
390                          LegacyBios,
391                          Controller,
392                          NULL,
393                          &Flags,
394                          NULL,
395                          NULL,
396                          NULL,
397                          NULL
398                          );
399   if (EFI_ERROR (Status)) {
400     goto Done;
401   }
402   //
403   // Allocate memory for this SimpleNetwork device instance
404   //
405   Status = gBS->AllocatePool (
406                   EfiBootServicesData,
407                   sizeof (EFI_SIMPLE_NETWORK_DEV),
408                   (VOID **) &SimpleNetworkDevice
409                   );
410   if (EFI_ERROR (Status)) {
411     Status = EFI_OUT_OF_RESOURCES;
412     goto Done;
413   }
414 
415   ZeroMem (SimpleNetworkDevice, sizeof (EFI_SIMPLE_NETWORK_DEV));
416 
417   //
418   // Initialize the SimpleNetwork device instance
419   //
420   SimpleNetworkDevice->Signature      = EFI_SIMPLE_NETWORK_DEV_SIGNATURE;
421   SimpleNetworkDevice->LegacyBios     = LegacyBios;
422   SimpleNetworkDevice->BaseDevicePath = DevicePath;
423   SimpleNetworkDevice->PciIo          = PciIo;
424 
425   //
426   // Initialize the Nii Protocol
427   //
428   SimpleNetworkDevice->Nii.Revision = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION;
429   SimpleNetworkDevice->Nii.Type     = EfiNetworkInterfaceUndi;
430 
431   CopyMem (&SimpleNetworkDevice->Nii.StringId, "UNDI", 4);
432 
433   //
434   // Load 16 bit UNDI Option ROM into Memory
435   //
436   Status = Undi16SimpleNetworkLoadUndi (SimpleNetworkDevice);
437   if (EFI_ERROR (Status)) {
438     DEBUG ((DEBUG_NET, "ERROR : Could not load UNDI.  Status = %r\n", Status));
439     goto Done;
440   }
441 
442   SimpleNetworkDevice->UndiLoaded = TRUE;
443 
444   //
445   // Call PXENV_START_UNDI - Initilizes the UNID interface for use.
446   //
447   PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
448   Status = Undi16SimpleNetworkStartUndi (
449              SimpleNetworkDevice,
450              (UINT16) ((Bus << 0x8) | (Device << 0x3) | (Function))
451              );
452   if (EFI_ERROR (Status)) {
453     DEBUG ((DEBUG_NET, "ERROR : Could not StartUndi.  Status = %r\n", Status));
454     goto Done;
455   }
456   //
457   // Initialize the Simple Network Protocol
458   //
459   DEBUG ((DEBUG_NET, "Initialize SimpleNetworkDevice instance\n"));
460 
461   SimpleNetworkDevice->SimpleNetwork.Revision       = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
462   SimpleNetworkDevice->SimpleNetwork.Start          = Undi16SimpleNetworkStart;
463   SimpleNetworkDevice->SimpleNetwork.Stop           = Undi16SimpleNetworkStop;
464   SimpleNetworkDevice->SimpleNetwork.Initialize     = Undi16SimpleNetworkInitialize;
465   SimpleNetworkDevice->SimpleNetwork.Reset          = Undi16SimpleNetworkReset;
466   SimpleNetworkDevice->SimpleNetwork.Shutdown       = Undi16SimpleNetworkShutdown;
467   SimpleNetworkDevice->SimpleNetwork.ReceiveFilters = Undi16SimpleNetworkReceiveFilters;
468   SimpleNetworkDevice->SimpleNetwork.StationAddress = Undi16SimpleNetworkStationAddress;
469   SimpleNetworkDevice->SimpleNetwork.Statistics     = Undi16SimpleNetworkStatistics;
470   SimpleNetworkDevice->SimpleNetwork.MCastIpToMac   = Undi16SimpleNetworkMCastIpToMac;
471   SimpleNetworkDevice->SimpleNetwork.NvData         = Undi16SimpleNetworkNvData;
472   SimpleNetworkDevice->SimpleNetwork.GetStatus      = Undi16SimpleNetworkGetStatus;
473   SimpleNetworkDevice->SimpleNetwork.Transmit       = Undi16SimpleNetworkTransmit;
474   SimpleNetworkDevice->SimpleNetwork.Receive        = Undi16SimpleNetworkReceive;
475   SimpleNetworkDevice->SimpleNetwork.Mode           = &(SimpleNetworkDevice->SimpleNetworkMode);
476 
477   Status = gBS->CreateEvent (
478                   EVT_NOTIFY_WAIT,
479                   TPL_NOTIFY,
480                   Undi16SimpleNetworkWaitForPacket,
481                   &SimpleNetworkDevice->SimpleNetwork,
482                   &SimpleNetworkDevice->SimpleNetwork.WaitForPacket
483                   );
484   if (EFI_ERROR (Status)) {
485     DEBUG ((DEBUG_ERROR, "ERROR : Could not create event.  Status = %r\n", Status));
486     goto Done;
487   }
488   //
489   // Create an event to be signalled when ExitBootServices occurs in order
490   // to clean up nicely
491   //
492   Status = gBS->CreateEventEx (
493                   EVT_NOTIFY_SIGNAL,
494                   TPL_NOTIFY,
495                   Undi16SimpleNetworkEvent,
496                   NULL,
497                   &gEfiEventExitBootServicesGuid,
498                   &SimpleNetworkDevice->EfiBootEvent
499                   );
500   if (EFI_ERROR (Status)) {
501     DEBUG ((DEBUG_ERROR, "ERROR : Could not create event.  Status = %r\n", Status));
502     goto Done;
503   }
504 
505   //
506   // Create an event to be signalled when Legacy Boot occurs to clean up the IVT
507   //
508   Status = EfiCreateEventLegacyBootEx(
509              TPL_NOTIFY,
510              Undi16SimpleNetworkEvent,
511              NULL,
512              &SimpleNetworkDevice->LegacyBootEvent
513              );
514 
515   if (EFI_ERROR(Status)) {
516     DEBUG ((DEBUG_ERROR,"ERROR : Could not create event.  Status = %r\n",Status));
517     goto Done;
518   }
519 
520   //
521   // Initialize the SimpleNetwork Mode Information
522   //
523   DEBUG ((DEBUG_NET, "Initialize Mode Information\n"));
524 
525   SimpleNetworkDevice->SimpleNetworkMode.State                = EfiSimpleNetworkStopped;
526   SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize      = 14;
527   SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable = TRUE;
528   SimpleNetworkDevice->SimpleNetworkMode.MultipleTxSupported  = TRUE;
529   SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
530     EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
531     EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
532     EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS |
533     EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
534   SimpleNetworkDevice->SimpleNetworkMode.MaxMCastFilterCount = MAXNUM_MCADDR;
535 
536   //
537   // Initialize the SimpleNetwork Private Information
538   //
539   DEBUG ((DEBUG_NET, "Initialize Private Information\n"));
540 
541   Status = BiosSnp16AllocatePagesBelowOneMb (
542              sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1,
543              (VOID **) &SimpleNetworkDevice->Xmit
544              );
545   if (EFI_ERROR (Status)) {
546     goto Done;
547   }
548 
549   Status = BiosSnp16AllocatePagesBelowOneMb (
550              1,
551              &SimpleNetworkDevice->TxRealModeMediaHeader
552              );
553   if (EFI_ERROR (Status)) {
554     goto Done;
555   }
556 
557   Status = BiosSnp16AllocatePagesBelowOneMb (
558              1,
559              &SimpleNetworkDevice->TxRealModeDataBuffer
560              );
561   if (EFI_ERROR (Status)) {
562     goto Done;
563   }
564 
565   Status = BiosSnp16AllocatePagesBelowOneMb (
566              1,
567              &SimpleNetworkDevice->TxDestAddr
568              );
569   if (EFI_ERROR (Status)) {
570     goto Done;
571   }
572 
573   SimpleNetworkDevice->Xmit->XmitOffset               = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeMediaHeader) & 0x000f);
574 
575   SimpleNetworkDevice->Xmit->XmitSegment              = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeMediaHeader) >> 4);
576 
577   SimpleNetworkDevice->Xmit->DataBlkCount             = 1;
578 
579   SimpleNetworkDevice->Xmit->DataBlock[0].TDPtrType   = 1;
580   SimpleNetworkDevice->Xmit->DataBlock[0].TDRsvdByte  = 0;
581 
582   SimpleNetworkDevice->Xmit->DataBlock[0].TDDataPtrOffset = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeDataBuffer) & 0x000f);
583 
584   SimpleNetworkDevice->Xmit->DataBlock[0].TDDataPtrSegment = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeDataBuffer) >> 4);
585 
586   SimpleNetworkDevice->TxBufferFifo.First = 0;
587   SimpleNetworkDevice->TxBufferFifo.Last  = 0;
588 
589   //
590   // Start() the SimpleNetwork device
591   //
592   DEBUG ((DEBUG_NET, "Start()\n"));
593 
594   Status = Undi16SimpleNetworkStart (&SimpleNetworkDevice->SimpleNetwork);
595   if (EFI_ERROR (Status)) {
596     goto Done;
597   }
598   //
599   // GetInformation() the SimpleNetwork device
600   //
601   DEBUG ((DEBUG_NET, "GetInformation()\n"));
602 
603   Status = Undi16SimpleNetworkGetInformation (&SimpleNetworkDevice->SimpleNetwork);
604   if (EFI_ERROR (Status)) {
605     goto Done;
606   }
607   //
608   // Build the device path for the child device
609   //
610   ZeroMem (&Node, sizeof (Node));
611   Node.DevPath.Type     = MESSAGING_DEVICE_PATH;
612   Node.DevPath.SubType  = MSG_MAC_ADDR_DP;
613   SetDevicePathNodeLength (&Node.DevPath, sizeof (MAC_ADDR_DEVICE_PATH));
614   CopyMem (
615     &Node.MacAddr.MacAddress,
616     &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
617     sizeof (EFI_MAC_ADDRESS)
618     );
619   SimpleNetworkDevice->DevicePath = AppendDevicePathNode (
620                                       SimpleNetworkDevice->BaseDevicePath,
621                                       &Node.DevPath
622                                       );
623 
624   //
625   // GetNicType()  the SimpleNetwork device
626   //
627   DEBUG ((DEBUG_NET, "GetNicType()\n"));
628 
629   Status = Undi16SimpleNetworkGetNicType (&SimpleNetworkDevice->SimpleNetwork);
630   if (EFI_ERROR (Status)) {
631     goto Done;
632   }
633   //
634   // GetNdisInfo() the SimpleNetwork device
635   //
636   DEBUG ((DEBUG_NET, "GetNdisInfo()\n"));
637 
638   Status = Undi16SimpleNetworkGetNdisInfo (&SimpleNetworkDevice->SimpleNetwork);
639   if (EFI_ERROR (Status)) {
640     goto Done;
641   }
642   //
643   // Stop() the SimpleNetwork device
644   //
645   DEBUG ((DEBUG_NET, "Stop()\n"));
646 
647   Status = SimpleNetworkDevice->SimpleNetwork.Stop (&SimpleNetworkDevice->SimpleNetwork);
648   if (EFI_ERROR (Status)) {
649     goto Done;
650   }
651   //
652   // Print Mode information
653   //
654   DEBUG ((DEBUG_NET, "Mode->State                = %d\n", SimpleNetworkDevice->SimpleNetworkMode.State));
655   DEBUG ((DEBUG_NET, "Mode->HwAddressSize        = %d\n", SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize));
656   DEBUG ((DEBUG_NET, "Mode->MacAddressChangeable = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable));
657   DEBUG ((DEBUG_NET, "Mode->MultiplTxSupported   = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MultipleTxSupported));
658   DEBUG ((DEBUG_NET, "Mode->NvRamSize            = %d\n", SimpleNetworkDevice->SimpleNetworkMode.NvRamSize));
659   DEBUG ((DEBUG_NET, "Mode->NvRamAccessSize      = %d\n", SimpleNetworkDevice->SimpleNetworkMode.NvRamAccessSize));
660   DEBUG ((DEBUG_NET, "Mode->ReceiveFilterSetting = %d\n", SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting));
661   DEBUG ((DEBUG_NET, "Mode->IfType               = %d\n", SimpleNetworkDevice->SimpleNetworkMode.IfType));
662   DEBUG ((DEBUG_NET, "Mode->MCastFilterCount     = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount));
663   for (Index = 0; Index < SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount; Index++) {
664     DEBUG ((DEBUG_NET, "  Filter[%02d] = ", Index));
665     for (Index2 = 0; Index2 < 16; Index2++) {
666       DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index].Addr[Index2]));
667     }
668 
669     DEBUG ((DEBUG_NET, "\n"));
670   }
671 
672   DEBUG ((DEBUG_NET, "CurrentAddress = "));
673   for (Index2 = 0; Index2 < 16; Index2++) {
674     DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress.Addr[Index2]));
675   }
676 
677   DEBUG ((DEBUG_NET, "\n"));
678 
679   DEBUG ((DEBUG_NET, "BroadcastAddress = "));
680   for (Index2 = 0; Index2 < 16; Index2++) {
681     DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress.Addr[Index2]));
682   }
683 
684   DEBUG ((DEBUG_NET, "\n"));
685 
686   DEBUG ((DEBUG_NET, "PermanentAddress = "));
687   for (Index2 = 0; Index2 < 16; Index2++) {
688     DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress.Addr[Index2]));
689   }
690 
691   DEBUG ((DEBUG_NET, "\n"));
692 
693   //
694   // The network device was started, information collected, and stopped.
695   // Install protocol interfaces for the SimpleNetwork device.
696   //
697   DEBUG ((DEBUG_NET, "Install Protocol Interfaces on network interface\n"));
698 
699   Status = gBS->InstallMultipleProtocolInterfaces (
700                   &SimpleNetworkDevice->Handle,
701                   &gEfiSimpleNetworkProtocolGuid,
702                   &SimpleNetworkDevice->SimpleNetwork,
703                   &gEfiNetworkInterfaceIdentifierProtocolGuid,
704                   &SimpleNetworkDevice->Nii,
705                   &gEfiDevicePathProtocolGuid,
706                   SimpleNetworkDevice->DevicePath,
707                   NULL
708                   );
709   if (EFI_ERROR (Status)) {
710     goto Done;
711   }
712   //
713   // Open PCI I/O from the newly created child handle
714   //
715   Status = gBS->OpenProtocol (
716                   Controller,
717                   &gEfiPciIoProtocolGuid,
718                   (VOID **) &PciIo,
719                   This->DriverBindingHandle,
720                   SimpleNetworkDevice->Handle,
721                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
722                   );
723 
724   DEBUG ((DEBUG_INIT, "UNDI16 Driver : EFI_SUCCESS\n"));
725 
726 Done:
727   if (EFI_ERROR (Status)) {
728     if (SimpleNetworkDevice != NULL) {
729 
730       Undi16SimpleNetworkShutdown (&SimpleNetworkDevice->SimpleNetwork);
731       //
732       // CLOSE + SHUTDOWN
733       //
734       Undi16SimpleNetworkCleanupUndi (SimpleNetworkDevice);
735       //
736       // CLEANUP
737       //
738       Undi16SimpleNetworkStopUndi (SimpleNetworkDevice);
739       //
740       // STOP
741       //
742       if (SimpleNetworkDevice->UndiLoaded) {
743         Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice);
744       }
745 
746       if (SimpleNetworkDevice->SimpleNetwork.WaitForPacket != NULL) {
747         gBS->CloseEvent (SimpleNetworkDevice->SimpleNetwork.WaitForPacket);
748       }
749 
750       if (SimpleNetworkDevice->LegacyBootEvent != NULL) {
751         gBS->CloseEvent (SimpleNetworkDevice->LegacyBootEvent);
752       }
753 
754       if (SimpleNetworkDevice->EfiBootEvent != NULL) {
755         gBS->CloseEvent (SimpleNetworkDevice->EfiBootEvent);
756       }
757 
758       if (SimpleNetworkDevice->Xmit != NULL) {
759         gBS->FreePages (
760                (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->Xmit,
761                sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1
762                );
763       }
764 
765       if (SimpleNetworkDevice->TxRealModeMediaHeader != NULL) {
766         gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeMediaHeader, 1);
767       }
768 
769       if (SimpleNetworkDevice->TxRealModeDataBuffer != NULL) {
770         gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeDataBuffer, 1);
771       }
772 
773       if (SimpleNetworkDevice->TxDestAddr != NULL) {
774         gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxDestAddr, 1);
775       }
776 
777       gBS->FreePool (SimpleNetworkDevice);
778 
779       //
780       //  Only restore the vector if it was cached.
781       //
782       if (mCachedInt1A) {
783         RestoreCachedVectorAddress (0x1A);
784         mCachedInt1A = FALSE;
785       }
786     }
787 
788     if (PciIo != NULL) {
789       Status = PciIo->Attributes (
790                         PciIo,
791                         EfiPciIoAttributeOperationSupported,
792                         0,
793                         &Supports
794                         );
795       if (!EFI_ERROR (Status)) {
796         Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
797         Status = PciIo->Attributes (
798                           PciIo,
799                           EfiPciIoAttributeOperationDisable,
800                           Supports,
801                           NULL
802                           );
803       }
804     }
805 
806     gBS->CloseProtocol (
807            Controller,
808            &gEfiPciIoProtocolGuid,
809            This->DriverBindingHandle,
810            Controller
811            );
812 
813     gBS->CloseProtocol (
814            Controller,
815            &gEfiDevicePathProtocolGuid,
816            This->DriverBindingHandle,
817            Controller
818            );
819     if (Status != EFI_OUT_OF_RESOURCES) {
820       Status = EFI_DEVICE_ERROR;
821     }
822   }
823   return Status;
824 }
825 
826 /**
827   Stops the device by given device controller.
828 
829   @param This               A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
830   @param Controller         The handle of the controller to test.
831   @param NumberOfChildren   The number of child device handles in ChildHandleBuffer.
832   @param ChildHandleBuffer  An array of child handles to be freed. May be NULL if
833                             NumberOfChildren is 0.
834 
835   @retval  EFI_SUCCESS      - The device was stopped.
836   @retval  EFI_DEVICE_ERROR - The device could not be stopped due to a device error.
837 **/
838 EFI_STATUS
839 EFIAPI
BiosSnp16DriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)840 BiosSnp16DriverBindingStop (
841   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
842   IN  EFI_HANDLE                      Controller,
843   IN  UINTN                           NumberOfChildren,
844   IN  EFI_HANDLE                      *ChildHandleBuffer
845   )
846 {
847   EFI_STATUS                  Status;
848   UINTN                       Index;
849   BOOLEAN                     AllChildrenStopped;
850   EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork;
851   EFI_SIMPLE_NETWORK_DEV      *SimpleNetworkDevice;
852   EFI_PCI_IO_PROTOCOL         *PciIo;
853   UINT64                      Supports;
854 
855   //
856   // Complete all outstanding transactions to Controller.
857   // Don't allow any new transaction to Controller to be started.
858   //
859   if (NumberOfChildren == 0) {
860     //
861     // Close the bus driver
862     //
863     Status = gBS->OpenProtocol (
864                     Controller,
865                     &gEfiPciIoProtocolGuid,
866                     (VOID **) &PciIo,
867                     This->DriverBindingHandle,
868                     Controller,
869                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
870                     );
871     if (!EFI_ERROR (Status)) {
872       Status = PciIo->Attributes (
873                         PciIo,
874                         EfiPciIoAttributeOperationSupported,
875                         0,
876                         &Supports
877                         );
878       if (!EFI_ERROR (Status)) {
879         Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
880         Status = PciIo->Attributes (
881                           PciIo,
882                           EfiPciIoAttributeOperationDisable,
883                           Supports,
884                           NULL
885                           );
886       }
887     }
888 
889     Status = gBS->CloseProtocol (
890                     Controller,
891                     &gEfiPciIoProtocolGuid,
892                     This->DriverBindingHandle,
893                     Controller
894                     );
895 
896     Status = gBS->CloseProtocol (
897                     Controller,
898                     &gEfiDevicePathProtocolGuid,
899                     This->DriverBindingHandle,
900                     Controller
901                     );
902 
903     if (EFI_ERROR (Status)) {
904       Status = EFI_DEVICE_ERROR;
905     }
906     return Status;
907   }
908 
909   AllChildrenStopped = TRUE;
910 
911   for (Index = 0; Index < NumberOfChildren; Index++) {
912 
913     Status = gBS->OpenProtocol (
914                     ChildHandleBuffer[Index],
915                     &gEfiSimpleNetworkProtocolGuid,
916                     (VOID **) &SimpleNetwork,
917                     This->DriverBindingHandle,
918                     Controller,
919                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
920                     );
921     if (!EFI_ERROR (Status)) {
922 
923       SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SimpleNetwork);
924 
925       Status = gBS->CloseProtocol (
926                       Controller,
927                       &gEfiPciIoProtocolGuid,
928                       This->DriverBindingHandle,
929                       ChildHandleBuffer[Index]
930                       );
931 
932       Status = gBS->UninstallMultipleProtocolInterfaces (
933                       SimpleNetworkDevice->Handle,
934                       &gEfiSimpleNetworkProtocolGuid,
935                       &SimpleNetworkDevice->SimpleNetwork,
936                       &gEfiNetworkInterfaceIdentifierProtocolGuid,
937                       &SimpleNetworkDevice->Nii,
938                       &gEfiDevicePathProtocolGuid,
939                       SimpleNetworkDevice->DevicePath,
940                       NULL
941                       );
942       if (EFI_ERROR (Status)) {
943         gBS->OpenProtocol (
944                Controller,
945                &gEfiPciIoProtocolGuid,
946                (VOID **) &PciIo,
947                This->DriverBindingHandle,
948                ChildHandleBuffer[Index],
949                EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
950                );
951       } else {
952 
953         Undi16SimpleNetworkShutdown (&SimpleNetworkDevice->SimpleNetwork);
954         //
955         // CLOSE + SHUTDOWN
956         //
957         Undi16SimpleNetworkCleanupUndi (SimpleNetworkDevice);
958         //
959         // CLEANUP
960         //
961         Undi16SimpleNetworkStopUndi (SimpleNetworkDevice);
962         //
963         // STOP
964         //
965         if (SimpleNetworkDevice->UndiLoaded) {
966           Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice);
967         }
968 
969         if (SimpleNetworkDevice->SimpleNetwork.WaitForPacket != NULL) {
970           gBS->CloseEvent (SimpleNetworkDevice->SimpleNetwork.WaitForPacket);
971         }
972 
973         if (SimpleNetworkDevice->LegacyBootEvent != NULL) {
974           gBS->CloseEvent (SimpleNetworkDevice->LegacyBootEvent);
975         }
976 
977         if (SimpleNetworkDevice->EfiBootEvent != NULL) {
978           gBS->CloseEvent (SimpleNetworkDevice->EfiBootEvent);
979         }
980 
981         if (SimpleNetworkDevice->Xmit != NULL) {
982           gBS->FreePages (
983                  (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->Xmit,
984                  sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1
985                  );
986         }
987 
988         if (SimpleNetworkDevice->TxRealModeMediaHeader != NULL) {
989           gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeMediaHeader, 1);
990         }
991 
992         if (SimpleNetworkDevice->TxRealModeDataBuffer != NULL) {
993           gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeDataBuffer, 1);
994         }
995 
996         if (SimpleNetworkDevice->TxDestAddr != NULL) {
997           gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxDestAddr, 1);
998         }
999 
1000         gBS->FreePool (SimpleNetworkDevice);
1001       }
1002 
1003     }
1004 
1005     if (EFI_ERROR (Status)) {
1006       AllChildrenStopped = FALSE;
1007     }
1008   }
1009 
1010   if (!AllChildrenStopped) {
1011     return EFI_DEVICE_ERROR;
1012   }
1013 
1014   return EFI_SUCCESS;
1015 }
1016 
1017 //
1018 // FIFO Support Functions
1019 //
1020 /**
1021   Judge whether transmit FIFO is full.
1022 
1023   @param Fifo Point to trasmit FIFO structure.
1024 
1025   @return BOOLEAN whether transmit FIFO is full.
1026 **/
1027 BOOLEAN
SimpleNetworkTransmitFifoFull(EFI_SIMPLE_NETWORK_DEV_FIFO * Fifo)1028 SimpleNetworkTransmitFifoFull (
1029   EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo
1030   )
1031 {
1032   if (((Fifo->Last + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE) == Fifo->First) {
1033     return TRUE;
1034   }
1035 
1036   return FALSE;
1037 }
1038 
1039 /**
1040   Judge whether transmit FIFO is empty.
1041 
1042   @param Fifo Point to trasmit FIFO structure.
1043 
1044   @return BOOLEAN whether transmit FIFO is empty.
1045 **/
1046 BOOLEAN
SimpleNetworkTransmitFifoEmpty(EFI_SIMPLE_NETWORK_DEV_FIFO * Fifo)1047 SimpleNetworkTransmitFifoEmpty (
1048   EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo
1049   )
1050 {
1051   if (Fifo->Last == Fifo->First) {
1052     return TRUE;
1053   }
1054 
1055   return FALSE;
1056 }
1057 
1058 
1059 /**
1060   Add data into transmit buffer.
1061 
1062   @param Fifo Point to trasmit FIFO structure.
1063   @param Data The data point want to be added.
1064 
1065   @retval EFI_OUT_OF_RESOURCES  FIFO is full
1066   @retval EFI_SUCCESS           Success operation.
1067 **/
1068 EFI_STATUS
SimpleNetworkTransmitFifoAdd(EFI_SIMPLE_NETWORK_DEV_FIFO * Fifo,VOID * Data)1069 SimpleNetworkTransmitFifoAdd (
1070   EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo,
1071   VOID                        *Data
1072   )
1073 {
1074   if (SimpleNetworkTransmitFifoFull (Fifo)) {
1075     return EFI_OUT_OF_RESOURCES;
1076   }
1077 
1078   Fifo->Data[Fifo->Last]  = Data;
1079   Fifo->Last              = (Fifo->Last + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE;
1080   return EFI_SUCCESS;
1081 }
1082 
1083 /**
1084   Get a data and remove it from network transmit FIFO.
1085 
1086   @param Fifo Point to trasmit FIFO structure.
1087   @param Data On return, point to the data point want to be got and removed.
1088 
1089   @retval EFI_OUT_OF_RESOURCES network transmit buffer is empty.
1090   @retval EFI_SUCCESS           Success operation.
1091 **/
1092 EFI_STATUS
SimpleNetworkTransmitFifoRemove(EFI_SIMPLE_NETWORK_DEV_FIFO * Fifo,VOID ** Data)1093 SimpleNetworkTransmitFifoRemove (
1094   EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo,
1095   VOID                        **Data
1096   )
1097 {
1098   if (SimpleNetworkTransmitFifoEmpty (Fifo)) {
1099     return EFI_OUT_OF_RESOURCES;
1100   }
1101 
1102   *Data       = Fifo->Data[Fifo->First];
1103   Fifo->First = (Fifo->First + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE;
1104   return EFI_SUCCESS;
1105 }
1106 
1107 /**
1108   Get recive filter setting according to EFI mask value.
1109 
1110   @param ReceiveFilterSetting  filter setting EFI mask value.
1111 
1112   @return UINT16 Undi filter setting value.
1113 **/
1114 UINT16
Undi16GetPacketFilterSetting(UINTN ReceiveFilterSetting)1115 Undi16GetPacketFilterSetting (
1116   UINTN ReceiveFilterSetting
1117   )
1118 {
1119   UINT16  PktFilter;
1120 
1121   PktFilter = 0;
1122   if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) != 0) {
1123     PktFilter |= FLTR_DIRECTED;
1124   }
1125 
1126   if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
1127     PktFilter |= FLTR_DIRECTED;
1128   }
1129 
1130   if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0) {
1131     PktFilter |= FLTR_BRDCST;
1132   }
1133 
1134   if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) {
1135     PktFilter |= FLTR_PRMSCS;
1136   }
1137 
1138   if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {
1139     PktFilter |= FLTR_PRMSCS;
1140     //
1141     // @bug : Do not know if this is right????
1142     //
1143   }
1144   //
1145   // @bug : What is FLTR_SRC_RTG?
1146   //
1147   return PktFilter;
1148 }
1149 
1150 /**
1151   Get filter setting from multi cast buffer .
1152 
1153   @param Mode           Point to mode structure.
1154   @param McastBuffer    The multi cast buffer
1155   @param HwAddressSize  Size of filter value.
1156 
1157 **/
1158 VOID
Undi16GetMCastFilters(IN EFI_SIMPLE_NETWORK_MODE * Mode,IN OUT PXENV_UNDI_MCAST_ADDR_T * McastBuffer,IN UINTN HwAddressSize)1159 Undi16GetMCastFilters (
1160   IN EFI_SIMPLE_NETWORK_MODE      *Mode,
1161   IN OUT PXENV_UNDI_MCAST_ADDR_T  *McastBuffer,
1162   IN UINTN                        HwAddressSize
1163   )
1164 {
1165   UINTN Index;
1166 
1167   //
1168   // @bug : What if Mode->MCastFilterCount > MAXNUM_MCADDR?
1169   //
1170   McastBuffer->MCastAddrCount = (UINT16) Mode->MCastFilterCount;
1171   for (Index = 0; Index < MAXNUM_MCADDR; Index++) {
1172     if (Index < McastBuffer->MCastAddrCount) {
1173       CopyMem (&McastBuffer->MCastAddr[Index], &Mode->MCastFilter[Index], HwAddressSize);
1174     } else {
1175       ZeroMem (&McastBuffer->MCastAddr[Index], HwAddressSize);
1176     }
1177   }
1178 }
1179 //
1180 // Load 16 bit UNDI Option ROM into memory
1181 //
1182 /**
1183   Loads the undi driver.
1184 
1185   @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
1186 
1187   @retval   EFI_SUCCESS   - Successfully loads undi driver.
1188   @retval   EFI_NOT_FOUND - Doesn't find undi driver or undi driver load failure.
1189 **/
1190 EFI_STATUS
Undi16SimpleNetworkLoadUndi(EFI_SIMPLE_NETWORK_DEV * SimpleNetworkDevice)1191 Undi16SimpleNetworkLoadUndi (
1192   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
1193   )
1194 {
1195   EFI_STATUS                Status;
1196   EFI_PCI_IO_PROTOCOL       *PciIo;
1197   UINTN                     RomAddress;
1198   PCI_EXPANSION_ROM_HEADER  *PciExpansionRomHeader;
1199   PCI_DATA_STRUCTURE        *PciDataStructure;
1200   PCI_TYPE00                Pci;
1201 
1202   if (!mCachedInt1A) {
1203     Status = CacheVectorAddress (0x1A);
1204     if (!EFI_ERROR (Status)) {
1205       mCachedInt1A = TRUE;
1206     }
1207   }
1208 
1209   PciIo = SimpleNetworkDevice->PciIo;
1210 
1211   PciIo->Pci.Read (
1212                PciIo,
1213                EfiPciIoWidthUint32,
1214                0,
1215                sizeof (Pci) / sizeof (UINT32),
1216                &Pci
1217                );
1218 
1219   for (RomAddress = 0xc0000; RomAddress < 0xfffff; RomAddress += 0x800) {
1220 
1221     PciExpansionRomHeader = (PCI_EXPANSION_ROM_HEADER *) RomAddress;
1222 
1223     if (PciExpansionRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
1224       continue;
1225     }
1226 
1227     DEBUG ((DEBUG_INIT, "Option ROM found at %X\n", RomAddress));
1228 
1229     //
1230     // If the pointer to the PCI Data Structure is invalid, no further images can be located.
1231     // The PCI Data Structure must be DWORD aligned.
1232     //
1233     if (PciExpansionRomHeader->PcirOffset == 0 ||
1234         (PciExpansionRomHeader->PcirOffset & 3) != 0 ||
1235         RomAddress + PciExpansionRomHeader->PcirOffset + sizeof (PCI_DATA_STRUCTURE) > 0x100000) {
1236       break;
1237     }
1238 
1239     PciDataStructure = (PCI_DATA_STRUCTURE *) (RomAddress + PciExpansionRomHeader->PcirOffset);
1240 
1241     if (PciDataStructure->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
1242       continue;
1243     }
1244 
1245     DEBUG ((DEBUG_INIT, "PCI Data Structure found at %X\n", PciDataStructure));
1246 
1247     if (PciDataStructure->VendorId != Pci.Hdr.VendorId || PciDataStructure->DeviceId != Pci.Hdr.DeviceId) {
1248       continue;
1249     }
1250 
1251     DEBUG (
1252         (DEBUG_INIT,
1253          "PCI device with matchinng VendorId and DeviceId (%d,%d)\n",
1254          (UINTN) PciDataStructure->VendorId,
1255          (UINTN) PciDataStructure->DeviceId)
1256         );
1257 
1258     Status = LaunchBaseCode (SimpleNetworkDevice, RomAddress);
1259 
1260     if (!EFI_ERROR (Status)) {
1261       return EFI_SUCCESS;
1262     }
1263 
1264     //
1265     // Free resources allocated in LaunchBaseCode
1266     //
1267     Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice);
1268   }
1269 
1270   return EFI_NOT_FOUND;
1271 }
1272 
1273 /**
1274   Unload 16 bit UNDI Option ROM from memory
1275 
1276   @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
1277 
1278   @return EFI_STATUS
1279 **/
1280 EFI_STATUS
Undi16SimpleNetworkUnloadUndi(EFI_SIMPLE_NETWORK_DEV * SimpleNetworkDevice)1281 Undi16SimpleNetworkUnloadUndi (
1282   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
1283   )
1284 {
1285   if (SimpleNetworkDevice->UndiLoaderTable != NULL) {
1286     ZeroMem (SimpleNetworkDevice->UndiLoaderTable, SimpleNetworkDevice->UndiLoaderTablePages << EFI_PAGE_SHIFT);
1287     gBS->FreePages (
1288           (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->UndiLoaderTable,
1289           SimpleNetworkDevice->UndiLoaderTablePages
1290           );
1291   }
1292 
1293   if (SimpleNetworkDevice->DestinationDataSegment != NULL) {
1294     ZeroMem (
1295       SimpleNetworkDevice->DestinationDataSegment,
1296       SimpleNetworkDevice->DestinationDataSegmentPages << EFI_PAGE_SHIFT
1297       );
1298     gBS->FreePages (
1299           (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationDataSegment,
1300           SimpleNetworkDevice->DestinationDataSegmentPages
1301           );
1302   }
1303 
1304   if (SimpleNetworkDevice->DestinationStackSegment != NULL) {
1305     ZeroMem (
1306       SimpleNetworkDevice->DestinationStackSegment,
1307       SimpleNetworkDevice->DestinationStackSegmentPages << EFI_PAGE_SHIFT
1308       );
1309     gBS->FreePages (
1310           (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationStackSegment,
1311           SimpleNetworkDevice->DestinationStackSegmentPages
1312           );
1313   }
1314 
1315   if (SimpleNetworkDevice->DestinationCodeSegment != NULL) {
1316     ZeroMem (
1317       SimpleNetworkDevice->DestinationCodeSegment,
1318       SimpleNetworkDevice->DestinationCodeSegmentPages << EFI_PAGE_SHIFT
1319       );
1320     gBS->FreePages (
1321           (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationCodeSegment,
1322           SimpleNetworkDevice->DestinationCodeSegmentPages
1323           );
1324   }
1325 
1326   return EFI_SUCCESS;
1327 }
1328 
1329 /**
1330   Start the UNDI interface.
1331 
1332   @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
1333   @param Ax                  PCI address of Undi device.
1334 
1335   @retval EFI_DEVICE_ERROR Fail to start 16 bit UNDI ROM.
1336   @retval Others           Status of start 16 bit UNDI ROM.
1337 **/
1338 EFI_STATUS
Undi16SimpleNetworkStartUndi(EFI_SIMPLE_NETWORK_DEV * SimpleNetworkDevice,UINT16 Ax)1339 Undi16SimpleNetworkStartUndi (
1340   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice,
1341   UINT16                  Ax
1342   )
1343 {
1344   EFI_STATUS          Status;
1345   PXENV_START_UNDI_T  Start;
1346 
1347   //
1348   // Call 16 bit UNDI ROM to start the network interface
1349   //
1350   //
1351   // @bug : What is this state supposed to be???
1352   //
1353   Start.Status  = INIT_PXE_STATUS;
1354   Start.Ax      = Ax;
1355   Start.Bx      = 0x0000;
1356   Start.Dx      = 0x0000;
1357   Start.Di      = 0x0000;
1358   Start.Es      = 0x0000;
1359 
1360   Status        = PxeStartUndi (SimpleNetworkDevice, &Start);
1361   if (EFI_ERROR (Status)) {
1362     return Status;
1363   }
1364   //
1365   // Check the status code from the 16 bit UNDI ROM
1366   //
1367   if (Start.Status != PXENV_STATUS_SUCCESS) {
1368     return EFI_DEVICE_ERROR;
1369   }
1370 
1371   return Status;
1372 }
1373 
1374 
1375 /**
1376   Stop the UNDI interface
1377 
1378   @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
1379 
1380   @retval EFI_DEVICE_ERROR Fail to stop 16 bit UNDI ROM.
1381   @retval Others           Status of stop 16 bit UNDI ROM.
1382 **/
1383 EFI_STATUS
Undi16SimpleNetworkStopUndi(EFI_SIMPLE_NETWORK_DEV * SimpleNetworkDevice)1384 Undi16SimpleNetworkStopUndi (
1385   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
1386   )
1387 {
1388   EFI_STATUS        Status;
1389   PXENV_STOP_UNDI_T Stop;
1390 
1391   //
1392   // Call 16 bit UNDI ROM to start the network interface
1393   //
1394   Stop.Status = INIT_PXE_STATUS;
1395 
1396   Status      = PxeUndiStop (SimpleNetworkDevice, &Stop);
1397   if (EFI_ERROR (Status)) {
1398     return Status;
1399   }
1400   //
1401   // Check the status code from the 16 bit UNDI ROM
1402   //
1403   if (Stop.Status != PXENV_STATUS_SUCCESS) {
1404     return EFI_DEVICE_ERROR;
1405   }
1406 
1407   return Status;
1408 }
1409 
1410 /**
1411   Cleanup Unid network interface
1412 
1413   @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
1414 
1415   @retval EFI_DEVICE_ERROR Fail to cleanup 16 bit UNDI ROM.
1416   @retval Others           Status of cleanup 16 bit UNDI ROM.
1417 **/
1418 EFI_STATUS
Undi16SimpleNetworkCleanupUndi(EFI_SIMPLE_NETWORK_DEV * SimpleNetworkDevice)1419 Undi16SimpleNetworkCleanupUndi (
1420   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
1421   )
1422 {
1423   EFI_STATUS            Status;
1424   PXENV_UNDI_CLEANUP_T  Cleanup;
1425 
1426   //
1427   // Call 16 bit UNDI ROM to cleanup the network interface
1428   //
1429   Cleanup.Status  = INIT_PXE_STATUS;
1430 
1431   Status          = PxeUndiCleanup (SimpleNetworkDevice, &Cleanup);
1432   if (EFI_ERROR (Status)) {
1433     return Status;
1434   }
1435   //
1436   // Check the status code from the 16 bit UNDI ROM
1437   //
1438   if (Cleanup.Status != PXENV_STATUS_SUCCESS) {
1439     return EFI_DEVICE_ERROR;
1440   }
1441 
1442   return Status;
1443 }
1444 
1445 /**
1446   Get runtime information for Undi network interface
1447 
1448   @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
1449 
1450   @retval EFI_SUCCESS Sucess operation.
1451   @retval Others      Fail to get runtime information for Undi network interface.
1452 **/
1453 EFI_STATUS
Undi16SimpleNetworkGetInformation(IN EFI_SIMPLE_NETWORK_PROTOCOL * This)1454 Undi16SimpleNetworkGetInformation (
1455   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
1456   )
1457 {
1458   EFI_STATUS              Status;
1459   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
1460   UINTN                   Index;
1461 
1462   if (This == NULL) {
1463     return EFI_INVALID_PARAMETER;
1464   }
1465 
1466   Status              = EFI_SUCCESS;
1467   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
1468 
1469   if (SimpleNetworkDevice == NULL) {
1470     return EFI_DEVICE_ERROR;
1471   }
1472   //
1473   // Verify that the current state of the adapter is valid for this call.
1474   //
1475   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
1476   case EfiSimpleNetworkStarted:
1477   case EfiSimpleNetworkInitialized:
1478     break;
1479 
1480   case EfiSimpleNetworkStopped:
1481     return EFI_NOT_STARTED;
1482 
1483   default:
1484     return EFI_DEVICE_ERROR;
1485   }
1486   //
1487   // Call 16 bit UNDI ROM to start the network interface
1488   //
1489   ZeroMem (&SimpleNetworkDevice->GetInformation, sizeof (PXENV_UNDI_GET_INFORMATION_T));
1490 
1491   SimpleNetworkDevice->GetInformation.Status  = INIT_PXE_STATUS;
1492 
1493   Status = PxeUndiGetInformation (SimpleNetworkDevice, &SimpleNetworkDevice->GetInformation);
1494   if (EFI_ERROR (Status)) {
1495     return Status;
1496   }
1497 
1498   DEBUG ((DEBUG_NET, "  GetInformation.Status      = %d\n", SimpleNetworkDevice->GetInformation.Status));
1499   DEBUG ((DEBUG_NET, "  GetInformation.BaseIo      = %d\n", SimpleNetworkDevice->GetInformation.BaseIo));
1500   DEBUG ((DEBUG_NET, "  GetInformation.IntNumber   = %d\n", SimpleNetworkDevice->GetInformation.IntNumber));
1501   DEBUG ((DEBUG_NET, "  GetInformation.MaxTranUnit = %d\n", SimpleNetworkDevice->GetInformation.MaxTranUnit));
1502   DEBUG ((DEBUG_NET, "  GetInformation.HwType      = %d\n", SimpleNetworkDevice->GetInformation.HwType));
1503   DEBUG ((DEBUG_NET, "  GetInformation.HwAddrLen   = %d\n", SimpleNetworkDevice->GetInformation.HwAddrLen));
1504   DEBUG ((DEBUG_NET, "  GetInformation.ROMAddress  = %d\n", SimpleNetworkDevice->GetInformation.ROMAddress));
1505   DEBUG ((DEBUG_NET, "  GetInformation.RxBufCt     = %d\n", SimpleNetworkDevice->GetInformation.RxBufCt));
1506   DEBUG ((DEBUG_NET, "  GetInformation.TxBufCt     = %d\n", SimpleNetworkDevice->GetInformation.TxBufCt));
1507 
1508   DEBUG ((DEBUG_NET, "  GetInformation.CurNodeAddr ="));
1509   for (Index = 0; Index < 16; Index++) {
1510     DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->GetInformation.CurrentNodeAddress[Index]));
1511   }
1512 
1513   DEBUG ((DEBUG_NET, "\n"));
1514 
1515   DEBUG ((DEBUG_NET, "  GetInformation.PermNodeAddr ="));
1516   for (Index = 0; Index < 16; Index++) {
1517     DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->GetInformation.PermNodeAddress[Index]));
1518   }
1519 
1520   DEBUG ((DEBUG_NET, "\n"));
1521 
1522   //
1523   // Check the status code from the 16 bit UNDI ROM
1524   //
1525   if (SimpleNetworkDevice->GetInformation.Status != PXENV_STATUS_SUCCESS) {
1526     return EFI_DEVICE_ERROR;
1527   }
1528   //
1529   // The information has been retrieved.  Fill in Mode data.
1530   //
1531   SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize  = SimpleNetworkDevice->GetInformation.HwAddrLen;
1532 
1533   SimpleNetworkDevice->SimpleNetworkMode.MaxPacketSize  = SimpleNetworkDevice->GetInformation.MaxTranUnit;
1534 
1535   SimpleNetworkDevice->SimpleNetworkMode.IfType         = (UINT8) SimpleNetworkDevice->GetInformation.HwType;
1536 
1537   ZeroMem (
1538     &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
1539     sizeof SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress
1540     );
1541 
1542   CopyMem (
1543     &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
1544     &SimpleNetworkDevice->GetInformation.CurrentNodeAddress,
1545     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
1546     );
1547 
1548   ZeroMem (
1549     &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,
1550     sizeof SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress
1551     );
1552 
1553   CopyMem (
1554     &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,
1555     &SimpleNetworkDevice->GetInformation.PermNodeAddress,
1556     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
1557     );
1558 
1559   //
1560   // hard code broadcast address - not avail in PXE2.1
1561   //
1562   ZeroMem (
1563     &SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress,
1564     sizeof SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress
1565     );
1566 
1567   SetMem (
1568     &SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress,
1569     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize,
1570     0xff
1571     );
1572 
1573   return Status;
1574 }
1575 
1576 /**
1577   Get NIC type
1578 
1579   @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
1580 
1581   @retval EFI_SUCCESS Sucess operation.
1582   @retval Others      Fail to get NIC type.
1583 **/
1584 EFI_STATUS
Undi16SimpleNetworkGetNicType(IN EFI_SIMPLE_NETWORK_PROTOCOL * This)1585 Undi16SimpleNetworkGetNicType (
1586   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
1587   )
1588 {
1589   EFI_STATUS              Status;
1590   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
1591 
1592   if (This == NULL) {
1593     return EFI_INVALID_PARAMETER;
1594   }
1595 
1596   Status              = EFI_SUCCESS;
1597   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
1598 
1599   if (SimpleNetworkDevice == NULL) {
1600     return EFI_DEVICE_ERROR;
1601   }
1602 
1603   ZeroMem (&SimpleNetworkDevice->GetNicType, sizeof (PXENV_UNDI_GET_NIC_TYPE_T));
1604 
1605   SimpleNetworkDevice->GetNicType.Status  = INIT_PXE_STATUS;
1606 
1607   Status = PxeUndiGetNicType (SimpleNetworkDevice, &SimpleNetworkDevice->GetNicType);
1608 
1609   if (EFI_ERROR (Status)) {
1610     return Status;
1611   }
1612 
1613   DEBUG ((DEBUG_NET, "  GetNicType.Status      = %d\n", SimpleNetworkDevice->GetNicType.Status));
1614   DEBUG ((DEBUG_NET, "  GetNicType.NicType     = %d\n", SimpleNetworkDevice->GetNicType.NicType));
1615   //
1616   // Check the status code from the 16 bit UNDI ROM
1617   //
1618   if (SimpleNetworkDevice->GetNicType.Status != PXENV_STATUS_SUCCESS) {
1619     return EFI_DEVICE_ERROR;
1620   }
1621   //
1622   // The information has been retrieved.  Fill in Mode data.
1623   //
1624   return Status;
1625 }
1626 
1627 /**
1628   Get NDIS information
1629 
1630   @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
1631 
1632   @retval EFI_SUCCESS Sucess operation.
1633   @retval Others      Fail to get NDIS information.
1634 **/
1635 EFI_STATUS
Undi16SimpleNetworkGetNdisInfo(IN EFI_SIMPLE_NETWORK_PROTOCOL * This)1636 Undi16SimpleNetworkGetNdisInfo (
1637   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
1638   )
1639 {
1640   EFI_STATUS              Status;
1641   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
1642 
1643   if (This == NULL) {
1644     return EFI_INVALID_PARAMETER;
1645   }
1646 
1647   Status              = EFI_SUCCESS;
1648   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
1649 
1650   if (SimpleNetworkDevice == NULL) {
1651     return EFI_DEVICE_ERROR;
1652   }
1653 
1654   ZeroMem (&SimpleNetworkDevice->GetNdisInfo, sizeof (PXENV_UNDI_GET_NDIS_INFO_T));
1655 
1656   SimpleNetworkDevice->GetNdisInfo.Status = INIT_PXE_STATUS;
1657 
1658   Status = PxeUndiGetNdisInfo (SimpleNetworkDevice, &SimpleNetworkDevice->GetNdisInfo);
1659 
1660   if (EFI_ERROR (Status)) {
1661     return Status;
1662   }
1663 
1664   DEBUG ((DEBUG_NET, "  GetNdisInfo.Status       = %d\n", SimpleNetworkDevice->GetNdisInfo.Status));
1665   DEBUG ((DEBUG_NET, "  GetNdisInfo.IfaceType    = %a\n", SimpleNetworkDevice->GetNdisInfo.IfaceType));
1666   DEBUG ((DEBUG_NET, "  GetNdisInfo.LinkSpeed    = %d\n", SimpleNetworkDevice->GetNdisInfo.LinkSpeed));
1667   DEBUG ((DEBUG_NET, "  GetNdisInfo.ServiceFlags = %08x\n", SimpleNetworkDevice->GetNdisInfo.ServiceFlags));
1668 
1669   //
1670   // Check the status code from the 16 bit UNDI ROM
1671   //
1672   if (SimpleNetworkDevice->GetNdisInfo.Status != PXENV_STATUS_SUCCESS) {
1673     return EFI_DEVICE_ERROR;
1674   }
1675   //
1676   // The information has been retrieved.  Fill in Mode data.
1677   //
1678   return Status;
1679 }
1680 
1681 /**
1682   Call Undi ROM 16bit ISR() to check interrupt cause.
1683 
1684   @param This               A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
1685   @param FrameLength        The length of frame buffer.
1686   @param FrameHeaderLength  The length of frame buffer's header if has.
1687   @param Frame              The frame buffer to process network interrupt.
1688   @param ProtType           The type network transmit protocol
1689   @param PktType            The type of package.
1690 
1691   @retval EFI_DEVICE_ERROR  Fail to execute 16 bit ROM's ISR, or status is invalid.
1692   @retval EFI_SUCCESS       Success operation.
1693 **/
1694 EFI_STATUS
Undi16SimpleNetworkIsr(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,IN UINTN * FrameLength,IN UINTN * FrameHeaderLength,OPTIONAL IN UINT8 * Frame,OPTIONAL IN UINT8 * ProtType,OPTIONAL IN UINT8 * PktType OPTIONAL)1695 Undi16SimpleNetworkIsr (
1696   IN EFI_SIMPLE_NETWORK_PROTOCOL * This,
1697   IN UINTN                       *FrameLength,
1698   IN UINTN                       *FrameHeaderLength, OPTIONAL
1699   IN UINT8                       *Frame, OPTIONAL
1700   IN UINT8                       *ProtType, OPTIONAL
1701   IN UINT8                       *PktType OPTIONAL
1702   )
1703 {
1704   EFI_STATUS              Status;
1705   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
1706   BOOLEAN                 FrameReceived;
1707 
1708   if (This == NULL) {
1709     return EFI_INVALID_PARAMETER;
1710   }
1711 
1712   Status              = EFI_SUCCESS;
1713   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
1714 
1715   if (SimpleNetworkDevice == NULL) {
1716     return EFI_DEVICE_ERROR;
1717   }
1718 
1719   FrameReceived = FALSE;
1720 
1721   //
1722   // Verify that the current state of the adapter is valid for this call.
1723   //
1724   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
1725   case EfiSimpleNetworkInitialized:
1726     break;
1727 
1728   case EfiSimpleNetworkStopped:
1729     return EFI_NOT_STARTED;
1730 
1731   case EfiSimpleNetworkStarted:
1732   default:
1733     return EFI_DEVICE_ERROR;
1734   }
1735 
1736   DEBUG ((DEBUG_NET, "Isr() IsrValid = %d\n", SimpleNetworkDevice->IsrValid));
1737 
1738   if (!SimpleNetworkDevice->IsrValid) {
1739     //
1740     // Call 16 bit UNDI ROM to open the network interface
1741     //
1742     ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T));
1743     SimpleNetworkDevice->Isr.Status   = INIT_PXE_STATUS;
1744     SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_START;
1745 
1746     DEBUG ((DEBUG_NET, "Isr() START\n"));
1747 
1748     Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr);
1749     if (EFI_ERROR (Status)) {
1750       return Status;
1751     }
1752     //
1753     // Check the status code from the 16 bit UNDI ROM
1754     //
1755     if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) {
1756       return EFI_DEVICE_ERROR;
1757     }
1758     //
1759     // There have been no events on this UNDI interface, so return EFI_NOT_READY
1760     //
1761     if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_NOT_OURS) {
1762       return EFI_SUCCESS;
1763     }
1764     //
1765     // There is data to process, so call until all events processed.
1766     //
1767     ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T));
1768     SimpleNetworkDevice->Isr.Status   = INIT_PXE_STATUS;
1769     SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_PROCESS;
1770 
1771     DEBUG ((DEBUG_NET, "Isr() PROCESS\n"));
1772 
1773     Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr);
1774     if (EFI_ERROR (Status)) {
1775       return Status;
1776     }
1777 
1778     SimpleNetworkDevice->IsrValid = TRUE;
1779   }
1780   //
1781   // Call UNDI GET_NEXT until DONE
1782   //
1783   while (SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_DONE) {
1784     //
1785     // Check the status code from the 16 bit UNDI ROM
1786     //
1787     if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) {
1788       return EFI_DEVICE_ERROR;
1789     }
1790     //
1791     // UNDI is busy.  Caller will have to call again.
1792     // This should never happen with a polled mode driver.
1793     //
1794     if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_BUSY) {
1795       DEBUG ((DEBUG_NET, "  BUSY\n"));
1796       return EFI_SUCCESS;
1797     }
1798     //
1799     // Check for invalud UNDI FuncFlag
1800     //
1801     if (SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_RECEIVE &&
1802         SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_TRANSMIT
1803         ) {
1804       DEBUG ((DEBUG_NET, "  Invalid SimpleNetworkDevice->Isr.FuncFlag value %d\n", SimpleNetworkDevice->Isr.FuncFlag));
1805       return EFI_DEVICE_ERROR;
1806     }
1807     //
1808     // Check for Transmit Event
1809     //
1810     if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_TRANSMIT) {
1811       DEBUG ((DEBUG_NET, "  TRANSMIT\n"));
1812       SimpleNetworkDevice->InterruptStatus |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
1813     }
1814     //
1815     // Check for Receive Event
1816     //
1817     else if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_RECEIVE) {
1818       //
1819       // note - this code will hang on a receive interrupt in a GetStatus loop
1820       //
1821       DEBUG ((DEBUG_NET, "  RECEIVE\n"));
1822       SimpleNetworkDevice->InterruptStatus |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
1823 
1824       DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.BufferLength      = %d\n", SimpleNetworkDevice->Isr.BufferLength));
1825       DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.FrameLength       = %d\n", SimpleNetworkDevice->Isr.FrameLength));
1826       DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.FrameHeaderLength = %d\n", SimpleNetworkDevice->Isr.FrameHeaderLength));
1827       DEBUG (
1828         (
1829         DEBUG_NET, "SimpleNetworkDevice->Isr.Frame             = %04x:%04x\n", SimpleNetworkDevice->Isr.FrameSegSel,
1830         SimpleNetworkDevice->Isr.FrameOffset
1831         )
1832         );
1833       DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.ProtType          = 0x%02x\n", SimpleNetworkDevice->Isr.BufferLength));
1834       DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.PktType           = 0x%02x\n", SimpleNetworkDevice->Isr.BufferLength));
1835 
1836       if (FrameReceived) {
1837         return EFI_SUCCESS;
1838       }
1839 
1840       if ((Frame == NULL) || (SimpleNetworkDevice->Isr.FrameLength > *FrameLength)) {
1841         DEBUG ((DEBUG_NET, "return EFI_BUFFER_TOO_SMALL   *FrameLength = %08x\n", *FrameLength));
1842         *FrameLength = SimpleNetworkDevice->Isr.FrameLength;
1843         return EFI_BUFFER_TOO_SMALL;
1844       }
1845 
1846       *FrameLength = SimpleNetworkDevice->Isr.FrameLength;
1847       if (FrameHeaderLength != NULL) {
1848         *FrameHeaderLength = SimpleNetworkDevice->Isr.FrameHeaderLength;
1849       }
1850 
1851       if (ProtType != NULL) {
1852         *ProtType = SimpleNetworkDevice->Isr.ProtType;
1853       }
1854 
1855       if (PktType != NULL) {
1856         *PktType = SimpleNetworkDevice->Isr.PktType;
1857       }
1858 
1859       CopyMem (
1860         Frame,
1861         (VOID *)(UINTN) ((SimpleNetworkDevice->Isr.FrameSegSel << 4) + SimpleNetworkDevice->Isr.FrameOffset),
1862         SimpleNetworkDevice->Isr.BufferLength
1863         );
1864       Frame = Frame + SimpleNetworkDevice->Isr.BufferLength;
1865       if (SimpleNetworkDevice->Isr.BufferLength == SimpleNetworkDevice->Isr.FrameLength) {
1866         FrameReceived = TRUE;
1867       }
1868     }
1869     //
1870     // There is data to process, so call until all events processed.
1871     //
1872     ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T));
1873     SimpleNetworkDevice->Isr.Status   = INIT_PXE_STATUS;
1874     SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
1875 
1876     DEBUG ((DEBUG_NET, "Isr() GET NEXT\n"));
1877 
1878     Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr);
1879     if (EFI_ERROR (Status)) {
1880       return Status;
1881     }
1882     //
1883     // Check the status code from the 16 bit UNDI ROM
1884     //
1885     //        if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) {
1886     //            return EFI_DEVICE_ERROR;
1887     //        }
1888     //
1889   }
1890 
1891   SimpleNetworkDevice->IsrValid = FALSE;
1892   return EFI_SUCCESS;
1893 }
1894 //
1895 // ///////////////////////////////////////////////////////////////////////////////////////
1896 // Simple Network Protocol Interface Functions using 16 bit UNDI Option ROMs
1897 /////////////////////////////////////////////////////////////////////////////////////////
1898 //
1899 // Start()
1900 //
1901 /**
1902   Call 16 bit UNDI ROM to start the network interface
1903 
1904   @param This       A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
1905 
1906   @retval EFI_DEVICE_ERROR Network interface has not be initialized.
1907   @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call.
1908   @retval EFI_SUCESS       Success operation.
1909 **/
1910 EFI_STATUS
1911 EFIAPI
Undi16SimpleNetworkStart(IN EFI_SIMPLE_NETWORK_PROTOCOL * This)1912 Undi16SimpleNetworkStart (
1913   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
1914   )
1915 {
1916   EFI_STATUS              Status;
1917   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
1918   PXENV_UNDI_STARTUP_T    Startup;
1919 
1920   if (This == NULL) {
1921     return EFI_INVALID_PARAMETER;
1922   }
1923 
1924   Status              = EFI_SUCCESS;
1925   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
1926 
1927   if (SimpleNetworkDevice == NULL) {
1928     return EFI_DEVICE_ERROR;
1929   }
1930   //
1931   // Verify that the current state of the adapter is valid for this call.
1932   //
1933   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
1934   case EfiSimpleNetworkStopped:
1935     break;
1936 
1937   case EfiSimpleNetworkStarted:
1938   case EfiSimpleNetworkInitialized:
1939     return EFI_ALREADY_STARTED;
1940 
1941   default:
1942     return EFI_DEVICE_ERROR;
1943   }
1944   //
1945   // Call 16 bit UNDI ROM to start the network interface
1946   //
1947   Startup.Status  = INIT_PXE_STATUS;
1948 
1949   Status          = PxeUndiStartup (SimpleNetworkDevice, &Startup);
1950   if (EFI_ERROR (Status)) {
1951     return Status;
1952   }
1953   //
1954   // Check the status code from the 16 bit UNDI ROM
1955   //
1956   if (Startup.Status != PXENV_STATUS_SUCCESS) {
1957     return EFI_DEVICE_ERROR;
1958   }
1959   //
1960   // The UNDI interface has been started, so update the State.
1961   //
1962   SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStarted;
1963 
1964   //
1965   //
1966   //
1967   SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting = 0;
1968   SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount     = 0;
1969 
1970   return Status;
1971 }
1972 //
1973 // Stop()
1974 //
1975 /**
1976   Call 16 bit UNDI ROM to stop the network interface
1977 
1978   @param This       A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
1979 
1980   @retval EFI_DEVICE_ERROR Network interface has not be initialized.
1981   @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call.
1982   @retval EFI_SUCESS       Success operation.
1983 **/
1984 EFI_STATUS
1985 EFIAPI
Undi16SimpleNetworkStop(IN EFI_SIMPLE_NETWORK_PROTOCOL * This)1986 Undi16SimpleNetworkStop (
1987   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
1988   )
1989 {
1990   EFI_STATUS              Status;
1991   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
1992 
1993   if (This == NULL) {
1994     return EFI_INVALID_PARAMETER;
1995   }
1996 
1997   Status              = EFI_SUCCESS;
1998   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
1999 
2000   if (SimpleNetworkDevice == NULL) {
2001     return EFI_DEVICE_ERROR;
2002   }
2003   //
2004   // Verify that the current state of the adapter is valid for this call.
2005   //
2006   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
2007   case EfiSimpleNetworkStarted:
2008     break;
2009 
2010   case EfiSimpleNetworkStopped:
2011     return EFI_NOT_STARTED;
2012 
2013   case EfiSimpleNetworkInitialized:
2014   default:
2015     return EFI_DEVICE_ERROR;
2016   }
2017 
2018   SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStopped;
2019 
2020   return Status;
2021 }
2022 
2023 //
2024 // Initialize()
2025 //
2026 /**
2027   Initialize network interface
2028 
2029   @param This                 A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
2030   @param ExtraRxBufferSize    The size of extra request receive buffer.
2031   @param ExtraTxBufferSize    The size of extra request transmit buffer.
2032 
2033   @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call.
2034   @retval EFI_SUCESS       Success operation.
2035 **/
2036 EFI_STATUS
2037 EFIAPI
Undi16SimpleNetworkInitialize(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,IN UINTN ExtraRxBufferSize OPTIONAL,IN UINTN ExtraTxBufferSize OPTIONAL)2038 Undi16SimpleNetworkInitialize (
2039   IN EFI_SIMPLE_NETWORK_PROTOCOL            *This,
2040   IN UINTN                                  ExtraRxBufferSize  OPTIONAL,
2041   IN UINTN                                  ExtraTxBufferSize  OPTIONAL
2042   )
2043 {
2044   EFI_STATUS              Status;
2045   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
2046   PXENV_UNDI_INITIALIZE_T Initialize;
2047   PXENV_UNDI_OPEN_T       Open;
2048 
2049   if (This == NULL) {
2050     return EFI_INVALID_PARAMETER;
2051   }
2052 
2053   Status              = EFI_SUCCESS;
2054   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
2055 
2056   if (SimpleNetworkDevice == NULL) {
2057     return EFI_DEVICE_ERROR;
2058   }
2059   //
2060   // Verify that the current state of the adapter is valid for this call.
2061   //
2062   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
2063   case EfiSimpleNetworkStopped:
2064     return EFI_NOT_STARTED;
2065 
2066   case EfiSimpleNetworkStarted:
2067     break;
2068 
2069   case EfiSimpleNetworkInitialized:
2070   default:
2071     return EFI_DEVICE_ERROR;
2072   }
2073   //
2074   // Call 16 bit UNDI ROM to start the network interface
2075   //
2076   Initialize.Status       = INIT_PXE_STATUS;
2077   Initialize.ProtocolIni  = 0;
2078 
2079   Status                  = PxeUndiInitialize (SimpleNetworkDevice, &Initialize);
2080 
2081   if (EFI_ERROR (Status)) {
2082     DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiInitialize() - Status = %r\n", Status));
2083     DEBUG ((DEBUG_ERROR, "Initialize.Status == %xh\n", Initialize.Status));
2084 
2085     if (Initialize.Status == PXENV_STATUS_UNDI_MEDIATEST_FAILED) {
2086       Status = EFI_NO_MEDIA;
2087     }
2088 
2089     return Status;
2090   }
2091   //
2092   // Check the status code from the 16 bit UNDI ROM
2093   //
2094   if (Initialize.Status != PXENV_STATUS_SUCCESS) {
2095     DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiInitialize() - Initialize.Status = %04x\n", Initialize.Status));
2096     return EFI_DEVICE_ERROR;
2097   }
2098   //
2099   // Call 16 bit UNDI ROM to open the network interface
2100   //
2101   Open.Status     = INIT_PXE_STATUS;
2102   Open.OpenFlag   = 0;
2103   Open.PktFilter  = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting);
2104   Undi16GetMCastFilters (
2105     &SimpleNetworkDevice->SimpleNetworkMode,
2106     &Open.McastBuffer,
2107     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
2108     );
2109 
2110   Status = PxeUndiOpen (SimpleNetworkDevice, &Open);
2111 
2112   if (EFI_ERROR (Status)) {
2113     DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiOpen() - Status = %r\n", Status));
2114     return Status;
2115   }
2116   //
2117   // Check the status code from the 16 bit UNDI ROM
2118   //
2119   if (Open.Status != PXENV_STATUS_SUCCESS) {
2120     DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiOpen() - Open.Status = %04x\n", Open.Status));
2121     return EFI_DEVICE_ERROR;
2122   }
2123   //
2124   // The UNDI interface has been initialized, so update the State.
2125   //
2126   SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkInitialized;
2127 
2128   //
2129   // If initialize succeeds, then assume that media is present.
2130   //
2131   SimpleNetworkDevice->SimpleNetworkMode.MediaPresent = TRUE;
2132 
2133   //
2134   // Reset the recycled transmit buffer FIFO
2135   //
2136   SimpleNetworkDevice->TxBufferFifo.First = 0;
2137   SimpleNetworkDevice->TxBufferFifo.Last  = 0;
2138   SimpleNetworkDevice->IsrValid           = FALSE;
2139 
2140   return Status;
2141 }
2142 //
2143 // Reset()
2144 //
2145 /**
2146   Reset network interface.
2147 
2148   @param This                 A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
2149   @param ExtendedVerification Need extended verfication.
2150 
2151   @retval EFI_INVALID_PARAMETER Invalid This paramter.
2152   @retval EFI_DEVICE_ERROR      Network device has not been initialized.
2153   @retval EFI_NOT_STARTED       Network device has been stopped.
2154   @retval EFI_DEVICE_ERROR      Invalid status for network device
2155   @retval EFI_SUCCESS           Success operation.
2156 **/
2157 EFI_STATUS
2158 EFIAPI
Undi16SimpleNetworkReset(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,IN BOOLEAN ExtendedVerification)2159 Undi16SimpleNetworkReset (
2160   IN EFI_SIMPLE_NETWORK_PROTOCOL   *This,
2161   IN BOOLEAN                       ExtendedVerification
2162   )
2163 {
2164   EFI_STATUS              Status;
2165   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
2166   PXENV_UNDI_RESET_T      Reset;
2167   UINT16                  Rx_filter;
2168 
2169   if (This == NULL) {
2170     return EFI_INVALID_PARAMETER;
2171   }
2172 
2173   Status              = EFI_SUCCESS;
2174   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
2175 
2176   if (SimpleNetworkDevice == NULL) {
2177     return EFI_DEVICE_ERROR;
2178   }
2179   //
2180   // Verify that the current state of the adapter is valid for this call.
2181   //
2182   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
2183   case EfiSimpleNetworkStopped:
2184     return EFI_NOT_STARTED;
2185 
2186   case EfiSimpleNetworkInitialized:
2187     break;
2188 
2189   case EfiSimpleNetworkStarted:
2190   default:
2191     return EFI_DEVICE_ERROR;
2192   }
2193 
2194   Reset.Status  = INIT_PXE_STATUS;
2195 
2196   Rx_filter     = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting);
2197 
2198   Undi16GetMCastFilters (
2199     &SimpleNetworkDevice->SimpleNetworkMode,
2200     &Reset.R_Mcast_Buf,
2201     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
2202     );
2203 
2204   Status = PxeUndiResetNic (SimpleNetworkDevice, &Reset, Rx_filter);
2205 
2206   if (EFI_ERROR (Status)) {
2207     return Status;
2208   }
2209   //
2210   // Check the status code from the 16 bit UNDI ROM
2211   //
2212   if (Reset.Status != PXENV_STATUS_SUCCESS) {
2213     return EFI_DEVICE_ERROR;
2214   }
2215   //
2216   // Reset the recycled transmit buffer FIFO
2217   //
2218   SimpleNetworkDevice->TxBufferFifo.First = 0;
2219   SimpleNetworkDevice->TxBufferFifo.Last  = 0;
2220   SimpleNetworkDevice->IsrValid           = FALSE;
2221 
2222   return Status;
2223 }
2224 //
2225 // Shutdown()
2226 //
2227 /**
2228   Shutdown network interface.
2229 
2230   @param This                 A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
2231 
2232   @retval EFI_INVALID_PARAMETER Invalid This paramter.
2233   @retval EFI_DEVICE_ERROR      Network device has not been initialized.
2234   @retval EFI_NOT_STARTED       Network device has been stopped.
2235   @retval EFI_DEVICE_ERROR      Invalid status for network device
2236   @retval EFI_SUCCESS           Success operation.
2237 **/
2238 EFI_STATUS
2239 EFIAPI
Undi16SimpleNetworkShutdown(IN EFI_SIMPLE_NETWORK_PROTOCOL * This)2240 Undi16SimpleNetworkShutdown (
2241   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
2242   )
2243 {
2244   EFI_STATUS              Status;
2245   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
2246   PXENV_UNDI_CLOSE_T      Close;
2247   PXENV_UNDI_SHUTDOWN_T   Shutdown;
2248 
2249   if (This == NULL) {
2250     return EFI_INVALID_PARAMETER;
2251   }
2252 
2253   Status              = EFI_SUCCESS;
2254   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
2255 
2256   if (SimpleNetworkDevice == NULL) {
2257     return EFI_DEVICE_ERROR;
2258   }
2259   //
2260   // Verify that the current state of the adapter is valid for this call.
2261   //
2262   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
2263   case EfiSimpleNetworkStopped:
2264     return EFI_NOT_STARTED;
2265 
2266   case EfiSimpleNetworkInitialized:
2267     break;
2268 
2269   case EfiSimpleNetworkStarted:
2270   default:
2271     return EFI_DEVICE_ERROR;
2272   }
2273 
2274   SimpleNetworkDevice->IsrValid = FALSE;
2275 
2276   //
2277   // Call 16 bit UNDI ROM to start the network interface
2278   //
2279   Close.Status  = INIT_PXE_STATUS;
2280 
2281   Status        = PxeUndiClose (SimpleNetworkDevice, &Close);
2282 
2283   if (EFI_ERROR (Status)) {
2284     return Status;
2285   }
2286   //
2287   // Check the status code from the 16 bit UNDI ROM
2288   //
2289   if (Close.Status != PXENV_STATUS_SUCCESS) {
2290     return EFI_DEVICE_ERROR;
2291   }
2292   //
2293   // Call 16 bit UNDI ROM to open the network interface
2294   //
2295   Shutdown.Status = INIT_PXE_STATUS;
2296 
2297   Status          = PxeUndiShutdown (SimpleNetworkDevice, &Shutdown);
2298 
2299   if (EFI_ERROR (Status)) {
2300     return Status;
2301   }
2302   //
2303   // Check the status code from the 16 bit UNDI ROM
2304   //
2305   if (Shutdown.Status != PXENV_STATUS_SUCCESS) {
2306     return EFI_DEVICE_ERROR;
2307   }
2308   //
2309   // The UNDI interface has been initialized, so update the State.
2310   //
2311   SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStarted;
2312 
2313   //
2314   // If shutdown succeeds, then assume that media is not present.
2315   //
2316   SimpleNetworkDevice->SimpleNetworkMode.MediaPresent = FALSE;
2317 
2318   //
2319   // Reset the recycled transmit buffer FIFO
2320   //
2321   SimpleNetworkDevice->TxBufferFifo.First = 0;
2322   SimpleNetworkDevice->TxBufferFifo.Last  = 0;
2323 
2324   //
2325   // A short delay.  Without this an initialize immediately following
2326   // a shutdown will cause some versions of UNDI-16 to stop operating.
2327   //
2328   gBS->Stall (250000);
2329 
2330   return Status;
2331 }
2332 //
2333 // ReceiveFilters()
2334 //
2335 /**
2336   Reset network interface.
2337 
2338   @param This                 A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
2339   @param Enable               Enable mask value
2340   @param Disable              Disable mask value
2341   @param ResetMCastFilter     Whether reset multi cast filter or not
2342   @param MCastFilterCnt       Count of mutli cast filter for different MAC address
2343   @param MCastFilter          Buffer for mustli cast filter for different MAC address.
2344 
2345   @retval EFI_INVALID_PARAMETER Invalid This paramter.
2346   @retval EFI_DEVICE_ERROR      Network device has not been initialized.
2347   @retval EFI_NOT_STARTED       Network device has been stopped.
2348   @retval EFI_DEVICE_ERROR      Invalid status for network device
2349   @retval EFI_SUCCESS           Success operation.
2350 **/
2351 EFI_STATUS
2352 EFIAPI
Undi16SimpleNetworkReceiveFilters(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,IN UINT32 Enable,IN UINT32 Disable,IN BOOLEAN ResetMCastFilter,IN UINTN MCastFilterCnt OPTIONAL,IN EFI_MAC_ADDRESS * MCastFilter OPTIONAL)2353 Undi16SimpleNetworkReceiveFilters (
2354   IN EFI_SIMPLE_NETWORK_PROTOCOL                     * This,
2355   IN UINT32                                          Enable,
2356   IN UINT32                                          Disable,
2357   IN BOOLEAN                                         ResetMCastFilter,
2358   IN UINTN                                           MCastFilterCnt     OPTIONAL,
2359   IN EFI_MAC_ADDRESS                                 * MCastFilter OPTIONAL
2360   )
2361 {
2362   EFI_STATUS              Status;
2363   UINTN                   Index;
2364   UINT32                  NewFilter;
2365   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
2366   PXENV_UNDI_CLOSE_T      Close;
2367   PXENV_UNDI_OPEN_T       Open;
2368 
2369   if (This == NULL) {
2370     return EFI_INVALID_PARAMETER;
2371   }
2372 
2373   Status              = EFI_SUCCESS;
2374   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
2375 
2376   if (SimpleNetworkDevice == NULL) {
2377     return EFI_DEVICE_ERROR;
2378   }
2379   //
2380   // Verify that the current state of the adapter is valid for this call.
2381   //
2382   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
2383   case EfiSimpleNetworkStopped:
2384     return EFI_NOT_STARTED;
2385 
2386   case EfiSimpleNetworkInitialized:
2387     break;
2388 
2389   case EfiSimpleNetworkStarted:
2390   default:
2391     return EFI_DEVICE_ERROR;
2392   }
2393   //
2394   // First deal with possible filter setting changes
2395   //
2396   if ((Enable == 0) && (Disable == 0) && !ResetMCastFilter) {
2397     return EFI_SUCCESS;
2398   }
2399 
2400   NewFilter = (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting | Enable) &~Disable;
2401 
2402   if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
2403     if ((MCastFilterCnt == 0) || (MCastFilter == 0) || MCastFilterCnt > SimpleNetworkDevice->SimpleNetworkMode.MaxMCastFilterCount) {
2404       return EFI_INVALID_PARAMETER;
2405     }
2406   }
2407   //
2408   // Call 16 bit UNDI ROM to close the network interface
2409   //
2410   Close.Status  = INIT_PXE_STATUS;
2411 
2412   Status        = PxeUndiClose (SimpleNetworkDevice, &Close);
2413 
2414   if (EFI_ERROR (Status)) {
2415     return Status;
2416   }
2417   //
2418   // Check the status code from the 16 bit UNDI ROM
2419   //
2420   if (Close.Status != PXENV_STATUS_SUCCESS) {
2421     return EFI_DEVICE_ERROR;
2422   }
2423   //
2424   // Call 16 bit UNDI ROM to open the network interface
2425   //
2426   //
2427   // Reset the recycled transmit buffer FIFO
2428   //
2429   SimpleNetworkDevice->TxBufferFifo.First = 0;
2430   SimpleNetworkDevice->TxBufferFifo.Last  = 0;
2431 
2432   //
2433   // Call 16 bit UNDI ROM to open the network interface
2434   //
2435   ZeroMem (&Open, sizeof Open);
2436 
2437   Open.Status     = INIT_PXE_STATUS;
2438   Open.PktFilter  = Undi16GetPacketFilterSetting (NewFilter);
2439 
2440   if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
2441     //
2442     // Copy the MAC addresses into the UNDI open parameter structure
2443     //
2444     Open.McastBuffer.MCastAddrCount = (UINT16) MCastFilterCnt;
2445     for (Index = 0; Index < MCastFilterCnt; ++Index) {
2446       CopyMem (
2447         Open.McastBuffer.MCastAddr[Index],
2448         &MCastFilter[Index],
2449         sizeof Open.McastBuffer.MCastAddr[Index]
2450         );
2451     }
2452   } else if (!ResetMCastFilter) {
2453     for (Index = 0; Index < SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount; ++Index) {
2454       CopyMem (
2455         Open.McastBuffer.MCastAddr[Index],
2456         &SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index],
2457         sizeof Open.McastBuffer.MCastAddr[Index]
2458         );
2459     }
2460   }
2461 
2462   Status = PxeUndiOpen (SimpleNetworkDevice, &Open);
2463 
2464   if (EFI_ERROR (Status)) {
2465     return Status;
2466   }
2467   //
2468   // Check the status code from the 16 bit UNDI ROM
2469   //
2470   if (Open.Status != PXENV_STATUS_SUCCESS) {
2471     return EFI_DEVICE_ERROR;
2472   }
2473 
2474   SimpleNetworkDevice->IsrValid = FALSE;
2475   SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting = NewFilter;
2476 
2477   if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
2478     SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount = (UINT32) MCastFilterCnt;
2479     for (Index = 0; Index < MCastFilterCnt; ++Index) {
2480       CopyMem (
2481         &SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index],
2482         &MCastFilter[Index],
2483         sizeof (EFI_MAC_ADDRESS)
2484         );
2485     }
2486   }
2487   //
2488   // Read back multicast addresses.
2489   //
2490   return EFI_SUCCESS;
2491 }
2492 //
2493 // StationAddress()
2494 //
2495 /**
2496   Set new MAC address.
2497 
2498   @param This                 A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
2499   @param Reset                Whether reset station MAC address to permenent address
2500   @param New                  A pointer to New address
2501 
2502   @retval EFI_INVALID_PARAMETER Invalid This paramter.
2503   @retval EFI_DEVICE_ERROR      Network device has not been initialized.
2504   @retval EFI_NOT_STARTED       Network device has been stopped.
2505   @retval EFI_DEVICE_ERROR      Invalid status for network device
2506   @retval EFI_SUCCESS           Success operation.
2507 **/
2508 EFI_STATUS
2509 EFIAPI
Undi16SimpleNetworkStationAddress(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,IN BOOLEAN Reset,IN EFI_MAC_ADDRESS * New OPTIONAL)2510 Undi16SimpleNetworkStationAddress (
2511   IN EFI_SIMPLE_NETWORK_PROTOCOL           * This,
2512   IN BOOLEAN                               Reset,
2513   IN EFI_MAC_ADDRESS                       * New OPTIONAL
2514   )
2515 {
2516   EFI_STATUS                    Status;
2517   EFI_SIMPLE_NETWORK_DEV        *SimpleNetworkDevice;
2518   PXENV_UNDI_SET_STATION_ADDR_T SetStationAddr;
2519   //
2520   // EFI_DEVICE_PATH_PROTOCOL     *OldDevicePath;
2521   //
2522   PXENV_UNDI_CLOSE_T            Close;
2523   PXENV_UNDI_OPEN_T             Open;
2524 
2525   if (This == NULL) {
2526     return EFI_INVALID_PARAMETER;
2527   }
2528 
2529   Status              = EFI_SUCCESS;
2530 
2531   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
2532 
2533   if (SimpleNetworkDevice == NULL) {
2534     return EFI_DEVICE_ERROR;
2535   }
2536   //
2537   // Verify that the current state of the adapter is valid for this call.
2538   //
2539   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
2540   case EfiSimpleNetworkInitialized:
2541     break;
2542 
2543   case EfiSimpleNetworkStopped:
2544     return EFI_NOT_STARTED;
2545 
2546   case EfiSimpleNetworkStarted:
2547   default:
2548     return EFI_DEVICE_ERROR;
2549   }
2550   //
2551   // Call 16 bit UNDI ROM to open the network interface
2552   //
2553   SetStationAddr.Status = INIT_PXE_STATUS;
2554 
2555   if (Reset) {
2556     //
2557     // If we are reseting the Station Address to the permanent address, and the
2558     // Station Address is not programmable, then just return EFI_SUCCESS.
2559     //
2560     if (!SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable) {
2561       return EFI_SUCCESS;
2562     }
2563     //
2564     // If the address is already the permanent address, then just return success.
2565     //
2566     if (CompareMem (
2567           &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
2568           &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,
2569           SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
2570           ) == 0) {
2571       return EFI_SUCCESS;
2572     }
2573     //
2574     // Copy the adapters permanent address to the new station address
2575     //
2576     CopyMem (
2577       &SetStationAddr.StationAddress,
2578       &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,
2579       SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
2580       );
2581   } else {
2582     //
2583     // If we are setting the Station Address, and the
2584     // Station Address is not programmable, return invalid parameter.
2585     //
2586     if (!SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable) {
2587       return EFI_INVALID_PARAMETER;
2588     }
2589     //
2590     // If the address is already the new address, then just return success.
2591     //
2592     if (CompareMem (
2593           &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
2594           New,
2595           SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
2596           ) == 0) {
2597       return EFI_SUCCESS;
2598     }
2599     //
2600     // Copy New to the new station address
2601     //
2602     CopyMem (
2603       &SetStationAddr.StationAddress,
2604       New,
2605       SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
2606       );
2607 
2608   }
2609   //
2610   // Call 16 bit UNDI ROM to stop the network interface
2611   //
2612   Close.Status = INIT_PXE_STATUS;
2613 
2614   PxeUndiClose (SimpleNetworkDevice, &Close);
2615 
2616   //
2617   // Call 16-bit UNDI ROM to set the station address
2618   //
2619   SetStationAddr.Status = PXENV_STATUS_SUCCESS;
2620 
2621   Status                = PxeUndiSetStationAddr (SimpleNetworkDevice, &SetStationAddr);
2622 
2623   //
2624   // Call 16-bit UNDI ROM to start the network interface
2625   //
2626   Open.Status     = PXENV_STATUS_SUCCESS;
2627   Open.OpenFlag   = 0;
2628   Open.PktFilter  = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting);
2629   Undi16GetMCastFilters (
2630     &SimpleNetworkDevice->SimpleNetworkMode,
2631     &Open.McastBuffer,
2632     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
2633     );
2634 
2635   PxeUndiOpen (SimpleNetworkDevice, &Open);
2636 
2637   //
2638   // Check status from station address change
2639   //
2640   if (EFI_ERROR (Status)) {
2641     return Status;
2642   }
2643   //
2644   // Check the status code from the 16 bit UNDI ROM
2645   //
2646   if (SetStationAddr.Status != PXENV_STATUS_SUCCESS) {
2647     return EFI_DEVICE_ERROR;
2648   }
2649 
2650   CopyMem (
2651     &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
2652     &SetStationAddr.StationAddress,
2653     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
2654     );
2655 
2656 #if 0 /* The device path is based on the permanent address not the current address. */
2657   //
2658   // The station address was changed, so update the device path with the new MAC address.
2659   //
2660   OldDevicePath                   = SimpleNetworkDevice->DevicePath;
2661   SimpleNetworkDevice->DevicePath = DuplicateDevicePath (SimpleNetworkDevice->BaseDevicePath);
2662   SimpleNetworkAppendMacAddressDevicePath (
2663     &SimpleNetworkDevice->DevicePath,
2664     &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress
2665     );
2666 
2667   Status = LibReinstallProtocolInterfaces (
2668             SimpleNetworkDevice->Handle,
2669             &DevicePathProtocol,
2670             OldDevicePath,
2671             SimpleNetworkDevice->DevicePath,
2672             NULL
2673             );
2674 
2675   if (EFI_ERROR (Status)) {
2676     DEBUG ((DEBUG_ERROR, "Failed to reinstall the DevicePath protocol for the Simple Network Device\n"));
2677     DEBUG ((DEBUG_ERROR, "  Status = %r\n", Status));
2678   }
2679 
2680   FreePool (OldDevicePath);
2681 #endif /* 0 */
2682 
2683   return Status;
2684 }
2685 //
2686 // Statistics()
2687 //
2688 /**
2689   Resets or collects the statistics on a network interface.
2690 
2691   @param  This            Protocol instance pointer.
2692   @param  Reset           Set to TRUE to reset the statistics for the network interface.
2693   @param  StatisticsSize  On input the size, in bytes, of StatisticsTable. On
2694                           output the size, in bytes, of the resulting table of
2695                           statistics.
2696   @param  StatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that
2697                           contains the statistics.
2698 
2699   @retval EFI_SUCCESS           The statistics were collected from the network interface.
2700   @retval EFI_NOT_STARTED       The network interface has not been started.
2701   @retval EFI_BUFFER_TOO_SMALL  The Statistics buffer was too small. The current buffer
2702                                 size needed to hold the statistics is returned in
2703                                 StatisticsSize.
2704   @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
2705   @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
2706   @retval EFI_UNSUPPORTED       This function is not supported by the network interface.
2707 
2708 **/
2709 EFI_STATUS
2710 EFIAPI
Undi16SimpleNetworkStatistics(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,IN BOOLEAN Reset,IN OUT UINTN * StatisticsSize OPTIONAL,OUT EFI_NETWORK_STATISTICS * StatisticsTable OPTIONAL)2711 Undi16SimpleNetworkStatistics (
2712   IN EFI_SIMPLE_NETWORK_PROTOCOL       * This,
2713   IN BOOLEAN                           Reset,
2714   IN OUT UINTN                         *StatisticsSize OPTIONAL,
2715   OUT EFI_NETWORK_STATISTICS           * StatisticsTable OPTIONAL
2716   )
2717 {
2718   EFI_STATUS                    Status;
2719   EFI_SIMPLE_NETWORK_DEV        *SimpleNetworkDevice;
2720   PXENV_UNDI_CLEAR_STATISTICS_T ClearStatistics;
2721   PXENV_UNDI_GET_STATISTICS_T   GetStatistics;
2722 
2723   if (This == NULL) {
2724     return EFI_INVALID_PARAMETER;
2725   }
2726 
2727   Status              = EFI_SUCCESS;
2728   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
2729 
2730   if (SimpleNetworkDevice == NULL) {
2731     return EFI_DEVICE_ERROR;
2732   }
2733   //
2734   // Verify that the current state of the adapter is valid for this call.
2735   //
2736   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
2737   case EfiSimpleNetworkInitialized:
2738     break;
2739 
2740   case EfiSimpleNetworkStopped:
2741     return EFI_NOT_STARTED;
2742 
2743   case EfiSimpleNetworkStarted:
2744   default:
2745     return EFI_DEVICE_ERROR;
2746   }
2747 
2748   if ((StatisticsSize != NULL) && (*StatisticsSize != 0) && (StatisticsTable == NULL)) {
2749     return EFI_INVALID_PARAMETER;
2750   }
2751 
2752   //
2753   // If Reset is TRUE, then clear all the statistics.
2754   //
2755   if (Reset) {
2756 
2757     DEBUG ((DEBUG_NET, "  RESET Statistics\n"));
2758 
2759     //
2760     // Call 16 bit UNDI ROM to open the network interface
2761     //
2762     ClearStatistics.Status  = INIT_PXE_STATUS;
2763 
2764     Status                  = PxeUndiClearStatistics (SimpleNetworkDevice, &ClearStatistics);
2765 
2766     if (EFI_ERROR (Status)) {
2767       return Status;
2768     }
2769     //
2770     // Check the status code from the 16 bit UNDI ROM
2771     //
2772     if (ClearStatistics.Status != PXENV_STATUS_SUCCESS) {
2773       return EFI_DEVICE_ERROR;
2774     }
2775 
2776     DEBUG ((DEBUG_NET, "  RESET Statistics Complete"));
2777   }
2778 
2779   if (StatisticsSize != NULL) {
2780     EFI_NETWORK_STATISTICS  LocalStatisticsTable;
2781 
2782     DEBUG ((DEBUG_NET, "  GET Statistics\n"));
2783 
2784     //
2785     // If the size if valid, then see if the table is valid
2786     //
2787     if (StatisticsTable == NULL) {
2788       DEBUG ((DEBUG_NET, "  StatisticsTable is NULL\n"));
2789       return EFI_INVALID_PARAMETER;
2790     }
2791     //
2792     // Call 16 bit UNDI ROM to open the network interface
2793     //
2794     GetStatistics.Status            = INIT_PXE_STATUS;
2795     GetStatistics.XmtGoodFrames     = 0;
2796     GetStatistics.RcvGoodFrames     = 0;
2797     GetStatistics.RcvCRCErrors      = 0;
2798     GetStatistics.RcvResourceErrors = 0;
2799 
2800     Status                          = PxeUndiGetStatistics (SimpleNetworkDevice, &GetStatistics);
2801 
2802     if (EFI_ERROR (Status)) {
2803       return Status;
2804     }
2805     //
2806     // Check the status code from the 16 bit UNDI ROM
2807     //
2808     if (GetStatistics.Status != PXENV_STATUS_SUCCESS) {
2809       return EFI_DEVICE_ERROR;
2810     }
2811     //
2812     // Fill in the Statistics Table with the collected values.
2813     //
2814     SetMem (&LocalStatisticsTable, sizeof LocalStatisticsTable, 0xff);
2815 
2816     LocalStatisticsTable.TxGoodFrames     = GetStatistics.XmtGoodFrames;
2817     LocalStatisticsTable.RxGoodFrames     = GetStatistics.RcvGoodFrames;
2818     LocalStatisticsTable.RxCrcErrorFrames = GetStatistics.RcvCRCErrors;
2819     LocalStatisticsTable.RxDroppedFrames  = GetStatistics.RcvResourceErrors;
2820 
2821     CopyMem (StatisticsTable, &LocalStatisticsTable, *StatisticsSize);
2822 
2823     DEBUG (
2824       (DEBUG_NET,
2825       "  Statistics Collected : Size=%d  Buf=%08x\n",
2826       *StatisticsSize,
2827       StatisticsTable)
2828       );
2829 
2830     DEBUG ((DEBUG_NET, "  GET Statistics Complete"));
2831 
2832     if (*StatisticsSize < sizeof LocalStatisticsTable) {
2833       DEBUG ((DEBUG_NET, "  BUFFER TOO SMALL\n"));
2834       Status = EFI_BUFFER_TOO_SMALL;
2835     }
2836 
2837     *StatisticsSize = sizeof LocalStatisticsTable;
2838 
2839     return Status;
2840 
2841   }
2842 
2843   return EFI_SUCCESS;
2844 }
2845 //
2846 // MCastIpToMac()
2847 //
2848 /**
2849   Translate IP address to MAC address.
2850 
2851   @param This                 A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
2852   @param IPv6                 IPv6 or IPv4
2853   @param IP                   A pointer to given Ip address.
2854   @param MAC                  On return, translated MAC address.
2855 
2856   @retval EFI_INVALID_PARAMETER Invalid This paramter.
2857   @retval EFI_INVALID_PARAMETER Invalid IP address.
2858   @retval EFI_INVALID_PARAMETER Invalid return buffer for holding MAC address.
2859   @retval EFI_UNSUPPORTED       Do not support IPv6
2860   @retval EFI_DEVICE_ERROR      Network device has not been initialized.
2861   @retval EFI_NOT_STARTED       Network device has been stopped.
2862   @retval EFI_DEVICE_ERROR      Invalid status for network device
2863   @retval EFI_SUCCESS           Success operation.
2864 **/
2865 EFI_STATUS
2866 EFIAPI
Undi16SimpleNetworkMCastIpToMac(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,IN BOOLEAN IPv6,IN EFI_IP_ADDRESS * IP,OUT EFI_MAC_ADDRESS * MAC)2867 Undi16SimpleNetworkMCastIpToMac (
2868   IN EFI_SIMPLE_NETWORK_PROTOCOL            *This,
2869   IN BOOLEAN                                IPv6,
2870   IN EFI_IP_ADDRESS                         *IP,
2871   OUT EFI_MAC_ADDRESS                       *MAC
2872   )
2873 {
2874   EFI_STATUS                  Status;
2875   EFI_SIMPLE_NETWORK_DEV      *SimpleNetworkDevice;
2876   PXENV_UNDI_GET_MCAST_ADDR_T GetMcastAddr;
2877 
2878   if (This == NULL || IP == NULL || MAC == NULL) {
2879     return EFI_INVALID_PARAMETER;
2880   }
2881 
2882   Status              = EFI_SUCCESS;
2883   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
2884 
2885   if (SimpleNetworkDevice == NULL) {
2886     return EFI_DEVICE_ERROR;
2887   }
2888   //
2889   // Verify that the current state of the adapter is valid for this call.
2890   //
2891   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
2892   case EfiSimpleNetworkStopped:
2893     return EFI_NOT_STARTED;
2894 
2895   case EfiSimpleNetworkInitialized:
2896     break;
2897 
2898   case EfiSimpleNetworkStarted:
2899   default:
2900     return EFI_DEVICE_ERROR;
2901   }
2902   //
2903   // 16 bit UNDI Option ROMS do not support IPv6.  Check for IPv6 usage.
2904   //
2905   if (IPv6) {
2906     return EFI_UNSUPPORTED;
2907   }
2908   //
2909   // Call 16 bit UNDI ROM to open the network interface
2910   //
2911   GetMcastAddr.Status = INIT_PXE_STATUS;
2912   CopyMem (&GetMcastAddr.InetAddr, IP, 4);
2913 
2914   Status = PxeUndiGetMcastAddr (SimpleNetworkDevice, &GetMcastAddr);
2915 
2916   if (EFI_ERROR (Status)) {
2917     return Status;
2918   }
2919   //
2920   // Check the status code from the 16 bit UNDI ROM
2921   //
2922   if (GetMcastAddr.Status != PXENV_STATUS_SUCCESS) {
2923     return EFI_DEVICE_ERROR;
2924   }
2925   //
2926   // Copy the MAC address from the returned data structure.
2927   //
2928   CopyMem (
2929     MAC,
2930     &GetMcastAddr.MediaAddr,
2931     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
2932     );
2933 
2934   return Status;
2935 }
2936 //
2937 // NvData()
2938 //
2939 /**
2940   Performs read and write operations on the NVRAM device attached to a
2941   network interface.
2942 
2943   @param  This       The protocol instance pointer.
2944   @param  ReadWrite  TRUE for read operations, FALSE for write operations.
2945   @param  Offset     Byte offset in the NVRAM device at which to start the read or
2946                      write operation. This must be a multiple of NvRamAccessSize and
2947                      less than NvRamSize.
2948   @param  BufferSize The number of bytes to read or write from the NVRAM device.
2949                      This must also be a multiple of NvramAccessSize.
2950   @param  Buffer     A pointer to the data buffer.
2951 
2952   @retval EFI_SUCCESS           The NVRAM access was performed.
2953   @retval EFI_NOT_STARTED       The network interface has not been started.
2954   @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
2955   @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
2956   @retval EFI_UNSUPPORTED       This function is not supported by the network interface.
2957 
2958 **/
2959 EFI_STATUS
2960 EFIAPI
Undi16SimpleNetworkNvData(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,IN BOOLEAN ReadWrite,IN UINTN Offset,IN UINTN BufferSize,IN OUT VOID * Buffer)2961 Undi16SimpleNetworkNvData (
2962   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This,
2963   IN BOOLEAN                      ReadWrite,
2964   IN UINTN                        Offset,
2965   IN UINTN                        BufferSize,
2966   IN OUT VOID                     *Buffer
2967   )
2968 {
2969   return EFI_UNSUPPORTED;
2970 }
2971 //
2972 // GetStatus()
2973 //
2974 /**
2975   Reads the current interrupt status and recycled transmit buffer status from
2976   a network interface.
2977 
2978   @param  This            The protocol instance pointer.
2979   @param  InterruptStatus A pointer to the bit mask of the currently active interrupts
2980                           If this is NULL, the interrupt status will not be read from
2981                           the device. If this is not NULL, the interrupt status will
2982                           be read from the device. When the  interrupt status is read,
2983                           it will also be cleared. Clearing the transmit  interrupt
2984                           does not empty the recycled transmit buffer array.
2985   @param  TxBuf           Recycled transmit buffer address. The network interface will
2986                           not transmit if its internal recycled transmit buffer array
2987                           is full. Reading the transmit buffer does not clear the
2988                           transmit interrupt. If this is NULL, then the transmit buffer
2989                           status will not be read. If there are no transmit buffers to
2990                           recycle and TxBuf is not NULL, * TxBuf will be set to NULL.
2991 
2992   @retval EFI_SUCCESS           The status of the network interface was retrieved.
2993   @retval EFI_NOT_STARTED       The network interface has not been started.
2994   @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
2995   @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
2996   @retval EFI_UNSUPPORTED       This function is not supported by the network interface.
2997 
2998 **/
2999 EFI_STATUS
3000 EFIAPI
Undi16SimpleNetworkGetStatus(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,OUT UINT32 * InterruptStatus OPTIONAL,OUT VOID ** TxBuf OPTIONAL)3001 Undi16SimpleNetworkGetStatus (
3002   IN EFI_SIMPLE_NETWORK_PROTOCOL  * This,
3003   OUT UINT32                      *InterruptStatus OPTIONAL,
3004   OUT VOID                        **TxBuf OPTIONAL
3005   )
3006 {
3007   EFI_STATUS              Status;
3008   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
3009   UINTN                   FrameLength;
3010 
3011   if (This == NULL) {
3012     return EFI_INVALID_PARAMETER;
3013   }
3014 
3015   Status              = EFI_SUCCESS;
3016   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
3017 
3018   if (SimpleNetworkDevice == NULL) {
3019     return EFI_DEVICE_ERROR;
3020   }
3021   //
3022   // Verify that the current state of the adapter is valid for this call.
3023   //
3024   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
3025   case EfiSimpleNetworkInitialized:
3026     break;
3027 
3028   case EfiSimpleNetworkStopped:
3029     return EFI_NOT_STARTED;
3030 
3031   case EfiSimpleNetworkStarted:
3032   default:
3033     return EFI_DEVICE_ERROR;
3034   }
3035 
3036   if (InterruptStatus == NULL && TxBuf == NULL) {
3037     return EFI_INVALID_PARAMETER;
3038   }
3039 
3040   FrameLength = 0;
3041   Status      = Undi16SimpleNetworkIsr (This, &FrameLength, NULL, NULL, NULL, NULL);
3042 
3043   if (Status != EFI_BUFFER_TOO_SMALL) {
3044     if (EFI_ERROR (Status)) {
3045       return Status;
3046     }
3047   }
3048   //
3049   // See if the caller wants interrupt info.
3050   //
3051   if (InterruptStatus != NULL) {
3052     *InterruptStatus                      = SimpleNetworkDevice->InterruptStatus;
3053     SimpleNetworkDevice->InterruptStatus  = 0;
3054   }
3055   //
3056   // See if the caller wants transmit buffer status info.
3057   //
3058   if (TxBuf != NULL) {
3059     *TxBuf = 0;
3060     SimpleNetworkTransmitFifoRemove (&(SimpleNetworkDevice->TxBufferFifo), TxBuf);
3061   }
3062 
3063   return EFI_SUCCESS;
3064 }
3065 
3066 /**
3067   Places a packet in the transmit queue of a network interface.
3068 
3069   @param  This       The protocol instance pointer.
3070   @param  HeaderSize The size, in bytes, of the media header to be filled in by
3071                      the Transmit() function. If HeaderSize is non-zero, then it
3072                      must be equal to This->Mode->MediaHeaderSize and the DestAddr
3073                      and Protocol parameters must not be NULL.
3074   @param  BufferSize The size, in bytes, of the entire packet (media header and
3075                      data) to be transmitted through the network interface.
3076   @param  Buffer     A pointer to the packet (media header followed by data) to be
3077                      transmitted. This parameter cannot be NULL. If HeaderSize is zero,
3078                      then the media header in Buffer must already be filled in by the
3079                      caller. If HeaderSize is non-zero, then the media header will be
3080                      filled in by the Transmit() function.
3081   @param  SrcAddr    The source HW MAC address. If HeaderSize is zero, then this parameter
3082                      is ignored. If HeaderSize is non-zero and SrcAddr is NULL, then
3083                      This->Mode->CurrentAddress is used for the source HW MAC address.
3084   @param  DestAddr   The destination HW MAC address. If HeaderSize is zero, then this
3085                      parameter is ignored.
3086   @param  Protocol   The type of header to build. If HeaderSize is zero, then this
3087                      parameter is ignored. See RFC 1700, section "Ether Types", for
3088                      examples.
3089 
3090   @retval EFI_SUCCESS           The packet was placed on the transmit queue.
3091   @retval EFI_NOT_STARTED       The network interface has not been started.
3092   @retval EFI_NOT_READY         The network interface is too busy to accept this transmit request.
3093   @retval EFI_BUFFER_TOO_SMALL  The BufferSize parameter is too small.
3094   @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
3095   @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
3096   @retval EFI_UNSUPPORTED       This function is not supported by the network interface.
3097 
3098 **/
3099 EFI_STATUS
3100 EFIAPI
Undi16SimpleNetworkTransmit(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,IN UINTN HeaderSize,IN UINTN BufferSize,IN VOID * Buffer,IN EFI_MAC_ADDRESS * SrcAddr OPTIONAL,IN EFI_MAC_ADDRESS * DestAddr OPTIONAL,IN UINT16 * Protocol OPTIONAL)3101 Undi16SimpleNetworkTransmit (
3102   IN EFI_SIMPLE_NETWORK_PROTOCOL           *This,
3103   IN UINTN                                 HeaderSize,
3104   IN UINTN                                 BufferSize,
3105   IN VOID                                  *Buffer,
3106   IN EFI_MAC_ADDRESS                       *SrcAddr OPTIONAL,
3107   IN EFI_MAC_ADDRESS                       *DestAddr OPTIONAL,
3108   IN UINT16                                *Protocol OPTIONAL
3109   )
3110 {
3111   EFI_STATUS              Status;
3112   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
3113   PXENV_UNDI_TRANSMIT_T   XmitInfo;
3114 
3115   if (This == NULL) {
3116     return EFI_INVALID_PARAMETER;
3117   }
3118 
3119   Status              = EFI_SUCCESS;
3120   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
3121 
3122   if (SimpleNetworkDevice == NULL) {
3123     return EFI_DEVICE_ERROR;
3124   }
3125   //
3126   // Verify that the current state of the adapter is valid for this call.
3127   //
3128   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
3129   case EfiSimpleNetworkInitialized:
3130     break;
3131 
3132   case EfiSimpleNetworkStopped:
3133     return EFI_NOT_STARTED;
3134 
3135   case EfiSimpleNetworkStarted:
3136   default:
3137     return EFI_DEVICE_ERROR;
3138   }
3139 
3140   if (Buffer == NULL) {
3141     return EFI_INVALID_PARAMETER;
3142   }
3143 
3144   if (BufferSize < SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize) {
3145     return EFI_BUFFER_TOO_SMALL;
3146   }
3147 
3148   if (HeaderSize != 0) {
3149     if (HeaderSize != SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize) {
3150       return EFI_INVALID_PARAMETER;
3151     }
3152 
3153     if (DestAddr == NULL || Protocol == NULL) {
3154       return EFI_INVALID_PARAMETER;
3155     }
3156 
3157     if (DestAddr != NULL) {
3158       CopyMem (
3159         Buffer,
3160         DestAddr,
3161         SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
3162         );
3163     }
3164 
3165     if (SrcAddr == NULL) {
3166       SrcAddr = &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress;
3167     }
3168 
3169     CopyMem (
3170       (UINT8 *) Buffer + SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize,
3171       SrcAddr,
3172       SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
3173       );
3174 
3175     if (Protocol != NULL) {
3176       *(UINT16 *) ((UINT8 *) Buffer + 2 * SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize) = (UINT16) (((*Protocol & 0xFF) << 8) | ((*Protocol >> 8) & 0xFF));
3177     }
3178   }
3179   //
3180   // See if the recycled transmit buffer FIFO is full.
3181   // If it is full, then we can not transmit until the caller calls GetStatus() to pull
3182   // off recycled transmit buffers.
3183   //
3184   if (SimpleNetworkTransmitFifoFull (&(SimpleNetworkDevice->TxBufferFifo))) {
3185     return EFI_NOT_READY;
3186   }
3187   //
3188   //  Output debug trace message.
3189   //
3190   DEBUG ((DEBUG_NET, "Undi16SimpleNetworkTransmit\n\r "));
3191 
3192   //
3193   // Initialize UNDI WRITE parameter structure.
3194   //
3195   XmitInfo.Status           = INIT_PXE_STATUS;
3196   XmitInfo.Protocol         = P_UNKNOWN;
3197   XmitInfo.XmitFlag         = XMT_DESTADDR;
3198   XmitInfo.DestAddrOffset   = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->TxDestAddr & 0x000f);
3199   XmitInfo.DestAddrSegment  = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->TxDestAddr >> 4);
3200   XmitInfo.TBDOffset        = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->Xmit & 0x000f);
3201   XmitInfo.TBDSegment       = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->Xmit >> 4);
3202   XmitInfo.Reserved[0]      = 0;
3203   XmitInfo.Reserved[1]      = 0;
3204 
3205   CopyMem (
3206     SimpleNetworkDevice->TxDestAddr,
3207     Buffer,
3208     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
3209     );
3210 
3211   CopyMem (
3212     SimpleNetworkDevice->TxRealModeMediaHeader,
3213     Buffer,
3214     SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize
3215     );
3216 
3217   SimpleNetworkDevice->Xmit->ImmedLength            = (UINT16) SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize;
3218 
3219   SimpleNetworkDevice->Xmit->DataBlock[0].TDDataLen = (UINT16) (BufferSize - SimpleNetworkDevice->Xmit->ImmedLength);
3220 
3221   CopyMem (
3222     SimpleNetworkDevice->TxRealModeDataBuffer,
3223     (UINT8 *) Buffer + SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize,
3224     SimpleNetworkDevice->Xmit->DataBlock[0].TDDataLen
3225     );
3226 
3227   //
3228   // Make API call to UNDI TRANSMIT
3229   //
3230   XmitInfo.Status = 0;
3231 
3232   Status          = PxeUndiTransmit (SimpleNetworkDevice, &XmitInfo);
3233 
3234   if (EFI_ERROR (Status)) {
3235     return Status;
3236   }
3237   //
3238   // Check the status code from the 16 bit UNDI ROM
3239   //
3240   switch (XmitInfo.Status) {
3241   case PXENV_STATUS_OUT_OF_RESOURCES:
3242     return EFI_NOT_READY;
3243 
3244   case PXENV_STATUS_SUCCESS:
3245     break;
3246 
3247   default:
3248     return EFI_DEVICE_ERROR;
3249   }
3250   //
3251   // Add address of Buffer to the recycled transmit buffer FIFO
3252   //
3253   SimpleNetworkTransmitFifoAdd (&(SimpleNetworkDevice->TxBufferFifo), Buffer);
3254 
3255   return EFI_SUCCESS;
3256 }
3257 
3258 /**
3259   Receives a packet from a network interface.
3260 
3261   @param  This       The protocol instance pointer.
3262   @param  HeaderSize The size, in bytes, of the media header received on the network
3263                      interface. If this parameter is NULL, then the media header size
3264                      will not be returned.
3265   @param  BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in
3266                      bytes, of the packet that was received on the network interface.
3267   @param  Buffer     A pointer to the data buffer to receive both the media header and
3268                      the data.
3269   @param  SrcAddr    The source HW MAC address. If this parameter is NULL, the
3270                      HW MAC source address will not be extracted from the media
3271                      header.
3272   @param  DestAddr   The destination HW MAC address. If this parameter is NULL,
3273                      the HW MAC destination address will not be extracted from the
3274                      media header.
3275   @param  Protocol   The media header type. If this parameter is NULL, then the
3276                      protocol will not be extracted from the media header. See
3277                      RFC 1700 section "Ether Types" for examples.
3278 
3279   @retval  EFI_SUCCESS           The received data was stored in Buffer, and BufferSize has
3280                                  been updated to the number of bytes received.
3281   @retval  EFI_NOT_STARTED       The network interface has not been started.
3282   @retval  EFI_NOT_READY         The network interface is too busy to accept this transmit
3283                                  request.
3284   @retval  EFI_BUFFER_TOO_SMALL  The BufferSize parameter is too small.
3285   @retval  EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
3286   @retval  EFI_DEVICE_ERROR      The command could not be sent to the network interface.
3287   @retval  EFI_UNSUPPORTED       This function is not supported by the network interface.
3288 
3289 **/
3290 EFI_STATUS
3291 EFIAPI
Undi16SimpleNetworkReceive(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,OUT UINTN * HeaderSize OPTIONAL,IN OUT UINTN * BufferSize,OUT VOID * Buffer,OUT EFI_MAC_ADDRESS * SrcAddr OPTIONAL,OUT EFI_MAC_ADDRESS * DestAddr OPTIONAL,OUT UINT16 * Protocol OPTIONAL)3292 Undi16SimpleNetworkReceive (
3293   IN EFI_SIMPLE_NETWORK_PROTOCOL            *This,
3294   OUT UINTN                                 *HeaderSize OPTIONAL,
3295   IN OUT UINTN                              *BufferSize,
3296   OUT VOID                                  *Buffer,
3297   OUT EFI_MAC_ADDRESS                       *SrcAddr OPTIONAL,
3298   OUT EFI_MAC_ADDRESS                       *DestAddr OPTIONAL,
3299   OUT UINT16                                *Protocol OPTIONAL
3300   )
3301 {
3302   EFI_STATUS              Status;
3303   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
3304   UINTN                   MediaAddrSize;
3305   UINT8                   ProtType;
3306 
3307   if (This == NULL || BufferSize == NULL || Buffer == NULL) {
3308     return EFI_INVALID_PARAMETER;
3309   }
3310 
3311   Status              = EFI_SUCCESS;
3312   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
3313 
3314   if (SimpleNetworkDevice == NULL) {
3315     return EFI_DEVICE_ERROR;
3316   }
3317   //
3318   // Verify that the current state of the adapter is valid for this call.
3319   //
3320   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
3321   case EfiSimpleNetworkInitialized:
3322     break;
3323 
3324   case EfiSimpleNetworkStopped:
3325     return EFI_NOT_STARTED;
3326 
3327   case EfiSimpleNetworkStarted:
3328   default:
3329     return EFI_DEVICE_ERROR;
3330   }
3331 
3332   Status = Undi16SimpleNetworkIsr (
3333             This,
3334             BufferSize,
3335             HeaderSize,
3336             Buffer,
3337             &ProtType,
3338             NULL
3339             );
3340 
3341   if (EFI_ERROR (Status)) {
3342     return Status;
3343   }
3344 
3345   if ((SimpleNetworkDevice->InterruptStatus & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT) == 0) {
3346     return EFI_NOT_READY;
3347 
3348   }
3349 
3350   SimpleNetworkDevice->InterruptStatus &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
3351 
3352   MediaAddrSize = This->Mode->HwAddressSize;
3353 
3354   if (SrcAddr != NULL) {
3355     CopyMem (SrcAddr, (UINT8 *) Buffer + MediaAddrSize, MediaAddrSize);
3356   }
3357 
3358   if (DestAddr != NULL) {
3359     CopyMem (DestAddr, Buffer, MediaAddrSize);
3360   }
3361 
3362   if (Protocol != NULL) {
3363     *((UINT8 *) Protocol)     = *((UINT8 *) Buffer + (2 * MediaAddrSize) + 1);
3364     *((UINT8 *) Protocol + 1) = *((UINT8 *) Buffer + (2 * MediaAddrSize));
3365   }
3366 
3367   DEBUG ((DEBUG_NET, "Packet Received: BufferSize=%d  HeaderSize = %d\n", *BufferSize, *HeaderSize));
3368 
3369   return Status;
3370 
3371 }
3372 //
3373 // WaitForPacket()
3374 //
3375 /**
3376   wait for a packet to be received.
3377 
3378   @param Event      Event used with WaitForEvent() to wait for a packet to be received.
3379   @param Context    Event Context
3380 
3381 **/
3382 VOID
3383 EFIAPI
Undi16SimpleNetworkWaitForPacket(IN EFI_EVENT Event,IN VOID * Context)3384 Undi16SimpleNetworkWaitForPacket (
3385   IN EFI_EVENT               Event,
3386   IN VOID                    *Context
3387   )
3388 {
3389   //
3390   // Someone is waiting on the receive packet event, if there's
3391   // a packet pending, signal the event
3392   //
3393   if (!EFI_ERROR (Undi16SimpleNetworkCheckForPacket (Context))) {
3394     gBS->SignalEvent (Event);
3395   }
3396 }
3397 //
3398 // CheckForPacket()
3399 //
3400 /**
3401   Check whether packet is ready for receive.
3402 
3403   @param This The protocol instance pointer.
3404 
3405   @retval  EFI_SUCCESS           Receive data is ready.
3406   @retval  EFI_NOT_STARTED       The network interface has not been started.
3407   @retval  EFI_NOT_READY         The network interface is too busy to accept this transmit
3408                                  request.
3409   @retval  EFI_BUFFER_TOO_SMALL  The BufferSize parameter is too small.
3410   @retval  EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
3411   @retval  EFI_DEVICE_ERROR      The command could not be sent to the network interface.
3412   @retval  EFI_UNSUPPORTED       This function is not supported by the network interface.
3413 **/
3414 EFI_STATUS
Undi16SimpleNetworkCheckForPacket(IN EFI_SIMPLE_NETWORK_PROTOCOL * This)3415 Undi16SimpleNetworkCheckForPacket (
3416   IN EFI_SIMPLE_NETWORK_PROTOCOL *This
3417   )
3418 {
3419   EFI_STATUS              Status;
3420   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
3421   UINTN                   FrameLength;
3422 
3423   if (This == NULL) {
3424     return EFI_INVALID_PARAMETER;
3425   }
3426 
3427   Status              = EFI_SUCCESS;
3428   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
3429 
3430   if (SimpleNetworkDevice == NULL) {
3431     return EFI_DEVICE_ERROR;
3432   }
3433   //
3434   // Verify that the current state of the adapter is valid for this call.
3435   //
3436   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
3437   case EfiSimpleNetworkInitialized:
3438     break;
3439 
3440   case EfiSimpleNetworkStopped:
3441     return EFI_NOT_STARTED;
3442 
3443   case EfiSimpleNetworkStarted:
3444   default:
3445     return EFI_DEVICE_ERROR;
3446   }
3447 
3448   FrameLength = 0;
3449   Status = Undi16SimpleNetworkIsr (
3450             This,
3451             &FrameLength,
3452             NULL,
3453             NULL,
3454             NULL,
3455             NULL
3456             );
3457 
3458   if (Status != EFI_BUFFER_TOO_SMALL) {
3459     if (EFI_ERROR (Status)) {
3460       return Status;
3461     }
3462   }
3463 
3464   return ((SimpleNetworkDevice->InterruptStatus & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT) != 0) ? EFI_SUCCESS : EFI_NOT_READY;
3465 }
3466 
3467 /**
3468   Signal handlers for ExitBootServices event.
3469 
3470   Clean up any Real-mode UNDI residue from the system
3471 
3472   @param Event      ExitBootServices event
3473   @param Context
3474 **/
3475 VOID
3476 EFIAPI
Undi16SimpleNetworkEvent(IN EFI_EVENT Event,IN VOID * Context)3477 Undi16SimpleNetworkEvent (
3478   IN EFI_EVENT        Event,
3479   IN VOID             *Context
3480   )
3481 {
3482   //
3483   // NOTE:  This is not the only way to effect this cleanup.  The prescribed mechanism
3484   //        would be to perform an UNDI STOP command.  This strategam has been attempted
3485   //        but results in problems making some of the EFI core services from TPL_CALLBACK.
3486   //        This issue needs to be resolved, but the other alternative has been to perform
3487   //        the unchain logic explicitly, as done below.
3488   //
3489   RestoreCachedVectorAddress (0x1A);
3490 }
3491 
3492 /**
3493   Allocate buffer below 1M for real mode.
3494 
3495   @param NumPages     The number pages want to be allocated.
3496   @param Buffer       On return, allocated buffer.
3497 
3498   @return Status of allocating pages.
3499 **/
3500 EFI_STATUS
BiosSnp16AllocatePagesBelowOneMb(UINTN NumPages,VOID ** Buffer)3501 BiosSnp16AllocatePagesBelowOneMb (
3502   UINTN  NumPages,
3503   VOID   **Buffer
3504   )
3505 {
3506   EFI_STATUS            Status;
3507   EFI_PHYSICAL_ADDRESS  PhysicalAddress;
3508 
3509   PhysicalAddress = 0x000fffff;
3510   Status = gBS->AllocatePages (
3511                   AllocateMaxAddress,
3512                   EfiRuntimeServicesData,
3513                   NumPages,
3514                   &PhysicalAddress
3515                   );
3516   if (EFI_ERROR (Status)) {
3517     return Status;
3518   }
3519 
3520   *Buffer = (VOID *) (UINTN) PhysicalAddress;
3521   return EFI_SUCCESS;
3522 }
3523