summaryrefslogtreecommitdiff
path: root/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe
diff options
context:
space:
mode:
authorjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>2011-06-27 23:32:56 +0000
committerjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>2011-06-27 23:32:56 +0000
commitbcecde140a561c64e297225904afebebd62336ce (patch)
tree5f6333ccb04d851d151970e5dee6c9d8ac7ade71 /IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe
parenta7a0f78bd6fa1fe4684bf6de2b3e5ed5d9b5bf1c (diff)
downloadedk2-platforms-bcecde140a561c64e297225904afebebd62336ce.tar.xz
IntelFrameworkModulePkg: Add Compatibility Support Module (CSM) drivers
Added these drivers: * LegacyBiosDxe * BlockIoDxe * KeyboardDxe * Snp16Dxe * VideoDxe Signed-off-by: jljusten Reviewed-by: mdkinney Reviewed-by: geekboy15a git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11905 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe')
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.c3507
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.h1655
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/ComponentName.c309
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Misc.c956
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Pxe.h613
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/PxeUndi.c1254
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf67
7 files changed, 8361 insertions, 0 deletions
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.c b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.c
new file mode 100644
index 0000000000..2ae8daca73
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.c
@@ -0,0 +1,3507 @@
+/** @file
+
+Copyright (c) 1999 - 2010, 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 &= 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 &= 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 &= 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));
+
+ 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;
+ }
+ }
+
+ 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 paramter.
+ @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 paramter.
+ @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 paramter.
+ @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 permenent address
+ @param New A pointer to New address
+
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.
+ @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 reseting 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 paramter.
+ @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;
+}
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.h b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.h
new file mode 100644
index 0000000000..b29059f685
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.h
@@ -0,0 +1,1655 @@
+/** @file
+
+Copyright (c) 1999 - 2010, 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.
+
+**/
+
+#ifndef _BIOS_SNP_16_H_
+#define _BIOS_SNP_16_H_
+
+#include <Uefi.h>
+
+#include <Protocol/LegacyBios.h>
+#include <Protocol/SimpleNetwork.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/NetworkInterfaceIdentifier.h>
+#include <Protocol/DevicePath.h>
+
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <Guid/EventGroup.h>
+
+#include <IndustryStandard/Pci.h>
+
+#include "Pxe.h"
+
+//
+// BIOS Simple Network Protocol Device Structure
+//
+#define EFI_SIMPLE_NETWORK_DEV_SIGNATURE SIGNATURE_32 ('s', 'n', '1', '6')
+
+#define INIT_PXE_STATUS 0xabcd
+
+#define EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE 64
+
+typedef struct {
+ UINT32 First;
+ UINT32 Last;
+ VOID * Data[EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE];
+} EFI_SIMPLE_NETWORK_DEV_FIFO;
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_SIMPLE_NETWORK_PROTOCOL SimpleNetwork;
+ EFI_SIMPLE_NETWORK_MODE SimpleNetworkMode;
+ EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL Nii;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+
+ //
+ // Local Data for Simple Network Protocol interface goes here
+ //
+ BOOLEAN UndiLoaded;
+ EFI_EVENT EfiBootEvent;
+ EFI_EVENT LegacyBootEvent;
+ UINT16 PxeEntrySegment;
+ UINT16 PxeEntryOffset;
+ EFI_SIMPLE_NETWORK_DEV_FIFO TxBufferFifo;
+ EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath;
+ PXE_T *Pxe; ///< Pointer to !PXE structure
+ PXENV_UNDI_GET_INFORMATION_T GetInformation; ///< Data from GET INFORMATION
+ PXENV_UNDI_GET_NIC_TYPE_T GetNicType; ///< Data from GET NIC TYPE
+ PXENV_UNDI_GET_NDIS_INFO_T GetNdisInfo; ///< Data from GET NDIS INFO
+ BOOLEAN IsrValid; ///< TRUE if Isr contains valid data
+ PXENV_UNDI_ISR_T Isr; ///< Data from ISR
+ PXENV_UNDI_TBD_T *Xmit; //
+ VOID *TxRealModeMediaHeader; ///< < 1 MB Size = 0x100
+ VOID *TxRealModeDataBuffer; ///< < 1 MB Size = GetInformation.MaxTranUnit
+ VOID *TxDestAddr; ///< < 1 MB Size = 16
+ UINT8 InterruptStatus; ///< returned/cleared by GetStatus, set in ISR
+ UINTN UndiLoaderTablePages;
+ UINTN DestinationDataSegmentPages;
+ UINTN DestinationStackSegmentPages;
+ UINTN DestinationCodeSegmentPages;
+ VOID *UndiLoaderTable;
+ VOID *DestinationDataSegment;
+ VOID *DestinationStackSegment;
+ VOID *DestinationCodeSegment;
+} EFI_SIMPLE_NETWORK_DEV;
+
+#define EFI_SIMPLE_NETWORK_DEV_FROM_THIS(a) \
+ CR (a, \
+ EFI_SIMPLE_NETWORK_DEV, \
+ SimpleNetwork, \
+ EFI_SIMPLE_NETWORK_DEV_SIGNATURE \
+ )
+
+//
+// Global Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gBiosSnp16DriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gBiosSnp16ComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gBiosSnp16ComponentName2;
+
+
+//
+// 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
+ )
+;
+
+/**
+ 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
+ )
+;
+
+/**
+ 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
+ )
+;
+
+//
+// Simple Network Protocol functions
+//
+/**
+ 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
+ )
+;
+
+/**
+ 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
+ )
+;
+
+/**
+ 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
+ )
+;
+
+/**
+ Reset network interface.
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @param ExtendedVerification Need extended verfication.
+
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.
+ @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
+ )
+;
+
+/**
+ Shutdown network interface.
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.
+ @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
+ )
+;
+
+/**
+ 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 paramter.
+ @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
+ )
+;
+
+/**
+ Set new MAC address.
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @param Reset Whether reset station MAC address to permenent address
+ @param New A pointer to New address
+
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.
+ @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
+ )
+;
+
+/**
+ Collect statistics.
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @param Reset Whether cleanup old statistics data.
+ @param StatisticsSize The buffer of statistics table.
+ @param StatisticsTable A pointer to statistics buffer.
+
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.
+ @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
+Undi16SimpleNetworkStatistics (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * This,
+ IN BOOLEAN Reset,
+ IN OUT UINTN *StatisticsSize OPTIONAL,
+ OUT EFI_NETWORK_STATISTICS * StatisticsTable OPTIONAL
+ )
+;
+
+/**
+ 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 paramter.
+ @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
+ )
+;
+
+/**
+ 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 Write,
+ IN UINTN Offset,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer
+ )
+;
+
+/**
+ 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
+ )
+;
+
+/**
+ 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
+ )
+;
+
+/**
+ 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
+ )
+;
+
+/**
+ 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
+ )
+;
+
+/**
+ 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
+ )
+;
+
+/**
+ Cache Interrupt verctor address converted from IVT number.
+
+ @param VectorNumber IVT number
+
+ @retval EFI_SUCCESS Success to operation.
+**/
+EFI_STATUS
+CacheVectorAddress (
+ UINT8 VectorNumber
+ )
+;
+
+/**
+ Get interrupt vector address according to IVT number.
+
+ @param VectorNumber Given IVT number
+
+ @return cached interrupt vector address.
+**/
+EFI_STATUS
+RestoreCachedVectorAddress (
+ UINT8 VectorNumber
+ )
+;
+
+/**
+ If available, launch the BaseCode from a NIC option ROM.
+ This should install the !PXE and PXENV+ structures in memory for
+ subsequent use.
+
+
+ @param SimpleNetworkDevice Simple network device instance
+ @param RomAddress The ROM base address for NIC rom.
+
+ @retval EFI_NOT_FOUND The check sum does not match
+ @retval EFI_NOT_FOUND Rom ID offset is wrong
+ @retval EFI_NOT_FOUND No Rom ID structure is found
+**/
+EFI_STATUS
+LaunchBaseCode (
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ UINTN RomAddress
+ )
+;
+
+/**
+ PXE
+ START UNDI
+ Op-Code: PXENV_START_UNDI (0000h)
+ Input: Far pointer to a PXENV_START_UNDI_T parameter structure that has been initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This service is used to pass the BIOS parameter registers to the UNDI driver. The UNDI driver is
+ responsible for saving the information it needs to communicate with the hardware.
+ This service is also responsible for hooking the Int 1Ah service routine
+ Note: This API service must be called only once during UNDI Option ROM boot.
+ The UNDI driver is responsible for saving this information and using it every time
+ PXENV_UNDI_STARTUP is called.
+ Service cannot be used in protected mode.
+ typedef struct {
+ PXENV_STATUS Status;
+ UINT16 AX;
+ UINT16 BX;
+ UINT16 DX;
+ UINT16 DI;
+ UINT16 ES;
+ } PXENV_START_UNDI_T;
+ Set before calling API service
+ AX, BX, DX, DI, ES: BIOS initialization parameter registers. These
+ fields should contain the same information passed to the option ROM
+ initialization routine by the Host System BIOS. Information about the
+ contents of these registers can be found in the [PnP], [PCI] and
+ [BBS] specifications.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeStartUndi (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_START_UNDI_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI STARTUP
+ Op-Code: PXENV_UNDI_STARTUP (0001h)
+ Input: Far pointer to a PXENV_UNDI_STARTUP_T parameter structure that has been initialized by the
+ caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the
+ PXENV_STATUS_xxx constants.
+ Description: This API is responsible for initializing the contents of the UNDI code & data segment for proper
+ operation. Information from the !PXE structure and the first PXENV_START_UNDI API call is used
+ to complete this initialization. The rest of the UNDI APIs will not be available until this call has
+ been completed.
+ Note: PXENV_UNDI_STARTUP must not be called again without first calling
+ PXENV_UNDI_SHUTDOWN.
+ PXENV_UNDI_STARTUP and PXENV_UNDI_SHUTDOWN are no longer responsible for
+ chaining interrupt 1Ah. This must be done by the PXENV_START_UNDI and
+ PXENV_STOP_UNDI API calls.
+ This service cannot be used in protected mode.
+ typedef struct
+ {
+ PXENV_STATUS Status;
+ } PXENV_UNDI_STARTUP_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiStartup (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_STARTUP_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI CLEANUP
+ Op-Code: PXENV_UNDI_CLEANUP (0002h)
+ Input: Far pointer to a PXENV_UNDI_CLEANUP_T parameter structure.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field
+ in the parameter structure must be set to one of the values represented by the
+ PXENV_STATUS_xxx constants.
+ Description: This call will prepare the network adapter driver to be unloaded from memory. This call must be
+ made just before unloading the Universal NIC Driver. The rest of the API will not be available
+ after this call executes.
+ This service cannot be used in protected mode.
+ typedef struct {
+ PXENX_STATUS Status;
+ } PXENV_UNDI_CLEANUP_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiCleanup (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_CLEANUP_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI INITIALIZE
+ Op-Code: PXENV_UNDI_INITIALIZE (0003h)
+ Input: Far pointer to a PXENV_UNDI_INITIALIZE_T parameter structure that has been initialized by the
+ caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call resets the adapter and programs it with default parameters. The default parameters used
+ are those supplied to the most recent UNDI_STARTUP call. This routine does not enable the
+ receive and transmit units of the network adapter to readily receive or transmit packets. The
+ application must call PXENV_UNDI_OPEN to logically connect the network adapter to the network.
+ This call must be made by an application to establish an interface to the network adapter driver.
+ Note: When the PXE code makes this call to initialize the network adapter, it passes a NULL pointer for
+ the Protocol field in the parameter structure.
+ typedef struct {
+ PXENV_STATUS Status;
+ ADDR32 ProtocolIni;
+ UINT8 reserved[8];
+ } PXENV_UNDI_INITIALIZE_T;
+ Set before calling API service
+ ProtocolIni: Physical address of a memory copy of the driver
+ module from the protocol.ini file obtained from the protocol manager
+ driver (refer to the NDIS 2.0 specification). This parameter is
+ supported for the universal NDIS driver to pass the information
+ contained in the protocol.ini file to the NIC driver for any specific
+ configuration of the NIC. (Note that the module identification in the
+ protocol.ini file was done by NDIS.) This value can be NULL for any
+ other application interfacing to the universal NIC driver
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance.
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiInitialize (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_INITIALIZE_T *PxeUndiTable
+ )
+;
+
+/**
+ Wrapper routine for reset adapter.
+
+ PXE
+ UNDI RESET ADAPTER
+ Op-Code: PXENV_UNDI_RESET_ADAPTER (0004h)
+ Input: Far pointer to a PXENV_UNDI_RESET_ADAPTER_t parameter structure that has been initialized
+ by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call resets and reinitializes the network adapter with the same set of parameters supplied to
+ Initialize Routine. Unlike Initialize, this call opens the adapter that is, it connects logically to the
+ network. This routine cannot be used to replace Initialize or Shutdown calls.
+ typedef struct {
+ PXENV_STATUS Status;
+ PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf;
+ } PXENV_UNDI_RESET_T;
+
+ #define MAXNUM_MCADDR 8
+
+ typedef struct {
+ UINT16 MCastAddrCount;
+ MAC_ADDR McastAddr[MAXNUM_MCADDR];
+ } PXENV_UNDI_MCAST_ADDRESS_t;
+
+ Set before calling API service
+ R_Mcast_Buf: This is a structure of MCastAddrCount and
+ McastAddr.
+ MCastAddrCount: Number of multicast MAC addresses in the
+ buffer.
+ McastAddr: List of up to MAXNUM_MCADDR multicast MAC
+ addresses.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance.
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+ @param RxFilter Filter setting mask value for PXE recive .
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiResetNic (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_RESET_T *PxeUndiTable,
+ IN UINT16 RxFilter
+ )
+;
+
+/**
+ PXE
+ UNDI SHUTDOWN
+ Op-Code: PXENV_UNDI_SHUTDOWN (0005h)
+ Input: Far pointer to a PXENV_UNDI_SHUTDOWN_T parameter.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call resets the network adapter and leaves it in a safe state for another driver to program it.
+ Note: The contents of the PXENV_UNDI_STARTUP parameter structure need to be saved by the
+ Universal NIC Driver in case PXENV_UNDI_INITIALIZE is called again.
+ typedef struct
+ {
+ PXENV_STATUS Status;
+ } PXENV_UNDI_SHUTDOWN_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiShutdown (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_SHUTDOWN_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI OPEN
+ Op-Code: PXENV_UNDI_OPEN (0006h)
+ Input: Far pointer to a PXENV_UNDI_OPEN_T parameter structure that has been initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call activates the adapter network connection and sets the adapter ready to accept packets
+ for transmit and receive.
+ typedef struct {
+ PXENV_STATUS Status;
+ UINT16 OpenFlag;
+ UINT16 PktFilter;
+ #define FLTR_DIRECTED 0x0001
+ #define FLTR_BRDCST 0x0002
+ #define FLTR_PRMSCS 0x0004
+ #define FLTR_SRC_RTG 0x0008
+ PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf;
+ } PXENV_UNDI_OPEN_T;
+ Set before calling API service
+ OpenFlag: This is an adapter specific input parameter. This is
+ supported for the universal NDIS 2.0 driver to pass in the open flags
+ provided by the protocol driver. (See the NDIS 2.0 specification.)
+ This can be zero.
+ PktFilter: Filter for receiving packets. This can be one, or more, of
+ the FLTR_xxx constants. Multiple values are arithmetically or-ed
+ together.
+ directed packets are packets that may come to your MAC address
+ or the multicast MAC address.
+ R_Mcast_Buf: See definition in UNDI RESET ADAPTER (0004h).
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiOpen (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_OPEN_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI CLOSE
+ Op-Code: PXENV_UNDI_CLOSE (0007h)
+ Input: Far pointer to a PXENV_UNDI_CLOSE_T parameter.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call disconnects the network adapter from the network. Packets cannot be transmitted or
+ received until the network adapter is open again.
+ typedef struct {
+ PXENV_STATUS Status;
+ } PXENV_UNDI_CLOSE_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiClose (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_CLOSE_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI TRANSMIT PACKET
+ Op-Code: PXENV_UNDI_TRANSMIT (0008h)
+ Input: Far pointer to a PXENV_UNDI_TRANSMIT_T parameter structure that
+ has been initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX.
+ The status code must be set to one of the values represented by the
+ PXENV_STATUS_xxx constants.
+ Description: This call transmits a buffer to the network. The media header
+ for the packet can be filled by the calling protocol, but it might not be.
+ The network adapter driver will fill it if required by the values in the
+ parameter block. The packet is buffered for transmission provided there is
+ an available buffer, and the function returns PXENV_EXIT_SUCCESS. If no
+ buffer is available the function returns PXENV_EXIT_FAILURE with a status
+ code of PXE_UNDI_STATUS__OUT OF_RESOURCE. The number of buffers is
+ implementation-dependent. An interrupt is generated on completion of the
+ transmission of one or more packets. A call to PXENV_UNDI_TRANSMIT is
+ permitted in the context of a transmit complete interrupt.
+
+ typedef struct {
+ PXENV_STATUS Status;
+ UINT8 Protocol;
+ #define P_UNKNOWN 0
+ #define P_IP 1
+ #define P_ARP 2
+ #define P_RARP 3
+ UINT8 XmitFlag;
+ #define XMT_DESTADDR 0x0000
+ #define XMT_BROADCAST 0x0001
+ SEGOFF16 DestAddr;
+ SEGOFF16 TBD;
+ UINT32 Reserved[2];
+ } t_PXENV_UNDI_TRANSMIT;
+
+ #define MAX_DATA_BLKS 8
+
+ typedef struct {
+ UINT16 ImmedLength;
+ SEGOFF16 Xmit;
+ UINT16 DataBlkCount;
+ struct DataBlk {
+ UINT8 TDPtrType;
+ UINT8 TDRsvdByte;
+ UINT16 TDDataLen;
+ SEGOFF16 TDDataPtr;
+ } DataBlock[MAX_DATA_BLKS];
+ } PXENV_UNDI_TBD_T
+
+ Set before calling API service
+ Protocol: This is the protocol of the upper layer that is calling UNDI
+ TRANSMIT call. If the upper layer has filled the media header, this
+ field must be P_UNKNOWN.
+ XmitFlag: If this flag is XMT_DESTADDR, the NIC driver expects a
+ pointer to the destination media address in the field DestAddr. If
+ XMT_BROADCAST, the NIC driver fills the broadcast address for the
+ destination.
+ TBD: Segment:Offset address of the transmit buffer descriptor.
+ ImmedLength: Length of the immediate transmit buffer: Xmit.
+ Xmit: Segment:Offset of the immediate transmit buffer.
+ DataBlkCount: Number of blocks in this transmit buffer.
+ TDPtrType:
+ 0 => 32-bit physical address in TDDataPtr (not supported in this
+ version of PXE)
+ 1 => segment:offset in TDDataPtr which can be a real mode or 16-bit
+ protected mode pointer
+ TDRsvdByte: Reserved must be zero.
+ TDDatalen: Data block length in bytes.
+ TDDataPtr: Segment:Offset of the transmit block.
+ DataBlock: Array of transmit data blocks.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiTransmit (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_TRANSMIT_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI SET MULTICAST ADDRESS
+ Op-Code: PXENV_UNDI_SET_MCAST_ADDRESS (0009h)
+ Input: Far pointer to a PXENV_TFTP_SET_MCAST_ADDRESS_t parameter structure that has been
+ initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call changes the current list of multicast addresses to the input list and resets the network
+ adapter to accept it. If the number of multicast addresses is zero, multicast is disabled.
+ typedef struct {
+ PXENV_STATUS Status;
+ PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf;
+ } PXENV_UNDI_SET_MCAST_ADDR_T;
+ Set before calling API service
+ R_Mcast_Buf: See description in the UNDI RESET ADAPTER
+ (0004h) API.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiSetMcastAddr (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_SET_MCAST_ADDR_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI SET STATION ADDRESS
+ Op-Code: PXENV_UNDI_SET_STATION_ADDRESS (000Ah)
+ Input: Far pointer to a PXENV_UNDI_SET_STATION_ADDRESS_t parameter structure that has been
+ initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call sets the MAC address to be the input value and is called before opening the network
+ adapter. Later, the open call uses this variable as a temporary MAC address to program the
+ adapter individual address registers.
+ typedef struct {
+ PXENV_STATUS Status;
+ MAC_ADDR StationAddress;
+ } PXENV_UNDI_SET_STATION_ADDR_T;
+ Set before calling API service
+ StationAddress: Temporary MAC address to be used for
+ transmit and receive.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiSetStationAddr (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_SET_STATION_ADDR_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI SET PACKET FILTER
+ Op-Code: PXENV_UNDI_SET_PACKET_FILTER (000Bh)
+ Input: Far pointer to a PXENV_UNDI_SET_PACKET_FILTER_T parameter structure that has been
+ initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call resets the adapter's receive unit to accept a new filter, different from the one provided with
+ the open call.
+ typedef struct {
+ PXENV_STATUS Status;
+ UINT8 filter;
+ } PXENV_UNDI_SET_PACKET_FILTER_T;
+ Set before calling API service
+ Filter: See the receive filter values in the UNDI OPEN
+ (0006h) API description.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiSetPacketFilter (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_SET_PACKET_FILTER_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI GET INFORMATION
+ Op-Code: PXENV_UNDI_GET_INFORMATION (000Ch)
+ Input: Far pointer to a PXENV_UNDI_GET_INFORMATION_T parameter structure that has been
+ initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the
+ PXENV_STATUS_xxx constants.
+ Description: This call copies the network adapter variables, including the MAC address, into the input buffer.
+ Note: The PermNodeAddress field must be valid after PXENV_START_UNDI and
+ PXENV_UNDI_STARTUP have been issued. All other fields must be valid after
+ PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE have been
+ called.
+ typedef struct {
+ PXENV_STATUS Status;
+ UINT16 BaseIo;
+ UINT16 IntNumber;
+ UINT16 MaxTranUnit;
+ UINT16 HwType;
+ #define ETHER_TYPE 1
+ #define EXP_ETHER_TYPE 2
+ #define IEEE_TYPE 6
+ #define ARCNET_TYPE 7
+ UINT16 HwAddrLen;
+ MAC_ADDR CurrentNodeAddress;
+ MAC_ADDR PermNodeAddress;
+ SEGSEL ROMAddress;
+ UINT16 RxBufCt;
+ UINT16 TxBufCt;
+ } PXENV_UNDI_GET_INFORMATION_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+ BaseIO: Adapter base I/O address.
+ IntNumber: Adapter IRQ number.
+ MaxTranUnit: Adapter maximum transmit unit.
+ HWType: Type of protocol at the hardware level.
+ HWAddrLen: Length of the hardware address.
+ CurrentNodeAddress: Current hardware address.
+ PermNodeAddress: Permanent hardware address.
+ ROMAddress: Real mode ROM segment address.
+ RxBufCnt: Receive queue length.
+ TxBufCnt: Transmit queue length.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiGetInformation (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_GET_INFORMATION_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI GET STATISTICS
+ Op-Code: PXENV_UNDI_GET_STATISTICS (000Dh)
+ Input: Far pointer to a PXENV_UNDI_GET_STATISTICS_T parameter structure that has been initialized
+ by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call reads statistical information from the network adapter, and returns.
+ typedef struct {
+ PXENV_STATUS Status;
+ UINT32 XmtGoodFrames;
+ UINT32 RcvGoodFrames;
+ UINT32 RcvCRCErrors;
+ UINT32 RcvResourceErrors;
+ } PXENV_UNDI_GET_STATISTICS_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+ XmtGoodFrames: Number of successful transmissions.
+ RcvGoodFrames: Number of good frames received.
+ RcvCRCErrors: Number of frames received with CRC
+ error.
+ RcvResourceErrors: Number of frames discarded
+ because receive queue was full.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiGetStatistics (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_GET_STATISTICS_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI CLEAR STATISTICS
+ Op-Code: PXENV_UNDI_CLEAR_STATISTICS (000Eh)
+ Input: Far pointer to a PXENV_UNDI_CLEAR_STATISTICS_T parameter.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the
+ PXENV_STATUS_xxx constants.
+ Description: This call clears the statistical information from the network adapter.
+ typedef struct {
+ PXENV_STATUS Status;
+ } PXENV_UNDI_CLEAR_STATISTICS_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiClearStatistics (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_CLEAR_STATISTICS_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI INITIATE DIAGS
+ Op-Code: PXENV_UNDI_INITIATE_DIAGS (000Fh)
+ Input: Far pointer to a PXENV_UNDI_INITIATE_DIAGS_T parameter.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the
+ PXENV_STATUS_xxx constants.
+ Description: This call can be used to initiate the run-time diagnostics. It causes the network adapter to run
+ hardware diagnostics and to update its status information.
+ typedef struct {
+ PXENV_STATUS Status;
+ } PXENV_UNDI_INITIATE_DIAGS_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiInitiateDiags (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_INITIATE_DIAGS_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI FORCE INTERRUPT
+ Op-Code: PXENV_UNDI_FORCE_INTERRUPT (0010h)
+ Input: Far pointer to a PXENV_UNDI_FORCE_INTERRUPT_T parameter structure that has been
+ initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call forces the network adapter to generate an interrupt. When a receive interrupt occurs, the
+ network adapter driver usually queues the packet and calls the application's callback receive
+ routine with a pointer to the packet received. Then, the callback routine either can copy the packet
+ to its buffer or can decide to delay the copy to a later time. If the packet is not immediately copied,
+ the network adapter driver does not remove it from the input queue. When the application wants to
+ copy the packet, it can call the PXENV_UNDI_FORCE_INTERRUPT routine to simulate the receive
+ interrupt.
+ typedef struct {
+ PXENV_STATUS Status;
+ } PXENV_UNDI_FORCE_INTERRUPT_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiForceInterrupt (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_FORCE_INTERRUPT_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI GET MULTICAST ADDRESS
+ Op-Code: PXENV_UNDI_GET_MCAST_ADDRESS (0011h)
+ Input: Far pointer to a PXENV_GET_MCAST_ADDRESS_t parameter structure that has been initialized
+ by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call converts the given IP multicast address to a hardware multicast address.
+ typedef struct {
+ PXENV_STATUS Status;
+ IP4 InetAddr;
+ MAC_ADDR MediaAddr;
+ } PXENV_UNDI_GET_MCAST_ADDR_T;
+ Set before calling API service
+ InetAddr: IP multicast address.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+ MediaAddr: MAC multicast address.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiGetMcastAddr (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_GET_MCAST_ADDR_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI GET NIC TYPE
+ Op-Code: PXENV_UNDI_GET_NIC_TYPE (0012h)
+ Input: Far pointer to a PXENV_UNDI_GET_NIC_TYPE_T parameter structure that has been initialized by
+ the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants. If the PXENV_EXIT_SUCCESS is returned the parameter structure must contain the
+ NIC information.
+ Description: This call, if successful, provides the NIC-specific information necessary to identify the network
+ adapter that is used to boot the system.
+ Note: The application first gets the DHCPDISCOVER packet using GET_CACHED_INFO and checks if
+ the UNDI is supported before making this call. If the UNDI is not supported, the NIC-specific
+ information can be obtained from the DHCPDISCOVER packet itself.
+ PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE must be called
+ before the information provided is valid.
+ typedef {
+ PXENV_STATUS Status;
+ UINT8 NicType;
+ #define PCI_NIC 2
+ #define PnP_NIC 3
+ #define CardBus_NIC 4
+ Union {
+ Struct {
+ UINT16 Vendor_ID;
+ UINT16 Dev_ID;
+ UINT8 Base_Class;
+ UINT8 Sub_Class;
+ UINT8 Prog_Intf;
+ UINT8 Rev;
+ UINT16 BusDevFunc;
+ UINT16 SubVendor_ID;
+ UINT16 SubDevice_ID;
+ } pci, cardbus;
+ struct {
+ UINT32 EISA_Dev_ID;
+ UINT8 Base_Class;
+ UINT8 Sub_Class;
+ UINT8 Prog_Intf;
+ UINT16 CardSelNum;
+ } pnp;
+ } info;
+ } PXENV_UNDI_GET_NIC_TYPE_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+ NICType: Type of NIC information stored in the parameter
+ structure.
+ Info: Information about the fields in this union can be found
+ in the [PnP] and [PCI] specifications
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiGetNicType (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_GET_NIC_TYPE_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI GET IFACE INFO
+ Op-Code: PXENV_UNDI_GET_IFACE_INFO (0013h)
+ Input: Far pointer to a PXENV_UNDI_GET_IFACE_INFO_t parameter structure that has been initialized
+ by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants. If the PXENV_EXIT_SUCCESS is returned, the parameter structure must contain the
+ interface specific information.
+ Description: This call, if successful, provides the network interface specific information such as the interface
+ type at the link layer (Ethernet, Tokenring) and the link speed. This information can be used in the
+ universal drivers such as NDIS or Miniport to communicate to the upper protocol modules.
+ Note: UNDI follows the NDIS2 specification in giving this information. It is the responsibility of the
+ universal driver to translate/convert this information into a format that is required in its specification
+ or to suit the expectation of the upper level protocol modules.
+ PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE must be called
+ before the information provided is valid.
+ typedef struct {
+ PXENV_STATUS Status
+ UINT8 IfaceType[16];
+ UINT32 LinkSpeed;
+ UINT32 ServiceFlags;
+ UINT32 Reserved[4];
+ } PXENV_UNDI_GET_NDIS_INFO_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+ IfaceType: Name of MAC type in ASCIIZ format. This is
+ used by the universal NDIS driver to specify its driver type
+ to the protocol driver.
+ LinkSpeed: Defined in the NDIS 2.0 specification.
+ ServiceFlags: Defined in the NDIS 2.0 specification.
+ Reserved: Must be zero.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiGetNdisInfo (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_GET_NDIS_INFO_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI ISR
+ Op-Code: PXENV_UNDI_ISR (0014h)
+ Input: Far pointer to a PXENV_UNDI_ISR_T parameter structure that has been initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This API function will be called at different levels of processing the interrupt. The FuncFlag field in
+ the parameter block indicates the operation to be performed for the call. This field is filled with the
+ status of that operation on return.
+ Note: Interrupt Service Routine Operation:
+ In this design the UNDI does not hook the interrupt for the Network Interface. Instead, the
+ application or the protocol driver hooks the interrupt and calls UNDI with the PXENV_UNDI_ISR
+ API call for interrupt verification (PXENV_UNDI_ISR_IN_START) and processing
+ (PXENV_UNDI_ISR_IN_PROCESS and PXENV_UNDI_ISR_GET_NEXT).
+ When the Network Interface HW generates an interrupt the protocol driver interrupt service
+ routine (ISR) gets control and takes care of the interrupt processing at the PIC level. The ISR then
+ calls the UNDI using the PXENV_UNDI_ISR API with the value PXENV_UNDI_ISR_IN_START for
+ the FuncFlag parameter. At this time UNDI must disable the interrupts at the Network Interface
+ level and read any status values required to further process the interrupt. UNDI must return as
+ quickly as possible with one of the two values, PXENV_UNDI_ISR_OUT_OURS or
+ PXENV_UNDI_ISR_OUT_NOT_OURS, for the parameter FuncFlag depending on whether the
+ interrupt was generated by this particular Network Interface or not.
+ If the value returned in FuncFlag is PXENV_UNDI_ISR_OUT_NOT_OURS, then the interrupt was
+ not generated by our NIC, and interrupt processing is complete.
+ If the value returned in FuncFlag is PXENV_UNDI_ISR_OUT_OURS, the protocol driver must start
+ a handler thread and send an end-of-interrupt (EOI) command to the PIC. Interrupt processing is
+ now complete.
+ The protocol driver strategy routine will call UNDI using this same API with FuncFlag equal to
+ PXENV_UNDI_ISR_IN_PROCESS. At this time UNDI must find the cause of this interrupt and
+ return the status in the FuncFlag. It first checks if there is a frame received and if so it returns the
+ first buffer pointer of that frame in the parameter block.
+ The protocol driver calls UNDI repeatedly with the FuncFlag equal to
+ PXENV_UNDI_ISR_IN_GET_NEXT to get all the buffers in a frame and also all the received
+ frames in the queue. On this call, UNDI must remember the previous buffer given to the protoco,l
+ remove it from the receive queue and recycle it. In case of a multi-buffered frame, if the previous
+ buffer is not the last buffer in the frame it must return the next buffer in the frame in the parameter
+ block. Otherwise it must return the first buffer in the next frame.
+ If there is no received frame pending to be processed, UNDI processes the transmit completes and
+ if there is no other interrupt status to be processed, UNDI re-enables the interrupt at the
+ NETWORK INTERFACE level and returns PXENV_UNDI_ISR_OUT_DONE in the FuncFlag.
+ IMPORTANT: It is possible for the protocol driver to be interrupted again while in the
+ strategy routine when the UNDI re-enables interrupts.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiIsr (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_ISR_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ STOP UNDI
+ Op-Code: PXENV_STOP_UNDI (0015h)
+ Input: Far pointer to a PXENV_STOP_UNDI_T parameter structure that has been initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This routine is responsible for unhooking the Int 1Ah service routine.
+ Note: This API service must be called only once at the end of UNDI Option ROM boot. One of the valid
+ status codes is PXENV_STATUS_KEEP. If this status is returned, UNDI must not be removed from
+ base memory. Also, UNDI must not be removed from base memory if BC is not removed from base
+ memory.
+ Service cannot be used in protected mode.
+ typedef struct {
+ PXENV_STATUS Status;
+ } PXENV_STOP_UNDI_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiStop (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_STOP_UNDI_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI GET STATE
+ Op-Code: PXENV_UNDI_GET_STATE (0015h)
+ Input: Far pointer to a PXENV_UNDI_GET_STATE_T parameter.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants. The UNDI_STATE field in the parameter structure must be set to one of the valid state
+ constants
+ Description: This call can be used to obtain state of the UNDI engine in order to avoid issuing adverse call
+ sequences
+ typedef struct {
+ #define PXE_UNDI_GET_STATE_STARTED 1
+ #define PXE_UNDI_GET_STATE_INITIALIZED 2
+ #define PXE_UNDI_GET_STATE_OPENED 3
+ PXENV_STATUS Status;
+ UINT8 UNDIstate;
+ } PXENV_UNDI_GET_STATE_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+ State: See definitions of the state constants.
+ Note. UNDI implementation is responsible for maintaining
+ internal state machine.
+ UNDI ISR
+ Op-Code: PXENV_UNDI_ISR (0014h)
+ Input: Far pointer to a t_PXENV_UNDI_ISR parameter structure that has been initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This API function will be called at different levels of processing the interrupt. The FuncFlag field in
+ the parameter block indicates the operation to be performed for the call. This field is filled with the
+ status of that operation on return.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiGetState (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_GET_STATE_T *PxeUndiTable
+ )
+;
+
+/**
+ Effect the Far Call into the PXE Layer
+
+ Note: When using a 32-bit stack segment do not push 32-bit words onto the stack. The PXE API
+ services will not work, unless there are three 16-bit parameters pushed onto the stack.
+ push DS ;Far pointer to parameter structure
+ push offset pxe_data_call_struct ;is pushed onto stack.
+ push Index ;UINT16 is pushed onto stack.
+ call dword ptr (s_PXE ptr es:[di]).EntryPointSP
+ add sp, 6 ;Caller cleans up stack.
+
+ @param SimpleNetworkDevice Device instance for simple network
+ @param Table Point to parameter/retun value table for legacy far call
+ @param TableSize The size of paramter/return value table
+ @param CallIndex The index of legacy call.
+
+ @return EFI_STATUS
+**/
+EFI_STATUS
+MakePxeCall (
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT VOID *Table,
+ IN UINTN TableSize,
+ IN UINT16 CallIndex
+ )
+;
+
+/**
+ 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
+ )
+;
+
+#endif
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/ComponentName.c b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/ComponentName.c
new file mode 100644
index 0000000000..a95d83459d
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/ComponentName.c
@@ -0,0 +1,309 @@
+/** @file
+
+Copyright (c) 1999 - 2010, 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"
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosSnp16ComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosSnp16ComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gBiosSnp16ComponentName = {
+ BiosSnp16ComponentNameGetDriverName,
+ BiosSnp16ComponentNameGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gBiosSnp16ComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) BiosSnp16ComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) BiosSnp16ComponentNameGetControllerName,
+ "en"
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mBiosSnp16DriverNameTable[] = {
+ {
+ "eng;en",
+ L"BIOS[UNDI] Simple Network Protocol Driver"
+ },
+ {
+ NULL,
+ NULL
+ }
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosSnp16ComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mBiosSnp16DriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gBiosSnp16ComponentName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosSnp16ComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Misc.c b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Misc.c
new file mode 100644
index 0000000000..0b3543e12c
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Misc.c
@@ -0,0 +1,956 @@
+/** @file
+ Helper Routines that use a PXE-enabled NIC option ROM.
+
+Copyright (c) 1999 - 2010, 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"
+
+#define TO_SEGMENT(x) ((UINT16) (RShiftU64 ((UINT32)(UINTN) (x), 4) & 0xF000))
+#define TO_OFFSET(x) ((UINT16) ((UINT32)(UINTN) (x) & 0xFFFF))
+#define PARAGRAPH_SIZE 0x10
+#define IVT_BASE 0x00000000
+
+#pragma pack(1)
+typedef struct {
+ UINT16 Signature; ///< 0xaa55
+ UINT8 ROMlength; ///< size of this ROM in 512 byte blocks
+ UINT8 InitEntryPoint[4]; ///< a jump to the initialization routine
+ UINT8 Reserved[0xf]; ///< various
+ UINT16 PxeRomIdOffset; ///< offset of UNDI, $BC$, or BUSD ROM ID structure
+ UINT16 PcirHeaderOffset; ///< offset of PCI Expansion Header
+ UINT16 PnpHeaderOffset; ///< offset of Plug and Play Expansion Header
+} OPTION_ROM_HEADER;
+#pragma pack()
+
+UINT32 CachedVectorAddress[0x100];
+
+/**
+ Cache Interrupt verctor address converted from IVT number.
+
+ @param VectorNumber IVT number
+
+ @retval EFI_SUCCESS Success to operation.
+**/
+EFI_STATUS
+CacheVectorAddress (
+ UINT8 VectorNumber
+ )
+{
+ UINT32 *Address;
+
+ Address = (UINT32 *)(UINTN) (IVT_BASE + VectorNumber * 4);
+ CachedVectorAddress[VectorNumber] = *Address;
+ return EFI_SUCCESS;
+}
+
+/**
+ Get interrupt vector address according to IVT number.
+
+ @param VectorNumber Given IVT number
+
+ @return cached interrupt vector address.
+**/
+EFI_STATUS
+RestoreCachedVectorAddress (
+ UINT8 VectorNumber
+ )
+{
+ UINT32 *Address;
+
+ Address = (UINT32 *)(UINTN) (IVT_BASE + VectorNumber * 4);
+ *Address = CachedVectorAddress[VectorNumber];
+ return EFI_SUCCESS;
+}
+
+/**
+ Print Undi loader table.
+
+ @param UndiLoaderStructure Point to Undi Loader table structure.
+
+**/
+VOID
+Print_Undi_Loader_Table (
+ VOID *UndiLoaderStructure
+ )
+{
+ UNDI_LOADER_T *DisplayPointer;
+
+ DisplayPointer = (UNDI_LOADER_T *) UndiLoaderStructure;
+
+ DEBUG ((DEBUG_NET, "Before Parsing the table contents, the table itself lives\n"));
+ DEBUG ((DEBUG_NET, "\tat the address 0x%X\n\r", (UINT32)(UINTN) UndiLoaderStructure));
+
+ DEBUG ((DEBUG_NET, "\n\rStatus = 0x%X\n\r", DisplayPointer->Status));
+ DEBUG ((DEBUG_NET, "\t_AX_= 0x%X\n\r", DisplayPointer->Ax));
+ DEBUG ((DEBUG_NET, "\t_BX_= 0x%X\n\r", DisplayPointer->Bx));
+ DEBUG ((DEBUG_NET, "\t_DX_= 0x%X\n\r", DisplayPointer->Dx));
+ DEBUG ((DEBUG_NET, "\t_DI_= 0x%X\n\r", DisplayPointer->Di));
+ DEBUG ((DEBUG_NET, "\t_ES_= 0x%X\n\r", DisplayPointer->Es));
+ DEBUG ((DEBUG_NET, "\tUNDI_DS= 0x%X\n\r", DisplayPointer->Undi_Ds));
+ DEBUG ((DEBUG_NET, "\tUNDI_CS= 0x%X\n\r", DisplayPointer->Undi_Cs));
+ DEBUG ((DEBUG_NET, "\tPXEptr:SEG= 0x%X\n\r", (UINT16) DisplayPointer->PXEptr.Segment));
+ DEBUG ((DEBUG_NET, "\tPXEptr:OFF= 0x%X\n\r", (UINT16) DisplayPointer->PXEptr.Offset));
+ DEBUG ((DEBUG_NET, "\tPXENVptr:SEG= 0x%X\n\r", (UINT16) DisplayPointer->PXENVptr.Segment));
+ DEBUG ((DEBUG_NET, "\tPXENVptr:OFF= 0x%X\n\r", (UINT16) DisplayPointer->PXENVptr.Offset));
+}
+
+/**
+ Simple table dumper. The ROMID table is necessary in order to effect
+ the "Early UNDI" trick. Herein, the UNDI layer can be loaded in the
+ pre-boot phase without having to download a Network Boot Program
+ across the wire. It is required in the implementation in that we
+ are not using PXE.
+
+ @param RomIDStructure Point to RomID structure.
+
+**/
+VOID
+Print_ROMID_Table (
+ IN VOID *RomIDStructure
+ )
+{
+ UNDI_ROMID_T *DisplayPointer;
+
+ DisplayPointer = (UNDI_ROMID_T *) RomIDStructure;
+
+ DEBUG ((DEBUG_NET, "Before Parsing the table contents, the table itself lives\n"));
+ DEBUG ((DEBUG_NET, "\tat the address 0x%X\n\r", (UINT32)(UINTN) RomIDStructure));
+
+ DEBUG (
+ (DEBUG_NET,
+ "\n\rROMID %c%c%c%c\n\r",
+ DisplayPointer->Signature[0],
+ DisplayPointer->Signature[1],
+ DisplayPointer->Signature[2],
+ DisplayPointer->Signature[3])
+ );
+
+ DEBUG (
+ (DEBUG_NET,
+ "Length of this structure in bytes = 0x%X\n\r",
+ DisplayPointer->StructLength)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Use to make byte checksum of this structure == zero is = 0x%X\n\r",
+ DisplayPointer->StructCksum)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Structure format revision number= 0x%X\n\r",
+ DisplayPointer->StructRev)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "API Revision number = 0x%X 0x%X 0x%X\n\r",
+ DisplayPointer->UNDI_Rev[0],
+ DisplayPointer->UNDI_Rev[1],
+ DisplayPointer->UNDI_Rev[2])
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Offset of UNDI loader routine in the option ROM image= 0x%X\n\r",
+ DisplayPointer->UNDI_Loader)
+ );
+ DEBUG ((DEBUG_NET, "From the data above, the absolute entry point of the UNDI loader is\n\r"));
+ DEBUG (
+ (DEBUG_NET,
+ "\tat address 0x%X\n\r",
+ (UINT32) (DisplayPointer->UNDI_Loader + ((UINT32) (UINTN)(DisplayPointer - 0x20) & 0xFFFF0)))
+ );
+ DEBUG ((DEBUG_NET, "Minimum stack segment size, in bytes,\n\r"));
+ DEBUG (
+ (DEBUG_NET,
+ "needed to load and run the UNDI= 0x%X \n\r",
+ DisplayPointer->StackSize)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "UNDI runtime code and data = 0x%X\n\r",
+ DisplayPointer->DataSize)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Segment size = 0x%X\n\r",
+ DisplayPointer->CodeSize)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "\n\rBus Type = %c%c%c%c\n\r",
+ DisplayPointer->BusType[0],
+ DisplayPointer->BusType[1],
+ DisplayPointer->BusType[2],
+ DisplayPointer->BusType[3])
+ );
+}
+
+/**
+ Print PXE table.
+
+ @param PxeTable Point to PXE table structure
+
+**/
+VOID
+Print_PXE_Table (
+ IN VOID* PxeTable
+ )
+{
+ PXE_T *DisplayPointer;
+ UINTN Index;
+ UINT8 *Dptr;
+
+ DisplayPointer = (PXE_T *) PxeTable;
+ Dptr = (UINT8 *) PxeTable;
+
+ DEBUG ((DEBUG_NET, "This is the PXE table at address 0x%X\n\r", PxeTable));
+
+ DEBUG ((DEBUG_NET, "A dump of the 0x%X bytes is:\n\r", sizeof (PXE_T)));
+
+ for (Index = 0; Index < sizeof (PXE_T); Index++) {
+ if ((Index % 0x10) == 0) {
+ DEBUG ((DEBUG_NET, "\t\n\r"));
+ }
+
+ DEBUG ((DEBUG_NET, " 0x%X ", *Dptr++));
+ }
+
+ DEBUG ((DEBUG_NET, "\n\r"));
+ DEBUG (
+ (DEBUG_NET,
+ "\n\rPXE %c%c%c%c%c%c\n\r",
+ DisplayPointer->Signature[0],
+ DisplayPointer->Signature[1],
+ DisplayPointer->Signature[2],
+ DisplayPointer->Signature[3])
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Length of this structure in bytes = 0x%X\n\r",
+ DisplayPointer->StructLength)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Use to make byte checksum of this structure == zero is = 0x%X\n\r",
+ DisplayPointer->StructCksum)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Structure format revision number = 0x%X\n\r",
+ DisplayPointer->StructRev)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Must be zero, is equal to 0x%X\n\r",
+ DisplayPointer->Reserved1)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Far pointer to UNDI ROMID = 0x%X\n\r",
+ (UINT32) (DisplayPointer->Undi.Segment << 0x4 | DisplayPointer->Undi.Offset))
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Far pointer to base-code ROMID = 0x%X\n\r",
+ (UINT32) ((DisplayPointer->Base.Segment << 0x04) | DisplayPointer->Base.Offset))
+ );
+ DEBUG ((DEBUG_NET, "16bit stack segment API entry point. This will be seg:off in \n\r"));
+ DEBUG (
+ (DEBUG_NET,
+ "real mode and sel:off in 16:16 protected mode = 0x%X:0x%X\n\r",
+ DisplayPointer->EntryPointSP.Segment,
+ DisplayPointer->EntryPointSP.Offset)
+ );
+
+ DEBUG ((DEBUG_NET, "\n\tNOTE to the implementer\n\tThis is the entry to use for call-ins\n\r"));
+
+ DEBUG ((DEBUG_NET, "32bit stack Segment API entry point. This will be sel:off. \n\r"));
+ DEBUG (
+ (DEBUG_NET,
+ "In real mode, sel == 0 = 0x%X:0x%X\n\r",
+ DisplayPointer->EntryPointESP.Segment,
+ DisplayPointer->EntryPointESP.Offset)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Reserved2 value, must be zero, is equal to 0x%X\n\r",
+ DisplayPointer->Reserved2)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Number of segment descriptors in this structur = 0x%X\n\r",
+ (UINT8) DisplayPointer->SegDescCnt)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "First segment descriptor in GDT assigned to PXE = 0x%X\n\r",
+ (UINT16) DisplayPointer->FirstSelector)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "The Stack is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",
+ (UINT16) DisplayPointer->Stack.Seg_Addr,
+ (UINT32) DisplayPointer->Stack.Phy_Addr,
+ (UINT16) DisplayPointer->Stack.Seg_Size)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "The UNDIData is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",
+ (UINT16) DisplayPointer->UNDIData.Seg_Addr,
+ (UINT32) DisplayPointer->UNDIData.Phy_Addr,
+ (UINT16) DisplayPointer->UNDIData.Seg_Size)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "The UNDICodeWrite is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",
+ (UINT16) DisplayPointer->UNDICode.Seg_Addr,
+ (UINT32) DisplayPointer->UNDICode.Phy_Addr,
+ (UINT16) DisplayPointer->UNDICode.Seg_Size)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "The Stack is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",
+ (UINT16) DisplayPointer->UNDICodeWrite.Seg_Addr,
+ (UINT32) DisplayPointer->UNDICodeWrite.Phy_Addr,
+ (UINT16) DisplayPointer->UNDICodeWrite.Seg_Size)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "The BC_Data is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",
+ (UINT16) DisplayPointer->BC_Data.Seg_Addr,
+ (UINT32) DisplayPointer->BC_Data.Phy_Addr,
+ (UINT16) DisplayPointer->BC_Data.Seg_Size)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "The BC_Code is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",
+ (UINT16) DisplayPointer->BC_Code.Seg_Addr,
+ (UINT32) DisplayPointer->BC_Code.Phy_Addr,
+ (UINT16) DisplayPointer->BC_Code.Seg_Size)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "The BC_CodeWrite is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",
+ (UINT16) DisplayPointer->BC_CodeWrite.Seg_Addr,
+ (UINT32) DisplayPointer->BC_CodeWrite.Phy_Addr,
+ (UINT16) DisplayPointer->BC_CodeWrite.Seg_Size)
+ );
+}
+
+/**
+ Print PXENV table.
+
+ @param PxenvTable Point to PXENV
+
+**/
+VOID
+Print_PXENV_Table (
+ IN VOID *PxenvTable
+ )
+{
+ PXENV_T *DisplayPointer;
+
+ DisplayPointer = (PXENV_T *) PxenvTable;
+
+ DEBUG (
+ (DEBUG_NET,
+ "\n\rPXENV+ %c%c%c%c%c%c\n\r",
+ DisplayPointer->Signature[0],
+ DisplayPointer->Signature[1],
+ DisplayPointer->Signature[2],
+ DisplayPointer->Signature[3],
+ DisplayPointer->Signature[4],
+ DisplayPointer->Signature[5])
+ );
+
+ DEBUG (
+ (DEBUG_NET,
+ "PXE version number. \n\r\tLSB is minor version. \n\r\tMSB is major version = 0x%X\n\r",
+ DisplayPointer->Version)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Length of PXE-2.0 Entry Point structure in bytes = 0x%X\n\r",
+ DisplayPointer->StructLength)
+ );
+ DEBUG ((DEBUG_NET, "Used to make structure checksum equal zero is now = 0x%X\n\r", DisplayPointer->StructCksum));
+ DEBUG ((DEBUG_NET, "Real mode API entry point segment:Offset. = 0x%X\n\r", DisplayPointer->RMEntry));
+ DEBUG ((DEBUG_NET, "Protected mode API entry point = 0x%X\n\r", DisplayPointer->PMEntryOff));
+ DEBUG ((DEBUG_NET, " segment:Offset. This will always be zero. \n\r"));
+ DEBUG ((DEBUG_NET, "Protected mode API calls = 0x%X\n\r", DisplayPointer->PMEntrySeg));
+ DEBUG ((DEBUG_NET, "Real mode stack segment = 0x%X\n\r", DisplayPointer->StackSeg));
+ DEBUG ((DEBUG_NET, "Stack segment size in bytes = 0x%X\n\r", DisplayPointer->StackSize));
+ DEBUG ((DEBUG_NET, "Real mode base-code code segment = 0x%X\n\r", DisplayPointer->BaseCodeSeg));
+ DEBUG ((DEBUG_NET, "Base-code code segment size = 0x%X\n\r", DisplayPointer->BaseCodeSize));
+ DEBUG ((DEBUG_NET, "Real mode base-code data segment = 0x%X\n\r", DisplayPointer->BaseDataSeg));
+ DEBUG ((DEBUG_NET, "Base-code data segment size = 0x%X\n\r", DisplayPointer->BaseDataSize));
+
+ DEBUG (
+ (DEBUG_NET,
+ "UNDI code segment size in bytes = 0x%X\n\r",
+ DisplayPointer->UNDICodeSize)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Real mode segment:Offset pointer \n\r\tto PXE Runtime ID structure, address = 0x%X\n\r",
+ DisplayPointer->RuntimePtr)
+ );
+ DEBUG (
+ (
+ DEBUG_NET,
+ "From above, we have a linear address of 0x%X\n\r",
+ (UINT32)
+ (
+ ((UINT32)(UINTN)(DisplayPointer->RuntimePtr) & 0xFFFF) +
+ (((UINT32)(UINTN)(DisplayPointer->RuntimePtr) & 0xFFFF0000) >> 12)
+ )
+ )
+ );
+}
+
+
+#define OPTION_ROM_PTR ((OPTION_ROM_HEADER *) RomAddress)
+
+/**
+ If available, launch the BaseCode from a NIC option ROM.
+ This should install the !PXE and PXENV+ structures in memory for
+ subsequent use.
+
+
+ @param SimpleNetworkDevice Simple network device instance
+ @param RomAddress The ROM base address for NIC rom.
+
+ @retval EFI_NOT_FOUND The check sum does not match
+ @retval EFI_NOT_FOUND Rom ID offset is wrong
+ @retval EFI_NOT_FOUND No Rom ID structure is found
+**/
+EFI_STATUS
+LaunchBaseCode (
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ UINTN RomAddress
+ )
+{
+ EFI_STATUS Status;
+ EFI_IA32_REGISTER_SET InOutRegs;
+ UNDI_ROMID_T *RomIdTableAddress;
+ UNDI_LOADER_T *UndiLoaderTable;
+ UINT16 Segment;
+ UINT16 *StackPointer;
+ VOID *Buffer;
+ UINTN Size;
+ PXE_T *Pxe;
+ UINT32 RomLength;
+ UINTN PciSegment;
+ UINTN Bus;
+ UINTN Device;
+ UINTN Function;
+ BOOLEAN ThunkFailed;
+
+ DEBUG ((DEBUG_NET, "\n\r\n\rCheck for the UNDI ROMID Signature\n\r"));
+
+ //
+ // paranoia - check structures for validity
+ //
+ RomLength = OPTION_ROM_PTR->ROMlength << 9;
+ if (CalculateSum8 ((UINT8 *) RomAddress, RomLength) != 0) {
+ DEBUG ((DEBUG_ERROR, "ROM Header Checksum Error\n\r"));
+ return EFI_NOT_FOUND;
+ }
+
+ RomIdTableAddress = (UNDI_ROMID_T *) (RomAddress + OPTION_ROM_PTR->PxeRomIdOffset);
+
+ if ((UINTN) (OPTION_ROM_PTR->PxeRomIdOffset + RomIdTableAddress->StructLength) > RomLength) {
+ DEBUG ((DEBUG_ERROR, "ROM ID Offset Error\n\r"));
+ return EFI_NOT_FOUND;
+ }
+ //
+ // see if this is a header for an UNDI ROM ID structure (vs. a $BC$ or BUSD type)
+ //
+ if (CompareMem (RomIdTableAddress->Signature, UNDI_ROMID_SIG, sizeof RomIdTableAddress->Signature) != 0) {
+ DEBUG ((DEBUG_ERROR, "No ROM ID Structure found....\n\r"));
+ return EFI_NOT_FOUND;
+ //
+ // its not - keep looking
+ //
+ }
+
+ if (CalculateSum8 ((UINT8 *) RomIdTableAddress, RomIdTableAddress->StructLength) != 0) {
+ DEBUG ((DEBUG_ERROR, "ROM ID Checksum Error\n\r"));
+ return EFI_NOT_FOUND;
+ }
+
+ Print_ROMID_Table (RomIdTableAddress);
+
+ DEBUG (
+ (DEBUG_NET,
+ "The ROM ID is located at 0x%X\n\r",
+ RomIdTableAddress)
+ );
+
+ DEBUG (
+ (DEBUG_NET,
+ "With an UNDI Loader located at 0x%X\n\r",
+ RomAddress + RomIdTableAddress->UNDI_Loader)
+ );
+
+ //
+ // found an UNDI ROM ID structure
+ //
+ SimpleNetworkDevice->Nii.ImageAddr = RomAddress;
+ SimpleNetworkDevice->Nii.ImageSize = RomLength;
+ SimpleNetworkDevice->Nii.MajorVer = RomIdTableAddress->UNDI_Rev[2];
+ SimpleNetworkDevice->Nii.MinorVer = RomIdTableAddress->UNDI_Rev[1];
+
+ DEBUG ((DEBUG_NET, "Allocate area for the UNDI_LOADER_T structure\n\r"));
+ //
+ // Allocate 1 page below 1MB to put real mode thunk code in
+ //
+ // Undi Loader Table is a PXE Specification prescribed data structure
+ // that is used to transfer information into and out of the Undi layer.
+ // Note how it must be located below 1 MB.
+ //
+ SimpleNetworkDevice->UndiLoaderTablePages = EFI_SIZE_TO_PAGES (PARAGRAPH_SIZE + sizeof (UNDI_LOADER_T));
+ Status = BiosSnp16AllocatePagesBelowOneMb (
+ SimpleNetworkDevice->UndiLoaderTablePages,
+ &SimpleNetworkDevice->UndiLoaderTable
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "We had a failure in AllocatePages, status code = 0x%X\n", Status));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ UndiLoaderTable = SimpleNetworkDevice->UndiLoaderTable;
+
+ DEBUG ((DEBUG_NET, "Allocate area for the real-mode stack whose sole purpose\n\r"));
+ DEBUG ((DEBUG_NET, "in life right now is to store a SEG:OFFSET combo pair that\n\r"));
+ DEBUG ((DEBUG_NET, "points to an Undi_Loader_t table structure\n\r"));
+
+ Size = 0x100;
+ Status = gBS->AllocatePool (EfiLoaderData, Size, &Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Now we want to put a pointer to the Under Loader Table in our MemPage
+ // Buffer. This will be the argument stack for the call into the Undi Loader
+ //
+ StackPointer = (UINT16 *) Buffer;
+ *StackPointer++ = TO_OFFSET (UndiLoaderTable);
+ //
+ // push the OFFSET
+ //
+ *StackPointer++ = TO_SEGMENT (UndiLoaderTable);
+ //
+ // push the SEGMENT
+ //
+ StackPointer = (UINT16 *) Buffer;
+ //
+ // reset the stack pointer
+ //
+ DEBUG (
+ (DEBUG_NET,
+ "After the fixups, the stack pointer is 0x%X\n\r",
+ (UINT64)(UINTN) StackPointer)
+ );
+
+ //
+ // Allocate memory for the Deployed UNDI.
+ // The UNDI is essentially telling us how much space it needs, and
+ // it is up to the EFI driver to allocate sufficient, boot-time
+ // persistent resources for the call
+ //
+ SimpleNetworkDevice->DestinationDataSegmentPages = EFI_SIZE_TO_PAGES (RomIdTableAddress->DataSize);
+ Status = BiosSnp16AllocatePagesBelowOneMb (
+ SimpleNetworkDevice->DestinationDataSegmentPages,
+ &SimpleNetworkDevice->DestinationDataSegment
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "We had a failure in AllocatePages, status code = 0x%X\n", Status));
+ return Status;
+ }
+
+ UndiLoaderTable->Undi_Ds = (UINT16) ((UINTN) SimpleNetworkDevice->DestinationDataSegment >> 4);
+
+ //
+ // Allocate memory for the Deployed UNDI stack
+ // The UNDI is essentially telling us how much space it needs, and
+ // it is up to the EFI driver to allocate sufficient, boot-time
+ // persistent resources for the call
+ //
+ SimpleNetworkDevice->DestinationStackSegmentPages = EFI_SIZE_TO_PAGES (RomIdTableAddress->StackSize);
+ Status = BiosSnp16AllocatePagesBelowOneMb (
+ SimpleNetworkDevice->DestinationStackSegmentPages,
+ &SimpleNetworkDevice->DestinationStackSegment
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "We had a failure in AllocatePages, status code = 0x%X\n", Status));
+ return Status;
+ }
+ //
+ // Allocate memory for the Deployed UNDI.
+ // The UNDI is essentially telling us how much space it needs, and
+ // it is up to the EFI driver to allocate sufficient, boot-time
+ // persistent resources for the call
+ //
+ SimpleNetworkDevice->DestinationCodeSegmentPages = EFI_SIZE_TO_PAGES (RomIdTableAddress->CodeSize);
+ Status = BiosSnp16AllocatePagesBelowOneMb (
+ SimpleNetworkDevice->DestinationCodeSegmentPages,
+ &SimpleNetworkDevice->DestinationCodeSegment
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "We had a failure in AllocatePages, status code = 0x%X\n", Status));
+ return Status;
+ }
+
+ UndiLoaderTable->Undi_Cs = (UINT16) ((UINTN) SimpleNetworkDevice->DestinationCodeSegment >> 4);
+
+ //
+ // these are in the Input and Output Parameter to be sent to the UNDI Loader code
+ //
+ UndiLoaderTable->Status = 0xAA55;
+ //
+ // -------------------- Changed by Michael_Huang@3Com.com -----------------
+ // UndiLoaderTable->_AX is AX value when UNDI ROM is initialized by BIOS, it is the PCI bus device
+ // function of the NIC. Please refer to PXE Spec for detail info.
+ // old code is:
+ // UndiLoaderTable->Ax = 0x0;
+ // -----------------------------------------------------------------------
+ //
+ SimpleNetworkDevice->PciIo->GetLocation (
+ SimpleNetworkDevice->PciIo,
+ &PciSegment,
+ &Bus,
+ &Device,
+ &Function
+ );
+ UndiLoaderTable->Ax = (UINT16) ((Bus << 0x8) | (Device << 0x3) | (Function));
+ UndiLoaderTable->Bx = 0x0;
+ UndiLoaderTable->Dx = 0x0;
+ UndiLoaderTable->Di = 0x0;
+ UndiLoaderTable->Es = 0x0;
+
+ //
+ // set these OUT values to zero in order to ensure that
+ // uninitialized memory is not mistaken for display data
+ //
+ UndiLoaderTable->PXEptr.Offset = 0;
+ UndiLoaderTable->PXEptr.Segment = 0;
+ UndiLoaderTable->PXENVptr.Segment = 0;
+ UndiLoaderTable->PXENVptr.Offset = 0;
+
+ DEBUG (
+ (DEBUG_INIT,
+ "The NIC is located at Bus 0x%X, Device 0x%X, Function 0x%X\n\r",
+ Bus,
+ Device,
+ Function)
+ );
+
+ //
+ // These are the values that set up the ACTUAL IA32 machine state, whether in
+ // Real16 in EFI32 or the IVE for IA64
+ // register values are unused except for CS:IP and SS:SP
+ //
+ InOutRegs.X.AX = 0;
+ InOutRegs.X.BX = 0;
+ InOutRegs.X.CX = 0;
+ InOutRegs.X.DX = 0;
+ InOutRegs.X.SI = 0;
+ InOutRegs.X.DI = 0;
+ InOutRegs.X.BP = 0;
+ InOutRegs.X.DS = 0;
+ InOutRegs.X.ES = 0;
+ //
+ // just to be clean
+ //
+ DEBUG ((DEBUG_NET, "The way this game works is that the SS:SP +4 should point\n\r"));
+ DEBUG ((DEBUG_NET, "to the contents of the UndiLoaderTable\n\r"));
+ DEBUG (
+ (DEBUG_NET,
+ "The Undi Loader Table is at address = 0x%X\n\r",
+ (UINT32)(UINTN) UndiLoaderTable)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "The segment and offsets are 0x%X and 0x%X, resp\n",
+ TO_SEGMENT (UndiLoaderTable),
+ TO_OFFSET (UndiLoaderTable))
+ );
+
+ DEBUG (
+ (DEBUG_NET,
+ "The Linear Address of the UNDI Loader entry is 0x%X\n",
+ RomAddress + RomIdTableAddress->UNDI_Loader)
+ );
+
+ DEBUG (
+ (DEBUG_NET,
+ "The Address offset of the UNDI Loader entry is 0x%X\n",
+ RomIdTableAddress->UNDI_Loader)
+ );
+
+ DEBUG ((DEBUG_NET, "Before the call, we have...\n\r"));
+ Print_Undi_Loader_Table (UndiLoaderTable);
+
+ Segment = ((UINT16) (RShiftU64 (RomAddress, 4) & 0xFFFF));
+ DEBUG ((DEBUG_NET, "The Segment of the call is 0x%X\n\r", Segment));
+
+ //
+ // make the call into the UNDI Code
+ //
+ DEBUG ((DEBUG_INIT, "Make the call into the UNDI code now\n\r"));
+
+ DEBUG ((DEBUG_NET, "\nThe 20-BIt address of the Call, and the location \n\r"));
+ DEBUG ((DEBUG_NET, "\twhere we should be able to set a breakpoint is \n\r"));
+ DEBUG (
+ (DEBUG_NET,
+ "\t\t0x%X, from SEG:OFF 0x%X:0x%X\n\r\n\r",
+ Segment * 0x10 + RomIdTableAddress->UNDI_Loader,
+ Segment,
+ RomIdTableAddress->UNDI_Loader)
+ );
+
+ ThunkFailed = SimpleNetworkDevice->LegacyBios->FarCall86 (
+ SimpleNetworkDevice->LegacyBios,
+ Segment, // Input segment
+ (UINT16) RomIdTableAddress->UNDI_Loader, // Offset
+ &InOutRegs, // Ptr to Regs
+ Buffer, // Reference to Stack
+ Size // Size of the Stack
+ );
+ if (ThunkFailed) {
+ return EFI_ABORTED;
+ }
+
+ DEBUG (
+ (DEBUG_NET,
+ "The return code UndiLoaderTable->Status is = 0x%X\n\r",
+ UndiLoaderTable->Status)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "This error code should match eax, which is = 0x%X\n\r",
+ InOutRegs.X.AX)
+ );
+
+ DEBUG ((DEBUG_NET, "Now returned from the UNDI code\n\r"));
+
+ DEBUG ((DEBUG_NET, "After the call, we have...\n\r"));
+ Print_Undi_Loader_Table (UndiLoaderTable);
+
+ DEBUG ((DEBUG_NET, "Display the PXENV+ and !PXE tables exported by NIC\n\r"));
+ Print_PXENV_Table ((VOID *)(UINTN)((UndiLoaderTable->PXENVptr.Segment << 4) | UndiLoaderTable->PXENVptr.Offset));
+ Print_PXE_Table ((VOID *)(UINTN)((UndiLoaderTable->PXEptr.Segment << 4) + UndiLoaderTable->PXEptr.Offset));
+
+ Pxe = (PXE_T *)(UINTN)((UndiLoaderTable->PXEptr.Segment << 4) + UndiLoaderTable->PXEptr.Offset);
+ SimpleNetworkDevice->Nii.Id = (UINT64)(UINTN) Pxe;
+
+ //
+ // FreePool (Buffer);
+ // paranoia - make sure a valid !PXE structure
+ //
+ if (CompareMem (Pxe->Signature, PXE_SIG, sizeof Pxe->Signature) != 0) {
+ DEBUG ((DEBUG_ERROR, "!PXE Structure not found....\n\r"));
+ return EFI_NOT_FOUND;
+ //
+ // its not - keep looking
+ //
+ }
+
+ if (CalculateSum8 ((UINT8 *) Pxe, Pxe->StructLength) != 0) {
+ DEBUG ((DEBUG_ERROR, "!PXE Checksum Error\n\r"));
+ return EFI_NOT_FOUND;
+ }
+
+ if (Pxe->StructLength < (UINT8 *) &Pxe->FirstSelector - (UINT8 *) Pxe->Signature) {
+ DEBUG ((DEBUG_ERROR, "!PXE Length Error\n\r"));
+ return EFI_NOT_FOUND;
+ }
+
+ if ((((UINTN) Pxe->Undi.Segment) << 4) + Pxe->Undi.Offset != (UINTN) RomIdTableAddress) {
+ DEBUG ((DEBUG_ERROR, "!PXE RomId Address Error\n\r"));
+ return EFI_NOT_FOUND;
+ }
+ //
+ // This is the magic to bind the global PXE interface
+ // This dirtiness is for non-protocol shrouded access
+ //
+ SimpleNetworkDevice->PxeEntrySegment = Pxe->EntryPointSP.Segment;
+
+ if (SimpleNetworkDevice->PxeEntrySegment == 0) {
+ DEBUG ((DEBUG_ERROR, "!PXE EntryPointSP segment Error\n\r"));
+ return EFI_NOT_FOUND;
+ }
+
+ SimpleNetworkDevice->PxeEntryOffset = Pxe->EntryPointSP.Offset;
+
+ DEBUG (
+ (
+ DEBUG_NET, "The entry point is 0x%X:0x%X\n\r", SimpleNetworkDevice->PxeEntrySegment, SimpleNetworkDevice->
+ PxeEntryOffset
+ )
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Effect the Far Call into the PXE Layer
+
+ Note: When using a 32-bit stack segment do not push 32-bit words onto the stack. The PXE API
+ services will not work, unless there are three 16-bit parameters pushed onto the stack.
+ push DS ;Far pointer to parameter structure
+ push offset pxe_data_call_struct ;is pushed onto stack.
+ push Index ;UINT16 is pushed onto stack.
+ call dword ptr (s_PXE ptr es:[di]).EntryPointSP
+ add sp, 6 ;Caller cleans up stack.
+
+ @param SimpleNetworkDevice Device instance for simple network
+ @param Table Point to parameter/retun value table for legacy far call
+ @param TableSize The size of paramter/return value table
+ @param CallIndex The index of legacy call.
+
+ @return EFI_STATUS
+**/
+EFI_STATUS
+MakePxeCall (
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT VOID *Table,
+ IN UINTN TableSize,
+ IN UINT16 CallIndex
+ )
+{
+ EFI_STATUS Status;
+ EFI_IA32_REGISTER_SET InOutRegs;
+ UINT16 *BPtr;
+ VOID *Buffer;
+ UINTN Size;
+ VOID *MemPageAddress;
+ UINTN Index;
+ BOOLEAN ThunkFailed;
+
+ DEBUG ((DEBUG_NET, "MakePxeCall(CallIndex = %02x, Table = %X, TableSize = %d)\n", CallIndex, Table, TableSize));
+
+ if (SimpleNetworkDevice->PxeEntrySegment == 0 && SimpleNetworkDevice->PxeEntryOffset == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Allocate a transient data structure for the argument table
+ // This table needs to have the input XXX_t structure copied into here.
+ // The PXE UNDI can only grab this table when it's below one-MB, and
+ // this implementation will not try to push this table on the stack
+ // (although this is a possible optimization path since EFI always allocates
+ // 4K as a minimum page size...............)
+ //
+ Status = BiosSnp16AllocatePagesBelowOneMb (
+ TableSize / EFI_PAGE_SIZE + 1,
+ &MemPageAddress
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "We had a failure in AllocatePages, status code = 0x%X\n", Status));
+ return Status;
+ }
+ //
+ // Copy the > 1MB pool table to a sub-1MB buffer
+ //
+ CopyMem (MemPageAddress, Table, TableSize);
+
+ //
+ // Allocate space for IA-32 register context
+ //
+ ZeroMem (&InOutRegs, sizeof (InOutRegs));
+ InOutRegs.X.ES = SimpleNetworkDevice->PxeEntrySegment;
+ InOutRegs.X.DI = SimpleNetworkDevice->PxeEntryOffset;
+
+ //
+ // The game here is to build the stack which will subsequently
+ // get copied down below 1 MB by the FarCall primitive.
+ // This is now our working stack
+ //
+ Size = 6;
+ Status = gBS->AllocatePool (
+ EfiRuntimeServicesData,
+ Size,
+ &Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ BPtr = (UINT16 *) Buffer;
+ *BPtr++ = CallIndex;
+ //
+ // SP + 2
+ //
+ *BPtr++ = TO_OFFSET (MemPageAddress);
+ *BPtr++ = TO_SEGMENT (MemPageAddress);
+
+ DEBUG ((DEBUG_NET, "State before FarCall86\n"));
+ DEBUG ((DEBUG_NET, "The Buffer is at 0x%X\n\r", Buffer));
+ BPtr = (UINT16 *) Buffer;
+ DEBUG ((DEBUG_NET, " Buffer = %04X %04X %04X", *BPtr, *(BPtr + 1), *(BPtr + 2)));
+ DEBUG ((DEBUG_NET, " MemPage = "));
+ for (Index = 0; Index < TableSize; Index++) {
+ DEBUG ((DEBUG_NET, " %02x", *((UINT8 *) MemPageAddress + Index)));
+ }
+
+ DEBUG ((DEBUG_NET, "\n"));
+
+ ThunkFailed = SimpleNetworkDevice->LegacyBios->FarCall86 (
+ SimpleNetworkDevice->LegacyBios,
+ SimpleNetworkDevice->PxeEntrySegment, // Input segment
+ SimpleNetworkDevice->PxeEntryOffset,
+ &InOutRegs, // Ptr to Regs
+ Buffer, // Reference to Stack
+ 6 // Size of the Stack
+ );
+ if (ThunkFailed) {
+ return EFI_ABORTED;
+ }
+
+ DEBUG ((DEBUG_NET, "State after FarCall86\n"));
+ DEBUG ((DEBUG_NET, "The Buffer is at 0x%X\n\r", Buffer));
+ BPtr = (UINT16 *) Buffer;
+ DEBUG ((DEBUG_NET, " Buffer = %04X %04X %04X", *BPtr, *(BPtr + 1), *(BPtr + 2)));
+ DEBUG ((DEBUG_NET, " MemPage = "));
+ for (Index = 0; Index < TableSize; Index++) {
+ DEBUG ((DEBUG_NET, " %02x", *((UINT8 *) MemPageAddress + Index)));
+ }
+
+ DEBUG ((DEBUG_NET, "\n"));
+
+ //
+ // Copy the sub 1MB table to > 1MB table
+ //
+ CopyMem (Table, MemPageAddress, TableSize);
+
+ //
+ // For PXE UNDI call, AX contains the return status.
+ // Convert the PXE UNDI Status to EFI_STATUS type
+ //
+ if (InOutRegs.X.AX == PXENV_EXIT_SUCCESS) {
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ }
+ //
+ // Clean up house
+ //
+ gBS->FreePool (Buffer);
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) MemPageAddress, TableSize / EFI_PAGE_SIZE + 1);
+
+ return Status;
+}
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Pxe.h b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Pxe.h
new file mode 100644
index 0000000000..54503a840f
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Pxe.h
@@ -0,0 +1,613 @@
+/** @file
+ These are PXE Specification 2.1-compliant data structures and defines.
+
+ This file relies upon the existence of a PXE-compliant ROM
+ in memory, as defined by the Preboot Execution Environment
+ Specification (PXE), Version 2.1, located at
+
+ http://developer.intel.com/ial/wfm/wfmspecs.htm
+
+Copyright (c) 1999 - 2010, 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.
+
+**/
+
+#ifndef _PXEDEF_H_
+#define _PXEDEF_H_
+
+#pragma pack(1)
+
+//
+// PXE structure signatures
+//
+#define BC_ROMID_SIG "$BC$"
+#define UNDI_ROMID_SIG "UNDI"
+#define BUSD_ROMID_SIG "BUSD"
+
+#define PXE_SIG "!PXE"
+#define PXENV_SIG "PXENV+"
+
+#define BC_ROMID_REV 0x00
+#define UNDI_ROMID_REV 0x00
+#define BUSD_ROMID_REV 0x00
+
+#define PXE_REV 0x00
+#define PXENV_REV 0x0201
+
+#define PXENV_PTR SIGNATURE_32 ('P', 'X', 'E', 'N')
+#define PXE_PTR SIGNATURE_32 ('!', 'P', 'X', 'E')
+#define UNDI_ROMID_SIG_PTR SIGNATURE_32 ('U', 'N', 'D', 'I')
+
+typedef UINT16 SEGSEL; // Real mode segment or protected mode selector.
+typedef UINT16 OFF16; // Unsigned 16bit offset.
+typedef UINT32 ADDR32;
+
+//
+// Bus types
+//
+#define PXENV_BUS_ISA 0
+#define PXENV_BUS_EISA 1
+#define PXENV_BUS_MCA 2
+#define PXENV_BUS_PCI 3
+#define PXENV_BUS_VESA 4
+#define PXENV_BUS_PCMCIA 5
+
+//
+//
+// Result codes returned in AX by a PXENV API service.
+//
+#define PXENV_EXIT_SUCCESS 0x0000
+#define PXENV_EXIT_FAILURE 0x0001
+
+//
+// Status codes returned in the status word of PXENV API parameter structures.
+//
+// Generic API errors - these do not match up with the M0x or E0x messages
+// that are reported by the loader.
+//
+#define PXENV_STATUS_SUCCESS 0x00
+#define PXENV_STATUS_FAILURE 0x01
+#define PXENV_STATUS_BAD_FUNC 0x02
+#define PXENV_STATUS_UNSUPPORTED 0x03
+#define PXENV_STATUS_KEEP_UNDI 0x04
+#define PXENV_STATUS_KEEP_ALL 0x05
+#define PXENV_STATUS_OUT_OF_RESOURCES 0x06
+
+typedef enum {
+ PxeEnvStatus_Success,
+ PxeEnvStatus_Failure,
+ PxeEnvStatus_BadFunc,
+ PxeEnvStatus_Unsupported,
+ PxeEnvStatus_KeepUndi,
+ PxeEnvStatus_KeepAll
+} EFI_PXE_STATUS;
+
+/* Driver errors (0x60 to 0x6F) */
+
+// These errors are for UNDI compatible NIC drivers.
+#define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x60
+#define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x61
+#define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST 0x62
+#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC 0x63
+#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY 0x64
+#define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA 0x65
+#define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA 0x66
+#define PXENV_STATUS_UNDI_BAD_MAC_ADDR 0x67
+#define PXENV_STATUS_UNDI_BAD_EEPROM_CKSUM 0x68
+#define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x69
+#define PXENV_STATUS_UNDI_INVALID_STATE 0x6A
+#define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x6B
+#define PXENV_STATUS_UNDI_INVALID_PARAMETER 0x6C
+
+typedef struct {
+ UINT16 Seg_Addr;
+ UINT32 Phy_Addr;
+ UINT16 Seg_Size;
+} NEWSEGDESC_T;
+
+typedef struct {
+ OFF16 Offset;
+ SEGSEL Segment;
+} SEGOFF16;
+
+typedef struct {
+ UINT8 Signature[4]; ///< Structure signature is not NULL terminated.
+ UINT8 StructLength; ///< Length of this structure in bytes.
+ UINT8 StructCksum; ///< Use to make byte checksum of this structure == zero.
+ UINT8 StructRev; ///< Structure format revision number.
+ UINT8 UNDI_Rev[3]; ///< API revision number stored in Intel order.
+ //
+ // Revision 2.1.0 == 0x00, 0x01, 0x02
+ //
+ UINT16 UNDI_Loader; ///< Offset of UNDI loader routine in the option ROM image.
+ UINT16 StackSize; ///< Minimum stack segment size, in bytes, needed to load and run the UNDI.
+ UINT16 DataSize; ///< UNDI runtime code and data
+ UINT16 CodeSize; ///< segment sizes.
+ UINT8 BusType[4]; ///< 'ISAR', 'EISA', 'PCIR', 'PCCR'
+} UNDI_ROMID_T;
+
+typedef struct {
+ UINT8 Signature[4]; ///< Structure signature is not NULL terminated.
+ UINT8 StructLength; ///< Length of this structure in bytes.
+ UINT8 StructCksum; ///< Use to make byte checksum of this structure == zero.
+ UINT8 StructRev; ///< Structure format revision number.
+ UINT8 BC_Rev[3]; ///< API revision number stored in Intel order.
+ //
+ // Revision 2.1.0 == 0x00, 0x01, 0x02
+ //
+ UINT16 BC_Loader; ///< Offset of base-code loader routine in the option ROM image.
+ UINT16 StackSize; ///< Minimum stack segment size (bytes) needed to load/run base-code.
+ UINT16 DataSize; ///< Base-code runtime code and data
+ UINT16 CodeSize; ///< segment sizes.
+} BC_ROMID_T;
+
+typedef struct {
+ UINT8 Signature[4]; ///< Structure signature is not NULL terminated.
+ UINT8 StructLength; ///< Length of this structure in bytes.
+ UINT8 StructCksum; ///< Use to make byte checksum of this structure == zero.
+ UINT8 StructRev; ///< Structure format revision number.
+ UINT8 Reserved1; ///< must be zero
+ ///
+ /// UNDI_ROMID_T __FAR *UNDI;// Far pointer to UNDI ROMID
+ ///
+ SEGOFF16 Undi;
+
+ ///
+ /// BC_ROMID_T __FAR *Base; // Far pointer to base-code ROMID
+ ///
+ SEGOFF16 Base;
+
+ ///
+ /// UINT16 (__FAR __CDECL *EntryPointSP)(UINT16 func, VOID __FAR *param);
+ /// 16bit stack segment API entry point. This will be seg:off in
+ /// real mode and sel:off in 16:16 protected mode.
+ ///
+ SEGOFF16 EntryPointSP;
+
+ ///
+ /// UINT16 (__FAR __CDECL *EntryPointESP)(UINT16 func, VOID __FAR *param);
+ /// 32bit stack segment API entry point. This will be sel:off.
+ /// In real mode, sel == 0
+ ///
+ SEGOFF16 EntryPointESP;
+ ///
+ /// UINT16 (__FAR __CDECL *StatusCallout)(UINT16 param);
+ /// Address of DHCP/TFTP status callout routine.
+ ///
+ SEGOFF16 StatusCallout;
+ UINT8 Reserved2; ///< must be zero
+ UINT8 SegDescCnt; ///< Number of segment descriptors in this structure.
+ UINT16 FirstSelector; ///< First segment descriptor in GDT assigned to PXE.
+ NEWSEGDESC_T Stack;
+ NEWSEGDESC_T UNDIData;
+ NEWSEGDESC_T UNDICode;
+ NEWSEGDESC_T UNDICodeWrite;
+ NEWSEGDESC_T BC_Data;
+ NEWSEGDESC_T BC_Code;
+ NEWSEGDESC_T BC_CodeWrite;
+} PXE_T;
+
+typedef struct {
+ CHAR8 Signature[6]; ///< "PXENV+"
+ UINT16 Version; ///< PXE version number. LSB is minor version. MSB is major version.
+ UINT8 StructLength; ///< Length of PXE-2.0 Entry Point structure in bytes.
+ UINT8 StructCksum; ///< Used to make structure checksum equal zero.
+ UINT32 RMEntry; ///< Real mode API entry point segment:offset.
+ UINT32 PMEntryOff; ///< Protected mode API entry point
+ UINT16 PMEntrySeg; ///< segment:offset. This will always be zero. Protected mode API calls
+ ///< must be made through the API entry points in the PXE Runtime ID structure.
+
+ UINT16 StackSeg; ///< Real mode stack segment.
+ UINT16 StackSize; ///< Stack segment size in bytes.
+ UINT16 BaseCodeSeg; ///< Real mode base-code code segment.
+ UINT16 BaseCodeSize; ///< Base-code code segment size
+ UINT16 BaseDataSeg; ///< Real mode base-code data segment.
+ UINT16 BaseDataSize; ///< Base-code data segment size
+ UINT16 UNDIDataSeg; ///< Real mode UNDI data segment.
+ UINT16 UNDIDataSize; ///< UNDI data segment size in bytes.
+ UINT16 UNDICodeSeg; ///< Real mode UNDI code segment.
+ UINT16 UNDICodeSize; ///< UNDI code segment size in bytes.
+ PXE_T *RuntimePtr; ///< Real mode segment:offset pointer to PXE Runtime ID structure.
+} PXENV_T;
+
+typedef struct {
+ OUT UINT16 Status;
+ IN OUT UINT16 Ax;
+ IN OUT UINT16 Bx;
+ IN OUT UINT16 Dx;
+ IN OUT UINT16 Di;
+ IN OUT UINT16 Es;
+ IN OUT UINT16 Undi_Ds;
+ IN OUT UINT16 Undi_Cs;
+ OUT SEGOFF16 PXEptr;
+ OUT SEGOFF16 PXENVptr;
+} UNDI_LOADER_T;
+
+//
+// Put in some UNDI-specific arguments
+//
+#define PXENV_START_UNDI 0x0000
+#define PXENV_UNDI_STARTUP 0x0001
+#define PXENV_UNDI_CLEANUP 0x0002
+#define PXENV_UNDI_INITIALIZE 0x0003
+#define PXENV_UNDI_RESET_NIC 0x0004
+#define PXENV_UNDI_SHUTDOWN 0x0005
+#define PXENV_UNDI_OPEN 0x0006
+#define PXENV_UNDI_CLOSE 0x0007
+#define PXENV_UNDI_TRANSMIT 0x0008
+#define PXENV_UNDI_SET_MCAST_ADDR 0x0009
+#define PXENV_UNDI_SET_STATION_ADDR 0x000A
+#define PXENV_UNDI_SET_PACKET_FILTER 0x000B
+#define PXENV_UNDI_GET_INFORMATION 0x000C
+#define PXENV_UNDI_GET_STATISTICS 0x000D
+#define PXENV_UNDI_CLEAR_STATISTICS 0x000E
+#define PXENV_UNDI_INITIATE_DIAGS 0x000F
+#define PXENV_UNDI_FORCE_INTERRUPT 0x0010
+#define PXENV_UNDI_GET_MCAST_ADDR 0x0011
+#define PXENV_UNDI_GET_NIC_TYPE 0x0012
+#define PXENV_UNDI_GET_NDIS_INFO 0x0013
+#define PXENV_UNDI_ISR 0x0014
+#define PXENV_STOP_UNDI 0x0015
+#define PXENV_UNDI_GET_STATE 0x0016
+
+#define ADDR_LEN 16
+#define MAXNUM_MCADDR 8
+#define IPLEN 4 ///< length of an IP address
+#define XMT_DESTADDR 0x0000 ///< destination address given
+#define XMT_BROADCAST 0x0001 ///< use broadcast address
+
+typedef struct {
+ UINT16 MCastAddrCount; ///< In: Number of multi-cast
+
+ /* addresses. */
+ UINT8 MCastAddr[MAXNUM_MCADDR][ADDR_LEN]; /* In: */
+
+ /* list of multi-cast addresses. */
+
+ /* Each address can take up to */
+
+ /* ADDR_LEN bytes and a maximum */
+
+ /* of MAXNUM_MCADDR address can */
+
+ /* be provided*/
+} PXENV_UNDI_MCAST_ADDR_T;
+
+/* Definitions of TFTP API parameter structures.
+ */
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+ IN UINT16 Ax; ///< In: These register fields must be
+ IN UINT16 Bx; ///< filled in with the same data
+ IN UINT16 Dx; ///< that was passed to the MLID
+ IN UINT16 Di; ///< option ROM boot code by the
+ IN UINT16 Es; ///< system BIOS.
+} PXENV_START_UNDI_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+} PXENV_UNDI_STARTUP_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+} PXENV_UNDI_CLEANUP_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+
+ ///
+ /// This is an input parameter and is a 32-bit physical address of
+ /// a memory copy of the driver module in the protocol.ini file
+ /// obtained from the Protocol Manager driver(refer to NDIS 2.0
+ /// specifications). This parameter is basically supported for
+ /// the universal NDIS driver to pass the information contained in
+ /// protocol.ini file to the NIC driver for any specific
+ /// configuration of the NIC. (Note that the module
+ /// identification in the protocol.ini file was done by NDIS
+ /// itself.) This value can be NULL for for any other application
+ /// interfacing to the Universal NIC Driver.
+ ///
+ IN UINT32 ProtocolIni;
+ UINT8 Reserved[8];
+} PXENV_UNDI_INITIALIZE_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+ IN PXENV_UNDI_MCAST_ADDR_T R_Mcast_Buf; ///< multicast address list
+ /* see note below */
+} PXENV_UNDI_RESET_T;
+
+/*++
+ Note: The NIC driver does not remember the multicast
+ addresses provided in any call. So the application must
+ provide the multicast address list with all the calls that
+ reset the receive unit of the adapter.
+ --*/
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+} PXENV_UNDI_SHUTDOWN_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+
+ ///
+ /// This is an input parameter and is adapter specific. This is
+ /// supported for Universal NDIS 2.0 driver to pass down the Open
+ /// flags provided by the protocol driver (See NDIS 2.0
+ /// specifications). This can be zero.
+ ///
+ IN UINT16 OpenFlag; ///< In: See description below
+ IN UINT16 PktFilter; ///< In: Filter for receiving
+
+ /* packet. It takes the following */
+
+ /* values, multiple values can be */
+
+ /* ORed together. */
+#define FLTR_DIRECTED 0x0001 ///< directed/multicast
+#define FLTR_BRDCST 0x0002 ///< broadcast packets
+#define FLTR_PRMSCS 0x0004 ///< any packet on LAN
+#define FLTR_SRC_RTG 0x0008 ///< source routing packet
+ IN PXENV_UNDI_MCAST_ADDR_T McastBuffer; /* In: */
+ /* See t_PXENV_UNDI_MCAST_ADDR. */
+} PXENV_UNDI_OPEN_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+} PXENV_UNDI_CLOSE_T;
+
+#define MAX_DATA_BLKS 8
+
+typedef struct {
+ IN UINT16 ImmedLength; ///< In: Data buffer length in
+
+ /* bytes. */
+ UINT16 XmitOffset; ///< 16-bit segment & offset of the
+ UINT16 XmitSegment; ///< immediate data buffer.
+ UINT16 DataBlkCount; ///< In: Number of data blocks.
+ struct DataBlk {
+ UINT8 TDPtrType; ///< 0 => 32 bit Phys pointer in TDDataPtr, not supported in this version of LSA
+ ///< 1 => seg:offser in TDDataPtr which can be a real mode or 16-bit protected mode pointer
+ UINT8 TDRsvdByte; ///< Reserved, must be zero.
+ UINT16 TDDataLen; ///< Data block length in bytes.
+ UINT16 TDDataPtrOffset; ///< Far pointer to data buffer.
+ UINT16 TDDataPtrSegment; ///< Far pointer to data buffer.
+ } DataBlock[MAX_DATA_BLKS];
+}
+PXENV_UNDI_TBD_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+
+ ///
+ /// This is the protocol of the upper layer that is calling
+ /// NICTransmit call. If the upper layer has filled the media
+ /// header this field must be 0.
+ ///
+ IN UINT8 Protocol;
+#define P_UNKNOWN 0
+#define P_IP 1
+#define P_ARP 2
+#define P_RARP 3
+
+ ///
+ /// If this flag is 0, the NIC driver expects a pointer to the
+ /// destination media address in the field DestMediaAddr. If 1,
+ /// the NIC driver fills the broadcast address for the
+ /// destination.
+ ///
+ IN UINT8 XmitFlag;
+#define XMT_DESTADDR 0x0000 ///< destination address given
+#define XMT_BROADCAST 0x0001 ///< use broadcast address
+
+ ///
+ /// This is a pointer to the hardware address of the destination
+ /// media. It can be null if the destination is not known in
+ /// which case the XmitFlag contains 1 for broadcast. Destination
+ /// media address must be obtained by the upper level protocol
+ /// (with Address Resolution Protocol) and NIC driver does not do
+ /// any address resolution.
+ ///
+ IN UINT16 DestAddrOffset; ///< 16-bit segment & offset of the
+ IN UINT16 DestAddrSegment; ///< destination media address
+
+
+ IN UINT16 TBDOffset; ///< 16-bit segment & offset of the
+ IN UINT16 TBDSegment; ///< transmit buffer descriptor of type
+
+ /// XmitBufferDesc
+ IN UINT32 Reserved[2];
+} PXENV_UNDI_TRANSMIT_T;
+
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+ IN PXENV_UNDI_MCAST_ADDR_T McastBuffer; ///< In:
+} PXENV_UNDI_SET_MCAST_ADDR_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+ IN UINT8 StationAddress[ADDR_LEN]; ///< new address to be set
+} PXENV_UNDI_SET_STATION_ADDR_T;
+
+typedef struct s_PXENV_UNDI_SET_PACKET_FILTER {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+ IN UINT8 Filter; ///< In: Receive filter value.
+} PXENV_UNDI_SET_PACKET_FILTER_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+ OUT UINT16 BaseIo; ///< Out: Adapter's Base IO
+ OUT UINT16 IntNumber; ///< Out: IRQ number
+ OUT UINT16 MaxTranUnit; ///< Out: MTU
+ OUT UINT16 HwType; ///< Out: type of protocol at hardware level
+
+#define ETHER_TYPE 1
+#define EXP_ETHER_TYPE 2
+#define IEEE_TYPE 6
+#define ARCNET_TYPE 7
+ /*++
+ other numbers can be obtained from rfc1010 for "Assigned
+ Numbers". This number may not be validated by the application
+ and hence adding new numbers to the list should be fine at any
+ time.
+ --*/
+ OUT UINT16 HwAddrLen; ///< Out: actual length of hardware address
+ OUT UINT8 CurrentNodeAddress[ADDR_LEN]; ///< Out: Current hardware address
+ OUT UINT8 PermNodeAddress[ADDR_LEN]; ///< Out: Permanent hardware address
+ OUT UINT16 ROMAddress; ///< Out: ROM address
+ OUT UINT16 RxBufCt; ///< Out: receive Queue length
+ OUT UINT16 TxBufCt; ///< Out: Transmit Queue length
+} PXENV_UNDI_GET_INFORMATION_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+ OUT UINT32 XmtGoodFrames; ///< Out: No. of good transmissions
+ OUT UINT32 RcvGoodFrames; ///< Out: No. of good frames received
+ OUT UINT32 RcvCRCErrors; ///< Out: No. of frames with CRC error
+ OUT UINT32 RcvResourceErrors; ///< Out: no. of frames discarded
+ /* Out: receive Queue full */
+} PXENV_UNDI_GET_STATISTICS_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+} PXENV_UNDI_CLEAR_STATISTICS_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+} PXENV_UNDI_INITIATE_DIAGS_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+} PXENV_UNDI_FORCE_INTERRUPT_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+ IN UINT32 InetAddr; ///< In: IP Multicast Address
+ OUT UINT8 MediaAddr[ADDR_LEN]; ///< Out: corresponding hardware
+ /* multicast address */
+} PXENV_UNDI_GET_MCAST_ADDR_T;
+
+typedef struct {
+ OUT UINT16 Vendor_ID; ///< OUT:
+ OUT UINT16 Dev_ID; ///< OUT:
+ OUT UINT8 Base_Class; ///< OUT:
+ OUT UINT8 Sub_Class; ///< OUT:
+ OUT UINT8 Prog_Intf; ///< OUT: program interface
+ OUT UINT8 Rev; ///< OUT: Revision number
+ OUT UINT16 BusDevFunc; ///< OUT: Bus, Device & Function numbers
+ OUT UINT16 SubVendor_ID; ///< OUT:
+ OUT UINT16 SubDevice_ID; ///< OUT:
+} PCI_INFO_T;
+
+typedef struct {
+ OUT UINT32 EISA_Dev_ID; ///< Out:
+ OUT UINT8 Base_Class; ///< OUT:
+ OUT UINT8 Sub_Class; ///< OUT:
+ OUT UINT8 Prog_Intf; ///< OUT: program interface
+ OUT UINT16 CardSelNum; ///< OUT: Card Selector Number
+ OUT UINT8 Reserved; ///< to make it 10 bytes
+} PNP_INFO_T;
+
+
+typedef union {
+ PCI_INFO_T Pci;
+ PNP_INFO_T Pnp;
+} PCI_PNP_INFO_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< OUT: PXENV_STATUS_xxx
+ OUT UINT8 NicType; ///< OUT: 2=PCI, 3=PnP
+ PCI_PNP_INFO_T PciPnpInfo;
+} PXENV_UNDI_GET_NIC_TYPE_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< OUT: PXENV_STATUS_xxx
+ OUT UINT8 IfaceType[16]; ///< OUT: Type name of MAC, AsciiZ
+
+ /* format. This is used by the */
+
+ /* Universal NDIS Driver to fill */
+
+ /* the driver type in it's MAC */
+
+ /* Service specific */
+
+ /* characteristic table */
+ OUT UINT32 LinkSpeed; ///< OUT:
+ OUT UINT32 ServiceFlags; ///< OUT: as defined in NDIS Spec 2.0X
+ OUT UINT32 Reserved[4]; ///< OUT: will be filled with 0s till defined
+} PXENV_UNDI_GET_NDIS_INFO_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< OUT: PXENV_STATUS_xxx
+ IN OUT UINT16 FuncFlag; ///< In: PXENV_UNDI_ISR_IN_xxx
+
+ /* Out: PXENV_UNDI_ISR_OUT_xxx */
+ OUT UINT16 BufferLength;
+ OUT UINT16 FrameLength;
+ OUT UINT16 FrameHeaderLength;
+ OUT UINT16 FrameOffset;
+ OUT UINT16 FrameSegSel;
+ OUT UINT8 ProtType;
+ OUT UINT8 PktType;
+} PXENV_UNDI_ISR_T;
+
+#define PXENV_UNDI_ISR_IN_START 1 /* This function must be first */
+
+/* when an interrupt is received. */
+
+/* It will tell us if the intr */
+
+/* was generated by our device. */
+#define PXENV_UNDI_ISR_IN_PROCESS 2 /* Call to start processing one of */
+
+/* our interrupts. */
+#define PXENV_UNDI_ISR_IN_GET_NEXT 3 /* Call to start/continue receiving */
+
+/* data from receive buffer(s). */
+
+/*++
+
+ Possible responses from PXENV_UNDI_ISR_IN_START
+
+ --*/
+#define PXENV_UNDI_ISR_OUT_OURS 0 ///< This is our interrupt. Deal with it.
+#define PXENV_UNDI_ISR_OUT_NOT_OURS 1 ///< This is not our interrupt.
+
+/*++
+
+ Possible responses from PXENV_UNDI_ISR_IN_PROCESS and
+ PXENV_UNDI_ISR_IN_PROCESS
+
+--*/
+#define PXENV_UNDI_ISR_OUT_DONE 0 ///< We are done processing this interrupt.
+#define PXENV_UNDI_ISR_OUT_TRANSMIT 2 ///< We completed a transmit interrupt.
+#define PXENV_UNDI_ISR_OUT_RECEIVE 3 ///< Get data from receive buffer.
+
+#define PXENV_UNDI_ISR_OUT_BUSY 4 /* ? */
+
+typedef struct {
+ UINT16 Status; ///< Out: PXENV_STATUS_xxx
+} PXENV_STOP_UNDI_T;
+
+#define PXENV_UNDI_STARTED 1 ///< not even initialized
+#define PXENV_UNDI_INITIALIZED 2 ///< initialized and closed (not opened)
+#define PXENV_UNDI_OPENED 3 ///< initialized & opened
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+ UINT16 UNDI_State;
+} PXENV_UNDI_GET_STATE_T;
+
+#pragma pack()
+
+#endif
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/PxeUndi.c b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/PxeUndi.c
new file mode 100644
index 0000000000..d35fc3f430
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/PxeUndi.c
@@ -0,0 +1,1254 @@
+/** @file
+ Wrapper routines that use a PXE-enabled NIC option ROM to
+ supply internal routines for an EFI SNI (Simple Network
+ Interface) Protocol.
+
+ This file relies upon the existence of a PXE-compliant ROM
+ in memory, as defined by the Preboot Execution Environment
+ Specification (PXE), Version 2.1, located at
+
+ http://developer.intel.com/ial/wfm/wfmspecs.htm
+
+Copyright (c) 1999 - 2010, 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"
+
+/**
+ PXE
+ START UNDI
+ Op-Code: PXENV_START_UNDI (0000h)
+ Input: Far pointer to a PXENV_START_UNDI_T parameter structure that has been initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This service is used to pass the BIOS parameter registers to the UNDI driver. The UNDI driver is
+ responsible for saving the information it needs to communicate with the hardware.
+ This service is also responsible for hooking the Int 1Ah service routine
+ Note: This API service must be called only once during UNDI Option ROM boot.
+ The UNDI driver is responsible for saving this information and using it every time
+ PXENV_UNDI_STARTUP is called.
+ Service cannot be used in protected mode.
+ typedef struct {
+ PXENV_STATUS Status;
+ UINT16 AX;
+ UINT16 BX;
+ UINT16 DX;
+ UINT16 DI;
+ UINT16 ES;
+ } PXENV_START_UNDI_T;
+ Set before calling API service
+ AX, BX, DX, DI, ES: BIOS initialization parameter registers. These
+ fields should contain the same information passed to the option ROM
+ initialization routine by the Host System BIOS. Information about the
+ contents of these registers can be found in the [PnP], [PCI] and
+ [BBS] specifications.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeStartUndi (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_START_UNDI_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_START_UNDI_T),
+ PXENV_START_UNDI
+ );
+}
+
+/**
+ PXE
+ UNDI STARTUP
+ Op-Code: PXENV_UNDI_STARTUP (0001h)
+ Input: Far pointer to a PXENV_UNDI_STARTUP_T parameter structure that has been initialized by the
+ caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the
+ PXENV_STATUS_xxx constants.
+ Description: This API is responsible for initializing the contents of the UNDI code & data segment for proper
+ operation. Information from the !PXE structure and the first PXENV_START_UNDI API call is used
+ to complete this initialization. The rest of the UNDI APIs will not be available until this call has
+ been completed.
+ Note: PXENV_UNDI_STARTUP must not be called again without first calling
+ PXENV_UNDI_SHUTDOWN.
+ PXENV_UNDI_STARTUP and PXENV_UNDI_SHUTDOWN are no longer responsible for
+ chaining interrupt 1Ah. This must be done by the PXENV_START_UNDI and
+ PXENV_STOP_UNDI API calls.
+ This service cannot be used in protected mode.
+ typedef struct
+ {
+ PXENV_STATUS Status;
+ } PXENV_UNDI_STARTUP_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiStartup (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_STARTUP_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_STARTUP_T),
+ PXENV_UNDI_STARTUP
+ );
+}
+
+/**
+ PXE
+ UNDI CLEANUP
+ Op-Code: PXENV_UNDI_CLEANUP (0002h)
+ Input: Far pointer to a PXENV_UNDI_CLEANUP_T parameter structure.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field
+ in the parameter structure must be set to one of the values represented by the
+ PXENV_STATUS_xxx constants.
+ Description: This call will prepare the network adapter driver to be unloaded from memory. This call must be
+ made just before unloading the Universal NIC Driver. The rest of the API will not be available
+ after this call executes.
+ This service cannot be used in protected mode.
+ typedef struct {
+ PXENX_STATUS Status;
+ } PXENV_UNDI_CLEANUP_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiCleanup (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_CLEANUP_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_CLEANUP_T),
+ PXENV_UNDI_CLEANUP
+ );
+}
+
+/**
+ PXE
+ UNDI INITIALIZE
+ Op-Code: PXENV_UNDI_INITIALIZE (0003h)
+ Input: Far pointer to a PXENV_UNDI_INITIALIZE_T parameter structure that has been initialized by the
+ caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call resets the adapter and programs it with default parameters. The default parameters used
+ are those supplied to the most recent UNDI_STARTUP call. This routine does not enable the
+ receive and transmit units of the network adapter to readily receive or transmit packets. The
+ application must call PXENV_UNDI_OPEN to logically connect the network adapter to the network.
+ This call must be made by an application to establish an interface to the network adapter driver.
+ Note: When the PXE code makes this call to initialize the network adapter, it passes a NULL pointer for
+ the Protocol field in the parameter structure.
+ typedef struct {
+ PXENV_STATUS Status;
+ ADDR32 ProtocolIni;
+ UINT8 reserved[8];
+ } PXENV_UNDI_INITIALIZE_T;
+ Set before calling API service
+ ProtocolIni: Physical address of a memory copy of the driver
+ module from the protocol.ini file obtained from the protocol manager
+ driver (refer to the NDIS 2.0 specification). This parameter is
+ supported for the universal NDIS driver to pass the information
+ contained in the protocol.ini file to the NIC driver for any specific
+ configuration of the NIC. (Note that the module identification in the
+ protocol.ini file was done by NDIS.) This value can be NULL for any
+ other application interfacing to the universal NIC driver
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiInitialize (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_INITIALIZE_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_INITIALIZE_T),
+ PXENV_UNDI_INITIALIZE
+ );
+}
+
+/**
+ Wrapper routine for reset adapter.
+
+ PXE
+ UNDI RESET ADAPTER
+ Op-Code: PXENV_UNDI_RESET_ADAPTER (0004h)
+ Input: Far pointer to a PXENV_UNDI_RESET_ADAPTER_t parameter structure that has been initialized
+ by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call resets and reinitializes the network adapter with the same set of parameters supplied to
+ Initialize Routine. Unlike Initialize, this call opens the adapter that is, it connects logically to the
+ network. This routine cannot be used to replace Initialize or Shutdown calls.
+ typedef struct {
+ PXENV_STATUS Status;
+ PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf;
+ } PXENV_UNDI_RESET_T;
+
+ #define MAXNUM_MCADDR 8
+
+ typedef struct {
+ UINT16 MCastAddrCount;
+ MAC_ADDR McastAddr[MAXNUM_MCADDR];
+ } PXENV_UNDI_MCAST_ADDRESS_t;
+
+ Set before calling API service
+ R_Mcast_Buf: This is a structure of MCastAddrCount and
+ McastAddr.
+ MCastAddrCount: Number of multicast MAC addresses in the
+ buffer.
+ McastAddr: List of up to MAXNUM_MCADDR multicast MAC
+ addresses.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance.
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+ @param RxFilter Filter setting mask value for PXE recive .
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiResetNic (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_RESET_T *PxeUndiTable,
+ IN UINT16 RxFilter
+ )
+{
+ PXENV_UNDI_OPEN_T Open;
+ PXENV_UNDI_CLOSE_T Close;
+ UINTN Status;
+
+ Status = MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_RESET_T),
+ PXENV_UNDI_RESET_NIC
+ );
+ if (!EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ Close.Status = PXENV_STATUS_SUCCESS;
+
+ Status = MakePxeCall (
+ SimpleNetworkDevice,
+ &Close,
+ sizeof (Close),
+ PXENV_UNDI_CLOSE
+ );
+ if (EFI_ERROR(Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_RESET_T),
+ PXENV_UNDI_RESET_NIC
+ );
+ if (EFI_ERROR(Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Open.Status = PXENV_STATUS_SUCCESS;
+ Open.OpenFlag = 0;
+ Open.PktFilter = RxFilter;
+ CopyMem (
+ &Open.McastBuffer,
+ &PxeUndiTable->R_Mcast_Buf,
+ sizeof (PXENV_UNDI_MCAST_ADDR_T)
+ );
+
+
+ Status = MakePxeCall (
+ SimpleNetworkDevice,
+ &Open,
+ sizeof (Open),
+ PXENV_UNDI_OPEN
+ );
+ if (EFI_ERROR(Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ PXE
+ UNDI SHUTDOWN
+ Op-Code: PXENV_UNDI_SHUTDOWN (0005h)
+ Input: Far pointer to a PXENV_UNDI_SHUTDOWN_T parameter.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call resets the network adapter and leaves it in a safe state for another driver to program it.
+ Note: The contents of the PXENV_UNDI_STARTUP parameter structure need to be saved by the
+ Universal NIC Driver in case PXENV_UNDI_INITIALIZE is called again.
+ typedef struct
+ {
+ PXENV_STATUS Status;
+ } PXENV_UNDI_SHUTDOWN_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiShutdown (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_SHUTDOWN_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_SHUTDOWN_T),
+ PXENV_UNDI_SHUTDOWN
+ );
+}
+
+/**
+ PXE
+ UNDI OPEN
+ Op-Code: PXENV_UNDI_OPEN (0006h)
+ Input: Far pointer to a PXENV_UNDI_OPEN_T parameter structure that has been initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call activates the adapter network connection and sets the adapter ready to accept packets
+ for transmit and receive.
+ typedef struct {
+ PXENV_STATUS Status;
+ UINT16 OpenFlag;
+ UINT16 PktFilter;
+ #define FLTR_DIRECTED 0x0001
+ #define FLTR_BRDCST 0x0002
+ #define FLTR_PRMSCS 0x0004
+ #define FLTR_SRC_RTG 0x0008
+ PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf;
+ } PXENV_UNDI_OPEN_T;
+ Set before calling API service
+ OpenFlag: This is an adapter specific input parameter. This is
+ supported for the universal NDIS 2.0 driver to pass in the open flags
+ provided by the protocol driver. (See the NDIS 2.0 specification.)
+ This can be zero.
+ PktFilter: Filter for receiving packets. This can be one, or more, of
+ the FLTR_xxx constants. Multiple values are arithmetically or-ed
+ together.
+ directed packets are packets that may come to your MAC address
+ or the multicast MAC address.
+ R_Mcast_Buf: See definition in UNDI RESET ADAPTER (0004h).
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiOpen (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_OPEN_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_OPEN_T),
+ PXENV_UNDI_OPEN
+ );
+}
+
+/**
+ PXE
+ UNDI CLOSE
+ Op-Code: PXENV_UNDI_CLOSE (0007h)
+ Input: Far pointer to a PXENV_UNDI_CLOSE_T parameter.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call disconnects the network adapter from the network. Packets cannot be transmitted or
+ received until the network adapter is open again.
+ typedef struct {
+ PXENV_STATUS Status;
+ } PXENV_UNDI_CLOSE_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiClose (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_CLOSE_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_CLOSE_T),
+ PXENV_UNDI_CLOSE
+ );
+}
+
+/**
+ PXE
+ UNDI TRANSMIT PACKET
+ Op-Code: PXENV_UNDI_TRANSMIT (0008h)
+ Input: Far pointer to a PXENV_UNDI_TRANSMIT_T parameter structure that
+ has been initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX.
+ The status code must be set to one of the values represented by the
+ PXENV_STATUS_xxx constants.
+ Description: This call transmits a buffer to the network. The media header
+ for the packet can be filled by the calling protocol, but it might not be.
+ The network adapter driver will fill it if required by the values in the
+ parameter block. The packet is buffered for transmission provided there is
+ an available buffer, and the function returns PXENV_EXIT_SUCCESS. If no
+ buffer is available the function returns PXENV_EXIT_FAILURE with a status
+ code of PXE_UNDI_STATUS__OUT OF_RESOURCE. The number of buffers is
+ implementation-dependent. An interrupt is generated on completion of the
+ transmission of one or more packets. A call to PXENV_UNDI_TRANSMIT is
+ permitted in the context of a transmit complete interrupt.
+
+ typedef struct {
+ PXENV_STATUS Status;
+ UINT8 Protocol;
+ #define P_UNKNOWN 0
+ #define P_IP 1
+ #define P_ARP 2
+ #define P_RARP 3
+ UINT8 XmitFlag;
+ #define XMT_DESTADDR 0x0000
+ #define XMT_BROADCAST 0x0001
+ SEGOFF16 DestAddr;
+ SEGOFF16 TBD;
+ UINT32 Reserved[2];
+ } t_PXENV_UNDI_TRANSMIT;
+
+ #define MAX_DATA_BLKS 8
+
+ typedef struct {
+ UINT16 ImmedLength;
+ SEGOFF16 Xmit;
+ UINT16 DataBlkCount;
+ struct DataBlk {
+ UINT8 TDPtrType;
+ UINT8 TDRsvdByte;
+ UINT16 TDDataLen;
+ SEGOFF16 TDDataPtr;
+ } DataBlock[MAX_DATA_BLKS];
+ } PXENV_UNDI_TBD_T
+
+ Set before calling API service
+ Protocol: This is the protocol of the upper layer that is calling UNDI
+ TRANSMIT call. If the upper layer has filled the media header, this
+ field must be P_UNKNOWN.
+ XmitFlag: If this flag is XMT_DESTADDR, the NIC driver expects a
+ pointer to the destination media address in the field DestAddr. If
+ XMT_BROADCAST, the NIC driver fills the broadcast address for the
+ destination.
+ TBD: Segment:Offset address of the transmit buffer descriptor.
+ ImmedLength: Length of the immediate transmit buffer: Xmit.
+ Xmit: Segment:Offset of the immediate transmit buffer.
+ DataBlkCount: Number of blocks in this transmit buffer.
+ TDPtrType:
+ 0 => 32-bit physical address in TDDataPtr (not supported in this
+ version of PXE)
+ 1 => segment:offset in TDDataPtr which can be a real mode or 16-bit
+ protected mode pointer
+ TDRsvdByte: Reserved must be zero.
+ TDDatalen: Data block length in bytes.
+ TDDataPtr: Segment:Offset of the transmit block.
+ DataBlock: Array of transmit data blocks.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiTransmit (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_TRANSMIT_T *PxeUndiTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_TRANSMIT_T),
+ PXENV_UNDI_TRANSMIT
+ );
+ if (Status == EFI_SUCCESS) {
+ return EFI_SUCCESS;
+ }
+
+ switch (PxeUndiTable->Status) {
+ case PXENV_STATUS_OUT_OF_RESOURCES:
+ return EFI_NOT_READY;
+
+ default:
+ return EFI_DEVICE_ERROR;
+ }
+}
+
+/**
+ PXE
+ UNDI SET MULTICAST ADDRESS
+ Op-Code: PXENV_UNDI_SET_MCAST_ADDRESS (0009h)
+ Input: Far pointer to a PXENV_TFTP_SET_MCAST_ADDRESS_t parameter structure that has been
+ initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call changes the current list of multicast addresses to the input list and resets the network
+ adapter to accept it. If the number of multicast addresses is zero, multicast is disabled.
+ typedef struct {
+ PXENV_STATUS Status;
+ PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf;
+ } PXENV_UNDI_SET_MCAST_ADDR_T;
+ Set before calling API service
+ R_Mcast_Buf: See description in the UNDI RESET ADAPTER
+ (0004h) API.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiSetMcastAddr (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_SET_MCAST_ADDR_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_SET_MCAST_ADDR_T),
+ PXENV_UNDI_SET_MCAST_ADDR
+ );
+}
+
+/**
+ PXE
+ UNDI SET STATION ADDRESS
+ Op-Code: PXENV_UNDI_SET_STATION_ADDRESS (000Ah)
+ Input: Far pointer to a PXENV_UNDI_SET_STATION_ADDRESS_t parameter structure that has been
+ initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call sets the MAC address to be the input value and is called before opening the network
+ adapter. Later, the open call uses this variable as a temporary MAC address to program the
+ adapter individual address registers.
+ typedef struct {
+ PXENV_STATUS Status;
+ MAC_ADDR StationAddress;
+ } PXENV_UNDI_SET_STATION_ADDR_T;
+ Set before calling API service
+ StationAddress: Temporary MAC address to be used for
+ transmit and receive.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiSetStationAddr (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_SET_STATION_ADDR_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_SET_STATION_ADDR_T),
+ PXENV_UNDI_SET_STATION_ADDR
+ );
+}
+
+/**
+ PXE
+ UNDI SET PACKET FILTER
+ Op-Code: PXENV_UNDI_SET_PACKET_FILTER (000Bh)
+ Input: Far pointer to a PXENV_UNDI_SET_PACKET_FILTER_T parameter structure that has been
+ initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call resets the adapter's receive unit to accept a new filter, different from the one provided with
+ the open call.
+ typedef struct {
+ PXENV_STATUS Status;
+ UINT8 filter;
+ } PXENV_UNDI_SET_PACKET_FILTER_T;
+ Set before calling API service
+ Filter: See the receive filter values in the UNDI OPEN
+ (0006h) API description.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiSetPacketFilter (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_SET_PACKET_FILTER_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_SET_PACKET_FILTER_T),
+ PXENV_UNDI_SET_PACKET_FILTER
+ );
+}
+
+/**
+ PXE
+ UNDI GET INFORMATION
+ Op-Code: PXENV_UNDI_GET_INFORMATION (000Ch)
+ Input: Far pointer to a PXENV_UNDI_GET_INFORMATION_T parameter structure that has been
+ initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the
+ PXENV_STATUS_xxx constants.
+ Description: This call copies the network adapter variables, including the MAC address, into the input buffer.
+ Note: The PermNodeAddress field must be valid after PXENV_START_UNDI and
+ PXENV_UNDI_STARTUP have been issued. All other fields must be valid after
+ PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE have been
+ called.
+ typedef struct {
+ PXENV_STATUS Status;
+ UINT16 BaseIo;
+ UINT16 IntNumber;
+ UINT16 MaxTranUnit;
+ UINT16 HwType;
+ #define ETHER_TYPE 1
+ #define EXP_ETHER_TYPE 2
+ #define IEEE_TYPE 6
+ #define ARCNET_TYPE 7
+ UINT16 HwAddrLen;
+ MAC_ADDR CurrentNodeAddress;
+ MAC_ADDR PermNodeAddress;
+ SEGSEL ROMAddress;
+ UINT16 RxBufCt;
+ UINT16 TxBufCt;
+ } PXENV_UNDI_GET_INFORMATION_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+ BaseIO: Adapter base I/O address.
+ IntNumber: Adapter IRQ number.
+ MaxTranUnit: Adapter maximum transmit unit.
+ HWType: Type of protocol at the hardware level.
+ HWAddrLen: Length of the hardware address.
+ CurrentNodeAddress: Current hardware address.
+ PermNodeAddress: Permanent hardware address.
+ ROMAddress: Real mode ROM segment address.
+ RxBufCnt: Receive queue length.
+ TxBufCnt: Transmit queue length.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiGetInformation (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_GET_INFORMATION_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_GET_INFORMATION_T),
+ PXENV_UNDI_GET_INFORMATION
+ );
+}
+
+/**
+ PXE
+ UNDI GET STATISTICS
+ Op-Code: PXENV_UNDI_GET_STATISTICS (000Dh)
+ Input: Far pointer to a PXENV_UNDI_GET_STATISTICS_T parameter structure that has been initialized
+ by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call reads statistical information from the network adapter, and returns.
+ typedef struct {
+ PXENV_STATUS Status;
+ UINT32 XmtGoodFrames;
+ UINT32 RcvGoodFrames;
+ UINT32 RcvCRCErrors;
+ UINT32 RcvResourceErrors;
+ } PXENV_UNDI_GET_STATISTICS_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+ XmtGoodFrames: Number of successful transmissions.
+ RcvGoodFrames: Number of good frames received.
+ RcvCRCErrors: Number of frames received with CRC
+ error.
+ RcvResourceErrors: Number of frames discarded
+ because receive queue was full.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiGetStatistics (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_GET_STATISTICS_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_GET_STATISTICS_T),
+ PXENV_UNDI_GET_STATISTICS
+ );
+}
+
+/**
+ PXE
+ UNDI CLEAR STATISTICS
+ Op-Code: PXENV_UNDI_CLEAR_STATISTICS (000Eh)
+ Input: Far pointer to a PXENV_UNDI_CLEAR_STATISTICS_T parameter.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the
+ PXENV_STATUS_xxx constants.
+ Description: This call clears the statistical information from the network adapter.
+ typedef struct {
+ PXENV_STATUS Status;
+ } PXENV_UNDI_CLEAR_STATISTICS_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiClearStatistics (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_CLEAR_STATISTICS_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_CLEAR_STATISTICS_T),
+ PXENV_UNDI_CLEAR_STATISTICS
+ );
+}
+
+/**
+ PXE
+ UNDI INITIATE DIAGS
+ Op-Code: PXENV_UNDI_INITIATE_DIAGS (000Fh)
+ Input: Far pointer to a PXENV_UNDI_INITIATE_DIAGS_T parameter.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the
+ PXENV_STATUS_xxx constants.
+ Description: This call can be used to initiate the run-time diagnostics. It causes the network adapter to run
+ hardware diagnostics and to update its status information.
+ typedef struct {
+ PXENV_STATUS Status;
+ } PXENV_UNDI_INITIATE_DIAGS_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiInitiateDiags (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_INITIATE_DIAGS_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_INITIATE_DIAGS_T),
+ PXENV_UNDI_INITIATE_DIAGS
+ );
+}
+
+/**
+ PXE
+ UNDI FORCE INTERRUPT
+ Op-Code: PXENV_UNDI_FORCE_INTERRUPT (0010h)
+ Input: Far pointer to a PXENV_UNDI_FORCE_INTERRUPT_T parameter structure that has been
+ initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call forces the network adapter to generate an interrupt. When a receive interrupt occurs, the
+ network adapter driver usually queues the packet and calls the application's callback receive
+ routine with a pointer to the packet received. Then, the callback routine either can copy the packet
+ to its buffer or can decide to delay the copy to a later time. If the packet is not immediately copied,
+ the network adapter driver does not remove it from the input queue. When the application wants to
+ copy the packet, it can call the PXENV_UNDI_FORCE_INTERRUPT routine to simulate the receive
+ interrupt.
+ typedef struct {
+ PXENV_STATUS Status;
+ } PXENV_UNDI_FORCE_INTERRUPT_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiForceInterrupt (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_FORCE_INTERRUPT_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_FORCE_INTERRUPT_T),
+ PXENV_UNDI_FORCE_INTERRUPT
+ );
+}
+
+/**
+ PXE
+ UNDI GET MULTICAST ADDRESS
+ Op-Code: PXENV_UNDI_GET_MCAST_ADDRESS (0011h)
+ Input: Far pointer to a PXENV_GET_MCAST_ADDRESS_t parameter structure that has been initialized
+ by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call converts the given IP multicast address to a hardware multicast address.
+ typedef struct {
+ PXENV_STATUS Status;
+ IP4 InetAddr;
+ MAC_ADDR MediaAddr;
+ } PXENV_UNDI_GET_MCAST_ADDR_T;
+ Set before calling API service
+ InetAddr: IP multicast address.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+ MediaAddr: MAC multicast address.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiGetMcastAddr (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_GET_MCAST_ADDR_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_GET_MCAST_ADDR_T),
+ PXENV_UNDI_GET_MCAST_ADDR
+ );
+}
+
+/**
+ PXE
+ UNDI GET NIC TYPE
+ Op-Code: PXENV_UNDI_GET_NIC_TYPE (0012h)
+ Input: Far pointer to a PXENV_UNDI_GET_NIC_TYPE parameter structure that has been initialized by
+ the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants. If the PXENV_EXIT_SUCCESS is returned the parameter structure must contain the
+ NIC information.
+ Description: This call, if successful, provides the NIC-specific information necessary to identify the network
+ adapter that is used to boot the system.
+ Note: The application first gets the DHCPDISCOVER packet using GET_CACHED_INFO and checks if
+ the UNDI is supported before making this call. If the UNDI is not supported, the NIC-specific
+ information can be obtained from the DHCPDISCOVER packet itself.
+ PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE must be called
+ before the information provided is valid.
+ typedef {
+ PXENV_STATUS Status;
+ UINT8 NicType;
+ #define PCI_NIC 2
+ #define PnP_NIC 3
+ #define CardBus_NIC 4
+ Union {
+ Struct {
+ UINT16 Vendor_ID;
+ UINT16 Dev_ID;
+ UINT8 Base_Class;
+ UINT8 Sub_Class;
+ UINT8 Prog_Intf;
+ UINT8 Rev;
+ UINT16 BusDevFunc;
+ UINT16 SubVendor_ID;
+ UINT16 SubDevice_ID;
+ } pci, cardbus;
+ struct {
+ UINT32 EISA_Dev_ID;
+ UINT8 Base_Class;
+ UINT8 Sub_Class;
+ UINT8 Prog_Intf;
+ UINT16 CardSelNum;
+ } pnp;
+ } info;
+ } PXENV_UNDI_GET_NIC_TYPE_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+ NICType: Type of NIC information stored in the parameter
+ structure.
+ Info: Information about the fields in this union can be found
+ in the [PnP] and [PCI] specifications
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiGetNicType (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_GET_NIC_TYPE_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_GET_NIC_TYPE_T),
+ PXENV_UNDI_GET_NIC_TYPE
+ );
+}
+
+/**
+ PXE
+ UNDI GET IFACE INFO
+ Op-Code: PXENV_UNDI_GET_IFACE_INFO (0013h)
+ Input: Far pointer to a PXENV_UNDI_GET_IFACE_INFO_t parameter structure that has been initialized
+ by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants. If the PXENV_EXIT_SUCCESS is returned, the parameter structure must contain the
+ interface specific information.
+ Description: This call, if successful, provides the network interface specific information such as the interface
+ type at the link layer (Ethernet, Tokenring) and the link speed. This information can be used in the
+ universal drivers such as NDIS or Miniport to communicate to the upper protocol modules.
+ Note: UNDI follows the NDIS2 specification in giving this information. It is the responsibility of the
+ universal driver to translate/convert this information into a format that is required in its specification
+ or to suit the expectation of the upper level protocol modules.
+ PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE must be called
+ before the information provided is valid.
+ typedef struct {
+ PXENV_STATUS Status
+ UINT8 IfaceType[16];
+ UINT32 LinkSpeed;
+ UINT32 ServiceFlags;
+ UINT32 Reserved[4];
+ } PXENV_UNDI_GET_NDIS_INFO_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+ IfaceType: Name of MAC type in ASCIIZ format. This is
+ used by the universal NDIS driver to specify its driver type
+ to the protocol driver.
+ LinkSpeed: Defined in the NDIS 2.0 specification.
+ ServiceFlags: Defined in the NDIS 2.0 specification.
+ Reserved: Must be zero.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiGetNdisInfo (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_GET_NDIS_INFO_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_GET_NDIS_INFO_T),
+ PXENV_UNDI_GET_NDIS_INFO
+ );
+}
+
+/**
+ PXE
+ UNDI ISR
+ Op-Code: PXENV_UNDI_ISR (0014h)
+ Input: Far pointer to a PXENV_UNDI_ISR_T parameter structure that has been initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This API function will be called at different levels of processing the interrupt. The FuncFlag field in
+ the parameter block indicates the operation to be performed for the call. This field is filled with the
+ status of that operation on return.
+ Note: Interrupt Service Routine Operation:
+ In this design the UNDI does not hook the interrupt for the Network Interface. Instead, the
+ application or the protocol driver hooks the interrupt and calls UNDI with the PXENV_UNDI_ISR
+ API call for interrupt verification (PXENV_UNDI_ISR_IN_START) and processing
+ (PXENV_UNDI_ISR_IN_PROCESS and PXENV_UNDI_ISR_GET_NEXT).
+ When the Network Interface HW generates an interrupt the protocol driver interrupt service
+ routine (ISR) gets control and takes care of the interrupt processing at the PIC level. The ISR then
+ calls the UNDI using the PXENV_UNDI_ISR API with the value PXENV_UNDI_ISR_IN_START for
+ the FuncFlag parameter. At this time UNDI must disable the interrupts at the Network Interface
+ level and read any status values required to further process the interrupt. UNDI must return as
+ quickly as possible with one of the two values, PXENV_UNDI_ISR_OUT_OURS or
+ PXENV_UNDI_ISR_OUT_NOT_OURS, for the parameter FuncFlag depending on whether the
+ interrupt was generated by this particular Network Interface or not.
+ If the value returned in FuncFlag is PXENV_UNDI_ISR_OUT_NOT_OURS, then the interrupt was
+ not generated by our NIC, and interrupt processing is complete.
+ If the value returned in FuncFlag is PXENV_UNDI_ISR_OUT_OURS, the protocol driver must start
+ a handler thread and send an end-of-interrupt (EOI) command to the PIC. Interrupt processing is
+ now complete.
+ The protocol driver strategy routine will call UNDI using this same API with FuncFlag equal to
+ PXENV_UNDI_ISR_IN_PROCESS. At this time UNDI must find the cause of this interrupt and
+ return the status in the FuncFlag. It first checks if there is a frame received and if so it returns the
+ first buffer pointer of that frame in the parameter block.
+ The protocol driver calls UNDI repeatedly with the FuncFlag equal to
+ PXENV_UNDI_ISR_IN_GET_NEXT to get all the buffers in a frame and also all the received
+ frames in the queue. On this call, UNDI must remember the previous buffer given to the protoco,l
+ remove it from the receive queue and recycle it. In case of a multi-buffered frame, if the previous
+ buffer is not the last buffer in the frame it must return the next buffer in the frame in the parameter
+ block. Otherwise it must return the first buffer in the next frame.
+ If there is no received frame pending to be processed, UNDI processes the transmit completes and
+ if there is no other interrupt status to be processed, UNDI re-enables the interrupt at the
+ NETWORK INTERFACE level and returns PXENV_UNDI_ISR_OUT_DONE in the FuncFlag.
+ IMPORTANT: It is possible for the protocol driver to be interrupted again while in the
+ strategy routine when the UNDI re-enables interrupts.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiIsr (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_ISR_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_ISR_T),
+ PXENV_UNDI_ISR
+ );
+}
+
+/**
+ PXE
+ STOP UNDI
+ Op-Code: PXENV_STOP_UNDI (0015h)
+ Input: Far pointer to a PXENV_STOP_UNDI_T parameter structure that has been initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This routine is responsible for unhooking the Int 1Ah service routine.
+ Note: This API service must be called only once at the end of UNDI Option ROM boot. One of the valid
+ status codes is PXENV_STATUS_KEEP. If this status is returned, UNDI must not be removed from
+ base memory. Also, UNDI must not be removed from base memory if BC is not removed from base
+ memory.
+ Service cannot be used in protected mode.
+ typedef struct {
+ PXENV_STATUS Status;
+ } PXENV_STOP_UNDI_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiStop (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_STOP_UNDI_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_STOP_UNDI_T),
+ PXENV_STOP_UNDI
+ );
+}
+
+/**
+ PXE
+ UNDI GET STATE
+ Op-Code: PXENV_UNDI_GET_STATE (0015h)
+ Input: Far pointer to a PXENV_UNDI_GET_STATE_T parameter.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants. The UNDI_STATE field in the parameter structure must be set to one of the valid state
+ constants
+ Description: This call can be used to obtain state of the UNDI engine in order to avoid issuing adverse call
+ sequences
+ typedef struct {
+ #define PXE_UNDI_GET_STATE_STARTED 1
+ #define PXE_UNDI_GET_STATE_INITIALIZED 2
+ #define PXE_UNDI_GET_STATE_OPENED 3
+ PXENV_STATUS Status;
+ UINT8 UNDIstate;
+ } PXENV_UNDI_GET_STATE_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+ State: See definitions of the state constants.
+ Note. UNDI implementation is responsible for maintaining
+ internal state machine.
+ UNDI ISR
+ Op-Code: PXENV_UNDI_ISR (0014h)
+ Input: Far pointer to a t_PXENV_UNDI_ISR parameter structure that has been initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This API function will be called at different levels of processing the interrupt. The FuncFlag field in
+ the parameter block indicates the operation to be performed for the call. This field is filled with the
+ status of that operation on return.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiGetState (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_GET_STATE_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_GET_STATE_T),
+ PXENV_UNDI_GET_STATE
+ );
+}
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf
new file mode 100644
index 0000000000..c37c4abb86
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf
@@ -0,0 +1,67 @@
+## @file
+# Thunk wrapper UEFI driver to produce EFI SNP protocol based on legacy 16 NIC ROM.
+#
+# Copyright (c) 1999 - 2010, 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.
+#
+##
+
+[Defines]
+ BASE_NAME = BiosSnp16
+ FILE_GUID = D0CAA91E-2DE4-4b0d-B3DC-09C67E854E34
+ MODULE_TYPE = UEFI_DRIVER
+ INF_VERSION = 0x00010005
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = BiosSnp16DriverEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+# DRIVER_BINDING = gBiosSnp16DriverBinding
+# COMPONENT_NAME = gBiosSnp16ComponentName
+#
+
+[Sources]
+ BiosSnp16.h
+ BiosSnp16.c
+ Misc.c
+ Pxe.h
+ PxeUndi.c
+ ComponentName.c
+
+
+[Libraryclasses]
+ UefiDriverEntryPoint
+ DebugLib
+ BaseMemoryLib
+ UefiBootServicesTableLib
+ UefiLib
+ BaseLib
+ DevicePathLib
+ MemoryAllocationLib
+
+[Guids]
+ gEfiEventExitBootServicesGuid
+
+[Protocols]
+ gEfiNetworkInterfaceIdentifierProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gEfiSimpleNetworkProtocolGuid
+ gEfiPciIoProtocolGuid
+ gEfiLegacyBiosProtocolGuid
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+