There are cases that the operands of an expression are all with rank less
than UINT64/INT64 and the result of the expression is explicitly cast to
UINT64/INT64 to fit the target size.
An example will be:
UINT32 a,b;
// a and b can be any unsigned int type with rank less than UINT64, like
// UINT8, UINT16, etc.
UINT64 c;
c = (UINT64) (a + b);
Some static code checkers may warn that the expression result might
overflow within the rank of "int" (integer promotions) and the result is
then cast to a bigger size.
The commit refines codes by the following rules:
1). When the expression is possible to overflow the range of unsigned int/
int:
c = (UINT64)a + b;
2). When the expression will not overflow within the rank of "int", remove
the explicit type casts:
c = a + b;
3). When the expression will be cast to pointer of possible greater size:
UINT32 a,b;
VOID *c;
c = (VOID *)(UINTN)(a + b); --> c = (VOID *)((UINTN)a + b);
4). When one side of a comparison expression contains only operands with
rank less than UINT32:
UINT8 a;
UINT16 b;
UINTN c;
if ((UINTN)(a + b) > c) {...} --> if (((UINT32)a + b) > c) {...}
For rule 4), if we remove the 'UINTN' type cast like:
if (a + b > c) {...}
The VS compiler will complain with warning C4018 (signed/unsigned
mismatch, level 3 warning) due to promoting 'a + b' to type 'int'.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Hao Wu <hao.a.wu@intel.com>
Reviewed-by: Jeff Fan <jeff.fan@intel.com>
		
	
		
			
				
	
	
		
			3523 lines
		
	
	
		
			107 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			3523 lines
		
	
	
		
			107 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
| 
 | |
| Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.<BR>
 | |
| 
 | |
| This program and the accompanying materials
 | |
| are licensed and made available under the terms and conditions
 | |
| of the BSD License which accompanies this distribution.  The
 | |
| full text of the license may be found at
 | |
| http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "BiosSnp16.h"
 | |
| 
 | |
| 
 | |
| ///
 | |
| /// EFI Driver Binding Protocol Instance
 | |
| ///
 | |
| EFI_DRIVER_BINDING_PROTOCOL gBiosSnp16DriverBinding = {
 | |
|   BiosSnp16DriverBindingSupported,
 | |
|   BiosSnp16DriverBindingStart,
 | |
|   BiosSnp16DriverBindingStop,
 | |
|   0x3,
 | |
|   NULL,
 | |
|   NULL
 | |
| };
 | |
| 
 | |
| ///
 | |
| ///  This boolean is used to determine if we should release the cached vector during an error condition.
 | |
| ///
 | |
| BOOLEAN     mCachedInt1A = FALSE;
 | |
| 
 | |
| //
 | |
| // Private worker functions;
 | |
| //
 | |
| 
 | |
| /**
 | |
|   Start the UNDI interface.
 | |
| 
 | |
|   @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
 | |
|   @param Ax                  PCI address of Undi device.
 | |
|   
 | |
|   @retval EFI_DEVICE_ERROR Fail to start 16 bit UNDI ROM. 
 | |
|   @retval Others           Status of start 16 bit UNDI ROM. 
 | |
| **/
 | |
| EFI_STATUS
 | |
