From bcecde140a561c64e297225904afebebd62336ce Mon Sep 17 00:00:00 2001 From: jljusten Date: Mon, 27 Jun 2011 23:32:56 +0000 Subject: 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 --- .../Csm/BiosThunk/Snp16Dxe/BiosSnp16.c | 3507 ++++++++++++++++++++ .../Csm/BiosThunk/Snp16Dxe/BiosSnp16.h | 1655 +++++++++ .../Csm/BiosThunk/Snp16Dxe/ComponentName.c | 309 ++ .../Csm/BiosThunk/Snp16Dxe/Misc.c | 956 ++++++ .../Csm/BiosThunk/Snp16Dxe/Pxe.h | 613 ++++ .../Csm/BiosThunk/Snp16Dxe/PxeUndi.c | 1254 +++++++ .../Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf | 67 + 7 files changed, 8361 insertions(+) create mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.c create mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.h create mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/ComponentName.c create mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Misc.c create mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Pxe.h create mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/PxeUndi.c create mode 100644 IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf (limited to 'IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe') 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.
+ +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.
+ +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 + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#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.
+ +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.
+ +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.
+ +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.
+ +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.
+# +# 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 + -- cgit v1.2.3