Home | History | Annotate | Download | only in Snp16Dxe
      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
    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
    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
    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
    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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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 parameter.
   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
   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 parameter.
   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
   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 parameter.
   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
   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 permanent address
   2500   @param New                  A pointer to New address
   2501 
   2502   @retval EFI_INVALID_PARAMETER Invalid This parameter.
   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
   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 resetting 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
   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 parameter.
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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