| Undi16SimpleNetworkStartUndi (
 | |
|   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice,
 | |
|   UINT16                  Ax
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Start the UNDI interface
 | |
| 
 | |
|   @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
 | |
|   
 | |
|   @retval EFI_DEVICE_ERROR Fail to start 16 bit UNDI ROM. 
 | |
|   @retval Others           Status of start 16 bit UNDI ROM. 
 | |
| **/
 | |
| EFI_STATUS
 | |
| Undi16SimpleNetworkStopUndi (
 | |
|   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Stop the UNDI interface
 | |
| 
 | |
|   @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
 | |
|   
 | |
|   @retval EFI_DEVICE_ERROR Fail to stop 16 bit UNDI ROM. 
 | |
|   @retval Others           Status of stop 16 bit UNDI ROM. 
 | |
| **/
 | |
| EFI_STATUS
 | |
| Undi16SimpleNetworkCleanupUndi (
 | |
|   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Get runtime information for Undi network interface
 | |
| 
 | |
|   @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | |
|   
 | |
|   @retval EFI_SUCCESS Sucess operation. 
 | |
|   @retval Others      Fail to get runtime information for Undi network interface. 
 | |
| **/
 | |
| EFI_STATUS
 | |
| Undi16SimpleNetworkGetInformation (
 | |
|   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Get NIC type
 | |
| 
 | |
|   @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | |
|   
 | |
|   @retval EFI_SUCCESS Sucess operation. 
 | |
|   @retval Others      Fail to get NIC type.
 | |
| **/
 | |
| EFI_STATUS
 | |
| Undi16SimpleNetworkGetNicType (
 | |
|   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Get NDIS information
 | |
| 
 | |
|   @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | |
|   
 | |
|   @retval EFI_SUCCESS Sucess operation. 
 | |
|   @retval Others      Fail to get NDIS information.
 | |
| **/
 | |
| EFI_STATUS
 | |
| Undi16SimpleNetworkGetNdisInfo (
 | |
|   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Signal handlers for ExitBootServices event.
 | |
|   
 | |
|   Clean up any Real-mode UNDI residue from the system 
 | |
|    
 | |
|   @param Event      ExitBootServices event
 | |
|   @param Context 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| Undi16SimpleNetworkEvent (
 | |
|   IN EFI_EVENT  Event,
 | |
|   IN VOID       *Context
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Loads the undi driver.
 | |
| 
 | |
|   @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
 | |
|   
 | |
|   @retval   EFI_SUCCESS   - Successfully loads undi driver.
 | |
|   @retval   EFI_NOT_FOUND - Doesn't find undi driver or undi driver load failure.
 | |
| **/
 | |
| EFI_STATUS
 | |
| Undi16SimpleNetworkLoadUndi (
 | |
|   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Unload 16 bit UNDI Option ROM from memory
 | |
| 
 | |
|   @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
 | |
|   
 | |
|   @return EFI_STATUS 
 | |
| **/
 | |
| EFI_STATUS
 | |
| Undi16SimpleNetworkUnloadUndi (
 | |
|   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Entry point for EFI drivers.
 | |
| 
 | |
|   @param ImageHandle Handle that identifies the loaded image.
 | |
|   @param SystemTable System Table for this image.
 | |
|   
 | |
|   @return EFI_STATUS Return status from EfiLibInstallAllDriverProtocols. 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| BiosSnp16DriverEntryPoint (
 | |
|   IN EFI_HANDLE         ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE   *SystemTable
 | |
|   )
 | |
| {
 | |
|   return EfiLibInstallDriverBindingComponentName2 (
 | |
|            ImageHandle,
 | |
|            SystemTable,
 | |
|            &gBiosSnp16DriverBinding,
 | |
|            ImageHandle,
 | |
|            &gBiosSnp16ComponentName,
 | |
|            &gBiosSnp16ComponentName2
 | |
|            );
 | |
| }
 | |
| 
 | |
| //
 | |
| // EFI Driver Binding Protocol Functions
 | |
| //
 | |
| /**
 | |
|   Tests to see if this driver supports a given controller.
 | |
| 
 | |
|   @param This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
 | |
|   @param Controller           The handle of the controller to test.
 | |
|   @param RemainingDevicePath  A pointer to the remaining portion of a device path.
 | |
|   
 | |
|   @retval EFI_SUCCESS    The driver supports given controller.
 | |
|   @retval EFI_UNSUPPORT  The driver doesn't support given controller.
 | |
|   @retval Other          Other errors prevent driver finishing to test
 | |
|                          if the driver supports given controller.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| BiosSnp16DriverBindingSupported (
 | |
|   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | |
|   IN EFI_HANDLE                   Controller,
 | |
|   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                Status;
 | |
|   EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;
 | |
|   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
 | |
|   EFI_PCI_IO_PROTOCOL       *PciIo;
 | |
|   PCI_TYPE00                Pci;
 | |
| 
 | |
|   //
 | |
|   // See if the Legacy BIOS Protocol is available
 | |
|   //
 | |
|   Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // Open the IO Abstraction(s) needed to perform the supported test
 | |
|   //
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   Controller,
 | |
|                   &gEfiDevicePathProtocolGuid,
 | |
|                   (VOID **) &DevicePath,
 | |
|                   This->DriverBindingHandle,
 | |
|                   Controller,
 | |
|                   EFI_OPEN_PROTOCOL_BY_DRIVER
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   gBS->CloseProtocol (
 | |
|         Controller,
 | |
|         &gEfiDevicePathProtocolGuid,
 | |
|         This->DriverBindingHandle,
 | |
|         Controller
 | |
|         );
 | |
| 
 | |
|   //
 | |
|   // Open the IO Abstraction(s) needed to perform the supported test
 | |
|   //
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   Controller,
 | |
|                   &gEfiPciIoProtocolGuid,
 | |
|                   (VOID **) &PciIo,
 | |
|                   This->DriverBindingHandle,
 | |
|                   Controller,
 | |
|                   EFI_OPEN_PROTOCOL_BY_DRIVER
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // See if this is a PCI Network Controller by looking at the Command register and
 | |
|   // Class Code Register
 | |
|   //
 | |
|   Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, sizeof (Pci) / sizeof (UINT32), &Pci);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Status = EFI_UNSUPPORTED;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   Status = EFI_UNSUPPORTED;
 | |
|   if (Pci.Hdr.ClassCode[2] == PCI_CLASS_NETWORK) {
 | |
|     Status = EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
| Done:
 | |
|   gBS->CloseProtocol (
 | |
|         Controller,
 | |
|         &gEfiPciIoProtocolGuid,
 | |
|         This->DriverBindingHandle,
 | |
|         Controller
 | |
|         );
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Starts the Snp device controller
 | |
| 
 | |
|   @param This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
 | |
|   @param Controller           The handle of the controller to test.
 | |
|   @param RemainingDevicePath  A pointer to the remaining portion of a device path.
 | |
|   
 | |
|   @retval  EFI_SUCCESS          - The device was started.   
 | |
|   @retval  EFI_DEVICE_ERROR     - The device could not be started due to a device error.
 | |
|   @retval  EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| BiosSnp16DriverBindingStart (
 | |
|   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | |
|   IN EFI_HANDLE                   Controller,
 | |
|   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                Status;
 | |
|   EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;
 | |
|   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
 | |
|   EFI_PCI_IO_PROTOCOL       *PciIo;
 | |
|   EFI_SIMPLE_NETWORK_DEV    *SimpleNetworkDevice;
 | |
|   EFI_DEV_PATH              Node;
 | |
|   UINTN                     Index;
 | |
|   UINTN                     Index2;
 | |
|   UINTN                     Segment;
 | |
|   UINTN                     Bus;
 | |
|   UINTN                     Device;
 | |
|   UINTN                     Function;
 | |
|   UINTN                     Flags;
 | |
|   UINT64                    Supports;
 | |
| 
 | |
|   SimpleNetworkDevice = NULL;
 | |
|   PciIo               = NULL;
 | |
| 
 | |
|   //
 | |
|   // See if the Legacy BIOS Protocol is available
 | |
|   //
 | |
|   Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // Open the IO Abstraction(s) needed
 | |
|   //
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   Controller,
 | |
|                   &gEfiDevicePathProtocolGuid,
 | |
|                   (VOID **) &DevicePath,
 | |
|                   This->DriverBindingHandle,
 | |
|                   Controller,
 | |
|                   EFI_OPEN_PROTOCOL_BY_DRIVER
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   Controller,
 | |
|                   &gEfiPciIoProtocolGuid,
 | |
|                   (VOID **) &PciIo,
 | |
|                   This->DriverBindingHandle,
 | |
|                   Controller,
 | |
|                   EFI_OPEN_PROTOCOL_BY_DRIVER
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   Status = PciIo->Attributes (
 | |
|                     PciIo,
 | |
|                     EfiPciIoAttributeOperationSupported,
 | |
|                     0,
 | |
|                     &Supports
 | |
|                     );
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
 | |
|     Status = PciIo->Attributes (
 | |
|                       PciIo,
 | |
|                       EfiPciIoAttributeOperationEnable,
 | |
|                       Supports,
 | |
|                       NULL
 | |
|                       );
 | |
|   }
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
|   //
 | |
|   // Check to see if there is a legacy option ROM image associated with this PCI device
 | |
|   //
 | |
|   Status = LegacyBios->CheckPciRom (
 | |
|                          LegacyBios,
 | |
|                          Controller,
 | |
|                          NULL,
 | |
|                          NULL,
 | |
|                          &Flags
 | |
|                          );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
|   //
 | |
|   // Post the legacy option ROM if it is available.
 | |
|   //
 | |
|   Status = LegacyBios->InstallPciRom (
 | |
|                          LegacyBios,
 | |
|                          Controller,
 | |
|                          NULL,
 | |
|                          &Flags,
 | |
|                          NULL,
 | |
|                          NULL,
 | |
|                          NULL,
 | |
|                          NULL
 | |
|                          );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
|   //
 | |
|   // Allocate memory for this SimpleNetwork device instance
 | |
|   //
 | |
|   Status = gBS->AllocatePool (
 | |
|                   EfiBootServicesData,
 | |
|                   sizeof (EFI_SIMPLE_NETWORK_DEV),
 | |
|                   (VOID **) &SimpleNetworkDevice
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   ZeroMem (SimpleNetworkDevice, sizeof (EFI_SIMPLE_NETWORK_DEV));
 | |
| 
 | |
|   //
 | |
|   // Initialize the SimpleNetwork device instance
 | |
|   //
 | |
|   SimpleNetworkDevice->Signature      = EFI_SIMPLE_NETWORK_DEV_SIGNATURE;
 | |
|   SimpleNetworkDevice->LegacyBios     = LegacyBios;
 | |
|   SimpleNetworkDevice->BaseDevicePath = DevicePath;
 | |
|   SimpleNetworkDevice->PciIo          = PciIo;
 | |
| 
 | |
|   //
 | |
|   // Initialize the Nii Protocol
 | |
|   //
 | |
|   SimpleNetworkDevice->Nii.Revision = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION;
 | |
|   SimpleNetworkDevice->Nii.Type     = EfiNetworkInterfaceUndi;
 | |
| 
 | |
|   CopyMem (&SimpleNetworkDevice->Nii.StringId, "UNDI", 4);
 | |
| 
 | |
|   //
 | |
|   // Load 16 bit UNDI Option ROM into Memory
 | |
|   //
 | |
|   Status = Undi16SimpleNetworkLoadUndi (SimpleNetworkDevice);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_NET, "ERROR : Could not load UNDI.  Status = %r\n", Status));
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   SimpleNetworkDevice->UndiLoaded = TRUE;
 | |
| 
 | |
|   //
 | |
|   // Call PXENV_START_UNDI - Initilizes the UNID interface for use.
 | |
|   //
 | |
|   PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
 | |
|   Status = Undi16SimpleNetworkStartUndi (
 | |
|              SimpleNetworkDevice,
 | |
|              (UINT16) ((Bus << 0x8) | (Device << 0x3) | (Function))
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_NET, "ERROR : Could not StartUndi.  Status = %r\n", Status));
 | |
|     goto Done;
 | |
|   }
 | |
|   //
 | |
|   // Initialize the Simple Network Protocol
 | |
|   //
 | |
|   DEBUG ((DEBUG_NET, "Initialize SimpleNetworkDevice instance\n"));
 | |
| 
 | |
|   SimpleNetworkDevice->SimpleNetwork.Revision       = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
 | |
|   SimpleNetworkDevice->SimpleNetwork.Start          = Undi16SimpleNetworkStart;
 | |
|   SimpleNetworkDevice->SimpleNetwork.Stop           = Undi16SimpleNetworkStop;
 | |
|   SimpleNetworkDevice->SimpleNetwork.Initialize     = Undi16SimpleNetworkInitialize;
 | |
|   SimpleNetworkDevice->SimpleNetwork.Reset          = Undi16SimpleNetworkReset;
 | |
|   SimpleNetworkDevice->SimpleNetwork.Shutdown       = Undi16SimpleNetworkShutdown;
 | |
|   SimpleNetworkDevice->SimpleNetwork.ReceiveFilters = Undi16SimpleNetworkReceiveFilters;
 | |
|   SimpleNetworkDevice->SimpleNetwork.StationAddress = Undi16SimpleNetworkStationAddress;
 | |
|   SimpleNetworkDevice->SimpleNetwork.Statistics     = Undi16SimpleNetworkStatistics;
 | |
|   SimpleNetworkDevice->SimpleNetwork.MCastIpToMac   = Undi16SimpleNetworkMCastIpToMac;
 | |
|   SimpleNetworkDevice->SimpleNetwork.NvData         = Undi16SimpleNetworkNvData;
 | |
|   SimpleNetworkDevice->SimpleNetwork.GetStatus      = Undi16SimpleNetworkGetStatus;
 | |
|   SimpleNetworkDevice->SimpleNetwork.Transmit       = Undi16SimpleNetworkTransmit;
 | |
|   SimpleNetworkDevice->SimpleNetwork.Receive        = Undi16SimpleNetworkReceive;
 | |
|   SimpleNetworkDevice->SimpleNetwork.Mode           = &(SimpleNetworkDevice->SimpleNetworkMode);
 | |
| 
 | |
|   Status = gBS->CreateEvent (
 | |
|                   EVT_NOTIFY_WAIT,
 | |
|                   TPL_NOTIFY,
 | |
|                   Undi16SimpleNetworkWaitForPacket,
 | |
|                   &SimpleNetworkDevice->SimpleNetwork,
 | |
|                   &SimpleNetworkDevice->SimpleNetwork.WaitForPacket
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "ERROR : Could not create event.  Status = %r\n", Status));
 | |
|     goto Done;
 | |
|   }
 | |
|   //
 | |
|   // Create an event to be signalled when ExitBootServices occurs in order
 | |
|   // to clean up nicely
 | |
|   //
 | |
|   Status = gBS->CreateEventEx (
 | |
|                   EVT_NOTIFY_SIGNAL,
 | |
|                   TPL_NOTIFY,
 | |
|                   Undi16SimpleNetworkEvent,
 | |
|                   NULL,
 | |
|                   &gEfiEventExitBootServicesGuid,
 | |
|                   &SimpleNetworkDevice->EfiBootEvent
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "ERROR : Could not create event.  Status = %r\n", Status));
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Create an event to be signalled when Legacy Boot occurs to clean up the IVT
 | |
|   //
 | |
|   Status = EfiCreateEventLegacyBootEx(
 | |
|              TPL_NOTIFY, 
 | |
|              Undi16SimpleNetworkEvent, 
 | |
|              NULL, 
 | |
|              &SimpleNetworkDevice->LegacyBootEvent
 | |
|              );
 | |
|   
 | |
|   if (EFI_ERROR(Status)) {
 | |
|     DEBUG ((DEBUG_ERROR,"ERROR : Could not create event.  Status = %r\n",Status));
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Initialize the SimpleNetwork Mode Information
 | |
|   //
 | |
|   DEBUG ((DEBUG_NET, "Initialize Mode Information\n"));
 | |
| 
 | |
|   SimpleNetworkDevice->SimpleNetworkMode.State                = EfiSimpleNetworkStopped;
 | |
|   SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize      = 14;
 | |
|   SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable = TRUE;
 | |
|   SimpleNetworkDevice->SimpleNetworkMode.MultipleTxSupported  = TRUE;
 | |
|   SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
 | |
|     EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
 | |
|     EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
 | |
|     EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS |
 | |
|     EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
 | |
|   SimpleNetworkDevice->SimpleNetworkMode.MaxMCastFilterCount = MAXNUM_MCADDR;
 | |
| 
 | |
|   //
 | |
|   // Initialize the SimpleNetwork Private Information
 | |
|   //
 | |
|   DEBUG ((DEBUG_NET, "Initialize Private Information\n"));
 | |
| 
 | |
|   Status = BiosSnp16AllocatePagesBelowOneMb (
 | |
|              sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1,
 | |
|              (VOID **) &SimpleNetworkDevice->Xmit
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   Status = BiosSnp16AllocatePagesBelowOneMb (
 | |
|              1,
 | |
|              &SimpleNetworkDevice->TxRealModeMediaHeader
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   Status = BiosSnp16AllocatePagesBelowOneMb (
 | |
|              1,
 | |
|              &SimpleNetworkDevice->TxRealModeDataBuffer
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   Status = BiosSnp16AllocatePagesBelowOneMb (
 | |
|              1,
 | |
|              &SimpleNetworkDevice->TxDestAddr
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   SimpleNetworkDevice->Xmit->XmitOffset               = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeMediaHeader) & 0x000f);
 | |
| 
 | |
|   SimpleNetworkDevice->Xmit->XmitSegment              = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeMediaHeader) >> 4);
 | |
| 
 | |
|   SimpleNetworkDevice->Xmit->DataBlkCount             = 1;
 | |
| 
 | |
|   SimpleNetworkDevice->Xmit->DataBlock[0].TDPtrType   = 1;
 | |
|   SimpleNetworkDevice->Xmit->DataBlock[0].TDRsvdByte  = 0;
 | |
| 
 | |
|   SimpleNetworkDevice->Xmit->DataBlock[0].TDDataPtrOffset = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeDataBuffer) & 0x000f);
 | |
| 
 | |
|   SimpleNetworkDevice->Xmit->DataBlock[0].TDDataPtrSegment = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeDataBuffer) >> 4);
 | |
| 
 | |
|   SimpleNetworkDevice->TxBufferFifo.First = 0;
 | |
|   SimpleNetworkDevice->TxBufferFifo.Last  = 0;
 | |
| 
 | |
|   //
 | |
|   // Start() the SimpleNetwork device
 | |
|   //
 | |
|   DEBUG ((DEBUG_NET, "Start()\n"));
 | |
| 
 | |
|   Status = Undi16SimpleNetworkStart (&SimpleNetworkDevice->SimpleNetwork);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
|   //
 | |
|   // GetInformation() the SimpleNetwork device
 | |
|   //
 | |
|   DEBUG ((DEBUG_NET, "GetInformation()\n"));
 | |
| 
 | |
|   Status = Undi16SimpleNetworkGetInformation (&SimpleNetworkDevice->SimpleNetwork);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
|   //
 | |
|   // Build the device path for the child device
 | |
|   //
 | |
|   ZeroMem (&Node, sizeof (Node));
 | |
|   Node.DevPath.Type     = MESSAGING_DEVICE_PATH;
 | |
|   Node.DevPath.SubType  = MSG_MAC_ADDR_DP;
 | |
|   SetDevicePathNodeLength (&Node.DevPath, sizeof (MAC_ADDR_DEVICE_PATH));
 | |
|   CopyMem (
 | |
|     &Node.MacAddr.MacAddress,
 | |
|     &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
 | |
|     sizeof (EFI_MAC_ADDRESS)
 | |
|     );
 | |
|   SimpleNetworkDevice->DevicePath = AppendDevicePathNode (
 | |
|                                       SimpleNetworkDevice->BaseDevicePath,
 | |
|                                       &Node.DevPath
 | |
|                                       );
 | |
| 
 | |
|   //
 | |
|   // GetNicType()  the SimpleNetwork device
 | |
|   //
 | |
|   DEBUG ((DEBUG_NET, "GetNicType()\n"));
 | |
| 
 | |
|   Status = Undi16SimpleNetworkGetNicType (&SimpleNetworkDevice->SimpleNetwork);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
|   //
 | |
|   // GetNdisInfo() the SimpleNetwork device
 | |
|   //
 | |
|   DEBUG ((DEBUG_NET, "GetNdisInfo()\n"));
 | |
| 
 | |
|   Status = Undi16SimpleNetworkGetNdisInfo (&SimpleNetworkDevice->SimpleNetwork);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
|   //
 | |
|   // Stop() the SimpleNetwork device
 | |
|   //
 | |
|   DEBUG ((DEBUG_NET, "Stop()\n"));
 | |
| 
 | |
|   Status = SimpleNetworkDevice->SimpleNetwork.Stop (&SimpleNetworkDevice->SimpleNetwork);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
|   //
 | |
|   // Print Mode information
 | |
|   //
 | |
|   DEBUG ((DEBUG_NET, "Mode->State                = %d\n", SimpleNetworkDevice->SimpleNetworkMode.State));
 | |
|   DEBUG ((DEBUG_NET, "Mode->HwAddressSize        = %d\n", SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize));
 | |
|   DEBUG ((DEBUG_NET, "Mode->MacAddressChangeable = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable));
 | |
|   DEBUG ((DEBUG_NET, "Mode->MultiplTxSupported   = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MultipleTxSupported));
 | |
|   DEBUG ((DEBUG_NET, "Mode->NvRamSize            = %d\n", SimpleNetworkDevice->SimpleNetworkMode.NvRamSize));
 | |
|   DEBUG ((DEBUG_NET, "Mode->NvRamAccessSize      = %d\n", SimpleNetworkDevice->SimpleNetworkMode.NvRamAccessSize));
 | |
|   DEBUG ((DEBUG_NET, "Mode->ReceiveFilterSetting = %d\n", SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting));
 | |
|   DEBUG ((DEBUG_NET, "Mode->IfType               = %d\n", SimpleNetworkDevice->SimpleNetworkMode.IfType));
 | |
|   DEBUG ((DEBUG_NET, "Mode->MCastFilterCount     = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount));
 | |
|   for (Index = 0; Index < SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount; Index++) {
 | |
|     DEBUG ((DEBUG_NET, "  Filter[%02d] = ", Index));
 | |
|     for (Index2 = 0; Index2 < 16; Index2++) {
 | |
|       DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index].Addr[Index2]));
 | |
|     }
 | |
| 
 | |
|     DEBUG ((DEBUG_NET, "\n"));
 | |
|   }
 | |
| 
 | |
|   DEBUG ((DEBUG_NET, "CurrentAddress = "));
 | |
|   for (Index2 = 0; Index2 < 16; Index2++) {
 | |
|     DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress.Addr[Index2]));
 | |
|   }
 | |
| 
 | |
|   DEBUG ((DEBUG_NET, "\n"));
 | |
| 
 | |
|   DEBUG ((DEBUG_NET, "BroadcastAddress = "));
 | |
|   for (Index2 = 0; Index2 < 16; Index2++) {
 | |
|     DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress.Addr[Index2]));
 | |
|   }
 | |
| 
 | |
|   DEBUG ((DEBUG_NET, "\n"));
 | |
| 
 | |
|   DEBUG ((DEBUG_NET, "PermanentAddress = "));
 | |
|   for (Index2 = 0; Index2 < 16; Index2++) {
 | |
|     DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress.Addr[Index2]));
 | |
|   }
 | |
| 
 | |
|   DEBUG ((DEBUG_NET, "\n"));
 | |
| 
 | |
|   //
 | |
|   // The network device was started, information collected, and stopped.
 | |
|   // Install protocol interfaces for the SimpleNetwork device.
 | |
|   //
 | |
|   DEBUG ((DEBUG_NET, "Install Protocol Interfaces on network interface\n"));
 | |
| 
 | |
|   Status = gBS->InstallMultipleProtocolInterfaces (
 | |
|                   &SimpleNetworkDevice->Handle,
 | |
|                   &gEfiSimpleNetworkProtocolGuid,
 | |
|                   &SimpleNetworkDevice->SimpleNetwork,
 | |
|                   &gEfiNetworkInterfaceIdentifierProtocolGuid,
 | |
|                   &SimpleNetworkDevice->Nii,
 | |
|                   &gEfiDevicePathProtocolGuid,
 | |
|                   SimpleNetworkDevice->DevicePath,
 | |
|                   NULL
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
|   //
 | |
|   // Open PCI I/O from the newly created child handle
 | |
|   //
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   Controller,
 | |
|                   &gEfiPciIoProtocolGuid,
 | |
|                   (VOID **) &PciIo,
 | |
|                   This->DriverBindingHandle,
 | |
|                   SimpleNetworkDevice->Handle,
 | |
|                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
 | |
|                   );
 | |
| 
 | |
|   DEBUG ((DEBUG_INIT, "UNDI16 Driver : EFI_SUCCESS\n"));
 | |
| 
 | |
| Done:
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     if (SimpleNetworkDevice != NULL) {
 | |
| 
 | |
|       Undi16SimpleNetworkShutdown (&SimpleNetworkDevice->SimpleNetwork);
 | |
|       //
 | |
|       // CLOSE + SHUTDOWN
 | |
|       //
 | |
|       Undi16SimpleNetworkCleanupUndi (SimpleNetworkDevice);
 | |
|       //
 | |
|       // CLEANUP
 | |
|       //
 | |
|       Undi16SimpleNetworkStopUndi (SimpleNetworkDevice);
 | |
|       //
 | |
|       // STOP
 | |
|       //
 | |
|       if (SimpleNetworkDevice->UndiLoaded) {
 | |
|         Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice);
 | |
|       }
 | |
| 
 | |
|       if (SimpleNetworkDevice->SimpleNetwork.WaitForPacket != NULL) {
 | |
|         gBS->CloseEvent (SimpleNetworkDevice->SimpleNetwork.WaitForPacket);
 | |
|       }
 | |
| 
 | |
|       if (SimpleNetworkDevice->LegacyBootEvent != NULL) {
 | |
|         gBS->CloseEvent (SimpleNetworkDevice->LegacyBootEvent);
 | |
|       }
 | |
|       
 | |
|       if (SimpleNetworkDevice->EfiBootEvent != NULL) {
 | |
|         gBS->CloseEvent (SimpleNetworkDevice->EfiBootEvent);
 | |
|       }
 | |
| 
 | |
|       if (SimpleNetworkDevice->Xmit != NULL) {
 | |
|         gBS->FreePages (
 | |
|                (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->Xmit,
 | |
|                sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1
 | |
|                );
 | |
|       }
 | |
| 
 | |
|       if (SimpleNetworkDevice->TxRealModeMediaHeader != NULL) {
 | |
|         gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeMediaHeader, 1);
 | |
|       }
 | |
| 
 | |
|       if (SimpleNetworkDevice->TxRealModeDataBuffer != NULL) {
 | |
|         gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeDataBuffer, 1);
 | |
|       }
 | |
| 
 | |
|       if (SimpleNetworkDevice->TxDestAddr != NULL) {
 | |
|         gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxDestAddr, 1);
 | |
|       }
 | |
| 
 | |
|       gBS->FreePool (SimpleNetworkDevice);
 | |
|       
 | |
|       //
 | |
|       //  Only restore the vector if it was cached.
 | |
|       //
 | |
|       if (mCachedInt1A) {
 | |
|         RestoreCachedVectorAddress (0x1A);
 | |
|         mCachedInt1A = FALSE;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (PciIo != NULL) {
 | |
|       Status = PciIo->Attributes (
 | |
|                         PciIo,
 | |
|                         EfiPciIoAttributeOperationSupported,
 | |
|                         0,
 | |
|                         &Supports
 | |
|                         );
 | |
|       if (!EFI_ERROR (Status)) {
 | |
|         Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
 | |
|         Status = PciIo->Attributes (
 | |
|                           PciIo,
 | |
|                           EfiPciIoAttributeOperationDisable,
 | |
|                           Supports,
 | |
|                           NULL
 | |
|                           );
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     gBS->CloseProtocol (
 | |
|            Controller,
 | |
|            &gEfiPciIoProtocolGuid,
 | |
|            This->DriverBindingHandle,
 | |
|            Controller
 | |
|            );
 | |
| 
 | |
|     gBS->CloseProtocol (
 | |
|            Controller,
 | |
|            &gEfiDevicePathProtocolGuid,
 | |
|            This->DriverBindingHandle,
 | |
|            Controller
 | |
|            );
 | |
|     if (Status != EFI_OUT_OF_RESOURCES) {
 | |
|       Status = EFI_DEVICE_ERROR;
 | |
|     }
 | |
|   }  
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Stops the device by given device controller.
 | |
| 
 | |
|   @param This               A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
 | |
|   @param Controller         The handle of the controller to test.
 | |
|   @param NumberOfChildren   The number of child device handles in ChildHandleBuffer.
 | |
|   @param ChildHandleBuffer  An array of child handles to be freed. May be NULL if
 | |
|                             NumberOfChildren is 0.
 | |
|   
 | |
|   @retval  EFI_SUCCESS      - The device was stopped.
 | |
|   @retval  EFI_DEVICE_ERROR - The device could not be stopped due to a device error.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| BiosSnp16DriverBindingStop (
 | |
|   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
 | |
|   IN  EFI_HANDLE                      Controller,
 | |
|   IN  UINTN                           NumberOfChildren,
 | |
|   IN  EFI_HANDLE                      *ChildHandleBuffer
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                  Status;
 | |
|   UINTN                       Index;
 | |
|   BOOLEAN                     AllChildrenStopped;
 | |
|   EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork;
 | |
|   EFI_SIMPLE_NETWORK_DEV      *SimpleNetworkDevice;
 | |
|   EFI_PCI_IO_PROTOCOL         *PciIo;
 | |
|   UINT64                      Supports;
 | |
| 
 | |
|   //
 | |
|   // Complete all outstanding transactions to Controller.
 | |
|   // Don't allow any new transaction to Controller to be started.
 | |
|   //
 | |
|   if (NumberOfChildren == 0) {
 | |
|     //
 | |
|     // Close the bus driver
 | |
|     //
 | |
|     Status = gBS->OpenProtocol (
 | |
|                     Controller,
 | |
|                     &gEfiPciIoProtocolGuid,
 | |
|                     (VOID **) &PciIo,
 | |
|                     This->DriverBindingHandle,
 | |
|                     Controller,
 | |
|                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | |
|                     );
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       Status = PciIo->Attributes (
 | |
|                         PciIo,
 | |
|                         EfiPciIoAttributeOperationSupported,
 | |
|                         0,
 | |
|                         &Supports
 | |
|                         );
 | |
|       if (!EFI_ERROR (Status)) {
 | |
|         Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
 | |
|         Status = PciIo->Attributes (
 | |
|                           PciIo,
 | |
|                           EfiPciIoAttributeOperationDisable,
 | |
|                           Supports,
 | |
|                           NULL
 | |
|                           );
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     Status = gBS->CloseProtocol (
 | |
|                     Controller,
 | |
|                     &gEfiPciIoProtocolGuid,
 | |
|                     This->DriverBindingHandle,
 | |
|                     Controller
 | |
|                     );
 | |
| 
 | |
|     Status = gBS->CloseProtocol (
 | |
|                     Controller,
 | |
|                     &gEfiDevicePathProtocolGuid,
 | |
|                     This->DriverBindingHandle,
 | |
|                     Controller
 | |
|                     );
 | |
|                     
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       Status = EFI_DEVICE_ERROR;
 | |
|     }
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   AllChildrenStopped = TRUE;
 | |
| 
 | |
|   for (Index = 0; Index < NumberOfChildren; Index++) {
 | |
| 
 | |
|     Status = gBS->OpenProtocol (
 | |
|                     ChildHandleBuffer[Index],
 | |
|                     &gEfiSimpleNetworkProtocolGuid,
 | |
|                     (VOID **) &SimpleNetwork,
 | |
|                     This->DriverBindingHandle,
 | |
|                     Controller,
 | |
|                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | |
|                     );
 | |
|     if (!EFI_ERROR (Status)) {
 | |
| 
 | |
|       SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SimpleNetwork);
 | |
| 
 | |
|       Status = gBS->CloseProtocol (
 | |
|                       Controller,
 | |
|                       &gEfiPciIoProtocolGuid,
 | |
|                       This->DriverBindingHandle,
 | |
|                       ChildHandleBuffer[Index]
 | |
|                       );
 | |
| 
 | |
|       Status = gBS->UninstallMultipleProtocolInterfaces (
 | |
|                       SimpleNetworkDevice->Handle,
 | |
|                       &gEfiSimpleNetworkProtocolGuid,
 | |
|                       &SimpleNetworkDevice->SimpleNetwork,
 | |
|                       &gEfiNetworkInterfaceIdentifierProtocolGuid,
 | |
|                       &SimpleNetworkDevice->Nii,
 | |
|                       &gEfiDevicePathProtocolGuid,
 | |
|                       SimpleNetworkDevice->DevicePath,
 | |
|                       NULL
 | |
|                       );
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         gBS->OpenProtocol (
 | |
|                Controller,
 | |
|                &gEfiPciIoProtocolGuid,
 | |
|                (VOID **) &PciIo,
 | |
|                This->DriverBindingHandle,
 | |
|                ChildHandleBuffer[Index],
 | |
|                EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
 | |
|                );
 | |
|       } else {
 | |
| 
 | |
|         Undi16SimpleNetworkShutdown (&SimpleNetworkDevice->SimpleNetwork);
 | |
|         //
 | |
|         // CLOSE + SHUTDOWN
 | |
|         //
 | |
|         Undi16SimpleNetworkCleanupUndi (SimpleNetworkDevice);
 | |
|         //
 | |
|         // CLEANUP
 | |
|         //
 | |
|         Undi16SimpleNetworkStopUndi (SimpleNetworkDevice);
 | |
|         //
 | |
|         // STOP
 | |
|         //
 | |
|         if (SimpleNetworkDevice->UndiLoaded) {
 | |
|           Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice);
 | |
|         }
 | |
| 
 | |
|         if (SimpleNetworkDevice->SimpleNetwork.WaitForPacket != NULL) {
 | |
|           gBS->CloseEvent (SimpleNetworkDevice->SimpleNetwork.WaitForPacket);
 | |
|         }
 | |
| 
 | |
|         if (SimpleNetworkDevice->LegacyBootEvent != NULL) {
 | |
|           gBS->CloseEvent (SimpleNetworkDevice->LegacyBootEvent);
 | |
|         }
 | |
|       
 | |
|         if (SimpleNetworkDevice->EfiBootEvent != NULL) {
 | |
|           gBS->CloseEvent (SimpleNetworkDevice->EfiBootEvent);
 | |
|         }
 | |
| 
 | |
|         if (SimpleNetworkDevice->Xmit != NULL) {
 | |
|           gBS->FreePages (
 | |
|                  (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->Xmit,
 | |
|                  sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1
 | |
|                  );
 | |
|         }
 | |
| 
 | |
|         if (SimpleNetworkDevice->TxRealModeMediaHeader != NULL) {
 | |
|           gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeMediaHeader, 1);
 | |
|         }
 | |
| 
 | |
|         if (SimpleNetworkDevice->TxRealModeDataBuffer != NULL) {
 | |
|           gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeDataBuffer, 1);
 | |
|         }
 | |
| 
 | |
|         if (SimpleNetworkDevice->TxDestAddr != NULL) {
 | |
|           gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxDestAddr, 1);
 | |
|         }
 | |
| 
 | |
|         gBS->FreePool (SimpleNetworkDevice);
 | |
|       }
 | |
| 
 | |
|     }
 | |
| 
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       AllChildrenStopped = FALSE;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (!AllChildrenStopped) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| //
 | |
| // FIFO Support Functions
 | |
| //
 | |
| /**
 | |
|   Judge whether transmit FIFO is full.
 | |
| 
 | |
|   @param Fifo Point to trasmit FIFO structure.
 | |
|   
 | |
|   @return BOOLEAN whether transmit FIFO is full.
 | |
| **/
 | |
| BOOLEAN
 | |
| SimpleNetworkTransmitFifoFull (
 | |
|   EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo
 | |
|   )
 | |
| {
 | |
|   if (((Fifo->Last + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE) == Fifo->First) {
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Judge whether transmit FIFO is empty.
 | |
| 
 | |
|   @param Fifo Point to trasmit FIFO structure.
 | |
|   
 | |
|   @return BOOLEAN whether transmit FIFO is empty.
 | |
| **/
 | |
| BOOLEAN
 | |
| SimpleNetworkTransmitFifoEmpty (
 | |
|   EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo
 | |
|   )
 | |
| {
 | |
|   if (Fifo->Last == Fifo->First) {
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Add data into transmit buffer.
 | |
| 
 | |
|   @param Fifo Point to trasmit FIFO structure.
 | |
|   @param Data The data point want to be added.
 | |
|   
 | |
|   @retval EFI_OUT_OF_RESOURCES  FIFO is full 
 | |
|   @retval EFI_SUCCESS           Success operation. 
 | |
| **/
 | |
| EFI_STATUS
 | |
| SimpleNetworkTransmitFifoAdd (
 | |
|   EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo,
 | |
|   VOID                        *Data
 | |
|   )
 | |
| {
 | |
|   if (SimpleNetworkTransmitFifoFull (Fifo)) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   Fifo->Data[Fifo->Last]  = Data;
 | |
|   Fifo->Last              = (Fifo->Last + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE;
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get a data and remove it from network transmit FIFO.
 | |
| 
 | |
|   @param Fifo Point to trasmit FIFO structure.
 | |
|   @param Data On return, point to the data point want to be got and removed.
 | |
|   
 | |
|   @retval EFI_OUT_OF_RESOURCES network transmit buffer is empty. 
 | |
|   @retval EFI_SUCCESS           Success operation. 
 | |
| **/
 | |
| EFI_STATUS
 | |
| SimpleNetworkTransmitFifoRemove (
 | |
|   EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo,
 | |
|   VOID                        **Data
 | |
|   )
 | |
| {
 | |
|   if (SimpleNetworkTransmitFifoEmpty (Fifo)) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   *Data       = Fifo->Data[Fifo->First];
 | |
|   Fifo->First = (Fifo->First + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE;
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get recive filter setting according to EFI mask value.
 | |
| 
 | |
|   @param ReceiveFilterSetting  filter setting EFI mask value.
 | |
|   
 | |
|   @return UINT16 Undi filter setting value.
 | |
| **/
 | |
| UINT16
 | |
| Undi16GetPacketFilterSetting (
 | |
|   UINTN ReceiveFilterSetting
 | |
|   )
 | |
| {
 | |
|   UINT16  PktFilter;
 | |
| 
 | |
|   PktFilter = 0;
 | |
|   if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) != 0) {
 | |
|     PktFilter |= FLTR_DIRECTED;
 | |
|   }
 | |
| 
 | |
|   if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
 | |
|     PktFilter |= FLTR_DIRECTED;
 | |
|   }
 | |
| 
 | |
|   if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0) {
 | |
|     PktFilter |= FLTR_BRDCST;
 | |
|   }
 | |
| 
 | |
|   if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) {
 | |
|     PktFilter |= FLTR_PRMSCS;
 | |
|   }
 | |
| 
 | |
|   if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {
 | |
|     PktFilter |= FLTR_PRMSCS;
 | |
|     //
 | |
|     // @bug : Do not know if this is right????
 | |
|     //
 | |
|   }
 | |
|   //
 | |
|   // @bug : What is FLTR_SRC_RTG?
 | |
|   //
 | |
|   return PktFilter;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get filter setting from multi cast buffer .
 | |
|    
 | |
|   @param Mode           Point to mode structure.
 | |
|   @param McastBuffer    The multi cast buffer 
 | |
|   @param HwAddressSize  Size of filter value.
 | |
|   
 | |
| **/
 | |
| VOID
 | |
| Undi16GetMCastFilters (
 | |
|   IN EFI_SIMPLE_NETWORK_MODE      *Mode,
 | |
|   IN OUT PXENV_UNDI_MCAST_ADDR_T  *McastBuffer,
 | |
|   IN UINTN                        HwAddressSize
 | |
|   )
 | |
| {
 | |
|   UINTN Index;
 | |
| 
 | |
|   //
 | |
|   // @bug : What if Mode->MCastFilterCount > MAXNUM_MCADDR?
 | |
|   //
 | |
|   McastBuffer->MCastAddrCount = (UINT16) Mode->MCastFilterCount;
 | |
|   for (Index = 0; Index < MAXNUM_MCADDR; Index++) {
 | |
|     if (Index < McastBuffer->MCastAddrCount) {
 | |
|       CopyMem (&McastBuffer->MCastAddr[Index], &Mode->MCastFilter[Index], HwAddressSize);
 | |
|     } else {
 | |
|       ZeroMem (&McastBuffer->MCastAddr[Index], HwAddressSize);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| //
 | |
| // Load 16 bit UNDI Option ROM into memory
 | |
| //
 | |
| /**
 | |
|   Loads the undi driver.
 | |
| 
 | |
|   @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
 | |
|   
 | |
|   @retval   EFI_SUCCESS   - Successfully loads undi driver.
 | |
|   @retval   EFI_NOT_FOUND - Doesn't find undi driver or undi driver load failure.
 | |
| **/
 | |
| EFI_STATUS
 | |
| Undi16SimpleNetworkLoadUndi (
 | |
|   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                Status;
 | |
|   EFI_PCI_IO_PROTOCOL       *PciIo;
 | |
|   UINTN                     RomAddress;
 | |
|   PCI_EXPANSION_ROM_HEADER  *PciExpansionRomHeader;
 | |
|   PCI_DATA_STRUCTURE        *PciDataStructure;
 | |
|   PCI_TYPE00                Pci;
 | |
|   
 | |
|   if (!mCachedInt1A) {
 | |
|     Status = CacheVectorAddress (0x1A);
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       mCachedInt1A = TRUE;    
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   PciIo = SimpleNetworkDevice->PciIo;
 | |
| 
 | |
|   PciIo->Pci.Read (
 | |
|                PciIo,
 | |
|                EfiPciIoWidthUint32,
 | |
|                0,
 | |
|                sizeof (Pci) / sizeof (UINT32),
 | |
|                &Pci
 | |
|                );
 | |
| 
 | |
|   for (RomAddress = 0xc0000; RomAddress < 0xfffff; RomAddress += 0x800) {
 | |
| 
 | |
|     PciExpansionRomHeader = (PCI_EXPANSION_ROM_HEADER *) RomAddress;
 | |
| 
 | |
|     if (PciExpansionRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     DEBUG ((DEBUG_INIT, "Option ROM found at %X\n", RomAddress));
 | |
| 
 | |
|     //
 | |
|     // If the pointer to the PCI Data Structure is invalid, no further images can be located. 
 | |
|     // The PCI Data Structure must be DWORD aligned. 
 | |
|     //
 | |
|     if (PciExpansionRomHeader->PcirOffset == 0 ||
 | |
|         (PciExpansionRomHeader->PcirOffset & 3) != 0 ||
 | |
|         RomAddress + PciExpansionRomHeader->PcirOffset + sizeof (PCI_DATA_STRUCTURE) > 0x100000) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     PciDataStructure = (PCI_DATA_STRUCTURE *) (RomAddress + PciExpansionRomHeader->PcirOffset);
 | |
| 
 | |
|     if (PciDataStructure->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     DEBUG ((DEBUG_INIT, "PCI Data Structure found at %X\n", PciDataStructure));
 | |
| 
 | |
|     if (PciDataStructure->VendorId != Pci.Hdr.VendorId || PciDataStructure->DeviceId != Pci.Hdr.DeviceId) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     DEBUG (
 | |
|         (DEBUG_INIT, 
 | |
|          "PCI device with matchinng VendorId and DeviceId (%d,%d)\n",
 | |
|          (UINTN) PciDataStructure->VendorId,
 | |
|          (UINTN) PciDataStructure->DeviceId)
 | |
|         );
 | |
| 
 | |
|     Status = LaunchBaseCode (SimpleNetworkDevice, RomAddress);
 | |
| 
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
|     
 | |
|     //
 | |
|     // Free resources allocated in LaunchBaseCode
 | |
|     //
 | |
|     Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice);
 | |
|   }
 | |
| 
 | |
|   return EFI_NOT_FOUND;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Unload 16 bit UNDI Option ROM from memory
 | |
| 
 | |
|   @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
 | |
|   
 | |
|   @return EFI_STATUS 
 | |
| **/
 | |
| EFI_STATUS
 | |
| Undi16SimpleNetworkUnloadUndi (
 | |
|   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
 | |
|   )
 | |
| {
 | |
|   if (SimpleNetworkDevice->UndiLoaderTable != NULL) {
 | |
|     ZeroMem (SimpleNetworkDevice->UndiLoaderTable, SimpleNetworkDevice->UndiLoaderTablePages << EFI_PAGE_SHIFT);
 | |
|     gBS->FreePages (
 | |
|           (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->UndiLoaderTable,
 | |
|           SimpleNetworkDevice->UndiLoaderTablePages
 | |
|           );
 | |
|   }
 | |
| 
 | |
|   if (SimpleNetworkDevice->DestinationDataSegment != NULL) {
 | |
|     ZeroMem (
 | |
|       SimpleNetworkDevice->DestinationDataSegment,
 | |
|       SimpleNetworkDevice->DestinationDataSegmentPages << EFI_PAGE_SHIFT
 | |
|       );
 | |
|     gBS->FreePages (
 | |
|           (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationDataSegment,
 | |
|           SimpleNetworkDevice->DestinationDataSegmentPages
 | |
|           );
 | |
|   }
 | |
| 
 | |
|   if (SimpleNetworkDevice->DestinationStackSegment != NULL) {
 | |
|     ZeroMem (
 | |
|       SimpleNetworkDevice->DestinationStackSegment,
 | |
|       SimpleNetworkDevice->DestinationStackSegmentPages << EFI_PAGE_SHIFT
 | |
|       );
 | |
|     gBS->FreePages (
 | |
|           (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationStackSegment,
 | |
|           SimpleNetworkDevice->DestinationStackSegmentPages
 | |
|           );
 | |
|   }
 | |
| 
 | |
|   if (SimpleNetworkDevice->DestinationCodeSegment != NULL) {
 | |
|     ZeroMem (
 | |
|       SimpleNetworkDevice->DestinationCodeSegment,
 | |
|       SimpleNetworkDevice->DestinationCodeSegmentPages << EFI_PAGE_SHIFT
 | |
|       );
 | |
|     gBS->FreePages (
 | |
|           (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationCodeSegment,
 | |
|           SimpleNetworkDevice->DestinationCodeSegmentPages
 | |
|           );
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Start the UNDI interface.
 | |
| 
 | |
|   @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
 | |
|   @param Ax                  PCI address of Undi device.
 | |
|   
 | |
|   @retval EFI_DEVICE_ERROR Fail to start 16 bit UNDI ROM. 
 | |
|   @retval Others           Status of start 16 bit UNDI ROM. 
 | |
| **/
 | |
| EFI_STATUS
 | |
| Undi16SimpleNetworkStartUndi (
 | |
|   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice,
 | |
|   UINT16                  Ax
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS          Status;
 | |
|   PXENV_START_UNDI_T  Start;
 | |
| 
 | |
|   //
 | |
|   // Call 16 bit UNDI ROM to start the network interface
 | |
|   //
 | |
|   //
 | |
|   // @bug : What is this state supposed to be???
 | |
|   //
 | |
|   Start.Status  = INIT_PXE_STATUS;
 | |
|   Start.Ax      = Ax;
 | |
|   Start.Bx      = 0x0000;
 | |
|   Start.Dx      = 0x0000;
 | |
|   Start.Di      = 0x0000;
 | |
|   Start.Es      = 0x0000;
 | |
| 
 | |
|   Status        = PxeStartUndi (SimpleNetworkDevice, &Start);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // Check the status code from the 16 bit UNDI ROM
 | |
|   //
 | |
|   if (Start.Status != PXENV_STATUS_SUCCESS) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Stop the UNDI interface
 | |
| 
 | |
|   @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
 | |
|   
 | |
|   @retval EFI_DEVICE_ERROR Fail to stop 16 bit UNDI ROM. 
 | |
|   @retval Others           Status of stop 16 bit UNDI ROM. 
 | |
| **/
 | |
| EFI_STATUS
 | |
| Undi16SimpleNetworkStopUndi (
 | |
|   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS        Status;
 | |
|   PXENV_STOP_UNDI_T Stop;
 | |
| 
 | |
|   //
 | |
|   // Call 16 bit UNDI ROM to start the network interface
 | |
|   //
 | |
|   Stop.Status = INIT_PXE_STATUS;
 | |
| 
 | |
|   Status      = PxeUndiStop (SimpleNetworkDevice, &Stop);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // Check the status code from the 16 bit UNDI ROM
 | |
|   //
 | |
|   if (Stop.Status != PXENV_STATUS_SUCCESS) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Cleanup Unid network interface
 | |
| 
 | |
|   @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
 | |
|   
 | |
|   @retval EFI_DEVICE_ERROR Fail to cleanup 16 bit UNDI ROM. 
 | |
|   @retval Others           Status of cleanup 16 bit UNDI ROM. 
 | |
| **/
 | |
| EFI_STATUS
 | |
| Undi16SimpleNetworkCleanupUndi (
 | |
|   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS            Status;
 | |
|   PXENV_UNDI_CLEANUP_T  Cleanup;
 | |
| 
 | |
|   //
 | |
|   // Call 16 bit UNDI ROM to cleanup the network interface
 | |
|   //
 | |
|   Cleanup.Status  = INIT_PXE_STATUS;
 | |
| 
 | |
|   Status          = PxeUndiCleanup (SimpleNetworkDevice, &Cleanup);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // Check the status code from the 16 bit UNDI ROM
 | |
|   //
 | |
|   if (Cleanup.Status != PXENV_STATUS_SUCCESS) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get runtime information for Undi network interface
 | |
| 
 | |
|   @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | |
|   
 | |
|   @retval EFI_SUCCESS Sucess operation. 
 | |
|   @retval Others      Fail to get runtime information for Undi network interface. 
 | |
| **/
 | |
| EFI_STATUS
 | |
| Undi16SimpleNetworkGetInformation (
 | |
|   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS              Status;
 | |
|   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | |
|   UINTN                   Index;
 | |
| 
 | |
|   if (This == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Status              = EFI_SUCCESS;
 | |
|   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | |
| 
 | |
|   if (SimpleNetworkDevice == NULL) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Verify that the current state of the adapter is valid for this call.
 | |
|   //
 | |
|   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | |
|   case EfiSimpleNetworkStarted:
 | |
|   case EfiSimpleNetworkInitialized:
 | |
|     break;
 | |
| 
 | |
|   case EfiSimpleNetworkStopped:
 | |
|     return EFI_NOT_STARTED;
 | |
| 
 | |
|   default:
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Call 16 bit UNDI ROM to start the network interface
 | |
|   //
 | |
|   ZeroMem (&SimpleNetworkDevice->GetInformation, sizeof (PXENV_UNDI_GET_INFORMATION_T));
 | |
| 
 | |
|   SimpleNetworkDevice->GetInformation.Status  = INIT_PXE_STATUS;
 | |
| 
 | |
|   Status = PxeUndiGetInformation (SimpleNetworkDevice, &SimpleNetworkDevice->GetInformation);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   DEBUG ((DEBUG_NET, "  GetInformation.Status      = %d\n", SimpleNetworkDevice->GetInformation.Status));
 | |
|   DEBUG ((DEBUG_NET, "  GetInformation.BaseIo      = %d\n", SimpleNetworkDevice->GetInformation.BaseIo));
 | |
|   DEBUG ((DEBUG_NET, "  GetInformation.IntNumber   = %d\n", SimpleNetworkDevice->GetInformation.IntNumber));
 | |
|   DEBUG ((DEBUG_NET, "  GetInformation.MaxTranUnit = %d\n", SimpleNetworkDevice->GetInformation.MaxTranUnit));
 | |
|   DEBUG ((DEBUG_NET, "  GetInformation.HwType      = %d\n", SimpleNetworkDevice->GetInformation.HwType));
 | |
|   DEBUG ((DEBUG_NET, "  GetInformation.HwAddrLen   = %d\n", SimpleNetworkDevice->GetInformation.HwAddrLen));
 | |
|   DEBUG ((DEBUG_NET, "  GetInformation.ROMAddress  = %d\n", SimpleNetworkDevice->GetInformation.ROMAddress));
 | |
|   DEBUG ((DEBUG_NET, "  GetInformation.RxBufCt     = %d\n", SimpleNetworkDevice->GetInformation.RxBufCt));
 | |
|   DEBUG ((DEBUG_NET, "  GetInformation.TxBufCt     = %d\n", SimpleNetworkDevice->GetInformation.TxBufCt));
 | |
| 
 | |
|   DEBUG ((DEBUG_NET, "  GetInformation.CurNodeAddr ="));
 | |
|   for (Index = 0; Index < 16; Index++) {
 | |
|     DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->GetInformation.CurrentNodeAddress[Index]));
 | |
|   }
 | |
| 
 | |
|   DEBUG ((DEBUG_NET, "\n"));
 | |
| 
 | |
|   DEBUG ((DEBUG_NET, "  GetInformation.PermNodeAddr ="));
 | |
|   for (Index = 0; Index < 16; Index++) {
 | |
|     DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->GetInformation.PermNodeAddress[Index]));
 | |
|   }
 | |
| 
 | |
|   DEBUG ((DEBUG_NET, "\n"));
 | |
| 
 | |
|   //
 | |
|   // Check the status code from the 16 bit UNDI ROM
 | |
|   //
 | |
|   if (SimpleNetworkDevice->GetInformation.Status != PXENV_STATUS_SUCCESS) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // The information has been retrieved.  Fill in Mode data.
 | |
|   //
 | |
|   SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize  = SimpleNetworkDevice->GetInformation.HwAddrLen;
 | |
| 
 | |
|   SimpleNetworkDevice->SimpleNetworkMode.MaxPacketSize  = SimpleNetworkDevice->GetInformation.MaxTranUnit;
 | |
| 
 | |
|   SimpleNetworkDevice->SimpleNetworkMode.IfType         = (UINT8) SimpleNetworkDevice->GetInformation.HwType;
 | |
| 
 | |
|   ZeroMem (
 | |
|     &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
 | |
|     sizeof SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress
 | |
|     );
 | |
| 
 | |
|   CopyMem (
 | |
|     &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
 | |
|     &SimpleNetworkDevice->GetInformation.CurrentNodeAddress,
 | |
|     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | |
|     );
 | |
| 
 | |
|   ZeroMem (
 | |
|     &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,
 | |
|     sizeof SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress
 | |
|     );
 | |
| 
 | |
|   CopyMem (
 | |
|     &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,
 | |
|     &SimpleNetworkDevice->GetInformation.PermNodeAddress,
 | |
|     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | |
|     );
 | |
| 
 | |
|   //
 | |
|   // hard code broadcast address - not avail in PXE2.1
 | |
|   //
 | |
|   ZeroMem (
 | |
|     &SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress,
 | |
|     sizeof SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress
 | |
|     );
 | |
| 
 | |
|   SetMem (
 | |
|     &SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress,
 | |
|     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize,
 | |
|     0xff
 | |
|     );
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get NIC type
 | |
| 
 | |
|   @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | |
|   
 | |
|   @retval EFI_SUCCESS Sucess operation. 
 | |
|   @retval Others      Fail to get NIC type.
 | |
| **/
 | |
| EFI_STATUS
 | |
| Undi16SimpleNetworkGetNicType (
 | |
|   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS              Status;
 | |
|   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | |
| 
 | |
|   if (This == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Status              = EFI_SUCCESS;
 | |
|   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | |
| 
 | |
|   if (SimpleNetworkDevice == NULL) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   ZeroMem (&SimpleNetworkDevice->GetNicType, sizeof (PXENV_UNDI_GET_NIC_TYPE_T));
 | |
| 
 | |
|   SimpleNetworkDevice->GetNicType.Status  = INIT_PXE_STATUS;
 | |
| 
 | |
|   Status = PxeUndiGetNicType (SimpleNetworkDevice, &SimpleNetworkDevice->GetNicType);
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   DEBUG ((DEBUG_NET, "  GetNicType.Status      = %d\n", SimpleNetworkDevice->GetNicType.Status));
 | |
|   DEBUG ((DEBUG_NET, "  GetNicType.NicType     = %d\n", SimpleNetworkDevice->GetNicType.NicType));
 | |
|   //
 | |
|   // Check the status code from the 16 bit UNDI ROM
 | |
|   //
 | |
|   if (SimpleNetworkDevice->GetNicType.Status != PXENV_STATUS_SUCCESS) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // The information has been retrieved.  Fill in Mode data.
 | |
|   //
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get NDIS information
 | |
| 
 | |
|   @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | |
|   
 | |
|   @retval EFI_SUCCESS Sucess operation. 
 | |
|   @retval Others      Fail to get NDIS information.
 | |
| **/
 | |
| EFI_STATUS
 | |
| Undi16SimpleNetworkGetNdisInfo (
 | |
|   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS              Status;
 | |
|   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | |
| 
 | |
|   if (This == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Status              = EFI_SUCCESS;
 | |
|   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | |
| 
 | |
|   if (SimpleNetworkDevice == NULL) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   ZeroMem (&SimpleNetworkDevice->GetNdisInfo, sizeof (PXENV_UNDI_GET_NDIS_INFO_T));
 | |
| 
 | |
|   SimpleNetworkDevice->GetNdisInfo.Status = INIT_PXE_STATUS;
 | |
| 
 | |
|   Status = PxeUndiGetNdisInfo (SimpleNetworkDevice, &SimpleNetworkDevice->GetNdisInfo);
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   DEBUG ((DEBUG_NET, "  GetNdisInfo.Status       = %d\n", SimpleNetworkDevice->GetNdisInfo.Status));
 | |
|   DEBUG ((DEBUG_NET, "  GetNdisInfo.IfaceType    = %a\n", SimpleNetworkDevice->GetNdisInfo.IfaceType));
 | |
|   DEBUG ((DEBUG_NET, "  GetNdisInfo.LinkSpeed    = %d\n", SimpleNetworkDevice->GetNdisInfo.LinkSpeed));
 | |
|   DEBUG ((DEBUG_NET, "  GetNdisInfo.ServiceFlags = %08x\n", SimpleNetworkDevice->GetNdisInfo.ServiceFlags));
 | |
| 
 | |
|   //
 | |
|   // Check the status code from the 16 bit UNDI ROM
 | |
|   //
 | |
|   if (SimpleNetworkDevice->GetNdisInfo.Status != PXENV_STATUS_SUCCESS) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // The information has been retrieved.  Fill in Mode data.
 | |
|   //
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Call Undi ROM 16bit ISR() to check interrupt cause.
 | |
| 
 | |
|   @param This               A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | |
|   @param FrameLength        The length of frame buffer.
 | |
|   @param FrameHeaderLength  The length of frame buffer's header if has.
 | |
|   @param Frame              The frame buffer to process network interrupt.
 | |
|   @param ProtType           The type network transmit protocol
 | |
|   @param PktType            The type of package.
 | |
|   
 | |
|   @retval EFI_DEVICE_ERROR  Fail to execute 16 bit ROM's ISR, or status is invalid. 
 | |
|   @retval EFI_SUCCESS       Success operation. 
 | |
| **/
 | |
| EFI_STATUS
 | |
| Undi16SimpleNetworkIsr (
 | |
|   IN EFI_SIMPLE_NETWORK_PROTOCOL * This,
 | |
|   IN UINTN                       *FrameLength,
 | |
|   IN UINTN                       *FrameHeaderLength, OPTIONAL
 | |
|   IN UINT8                       *Frame, OPTIONAL
 | |
|   IN UINT8                       *ProtType, OPTIONAL
 | |
|   IN UINT8                       *PktType OPTIONAL
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS              Status;
 | |
|   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | |
|   BOOLEAN                 FrameReceived;
 | |
| 
 | |
|   if (This == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Status              = EFI_SUCCESS;
 | |
|   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | |
| 
 | |
|   if (SimpleNetworkDevice == NULL) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   FrameReceived = FALSE;
 | |
| 
 | |
|   //
 | |
|   // Verify that the current state of the adapter is valid for this call.
 | |
|   //
 | |
|   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | |
|   case EfiSimpleNetworkInitialized:
 | |
|     break;
 | |
| 
 | |
|   case EfiSimpleNetworkStopped:
 | |
|     return EFI_NOT_STARTED;
 | |
| 
 | |
|   case EfiSimpleNetworkStarted:
 | |
|   default:
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   DEBUG ((DEBUG_NET, "Isr() IsrValid = %d\n", SimpleNetworkDevice->IsrValid));
 | |
| 
 | |
|   if (!SimpleNetworkDevice->IsrValid) {
 | |
|     //
 | |
|     // Call 16 bit UNDI ROM to open the network interface
 | |
|     //
 | |
|     ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T));
 | |
|     SimpleNetworkDevice->Isr.Status   = INIT_PXE_STATUS;
 | |
|     SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_START;
 | |
| 
 | |
|     DEBUG ((DEBUG_NET, "Isr() START\n"));
 | |
| 
 | |
|     Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
|     //
 | |
|     // Check the status code from the 16 bit UNDI ROM
 | |
|     //
 | |
|     if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) {
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
|     //
 | |
|     // There have been no events on this UNDI interface, so return EFI_NOT_READY
 | |
|     //
 | |
|     if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_NOT_OURS) {
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
|     //
 | |
|     // There is data to process, so call until all events processed.
 | |
|     //
 | |
|     ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T));
 | |
|     SimpleNetworkDevice->Isr.Status   = INIT_PXE_STATUS;
 | |
|     SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_PROCESS;
 | |
| 
 | |
|     DEBUG ((DEBUG_NET, "Isr() PROCESS\n"));
 | |
| 
 | |
|     Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     SimpleNetworkDevice->IsrValid = TRUE;
 | |
|   }
 | |
|   //
 | |
|   // Call UNDI GET_NEXT until DONE
 | |
|   //
 | |
|   while (SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_DONE) {
 | |
|     //
 | |
|     // Check the status code from the 16 bit UNDI ROM
 | |
|     //
 | |
|     if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) {
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
|     //
 | |
|     // UNDI is busy.  Caller will have to call again.
 | |
|     // This should never happen with a polled mode driver.
 | |
|     //
 | |
|     if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_BUSY) {
 | |
|       DEBUG ((DEBUG_NET, "  BUSY\n"));
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
|     //
 | |
|     // Check for invalud UNDI FuncFlag
 | |
|     //
 | |
|     if (SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_RECEIVE &&
 | |
|         SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_TRANSMIT
 | |
|         ) {
 | |
|       DEBUG ((DEBUG_NET, "  Invalid SimpleNetworkDevice->Isr.FuncFlag value %d\n", SimpleNetworkDevice->Isr.FuncFlag));
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
|     //
 | |
|     // Check for Transmit Event
 | |
|     //
 | |
|     if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_TRANSMIT) {
 | |
|       DEBUG ((DEBUG_NET, "  TRANSMIT\n"));
 | |
|       SimpleNetworkDevice->InterruptStatus |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
 | |
|     }
 | |
|     //
 | |
|     // Check for Receive Event
 | |
|     //
 | |
|     else if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_RECEIVE) {
 | |
|       //
 | |
|       // note - this code will hang on a receive interrupt in a GetStatus loop
 | |
|       //
 | |
|       DEBUG ((DEBUG_NET, "  RECEIVE\n"));
 | |
|       SimpleNetworkDevice->InterruptStatus |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
 | |
| 
 | |
|       DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.BufferLength      = %d\n", SimpleNetworkDevice->Isr.BufferLength));
 | |
|       DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.FrameLength       = %d\n", SimpleNetworkDevice->Isr.FrameLength));
 | |
|       DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.FrameHeaderLength = %d\n", SimpleNetworkDevice->Isr.FrameHeaderLength));
 | |
|       DEBUG (
 | |
|         (
 | |
|         DEBUG_NET, "SimpleNetworkDevice->Isr.Frame             = %04x:%04x\n", SimpleNetworkDevice->Isr.FrameSegSel,
 | |
|         SimpleNetworkDevice->Isr.FrameOffset
 | |
|         )
 | |
|         );
 | |
|       DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.ProtType          = 0x%02x\n", SimpleNetworkDevice->Isr.BufferLength));
 | |
|       DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.PktType           = 0x%02x\n", SimpleNetworkDevice->Isr.BufferLength));
 | |
| 
 | |
|       if (FrameReceived) {
 | |
|         return EFI_SUCCESS;
 | |
|       }
 | |
| 
 | |
|       if ((Frame == NULL) || (SimpleNetworkDevice->Isr.FrameLength > *FrameLength)) {
 | |
|         DEBUG ((DEBUG_NET, "return EFI_BUFFER_TOO_SMALL   *FrameLength = %08x\n", *FrameLength));
 | |
|         *FrameLength = SimpleNetworkDevice->Isr.FrameLength;
 | |
|         return EFI_BUFFER_TOO_SMALL;
 | |
|       }
 | |
| 
 | |
|       *FrameLength = SimpleNetworkDevice->Isr.FrameLength;
 | |
|       if (FrameHeaderLength != NULL) {
 | |
|         *FrameHeaderLength = SimpleNetworkDevice->Isr.FrameHeaderLength;
 | |
|       }
 | |
| 
 | |
|       if (ProtType != NULL) {
 | |
|         *ProtType = SimpleNetworkDevice->Isr.ProtType;
 | |
|       }
 | |
| 
 | |
|       if (PktType != NULL) {
 | |
|         *PktType = SimpleNetworkDevice->Isr.PktType;
 | |
|       }
 | |
| 
 | |
|       CopyMem (
 | |
|         Frame,
 | |
|         (VOID *) (((UINTN) SimpleNetworkDevice->Isr.FrameSegSel << 4) + SimpleNetworkDevice->Isr.FrameOffset),
 | |
|         SimpleNetworkDevice->Isr.BufferLength
 | |
|         );
 | |
|       Frame = Frame + SimpleNetworkDevice->Isr.BufferLength;
 | |
|       if (SimpleNetworkDevice->Isr.BufferLength == SimpleNetworkDevice->Isr.FrameLength) {
 | |
|         FrameReceived = TRUE;
 | |
|       }
 | |
|     }
 | |
|     //
 | |
|     // There is data to process, so call until all events processed.
 | |
|     //
 | |
|     ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T));
 | |
|     SimpleNetworkDevice->Isr.Status   = INIT_PXE_STATUS;
 | |
|     SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
 | |
| 
 | |
|     DEBUG ((DEBUG_NET, "Isr() GET NEXT\n"));
 | |
| 
 | |
|     Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
|     //
 | |
|     // Check the status code from the 16 bit UNDI ROM
 | |
|     //
 | |
|     //        if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) {
 | |
|     //            return EFI_DEVICE_ERROR;
 | |
|     //        }
 | |
|     //
 | |
|   }
 | |
| 
 | |
|   SimpleNetworkDevice->IsrValid = FALSE;
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| //
 | |
| // ///////////////////////////////////////////////////////////////////////////////////////
 | |
| // Simple Network Protocol Interface Functions using 16 bit UNDI Option ROMs
 | |
| /////////////////////////////////////////////////////////////////////////////////////////
 | |
| //
 | |
| // Start()
 | |
| //
 | |
| /**
 | |
|   Call 16 bit UNDI ROM to start the network interface
 | |
| 
 | |
|   @param This       A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | |
|   
 | |
|   @retval EFI_DEVICE_ERROR Network interface has not be initialized.
 | |
|   @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call.
 | |
|   @retval EFI_SUCESS       Success operation.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Undi16SimpleNetworkStart (
 | |
|   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS              Status;
 | |
|   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | |
|   PXENV_UNDI_STARTUP_T    Startup;
 | |
| 
 | |
|   if (This == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Status              = EFI_SUCCESS;
 | |
|   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | |
| 
 | |
|   if (SimpleNetworkDevice == NULL) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Verify that the current state of the adapter is valid for this call.
 | |
|   //
 | |
|   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | |
|   case EfiSimpleNetworkStopped:
 | |
|     break;
 | |
| 
 | |
|   case EfiSimpleNetworkStarted:
 | |
|   case EfiSimpleNetworkInitialized:
 | |
|     return EFI_ALREADY_STARTED;
 | |
| 
 | |
|   default:
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Call 16 bit UNDI ROM to start the network interface
 | |
|   //
 | |
|   Startup.Status  = INIT_PXE_STATUS;
 | |
| 
 | |
|   Status          = PxeUndiStartup (SimpleNetworkDevice, &Startup);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // Check the status code from the 16 bit UNDI ROM
 | |
|   //
 | |
|   if (Startup.Status != PXENV_STATUS_SUCCESS) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // The UNDI interface has been started, so update the State.
 | |
|   //
 | |
|   SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStarted;
 | |
| 
 | |
|   //
 | |
|   //
 | |
|   //
 | |
|   SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting = 0;
 | |
|   SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount     = 0;
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| //
 | |
| // Stop()
 | |
| //
 | |
| /**
 | |
|   Call 16 bit UNDI ROM to stop the network interface
 | |
| 
 | |
|   @param This       A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | |
|   
 | |
|   @retval EFI_DEVICE_ERROR Network interface has not be initialized.
 | |
|   @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call.
 | |
|   @retval EFI_SUCESS       Success operation.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Undi16SimpleNetworkStop (
 | |
|   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS              Status;
 | |
|   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | |
| 
 | |
|   if (This == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Status              = EFI_SUCCESS;
 | |
|   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | |
| 
 | |
|   if (SimpleNetworkDevice == NULL) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Verify that the current state of the adapter is valid for this call.
 | |
|   //
 | |
|   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | |
|   case EfiSimpleNetworkStarted:
 | |
|     break;
 | |
| 
 | |
|   case EfiSimpleNetworkStopped:
 | |
|     return EFI_NOT_STARTED;
 | |
| 
 | |
|   case EfiSimpleNetworkInitialized:
 | |
|   default:
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStopped;
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| //
 | |
| // Initialize()
 | |
| //
 | |
| /**
 | |
|   Initialize network interface 
 | |
| 
 | |
|   @param This                 A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | |
|   @param ExtraRxBufferSize    The size of extra request receive buffer.
 | |
|   @param ExtraTxBufferSize    The size of extra request transmit buffer.
 | |
|  
 | |
|   @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call.
 | |
|   @retval EFI_SUCESS       Success operation.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Undi16SimpleNetworkInitialize (
 | |
|   IN EFI_SIMPLE_NETWORK_PROTOCOL            *This,
 | |
|   IN UINTN                                  ExtraRxBufferSize  OPTIONAL,
 | |
|   IN UINTN                                  ExtraTxBufferSize  OPTIONAL
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS              Status;
 | |
|   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | |
|   PXENV_UNDI_INITIALIZE_T Initialize;
 | |
|   PXENV_UNDI_OPEN_T       Open;
 | |
| 
 | |
|   if (This == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Status              = EFI_SUCCESS;
 | |
|   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | |
| 
 | |
|   if (SimpleNetworkDevice == NULL) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Verify that the current state of the adapter is valid for this call.
 | |
|   //
 | |
|   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | |
|   case EfiSimpleNetworkStopped:
 | |
|     return EFI_NOT_STARTED;
 | |
| 
 | |
|   case EfiSimpleNetworkStarted:
 | |
|     break;
 | |
| 
 | |
|   case EfiSimpleNetworkInitialized:
 | |
|   default:
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Call 16 bit UNDI ROM to start the network interface
 | |
|   //
 | |
|   Initialize.Status       = INIT_PXE_STATUS;
 | |
|   Initialize.ProtocolIni  = 0;
 | |
| 
 | |
|   Status                  = PxeUndiInitialize (SimpleNetworkDevice, &Initialize);
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiInitialize() - Status = %r\n", Status));
 | |
|     DEBUG ((DEBUG_ERROR, "Initialize.Status == %xh\n", Initialize.Status));
 | |
| 
 | |
|     if (Initialize.Status == PXENV_STATUS_UNDI_MEDIATEST_FAILED) {
 | |
|       Status = EFI_NO_MEDIA;
 | |
|     }
 | |
| 
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // Check the status code from the 16 bit UNDI ROM
 | |
|   //
 | |
|   if (Initialize.Status != PXENV_STATUS_SUCCESS) {
 | |
|     DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiInitialize() - Initialize.Status = %04x\n", Initialize.Status));
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Call 16 bit UNDI ROM to open the network interface
 | |
|   //
 | |
|   Open.Status     = INIT_PXE_STATUS;
 | |
|   Open.OpenFlag   = 0;
 | |
|   Open.PktFilter  = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting);
 | |
|   Undi16GetMCastFilters (
 | |
|     &SimpleNetworkDevice->SimpleNetworkMode,
 | |
|     &Open.McastBuffer,
 | |
|     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | |
|     );
 | |
| 
 | |
|   Status = PxeUndiOpen (SimpleNetworkDevice, &Open);
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiOpen() - Status = %r\n", Status));
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // Check the status code from the 16 bit UNDI ROM
 | |
|   //
 | |
|   if (Open.Status != PXENV_STATUS_SUCCESS) {
 | |
|     DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiOpen() - Open.Status = %04x\n", Open.Status));
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // The UNDI interface has been initialized, so update the State.
 | |
|   //
 | |
|   SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkInitialized;
 | |
| 
 | |
|   //
 | |
|   // If initialize succeeds, then assume that media is present.
 | |
|   //
 | |
|   SimpleNetworkDevice->SimpleNetworkMode.MediaPresent = TRUE;
 | |
| 
 | |
|   //
 | |
|   // Reset the recycled transmit buffer FIFO
 | |
|   //
 | |
|   SimpleNetworkDevice->TxBufferFifo.First = 0;
 | |
|   SimpleNetworkDevice->TxBufferFifo.Last  = 0;
 | |
|   SimpleNetworkDevice->IsrValid           = FALSE;
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| //
 | |
| // Reset()
 | |
| //
 | |
| /**
 | |
|   Reset network interface.
 | |
| 
 | |
|   @param This                 A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | |
|   @param ExtendedVerification Need extended verfication.
 | |
|   
 | |
|   @retval EFI_INVALID_PARAMETER Invalid This parameter.
 | |
|   @retval EFI_DEVICE_ERROR      Network device has not been initialized.
 | |
|   @retval EFI_NOT_STARTED       Network device has been stopped.
 | |
|   @retval EFI_DEVICE_ERROR      Invalid status for network device
 | |
|   @retval EFI_SUCCESS           Success operation.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Undi16SimpleNetworkReset (
 | |
|   IN EFI_SIMPLE_NETWORK_PROTOCOL   *This,
 | |
|   IN BOOLEAN                       ExtendedVerification
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS              Status;
 | |
|   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | |
|   PXENV_UNDI_RESET_T      Reset;
 | |
|   UINT16                  Rx_filter;
 | |
| 
 | |
|   if (This == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Status              = EFI_SUCCESS;
 | |
|   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | |
| 
 | |
|   if (SimpleNetworkDevice == NULL) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Verify that the current state of the adapter is valid for this call.
 | |
|   //
 | |
|   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | |
|   case EfiSimpleNetworkStopped:
 | |
|     return EFI_NOT_STARTED;
 | |
| 
 | |
|   case EfiSimpleNetworkInitialized:
 | |
|     break;
 | |
| 
 | |
|   case EfiSimpleNetworkStarted:
 | |
|   default:
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   Reset.Status  = INIT_PXE_STATUS;
 | |
| 
 | |
|   Rx_filter     = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting);
 | |
| 
 | |
|   Undi16GetMCastFilters (
 | |
|     &SimpleNetworkDevice->SimpleNetworkMode,
 | |
|     &Reset.R_Mcast_Buf,
 | |
|     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | |
|     );
 | |
| 
 | |
|   Status = PxeUndiResetNic (SimpleNetworkDevice, &Reset, Rx_filter);
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // Check the status code from the 16 bit UNDI ROM
 | |
|   //
 | |
|   if (Reset.Status != PXENV_STATUS_SUCCESS) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Reset the recycled transmit buffer FIFO
 | |
|   //
 | |
|   SimpleNetworkDevice->TxBufferFifo.First = 0;
 | |
|   SimpleNetworkDevice->TxBufferFifo.Last  = 0;
 | |
|   SimpleNetworkDevice->IsrValid           = FALSE;
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| //
 | |
| // Shutdown()
 | |
| //
 | |
| /**
 | |
|   Shutdown network interface.
 | |
| 
 | |
|   @param This                 A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | |
|   
 | |
|   @retval EFI_INVALID_PARAMETER Invalid This parameter.
 | |
|   @retval EFI_DEVICE_ERROR      Network device has not been initialized.
 | |
|   @retval EFI_NOT_STARTED       Network device has been stopped.
 | |
|   @retval EFI_DEVICE_ERROR      Invalid status for network device
 | |
|   @retval EFI_SUCCESS           Success operation.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Undi16SimpleNetworkShutdown (
 | |
|   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS              Status;
 | |
|   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | |
|   PXENV_UNDI_CLOSE_T      Close;
 | |
|   PXENV_UNDI_SHUTDOWN_T   Shutdown;
 | |
| 
 | |
|   if (This == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Status              = EFI_SUCCESS;
 | |
|   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | |
| 
 | |
|   if (SimpleNetworkDevice == NULL) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Verify that the current state of the adapter is valid for this call.
 | |
|   //
 | |
|   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | |
|   case EfiSimpleNetworkStopped:
 | |
|     return EFI_NOT_STARTED;
 | |
| 
 | |
|   case EfiSimpleNetworkInitialized:
 | |
|     break;
 | |
| 
 | |
|   case EfiSimpleNetworkStarted:
 | |
|   default:
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   SimpleNetworkDevice->IsrValid = FALSE;
 | |
| 
 | |
|   //
 | |
|   // Call 16 bit UNDI ROM to start the network interface
 | |
|   //
 | |
|   Close.Status  = INIT_PXE_STATUS;
 | |
| 
 | |
|   Status        = PxeUndiClose (SimpleNetworkDevice, &Close);
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // Check the status code from the 16 bit UNDI ROM
 | |
|   //
 | |
|   if (Close.Status != PXENV_STATUS_SUCCESS) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Call 16 bit UNDI ROM to open the network interface
 | |
|   //
 | |
|   Shutdown.Status = INIT_PXE_STATUS;
 | |
| 
 | |
|   Status          = PxeUndiShutdown (SimpleNetworkDevice, &Shutdown);
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // Check the status code from the 16 bit UNDI ROM
 | |
|   //
 | |
|   if (Shutdown.Status != PXENV_STATUS_SUCCESS) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // The UNDI interface has been initialized, so update the State.
 | |
|   //
 | |
|   SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStarted;
 | |
| 
 | |
|   //
 | |
|   // If shutdown succeeds, then assume that media is not present.
 | |
|   //
 | |
|   SimpleNetworkDevice->SimpleNetworkMode.MediaPresent = FALSE;
 | |
| 
 | |
|   //
 | |
|   // Reset the recycled transmit buffer FIFO
 | |
|   //
 | |
|   SimpleNetworkDevice->TxBufferFifo.First = 0;
 | |
|   SimpleNetworkDevice->TxBufferFifo.Last  = 0;
 | |
| 
 | |
|   //
 | |
|   // A short delay.  Without this an initialize immediately following
 | |
|   // a shutdown will cause some versions of UNDI-16 to stop operating.
 | |
|   //
 | |
|   gBS->Stall (250000);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| //
 | |
| // ReceiveFilters()
 | |
| //
 | |
| /**
 | |
|   Reset network interface.
 | |
| 
 | |
|   @param This                 A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | |
|   @param Enable               Enable mask value
 | |
|   @param Disable              Disable mask value
 | |
|   @param ResetMCastFilter     Whether reset multi cast filter or not
 | |
|   @param MCastFilterCnt       Count of mutli cast filter for different MAC address
 | |
|   @param MCastFilter          Buffer for mustli cast filter for different MAC address.
 | |
|   
 | |
|   @retval EFI_INVALID_PARAMETER Invalid This parameter.
 | |
|   @retval EFI_DEVICE_ERROR      Network device has not been initialized.
 | |
|   @retval EFI_NOT_STARTED       Network device has been stopped.
 | |
|   @retval EFI_DEVICE_ERROR      Invalid status for network device
 | |
|   @retval EFI_SUCCESS           Success operation.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Undi16SimpleNetworkReceiveFilters (
 | |
|   IN EFI_SIMPLE_NETWORK_PROTOCOL                     * This,
 | |
|   IN UINT32                                          Enable,
 | |
|   IN UINT32                                          Disable,
 | |
|   IN BOOLEAN                                         ResetMCastFilter,
 | |
|   IN UINTN                                           MCastFilterCnt     OPTIONAL,
 | |
|   IN EFI_MAC_ADDRESS                                 * MCastFilter OPTIONAL
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS              Status;
 | |
|   UINTN                   Index;
 | |
|   UINT32                  NewFilter;
 | |
|   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | |
|   PXENV_UNDI_CLOSE_T      Close;
 | |
|   PXENV_UNDI_OPEN_T       Open;
 | |
| 
 | |
|   if (This == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Status              = EFI_SUCCESS;
 | |
|   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | |
| 
 | |
|   if (SimpleNetworkDevice == NULL) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Verify that the current state of the adapter is valid for this call.
 | |
|   //
 | |
|   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | |
|   case EfiSimpleNetworkStopped:
 | |
|     return EFI_NOT_STARTED;
 | |
| 
 | |
|   case EfiSimpleNetworkInitialized:
 | |
|     break;
 | |
| 
 | |
|   case EfiSimpleNetworkStarted:
 | |
|   default:
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // First deal with possible filter setting changes
 | |
|   //
 | |
|   if ((Enable == 0) && (Disable == 0) && !ResetMCastFilter) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   NewFilter = (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting | Enable) &~Disable;
 | |
| 
 | |
|   if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
 | |
|     if ((MCastFilterCnt == 0) || (MCastFilter == 0) || MCastFilterCnt > SimpleNetworkDevice->SimpleNetworkMode.MaxMCastFilterCount) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // Call 16 bit UNDI ROM to close the network interface
 | |
|   //
 | |
|   Close.Status  = INIT_PXE_STATUS;
 | |
| 
 | |
|   Status        = PxeUndiClose (SimpleNetworkDevice, &Close);
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // Check the status code from the 16 bit UNDI ROM
 | |
|   //
 | |
|   if (Close.Status != PXENV_STATUS_SUCCESS) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Call 16 bit UNDI ROM to open the network interface
 | |
|   //
 | |
|   //
 | |
|   // Reset the recycled transmit buffer FIFO
 | |
|   //
 | |
|   SimpleNetworkDevice->TxBufferFifo.First = 0;
 | |
|   SimpleNetworkDevice->TxBufferFifo.Last  = 0;
 | |
| 
 | |
|   //
 | |
|   // Call 16 bit UNDI ROM to open the network interface
 | |
|   //
 | |
|   ZeroMem (&Open, sizeof Open);
 | |
| 
 | |
|   Open.Status     = INIT_PXE_STATUS;
 | |
|   Open.PktFilter  = Undi16GetPacketFilterSetting (NewFilter);
 | |
| 
 | |
|   if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
 | |
|     //
 | |
|     // Copy the MAC addresses into the UNDI open parameter structure
 | |
|     //
 | |
|     Open.McastBuffer.MCastAddrCount = (UINT16) MCastFilterCnt;
 | |
|     for (Index = 0; Index < MCastFilterCnt; ++Index) {
 | |
|       CopyMem (
 | |
|         Open.McastBuffer.MCastAddr[Index],
 | |
|         &MCastFilter[Index],
 | |
|         sizeof Open.McastBuffer.MCastAddr[Index]
 | |
|         );
 | |
|     }
 | |
|   } else if (!ResetMCastFilter) {
 | |
|     for (Index = 0; Index < SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount; ++Index) {
 | |
|       CopyMem (
 | |
|         Open.McastBuffer.MCastAddr[Index],
 | |
|         &SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index],
 | |
|         sizeof Open.McastBuffer.MCastAddr[Index]
 | |
|         );
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Status = PxeUndiOpen (SimpleNetworkDevice, &Open);
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // Check the status code from the 16 bit UNDI ROM
 | |
|   //
 | |
|   if (Open.Status != PXENV_STATUS_SUCCESS) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   SimpleNetworkDevice->IsrValid = FALSE;
 | |
|   SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting = NewFilter;
 | |
| 
 | |
|   if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
 | |
|     SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount = (UINT32) MCastFilterCnt;
 | |
|     for (Index = 0; Index < MCastFilterCnt; ++Index) {
 | |
|       CopyMem (
 | |
|         &SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index],
 | |
|         &MCastFilter[Index],
 | |
|         sizeof (EFI_MAC_ADDRESS)
 | |
|         );      
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // Read back multicast addresses.
 | |
|   //
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| //
 | |
| // StationAddress()
 | |
| //
 | |
| /**
 | |
|   Set new MAC address.
 | |
| 
 | |
|   @param This                 A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | |
|   @param Reset                Whether reset station MAC address to permanent address
 | |
|   @param New                  A pointer to New address
 | |
|   
 | |
|   @retval EFI_INVALID_PARAMETER Invalid This parameter.
 | |
|   @retval EFI_DEVICE_ERROR      Network device has not been initialized.
 | |
|   @retval EFI_NOT_STARTED       Network device has been stopped.
 | |
|   @retval EFI_DEVICE_ERROR      Invalid status for network device
 | |
|   @retval EFI_SUCCESS           Success operation.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Undi16SimpleNetworkStationAddress (
 | |
|   IN EFI_SIMPLE_NETWORK_PROTOCOL           * This,
 | |
|   IN BOOLEAN                               Reset,
 | |
|   IN EFI_MAC_ADDRESS                       * New OPTIONAL
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                    Status;
 | |
|   EFI_SIMPLE_NETWORK_DEV        *SimpleNetworkDevice;
 | |
|   PXENV_UNDI_SET_STATION_ADDR_T SetStationAddr;
 | |
|   //
 | |
|   // EFI_DEVICE_PATH_PROTOCOL     *OldDevicePath;
 | |
|   //
 | |
|   PXENV_UNDI_CLOSE_T            Close;
 | |
|   PXENV_UNDI_OPEN_T             Open;
 | |
| 
 | |
|   if (This == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Status              = EFI_SUCCESS;
 | |
| 
 | |
|   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | |
| 
 | |
|   if (SimpleNetworkDevice == NULL) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Verify that the current state of the adapter is valid for this call.
 | |
|   //
 | |
|   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | |
|   case EfiSimpleNetworkInitialized:
 | |
|     break;
 | |
| 
 | |
|   case EfiSimpleNetworkStopped:
 | |
|     return EFI_NOT_STARTED;
 | |
| 
 | |
|   case EfiSimpleNetworkStarted:
 | |
|   default:
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Call 16 bit UNDI ROM to open the network interface
 | |
|   //
 | |
|   SetStationAddr.Status = INIT_PXE_STATUS;
 | |
| 
 | |
|   if (Reset) {
 | |
|     //
 | |
|     // If we are resetting the Station Address to the permanent address, and the
 | |
|     // Station Address is not programmable, then just return EFI_SUCCESS.
 | |
|     //
 | |
|     if (!SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable) {
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
|     //
 | |
|     // If the address is already the permanent address, then just return success.
 | |
|     //
 | |
|     if (CompareMem (
 | |
|           &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
 | |
|           &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,
 | |
|           SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | |
|           ) == 0) {
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
|     //
 | |
|     // Copy the adapters permanent address to the new station address
 | |
|     //
 | |
|     CopyMem (
 | |
|       &SetStationAddr.StationAddress,
 | |
|       &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,
 | |
|       SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | |
|       );
 | |
|   } else {
 | |
|     //
 | |
|     // If we are setting the Station Address, and the
 | |
|     // Station Address is not programmable, return invalid parameter.
 | |
|     //
 | |
|     if (!SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
|     //
 | |
|     // If the address is already the new address, then just return success.
 | |
|     //
 | |
|     if (CompareMem (
 | |
|           &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
 | |
|           New,
 | |
|           SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | |
|           ) == 0) {
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
|     //
 | |
|     // Copy New to the new station address
 | |
|     //
 | |
|     CopyMem (
 | |
|       &SetStationAddr.StationAddress,
 | |
|       New,
 | |
|       SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | |
|       );
 | |
| 
 | |
|   }
 | |
|   //
 | |
|   // Call 16 bit UNDI ROM to stop the network interface
 | |
|   //
 | |
|   Close.Status = INIT_PXE_STATUS;
 | |
| 
 | |
|   PxeUndiClose (SimpleNetworkDevice, &Close);
 | |
| 
 | |
|   //
 | |
|   // Call 16-bit UNDI ROM to set the station address
 | |
|   //
 | |
|   SetStationAddr.Status = PXENV_STATUS_SUCCESS;
 | |
| 
 | |
|   Status                = PxeUndiSetStationAddr (SimpleNetworkDevice, &SetStationAddr);
 | |
| 
 | |
|   //
 | |
|   // Call 16-bit UNDI ROM to start the network interface
 | |
|   //
 | |
|   Open.Status     = PXENV_STATUS_SUCCESS;
 | |
|   Open.OpenFlag   = 0;
 | |
|   Open.PktFilter  = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting);
 | |
|   Undi16GetMCastFilters (
 | |
|     &SimpleNetworkDevice->SimpleNetworkMode,
 | |
|     &Open.McastBuffer,
 | |
|     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | |
|     );
 | |
| 
 | |
|   PxeUndiOpen (SimpleNetworkDevice, &Open);
 | |
| 
 | |
|   //
 | |
|   // Check status from station address change
 | |
|   //
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // Check the status code from the 16 bit UNDI ROM
 | |
|   //
 | |
|   if (SetStationAddr.Status != PXENV_STATUS_SUCCESS) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   CopyMem (
 | |
|     &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
 | |
|     &SetStationAddr.StationAddress,
 | |
|     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | |
|     );
 | |
| 
 | |
| #if 0 /* The device path is based on the permanent address not the current address. */
 | |
|   //
 | |
|   // The station address was changed, so update the device path with the new MAC address.
 | |
|   //
 | |
|   OldDevicePath                   = SimpleNetworkDevice->DevicePath;
 | |
|   SimpleNetworkDevice->DevicePath = DuplicateDevicePath (SimpleNetworkDevice->BaseDevicePath);
 | |
|   SimpleNetworkAppendMacAddressDevicePath (
 | |
|     &SimpleNetworkDevice->DevicePath,
 | |
|     &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress
 | |
|     );
 | |
| 
 | |
|   Status = LibReinstallProtocolInterfaces (
 | |
|             SimpleNetworkDevice->Handle,
 | |
|             &DevicePathProtocol,
 | |
|             OldDevicePath,
 | |
|             SimpleNetworkDevice->DevicePath,
 | |
|             NULL
 | |
|             );
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "Failed to reinstall the DevicePath protocol for the Simple Network Device\n"));
 | |
|     DEBUG ((DEBUG_ERROR, "  Status = %r\n", Status));
 | |
|   }
 | |
| 
 | |
|   FreePool (OldDevicePath);
 | |
| #endif /* 0 */
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| //
 | |
| // Statistics()
 | |
| //
 | |
| /**
 | |
|   Resets or collects the statistics on a network interface.
 | |
| 
 | |
|   @param  This            Protocol instance pointer.
 | |
|   @param  Reset           Set to TRUE to reset the statistics for the network interface.
 | |
|   @param  StatisticsSize  On input the size, in bytes, of StatisticsTable. On
 | |
|                           output the size, in bytes, of the resulting table of
 | |
|                           statistics.
 | |
|   @param  StatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that
 | |
|                           contains the statistics.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The statistics were collected from the network interface.
 | |
|   @retval EFI_NOT_STARTED       The network interface has not been started.
 | |
|   @retval EFI_BUFFER_TOO_SMALL  The Statistics buffer was too small. The current buffer
 | |
|                                 size needed to hold the statistics is returned in
 | |
|                                 StatisticsSize.
 | |
|   @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
 | |
|   @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
 | |
|   @retval EFI_UNSUPPORTED       This function is not supported by the network interface.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Undi16SimpleNetworkStatistics (
 | |
|   IN EFI_SIMPLE_NETWORK_PROTOCOL       * This,
 | |
|   IN BOOLEAN                           Reset,
 | |
|   IN OUT UINTN                         *StatisticsSize OPTIONAL,
 | |
|   OUT EFI_NETWORK_STATISTICS           * StatisticsTable OPTIONAL
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                    Status;
 | |
|   EFI_SIMPLE_NETWORK_DEV        *SimpleNetworkDevice;
 | |
|   PXENV_UNDI_CLEAR_STATISTICS_T ClearStatistics;
 | |
|   PXENV_UNDI_GET_STATISTICS_T   GetStatistics;
 | |
| 
 | |
|   if (This == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Status              = EFI_SUCCESS;
 | |
|   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | |
| 
 | |
|   if (SimpleNetworkDevice == NULL) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Verify that the current state of the adapter is valid for this call.
 | |
|   //
 | |
|   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | |
|   case EfiSimpleNetworkInitialized:
 | |
|     break;
 | |
| 
 | |
|   case EfiSimpleNetworkStopped:
 | |
|     return EFI_NOT_STARTED;
 | |
| 
 | |
|   case EfiSimpleNetworkStarted:
 | |
|   default:
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   if ((StatisticsSize != NULL) && (*StatisticsSize != 0) && (StatisticsTable == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // If Reset is TRUE, then clear all the statistics.
 | |
|   //
 | |
|   if (Reset) {
 | |
| 
 | |
|     DEBUG ((DEBUG_NET, "  RESET Statistics\n"));
 | |
| 
 | |
|     //
 | |
|     // Call 16 bit UNDI ROM to open the network interface
 | |
|     //
 | |
|     ClearStatistics.Status  = INIT_PXE_STATUS;
 | |
| 
 | |
|     Status                  = PxeUndiClearStatistics (SimpleNetworkDevice, &ClearStatistics);
 | |
| 
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
|     //
 | |
|     // Check the status code from the 16 bit UNDI ROM
 | |
|     //
 | |
|     if (ClearStatistics.Status != PXENV_STATUS_SUCCESS) {
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
| 
 | |
|     DEBUG ((DEBUG_NET, "  RESET Statistics Complete"));
 | |
|   }
 | |
| 
 | |
|   if (StatisticsSize != NULL) {
 | |
|     EFI_NETWORK_STATISTICS  LocalStatisticsTable;
 | |
| 
 | |
|     DEBUG ((DEBUG_NET, "  GET Statistics\n"));
 | |
| 
 | |
|     //
 | |
|     // If the size if valid, then see if the table is valid
 | |
|     //
 | |
|     if (StatisticsTable == NULL) {
 | |
|       DEBUG ((DEBUG_NET, "  StatisticsTable is NULL\n"));
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
|     //
 | |
|     // Call 16 bit UNDI ROM to open the network interface
 | |
|     //
 | |
|     GetStatistics.Status            = INIT_PXE_STATUS;
 | |
|     GetStatistics.XmtGoodFrames     = 0;
 | |
|     GetStatistics.RcvGoodFrames     = 0;
 | |
|     GetStatistics.RcvCRCErrors      = 0;
 | |
|     GetStatistics.RcvResourceErrors = 0;
 | |
| 
 | |
|     Status                          = PxeUndiGetStatistics (SimpleNetworkDevice, &GetStatistics);
 | |
| 
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
|     //
 | |
|     // Check the status code from the 16 bit UNDI ROM
 | |
|     //
 | |
|     if (GetStatistics.Status != PXENV_STATUS_SUCCESS) {
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
|     //
 | |
|     // Fill in the Statistics Table with the collected values.
 | |
|     //
 | |
|     SetMem (&LocalStatisticsTable, sizeof LocalStatisticsTable, 0xff);
 | |
| 
 | |
|     LocalStatisticsTable.TxGoodFrames     = GetStatistics.XmtGoodFrames;
 | |
|     LocalStatisticsTable.RxGoodFrames     = GetStatistics.RcvGoodFrames;
 | |
|     LocalStatisticsTable.RxCrcErrorFrames = GetStatistics.RcvCRCErrors;
 | |
|     LocalStatisticsTable.RxDroppedFrames  = GetStatistics.RcvResourceErrors;
 | |
| 
 | |
|     CopyMem (StatisticsTable, &LocalStatisticsTable, *StatisticsSize);
 | |
| 
 | |
|     DEBUG (
 | |
|       (DEBUG_NET,
 | |
|       "  Statistics Collected : Size=%d  Buf=%08x\n",
 | |
|       *StatisticsSize,
 | |
|       StatisticsTable)
 | |
|       );
 | |
| 
 | |
|     DEBUG ((DEBUG_NET, "  GET Statistics Complete"));
 | |
| 
 | |
|     if (*StatisticsSize < sizeof LocalStatisticsTable) {
 | |
|       DEBUG ((DEBUG_NET, "  BUFFER TOO SMALL\n"));
 | |
|       Status = EFI_BUFFER_TOO_SMALL;
 | |
|     }
 | |
| 
 | |
|     *StatisticsSize = sizeof LocalStatisticsTable;
 | |
| 
 | |
|     return Status;
 | |
| 
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| //
 | |
| // MCastIpToMac()
 | |
| //
 | |
| /**
 | |
|   Translate IP address to MAC address.
 | |
| 
 | |
|   @param This                 A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | |
|   @param IPv6                 IPv6 or IPv4
 | |
|   @param IP                   A pointer to given Ip address.
 | |
|   @param MAC                  On return, translated MAC address.
 | |
|   
 | |
|   @retval EFI_INVALID_PARAMETER Invalid This parameter.
 | |
|   @retval EFI_INVALID_PARAMETER Invalid IP address.
 | |
|   @retval EFI_INVALID_PARAMETER Invalid return buffer for holding MAC address.
 | |
|   @retval EFI_UNSUPPORTED       Do not support IPv6 
 | |
|   @retval EFI_DEVICE_ERROR      Network device has not been initialized.
 | |
|   @retval EFI_NOT_STARTED       Network device has been stopped.
 | |
|   @retval EFI_DEVICE_ERROR      Invalid status for network device
 | |
|   @retval EFI_SUCCESS           Success operation.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Undi16SimpleNetworkMCastIpToMac (
 | |
|   IN EFI_SIMPLE_NETWORK_PROTOCOL            *This,
 | |
|   IN BOOLEAN                                IPv6,
 | |
|   IN EFI_IP_ADDRESS                         *IP,
 | |
|   OUT EFI_MAC_ADDRESS                       *MAC
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                  Status;
 | |
|   EFI_SIMPLE_NETWORK_DEV      *SimpleNetworkDevice;
 | |
|   PXENV_UNDI_GET_MCAST_ADDR_T GetMcastAddr;
 | |
| 
 | |
|   if (This == NULL || IP == NULL || MAC == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Status              = EFI_SUCCESS;
 | |
|   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | |
| 
 | |
|   if (SimpleNetworkDevice == NULL) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Verify that the current state of the adapter is valid for this call.
 | |
|   //
 | |
|   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | |
|   case EfiSimpleNetworkStopped:
 | |
|     return EFI_NOT_STARTED;
 | |
| 
 | |
|   case EfiSimpleNetworkInitialized:
 | |
|     break;
 | |
| 
 | |
|   case EfiSimpleNetworkStarted:
 | |
|   default:
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // 16 bit UNDI Option ROMS do not support IPv6.  Check for IPv6 usage.
 | |
|   //
 | |
|   if (IPv6) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
|   //
 | |
|   // Call 16 bit UNDI ROM to open the network interface
 | |
|   //
 | |
|   GetMcastAddr.Status = INIT_PXE_STATUS;
 | |
|   CopyMem (&GetMcastAddr.InetAddr, IP, 4);
 | |
| 
 | |
|   Status = PxeUndiGetMcastAddr (SimpleNetworkDevice, &GetMcastAddr);
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // Check the status code from the 16 bit UNDI ROM
 | |
|   //
 | |
|   if (GetMcastAddr.Status != PXENV_STATUS_SUCCESS) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Copy the MAC address from the returned data structure.
 | |
|   //
 | |
|   CopyMem (
 | |
|     MAC,
 | |
|     &GetMcastAddr.MediaAddr,
 | |
|     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | |
|     );
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| //
 | |
| // NvData()
 | |
| //
 | |
| /**
 | |
|   Performs read and write operations on the NVRAM device attached to a 
 | |
|   network interface.
 | |
| 
 | |
|   @param  This       The protocol instance pointer.
 | |
|   @param  ReadWrite  TRUE for read operations, FALSE for write operations.
 | |
|   @param  Offset     Byte offset in the NVRAM device at which to start the read or
 | |
|                      write operation. This must be a multiple of NvRamAccessSize and
 | |
|                      less than NvRamSize.
 | |
|   @param  BufferSize The number of bytes to read or write from the NVRAM device.
 | |
|                      This must also be a multiple of NvramAccessSize.
 | |
|   @param  Buffer     A pointer to the data buffer.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The NVRAM access was performed.
 | |
|   @retval EFI_NOT_STARTED       The network interface has not been started.
 | |
|   @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
 | |
|   @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
 | |
|   @retval EFI_UNSUPPORTED       This function is not supported by the network interface.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Undi16SimpleNetworkNvData (
 | |
|   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This,
 | |
|   IN BOOLEAN                      ReadWrite,
 | |
|   IN UINTN                        Offset,
 | |
|   IN UINTN                        BufferSize,
 | |
|   IN OUT VOID                     *Buffer
 | |
|   )
 | |
| {
 | |
|   return EFI_UNSUPPORTED;
 | |
| }
 | |
| //
 | |
| // GetStatus()
 | |
| //
 | |
| /**
 | |
|   Reads the current interrupt status and recycled transmit buffer status from 
 | |
|   a network interface.
 | |
| 
 | |
|   @param  This            The protocol instance pointer.
 | |
|   @param  InterruptStatus A pointer to the bit mask of the currently active interrupts
 | |
|                           If this is NULL, the interrupt status will not be read from
 | |
|                           the device. If this is not NULL, the interrupt status will
 | |
|                           be read from the device. When the  interrupt status is read,
 | |
|                           it will also be cleared. Clearing the transmit  interrupt
 | |
|                           does not empty the recycled transmit buffer array.
 | |
|   @param  TxBuf           Recycled transmit buffer address. The network interface will
 | |
|                           not transmit if its internal recycled transmit buffer array
 | |
|                           is full. Reading the transmit buffer does not clear the
 | |
|                           transmit interrupt. If this is NULL, then the transmit buffer
 | |
|                           status will not be read. If there are no transmit buffers to
 | |
|                           recycle and TxBuf is not NULL, * TxBuf will be set to NULL.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The status of the network interface was retrieved.
 | |
|   @retval EFI_NOT_STARTED       The network interface has not been started.
 | |
|   @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
 | |
|   @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
 | |
|   @retval EFI_UNSUPPORTED       This function is not supported by the network interface.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Undi16SimpleNetworkGetStatus (
 | |
|   IN EFI_SIMPLE_NETWORK_PROTOCOL  * This,
 | |
|   OUT UINT32                      *InterruptStatus OPTIONAL,
 | |
|   OUT VOID                        **TxBuf OPTIONAL
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS              Status;
 | |
|   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | |
|   UINTN                   FrameLength;
 | |
| 
 | |
|   if (This == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Status              = EFI_SUCCESS;
 | |
|   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | |
| 
 | |
|   if (SimpleNetworkDevice == NULL) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Verify that the current state of the adapter is valid for this call.
 | |
|   //
 | |
|   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | |
|   case EfiSimpleNetworkInitialized:
 | |
|     break;
 | |
| 
 | |
|   case EfiSimpleNetworkStopped:
 | |
|     return EFI_NOT_STARTED;
 | |
| 
 | |
|   case EfiSimpleNetworkStarted:
 | |
|   default:
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   if (InterruptStatus == NULL && TxBuf == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   FrameLength = 0;
 | |
|   Status      = Undi16SimpleNetworkIsr (This, &FrameLength, NULL, NULL, NULL, NULL);
 | |
| 
 | |
|   if (Status != EFI_BUFFER_TOO_SMALL) {
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // See if the caller wants interrupt info.
 | |
|   //
 | |
|   if (InterruptStatus != NULL) {
 | |
|     *InterruptStatus                      = SimpleNetworkDevice->InterruptStatus;
 | |
|     SimpleNetworkDevice->InterruptStatus  = 0;
 | |
|   }
 | |
|   //
 | |
|   // See if the caller wants transmit buffer status info.
 | |
|   //
 | |
|   if (TxBuf != NULL) {
 | |
|     *TxBuf = 0;
 | |
|     SimpleNetworkTransmitFifoRemove (&(SimpleNetworkDevice->TxBufferFifo), TxBuf);
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Places a packet in the transmit queue of a network interface.
 | |
| 
 | |
|   @param  This       The protocol instance pointer.
 | |
|   @param  HeaderSize The size, in bytes, of the media header to be filled in by
 | |
|                      the Transmit() function. If HeaderSize is non-zero, then it
 | |
|                      must be equal to This->Mode->MediaHeaderSize and the DestAddr
 | |
|                      and Protocol parameters must not be NULL.
 | |
|   @param  BufferSize The size, in bytes, of the entire packet (media header and
 | |
|                      data) to be transmitted through the network interface.
 | |
|   @param  Buffer     A pointer to the packet (media header followed by data) to be
 | |
|                      transmitted. This parameter cannot be NULL. If HeaderSize is zero,
 | |
|                      then the media header in Buffer must already be filled in by the
 | |
|                      caller. If HeaderSize is non-zero, then the media header will be
 | |
|                      filled in by the Transmit() function.
 | |
|   @param  SrcAddr    The source HW MAC address. If HeaderSize is zero, then this parameter
 | |
|                      is ignored. If HeaderSize is non-zero and SrcAddr is NULL, then
 | |
|                      This->Mode->CurrentAddress is used for the source HW MAC address.
 | |
|   @param  DestAddr   The destination HW MAC address. If HeaderSize is zero, then this
 | |
|                      parameter is ignored.
 | |
|   @param  Protocol   The type of header to build. If HeaderSize is zero, then this
 | |
|                      parameter is ignored. See RFC 1700, section "Ether Types", for
 | |
|                      examples.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The packet was placed on the transmit queue.
 | |
|   @retval EFI_NOT_STARTED       The network interface has not been started.
 | |
|   @retval EFI_NOT_READY         The network interface is too busy to accept this transmit request.                      
 | |
|   @retval EFI_BUFFER_TOO_SMALL  The BufferSize parameter is too small.
 | |
|   @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
 | |
|   @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
 | |
|   @retval EFI_UNSUPPORTED       This function is not supported by the network interface.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Undi16SimpleNetworkTransmit (
 | |
|   IN EFI_SIMPLE_NETWORK_PROTOCOL           *This,
 | |
|   IN UINTN                                 HeaderSize,
 | |
|   IN UINTN                                 BufferSize,
 | |
|   IN VOID                                  *Buffer,
 | |
|   IN EFI_MAC_ADDRESS                       *SrcAddr OPTIONAL,
 | |
|   IN EFI_MAC_ADDRESS                       *DestAddr OPTIONAL,
 | |
|   IN UINT16                                *Protocol OPTIONAL
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS              Status;
 | |
|   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | |
|   PXENV_UNDI_TRANSMIT_T   XmitInfo;
 | |
| 
 | |
|   if (This == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Status              = EFI_SUCCESS;
 | |
|   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | |
| 
 | |
|   if (SimpleNetworkDevice == NULL) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Verify that the current state of the adapter is valid for this call.
 | |
|   //
 | |
|   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | |
|   case EfiSimpleNetworkInitialized:
 | |
|     break;
 | |
| 
 | |
|   case EfiSimpleNetworkStopped:
 | |
|     return EFI_NOT_STARTED;
 | |
| 
 | |
|   case EfiSimpleNetworkStarted:
 | |
|   default:
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   if (Buffer == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (BufferSize < SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize) {
 | |
|     return EFI_BUFFER_TOO_SMALL;
 | |
|   }
 | |
| 
 | |
|   if (HeaderSize != 0) {
 | |
|     if (HeaderSize != SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     if (DestAddr == NULL || Protocol == NULL) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     if (DestAddr != NULL) {
 | |
|       CopyMem (
 | |
|         Buffer,
 | |
|         DestAddr,
 | |
|         SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | |
|         );
 | |
|     }
 | |
| 
 | |
|     if (SrcAddr == NULL) {
 | |
|       SrcAddr = &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress;
 | |
|     }
 | |
| 
 | |
|     CopyMem (
 | |
|       (UINT8 *) Buffer + SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize,
 | |
|       SrcAddr,
 | |
|       SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | |
|       );
 | |
| 
 | |
|     if (Protocol != NULL) {
 | |
|       *(UINT16 *) ((UINT8 *) Buffer + 2 * SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize) = (UINT16) (((*Protocol & 0xFF) << 8) | ((*Protocol >> 8) & 0xFF));
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // See if the recycled transmit buffer FIFO is full.
 | |
|   // If it is full, then we can not transmit until the caller calls GetStatus() to pull
 | |
|   // off recycled transmit buffers.
 | |
|   //
 | |
|   if (SimpleNetworkTransmitFifoFull (&(SimpleNetworkDevice->TxBufferFifo))) {
 | |
|     return EFI_NOT_READY;
 | |
|   }
 | |
|   //
 | |
|   //  Output debug trace message.
 | |
|   //
 | |
|   DEBUG ((DEBUG_NET, "Undi16SimpleNetworkTransmit\n\r "));
 | |
| 
 | |
|   //
 | |
|   // Initialize UNDI WRITE parameter structure.
 | |
|   //
 | |
|   XmitInfo.Status           = INIT_PXE_STATUS;
 | |
|   XmitInfo.Protocol         = P_UNKNOWN;
 | |
|   XmitInfo.XmitFlag         = XMT_DESTADDR;
 | |
|   XmitInfo.DestAddrOffset   = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->TxDestAddr & 0x000f);
 | |
|   XmitInfo.DestAddrSegment  = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->TxDestAddr >> 4);
 | |
|   XmitInfo.TBDOffset        = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->Xmit & 0x000f);
 | |
|   XmitInfo.TBDSegment       = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->Xmit >> 4);
 | |
|   XmitInfo.Reserved[0]      = 0;
 | |
|   XmitInfo.Reserved[1]      = 0;
 | |
| 
 | |
|   CopyMem (
 | |
|     SimpleNetworkDevice->TxDestAddr,
 | |
|     Buffer,
 | |
|     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | |
|     );
 | |
| 
 | |
|   CopyMem (
 | |
|     SimpleNetworkDevice->TxRealModeMediaHeader,
 | |
|     Buffer,
 | |
|     SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize
 | |
|     );
 | |
| 
 | |
|   SimpleNetworkDevice->Xmit->ImmedLength            = (UINT16) SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize;
 | |
| 
 | |
|   SimpleNetworkDevice->Xmit->DataBlock[0].TDDataLen = (UINT16) (BufferSize - SimpleNetworkDevice->Xmit->ImmedLength);
 | |
| 
 | |
|   CopyMem (
 | |
|     SimpleNetworkDevice->TxRealModeDataBuffer,
 | |
|     (UINT8 *) Buffer + SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize,
 | |
|     SimpleNetworkDevice->Xmit->DataBlock[0].TDDataLen
 | |
|     );
 | |
| 
 | |
|   //
 | |
|   // Make API call to UNDI TRANSMIT
 | |
|   //
 | |
|   XmitInfo.Status = 0;
 | |
| 
 | |
|   Status          = PxeUndiTransmit (SimpleNetworkDevice, &XmitInfo);
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // Check the status code from the 16 bit UNDI ROM
 | |
|   //
 | |
|   switch (XmitInfo.Status) {
 | |
|   case PXENV_STATUS_OUT_OF_RESOURCES:
 | |
|     return EFI_NOT_READY;
 | |
| 
 | |
|   case PXENV_STATUS_SUCCESS:
 | |
|     break;
 | |
| 
 | |
|   default:
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Add address of Buffer to the recycled transmit buffer FIFO
 | |
|   //
 | |
|   SimpleNetworkTransmitFifoAdd (&(SimpleNetworkDevice->TxBufferFifo), Buffer);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Receives a packet from a network interface.
 | |
|   
 | |
|   @param  This       The protocol instance pointer.
 | |
|   @param  HeaderSize The size, in bytes, of the media header received on the network
 | |
|                      interface. If this parameter is NULL, then the media header size
 | |
|                      will not be returned.
 | |
|   @param  BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in
 | |
|                      bytes, of the packet that was received on the network interface.
 | |
|   @param  Buffer     A pointer to the data buffer to receive both the media header and
 | |
|                      the data.
 | |
|   @param  SrcAddr    The source HW MAC address. If this parameter is NULL, the
 | |
|                      HW MAC source address will not be extracted from the media
 | |
|                      header.
 | |
|   @param  DestAddr   The destination HW MAC address. If this parameter is NULL,
 | |
|                      the HW MAC destination address will not be extracted from the
 | |
|                      media header.
 | |
|   @param  Protocol   The media header type. If this parameter is NULL, then the
 | |
|                      protocol will not be extracted from the media header. See
 | |
|                      RFC 1700 section "Ether Types" for examples.
 | |
| 
 | |
|   @retval  EFI_SUCCESS           The received data was stored in Buffer, and BufferSize has
 | |
|                                  been updated to the number of bytes received.
 | |
|   @retval  EFI_NOT_STARTED       The network interface has not been started.
 | |
|   @retval  EFI_NOT_READY         The network interface is too busy to accept this transmit
 | |
|                                  request.
 | |
|   @retval  EFI_BUFFER_TOO_SMALL  The BufferSize parameter is too small.
 | |
|   @retval  EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
 | |
|   @retval  EFI_DEVICE_ERROR      The command could not be sent to the network interface.
 | |
|   @retval  EFI_UNSUPPORTED       This function is not supported by the network interface.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Undi16SimpleNetworkReceive (
 | |
|   IN EFI_SIMPLE_NETWORK_PROTOCOL            *This,
 | |
|   OUT UINTN                                 *HeaderSize OPTIONAL,
 | |
|   IN OUT UINTN                              *BufferSize,
 | |
|   OUT VOID                                  *Buffer,
 | |
|   OUT EFI_MAC_ADDRESS                       *SrcAddr OPTIONAL,
 | |
|   OUT EFI_MAC_ADDRESS                       *DestAddr OPTIONAL,
 | |
|   OUT UINT16                                *Protocol OPTIONAL
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS              Status;
 | |
|   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | |
|   UINTN                   MediaAddrSize;
 | |
|   UINT8                   ProtType;
 | |
| 
 | |
|   if (This == NULL || BufferSize == NULL || Buffer == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Status              = EFI_SUCCESS;
 | |
|   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | |
| 
 | |
|   if (SimpleNetworkDevice == NULL) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Verify that the current state of the adapter is valid for this call.
 | |
|   //
 | |
|   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | |
|   case EfiSimpleNetworkInitialized:
 | |
|     break;
 | |
| 
 | |
|   case EfiSimpleNetworkStopped:
 | |
|     return EFI_NOT_STARTED;
 | |
| 
 | |
|   case EfiSimpleNetworkStarted:
 | |
|   default:
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   Status = Undi16SimpleNetworkIsr (
 | |
|             This,
 | |
|             BufferSize,
 | |
|             HeaderSize,
 | |
|             Buffer,
 | |
|             &ProtType,
 | |
|             NULL
 | |
|             );
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if ((SimpleNetworkDevice->InterruptStatus & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT) == 0) {
 | |
|     return EFI_NOT_READY;
 | |
| 
 | |
|   }
 | |
| 
 | |
|   SimpleNetworkDevice->InterruptStatus &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
 | |
| 
 | |
|   MediaAddrSize = This->Mode->HwAddressSize;
 | |
| 
 | |
|   if (SrcAddr != NULL) {
 | |
|     CopyMem (SrcAddr, (UINT8 *) Buffer + MediaAddrSize, MediaAddrSize);
 | |
|   }
 | |
| 
 | |
|   if (DestAddr != NULL) {
 | |
|     CopyMem (DestAddr, Buffer, MediaAddrSize);
 | |
|   }
 | |
| 
 | |
|   if (Protocol != NULL) {
 | |
|     *((UINT8 *) Protocol)     = *((UINT8 *) Buffer + (2 * MediaAddrSize) + 1);
 | |
|     *((UINT8 *) Protocol + 1) = *((UINT8 *) Buffer + (2 * MediaAddrSize));
 | |
|   }
 | |
| 
 | |
|   DEBUG ((DEBUG_NET, "Packet Received: BufferSize=%d  HeaderSize = %d\n", *BufferSize, *HeaderSize));
 | |
| 
 | |
|   return Status;
 | |
| 
 | |
| }
 | |
| //
 | |
| // WaitForPacket()
 | |
| //
 | |
| /**
 | |
|   wait for a packet to be received.
 | |
| 
 | |
|   @param Event      Event used with WaitForEvent() to wait for a packet to be received.
 | |
|   @param Context    Event Context
 | |
|   
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| Undi16SimpleNetworkWaitForPacket (
 | |
|   IN EFI_EVENT               Event,
 | |
|   IN VOID                    *Context
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // Someone is waiting on the receive packet event, if there's
 | |
|   // a packet pending, signal the event
 | |
|   //
 | |
|   if (!EFI_ERROR (Undi16SimpleNetworkCheckForPacket (Context))) {
 | |
|     gBS->SignalEvent (Event);
 | |
|   }
 | |
| }
 | |
| //
 | |
| // CheckForPacket()
 | |
| //
 | |
| /**
 | |
|   Check whether packet is ready for receive.
 | |
| 
 | |
|   @param This The protocol instance pointer.
 | |
|   
 | |
|   @retval  EFI_SUCCESS           Receive data is ready.
 | |
|   @retval  EFI_NOT_STARTED       The network interface has not been started.
 | |
|   @retval  EFI_NOT_READY         The network interface is too busy to accept this transmit
 | |
|                                  request.
 | |
|   @retval  EFI_BUFFER_TOO_SMALL  The BufferSize parameter is too small.
 | |
|   @retval  EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
 | |
|   @retval  EFI_DEVICE_ERROR      The command could not be sent to the network interface.
 | |
|   @retval  EFI_UNSUPPORTED       This function is not supported by the network interface.
 | |
| **/
 | |
| EFI_STATUS
 | |
| Undi16SimpleNetworkCheckForPacket (
 | |
|   IN EFI_SIMPLE_NETWORK_PROTOCOL *This
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS              Status;
 | |
|   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | |
|   UINTN                   FrameLength;
 | |
| 
 | |
|   if (This == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Status              = EFI_SUCCESS;
 | |
|   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | |
| 
 | |
|   if (SimpleNetworkDevice == NULL) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Verify that the current state of the adapter is valid for this call.
 | |
|   //
 | |
|   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | |
|   case EfiSimpleNetworkInitialized:
 | |
|     break;
 | |
| 
 | |
|   case EfiSimpleNetworkStopped:
 | |
|     return EFI_NOT_STARTED;
 | |
| 
 | |
|   case EfiSimpleNetworkStarted:
 | |
|   default:
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   FrameLength = 0;
 | |
|   Status = Undi16SimpleNetworkIsr (
 | |
|             This,
 | |
|             &FrameLength,
 | |
|             NULL,
 | |
|             NULL,
 | |
|             NULL,
 | |
|             NULL
 | |
|             );
 | |
| 
 | |
|   if (Status != EFI_BUFFER_TOO_SMALL) {
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return ((SimpleNetworkDevice->InterruptStatus & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT) != 0) ? EFI_SUCCESS : EFI_NOT_READY;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Signal handlers for ExitBootServices event.
 | |
|   
 | |
|   Clean up any Real-mode UNDI residue from the system 
 | |
|    
 | |
|   @param Event      ExitBootServices event
 | |
|   @param Context 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| Undi16SimpleNetworkEvent (
 | |
|   IN EFI_EVENT        Event,
 | |
|   IN VOID             *Context
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // NOTE:  This is not the only way to effect this cleanup.  The prescribed mechanism
 | |
|   //        would be to perform an UNDI STOP command.  This strategam has been attempted
 | |
|   //        but results in problems making some of the EFI core services from TPL_CALLBACK.
 | |
|   //        This issue needs to be resolved, but the other alternative has been to perform
 | |
|   //        the unchain logic explicitly, as done below.
 | |
|   //
 | |
|   RestoreCachedVectorAddress (0x1A);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Allocate buffer below 1M for real mode.
 | |
| 
 | |
|   @param NumPages     The number pages want to be allocated.
 | |
|   @param Buffer       On return, allocated buffer.
 | |
|   
 | |
|   @return Status of allocating pages.
 | |
| **/
 | |
| EFI_STATUS
 | |
| BiosSnp16AllocatePagesBelowOneMb (
 | |
|   UINTN  NumPages,
 | |
|   VOID   **Buffer
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS            Status;
 | |
|   EFI_PHYSICAL_ADDRESS  PhysicalAddress;
 | |
| 
 | |
|   PhysicalAddress = 0x000fffff;
 | |
|   Status = gBS->AllocatePages (
 | |
|                   AllocateMaxAddress,
 | |
|                   EfiRuntimeServicesData,
 | |
|                   NumPages,
 | |
|                   &PhysicalAddress
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   *Buffer = (VOID *) (UINTN) PhysicalAddress;
 | |
|   return EFI_SUCCESS;
 | |
| }
 |