/** @file | |
Copyright (c) 2006 - 2007, 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. | |
Module Name: | |
SnpNt32.c | |
Abstract: | |
-**/ | |
#include "SnpNt32.h" | |
EFI_DRIVER_BINDING_PROTOCOL gSnpNt32DriverBinding = { | |
SnpNt32DriverBindingSupported, | |
SnpNt32DriverBindingStart, | |
SnpNt32DriverBindingStop, | |
0xa, | |
NULL, | |
NULL | |
}; | |
SNPNT32_GLOBAL_DATA gSnpNt32GlobalData = { | |
SNP_NT32_DRIVER_SIGNATURE, // Signature | |
{ | |
NULL, | |
NULL | |
}, // InstanceList | |
NULL, // WinNtThunk | |
NULL, // NetworkLibraryHandle | |
{ | |
0 | |
}, // NtNetUtilityTable | |
{ | |
0, | |
0, | |
0 | |
}, // Lock | |
// | |
// Private functions | |
// | |
SnpNt32InitializeGlobalData, // InitializeGlobalData | |
SnpNt32InitializeInstanceData, // InitializeInstanceData | |
SnpNt32CloseInstance // CloseInstance | |
}; | |
/** | |
Test to see if this driver supports ControllerHandle. | |
@param This Protocol instance pointer. | |
@param ControllerHandle Handle of device to test. | |
@param RemainingDevicePath Optional parameter use to pick a specific child | |
device to start. | |
@retval EFI_SUCCES This driver supports this device. | |
@retval other This driver does not support this device. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
SnpNt32DriverBindingSupported ( | |
IN EFI_DRIVER_BINDING_PROTOCOL * This, | |
IN EFI_HANDLE ControllerHandle, | |
IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL | |
) | |
{ | |
SNPNT32_GLOBAL_DATA *GlobalData; | |
LIST_ENTRY *Entry; | |
SNPNT32_INSTANCE_DATA *Instance; | |
GlobalData = &gSnpNt32GlobalData; | |
NET_LIST_FOR_EACH (Entry, &GlobalData->InstanceList) { | |
Instance = NET_LIST_USER_STRUCT_S (Entry, SNPNT32_INSTANCE_DATA, Entry, SNP_NT32_INSTANCE_SIGNATURE); | |
if (Instance->DeviceHandle == ControllerHandle) { | |
return EFI_SUCCESS; | |
} | |
} | |
return EFI_UNSUPPORTED; | |
} | |
/** | |
Start this driver on ControllerHandle. | |
@param This Protocol instance pointer. | |
@param ControllerHandle Handle of device to bind driver to. | |
@param RemainingDevicePath Optional parameter use to pick a specific child | |
device to start. | |
@retval EFI_SUCCES This driver is added to ControllerHandle. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
SnpNt32DriverBindingStart ( | |
IN EFI_DRIVER_BINDING_PROTOCOL * This, | |
IN EFI_HANDLE ControllerHandle, | |
IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL | |
) | |
{ | |
return EFI_SUCCESS; | |
} | |
/** | |
Stop this driver on ControllerHandle. | |
@param This Protocol instance pointer. | |
@param ControllerHandle Handle of device to stop driver on. | |
@param NumberOfChildren Number of Handles in ChildHandleBuffer. If number | |
of children is zero stop the entire bus driver. | |
@param ChildHandleBuffer List of Child Handles to Stop. | |
@retval EFI_SUCCES This driver is removed ControllerHandle. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
SnpNt32DriverBindingStop ( | |
IN EFI_DRIVER_BINDING_PROTOCOL *This, | |
IN EFI_HANDLE ControllerHandle, | |
IN UINTN NumberOfChildren, | |
IN EFI_HANDLE *ChildHandleBuffer | |
) | |
{ | |
return EFI_SUCCESS; | |
} | |
/** | |
Start the SnpNt32 interface. | |
@param This Context pointer. | |
@retval EFI_SUCCESS The interface is started. | |
**/ | |
EFI_STATUS | |
SnpNt32Start ( | |
IN EFI_SIMPLE_NETWORK_PROTOCOL *This | |
) | |
{ | |
return EFI_SUCCESS; | |
} | |
/** | |
Stop the SnpNt32 interface. | |
@param This Context pointer. | |
@retval EFI_SUCCESS The interface is stopped. | |
**/ | |
EFI_STATUS | |
SnpNt32Stop ( | |
IN EFI_SIMPLE_NETWORK_PROTOCOL *This | |
) | |
{ | |
return EFI_SUCCESS; | |
} | |
/** | |
Initialize the SnpNt32 interface. | |
@param This Context pointer. | |
@param ExtraRxBufferSize Number of extra receive buffer. | |
@param ExtraTxBufferSize Number of extra transmit buffer. | |
@retval EFI_SUCCESS The interface is initialized. | |
**/ | |
EFI_STATUS | |
SnpNt32Initialize ( | |
IN EFI_SIMPLE_NETWORK_PROTOCOL *This, | |
IN UINTN ExtraRxBufferSize OPTIONAL, | |
IN UINTN ExtraTxBufferSize OPTIONAL | |
) | |
{ | |
return EFI_SUCCESS; | |
} | |
/** | |
Reset the snpnt32 interface. | |
@param This Context pointer. | |
@param ExtendedVerification Not implemented. | |
@retval EFI_SUCCESS The interface is reseted. | |
**/ | |
EFI_STATUS | |
SnpNt32Reset ( | |
IN EFI_SIMPLE_NETWORK_PROTOCOL *This, | |
IN BOOLEAN ExtendedVerification | |
) | |
{ | |
return EFI_SUCCESS; | |
} | |
/** | |
Shut down the snpnt32 interface. | |
@param This Context pointer. | |
@retval EFI_SUCCESS The interface is shut down. | |
**/ | |
EFI_STATUS | |
SnpNt32Shutdown ( | |
IN EFI_SIMPLE_NETWORK_PROTOCOL *This | |
) | |
{ | |
return EFI_SUCCESS; | |
} | |
/** | |
Change the interface's receive filter setting. | |
@param This Context pointer. | |
@param EnableBits The receive filters to enable. | |
@param DisableBits The receive filters to disable | |
@param ResetMcastFilter Reset the multicast filters or not. | |
@param McastFilterCount The count of multicast filter to set. | |
@param McastFilter Pointer to the arrya of multicast addresses to set. | |
@retval EFI_SUCCESS The receive filter is updated. | |
@retval EFI_ACCESS_DENIED The snpnt32 lock is already owned by another | |
routine. | |
@retval EFI_DEVICE_ERROR Failed to update the receive filter. | |
**/ | |
EFI_STATUS | |
SnpNt32ReceiveFilters ( | |
IN EFI_SIMPLE_NETWORK_PROTOCOL *This, | |
IN UINT32 EnableBits, | |
IN UINT32 DisableBits, | |
IN BOOLEAN ResetMcastFilter, | |
IN UINTN McastFilterCount OPTIONAL, | |
IN EFI_MAC_ADDRESS *McastFilter OPTIONAL | |
) | |
{ | |
SNPNT32_INSTANCE_DATA *Instance; | |
SNPNT32_GLOBAL_DATA *GlobalData; | |
INT32 ReturnValue; | |
Instance = SNP_NT32_INSTANCE_DATA_FROM_SNP_THIS (This); | |
GlobalData = Instance->GlobalData; | |
if (EFI_ERROR (EfiAcquireLockOrFail (&GlobalData->Lock))) { | |
return EFI_ACCESS_DENIED; | |
} | |
ReturnValue = GlobalData->NtNetUtilityTable.SetReceiveFilter ( | |
Instance->InterfaceInfo.InterfaceIndex, | |
EnableBits, | |
McastFilterCount, | |
McastFilter | |
); | |
EfiReleaseLock (&GlobalData->Lock); | |
if (ReturnValue <= 0) { | |
return EFI_DEVICE_ERROR; | |
} | |
return EFI_SUCCESS; | |
} | |
/** | |
Change or reset the mac address of the interface. | |
@param This Context pointer. | |
@param reset Reset the mac address to the original one or not. | |
@param NewMacAddr Pointer to the new mac address to set. | |
@retval EFI_UNSUPPORTED Not supported yet. | |
**/ | |
EFI_STATUS | |
SnpNt32StationAddress ( | |
IN EFI_SIMPLE_NETWORK_PROTOCOL *This, | |
IN BOOLEAN Reset, | |
IN EFI_MAC_ADDRESS *NewMacAddr OPTIONAL | |
) | |
{ | |
return EFI_UNSUPPORTED; | |
} | |
/** | |
Get or reset the statistics data. | |
@param This Context pointer. | |
@param Reset Reset the statistics or not. | |
@param StatisticsSize The size of the buffer used to receive the | |
statistics data. | |
@param StatisticsTable Pointer to the table used to receive the statistics | |
data. | |
@retval EFI_UNSUPPORTED Not supported yet. | |
**/ | |
EFI_STATUS | |
SnpNt32Statistics ( | |
IN EFI_SIMPLE_NETWORK_PROTOCOL * This, | |
IN BOOLEAN Reset, | |
IN OUT UINTN *StatisticsSize OPTIONAL, | |
IN OUT EFI_NETWORK_STATISTICS *StatisticsTable OPTIONAL | |
) | |
{ | |
return EFI_UNSUPPORTED; | |
} | |
/** | |
Convert a multicast ip address to the multicast mac address. | |
@param This Context pointer. | |
@param Ipv6 The Ip is an Ipv6 address or not. | |
@param Ip Pointer to the Ip address to convert. | |
@param Mac Pointer to the buffer used to hold the converted | |
mac address. | |
@retval EFI_UNSUPPORTED Not supported yet. | |
**/ | |
EFI_STATUS | |
SnpNt32McastIptoMac ( | |
IN EFI_SIMPLE_NETWORK_PROTOCOL *This, | |
IN BOOLEAN Ipv6, | |
IN EFI_IP_ADDRESS *Ip, | |
OUT EFI_MAC_ADDRESS *Mac | |
) | |
{ | |
return EFI_UNSUPPORTED; | |
} | |
/** | |
Read or write the nv data. | |
@param This Context pinter. | |
@param ReadOrWrite Read or write the nv data. | |
@param Offset The offset to the start of the nv data. | |
@param BufferSize Size of the buffer. | |
@param Buffer Pointer to the buffer containing the data to write | |
or used to receive the data read. | |
@retval EFI_UNSUPPORTED Not supported yet. | |
**/ | |
EFI_STATUS | |
SnpNt32Nvdata ( | |
IN EFI_SIMPLE_NETWORK_PROTOCOL *This, | |
IN BOOLEAN ReadOrWrite, | |
IN UINTN Offset, | |
IN UINTN BufferSize, | |
IN OUT VOID *Buffer | |
) | |
{ | |
return EFI_UNSUPPORTED; | |
} | |
/** | |
Get the status information of the interface. | |
@param This Context pointer. | |
@param InterruptStatus The storage to hold the interrupt status. | |
@param TxBuffer Pointer to get the list of pointers of previously | |
transmitted buffers whose transmission was | |
completed asynchrnously. | |
@retval EFI_SUCCESS The status is got. | |
**/ | |
EFI_STATUS | |
SnpNt32GetStatus ( | |
IN EFI_SIMPLE_NETWORK_PROTOCOL *This, | |
OUT UINT32 *InterruptStatus, | |
OUT VOID **TxBuffer | |
) | |
{ | |
if (TxBuffer != NULL) { | |
*((UINT8 **) TxBuffer) = (UINT8 *) 1; | |
} | |
if (InterruptStatus != NULL) { | |
*InterruptStatus = EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT; | |
} | |
return EFI_SUCCESS; | |
} | |
/** | |
Transmit a packet. | |
@param This Context pointer. | |
@param HeaderSize The media header size contained in the packet | |
buffer. | |
@param BufferSize The size of the packet buffer. | |
@param Buffer Pointer to the buffer containing the packet data. | |
@param SrcAddr If non null, points to the source address of this | |
packet. | |
@param DestAddr If non null, points to the destination address of | |
this packet. | |
@param Protocol The protocol type of this packet. | |
@retval EFI_SUCCESS The packet is transmitted or put into the transmit | |
queue. | |
@retval other Some error occurs. | |
**/ | |
EFI_STATUS | |
SnpNt32Transmit ( | |
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 | |
) | |
{ | |
SNPNT32_INSTANCE_DATA *Instance; | |
SNPNT32_GLOBAL_DATA *GlobalData; | |
INT32 ReturnValue; | |
Instance = SNP_NT32_INSTANCE_DATA_FROM_SNP_THIS (This); | |
GlobalData = Instance->GlobalData; | |
if ((HeaderSize != 0) && (SrcAddr == NULL)) { | |
SrcAddr = &Instance->Mode.CurrentAddress; | |
} | |
if (EFI_ERROR (EfiAcquireLockOrFail (&GlobalData->Lock))) { | |
return EFI_ACCESS_DENIED; | |
} | |
ReturnValue = GlobalData->NtNetUtilityTable.Transmit ( | |
Instance->InterfaceInfo.InterfaceIndex, | |
HeaderSize, | |
BufferSize, | |
Buffer, | |
SrcAddr, | |
DestAddr, | |
Protocol | |
); | |
EfiReleaseLock (&GlobalData->Lock); | |
if (ReturnValue < 0) { | |
return EFI_DEVICE_ERROR; | |
} | |
return EFI_SUCCESS; | |
} | |
/** | |
Receive network data. | |
@param This Context pointer. | |
@param HeaderSize Optional parameter and is a pointer to the header | |
portion of the data received. | |
@param BuffSize Pointer to the length of the Buffer on entry and | |
contains the length of the received data on return | |
@param Buffer Pointer to the memory for the received data | |
@param SourceAddr Optional parameter, is a pointer to contain the | |
source ethernet address on return | |
@param DestinationAddr Optional parameter, is a pointer to contain the | |
destination ethernet address on return. | |
@param Protocol Optional parameter, is a pointer to contain the | |
Protocol type from the ethernet header on return. | |
@retval EFI_SUCCESS A packet is received and put into the buffer. | |
@retval EFI_BUFFER_TOO_SMALL The provided buffer is too small to receive the | |
packet. | |
@retval EFI_NOT_READY There is no packet received. | |
**/ | |
EFI_STATUS | |
SnpNt32Receive ( | |
IN EFI_SIMPLE_NETWORK_PROTOCOL *This, | |
OUT UINTN *HeaderSize, | |
IN OUT UINTN *BuffSize, | |
OUT VOID *Buffer, | |
OUT EFI_MAC_ADDRESS *SourceAddr, | |
OUT EFI_MAC_ADDRESS *DestinationAddr, | |
OUT UINT16 *Protocol | |
) | |
{ | |
SNPNT32_INSTANCE_DATA *Instance; | |
SNPNT32_GLOBAL_DATA *GlobalData; | |
INT32 ReturnValue; | |
Instance = SNP_NT32_INSTANCE_DATA_FROM_SNP_THIS (This); | |
GlobalData = Instance->GlobalData; | |
ASSERT (GlobalData->NtNetUtilityTable.Receive != NULL); | |
if (EFI_ERROR (EfiAcquireLockOrFail (&GlobalData->Lock))) { | |
return EFI_ACCESS_DENIED; | |
} | |
ReturnValue = GlobalData->NtNetUtilityTable.Receive ( | |
Instance->InterfaceInfo.InterfaceIndex, | |
BuffSize, | |
Buffer | |
); | |
EfiReleaseLock (&GlobalData->Lock); | |
if (ReturnValue < 0) { | |
if (ReturnValue == -100) { | |
return EFI_BUFFER_TOO_SMALL; | |
} | |
return EFI_DEVICE_ERROR; | |
} else if (ReturnValue == 0) { | |
return EFI_NOT_READY; | |
} | |
if (HeaderSize != NULL) { | |
*HeaderSize = 14; | |
} | |
if (SourceAddr != NULL) { | |
ZeroMem (SourceAddr, sizeof (EFI_MAC_ADDRESS)); | |
CopyMem (SourceAddr, ((UINT8 *) Buffer) + 6, 6); | |
} | |
if (DestinationAddr != NULL) { | |
ZeroMem (DestinationAddr, sizeof (EFI_MAC_ADDRESS)); | |
CopyMem (DestinationAddr, ((UINT8 *) Buffer), 6); | |
} | |
if (Protocol != NULL) { | |
*Protocol = NTOHS (*((UINT16 *) (((UINT8 *) Buffer) + 12))); | |
} | |
return EFI_SUCCESS; | |
} | |
SNPNT32_INSTANCE_DATA gSnpNt32InstanceTemplate = { | |
SNP_NT32_INSTANCE_SIGNATURE, // Signature | |
{ | |
NULL, | |
NULL | |
}, // Entry | |
NULL, // GlobalData | |
NULL, // DeviceHandle | |
NULL, // DevicePath | |
{ // Snp | |
EFI_SIMPLE_NETWORK_PROTOCOL_REVISION, // Revision | |
SnpNt32Start, // Start | |
SnpNt32Stop, // Stop | |
SnpNt32Initialize, // Initialize | |
SnpNt32Reset, // Reset | |
SnpNt32Shutdown, // Shutdown | |
SnpNt32ReceiveFilters, // ReceiveFilters | |
SnpNt32StationAddress, // StationAddress | |
SnpNt32Statistics, // Statistics | |
SnpNt32McastIptoMac, // MCastIpToMac | |
SnpNt32Nvdata, // NvData | |
SnpNt32GetStatus, // GetStatus | |
SnpNt32Transmit, // Transmit | |
SnpNt32Receive, // Receive | |
NULL, // WaitForPacket | |
NULL // Mode | |
}, | |
{ // Mode | |
EfiSimpleNetworkInitialized, // State | |
NET_ETHER_ADDR_LEN, // HwAddressSize | |
NET_ETHER_HEADER_SIZE, // MediaHeaderSize | |
1500, // MaxPacketSize | |
0, // NvRamSize | |
0, // NvRamAccessSize | |
0, // ReceiveFilterMask | |
0, // ReceiveFilterSetting | |
MAX_MCAST_FILTER_CNT, // MaxMCastFilterCount | |
0, // MCastFilterCount | |
{ | |
0 | |
}, // MCastFilter | |
{ | |
0 | |
}, // CurrentAddress | |
{ | |
0 | |
}, // BroadcastAddress | |
{ | |
0 | |
}, // PermanentAddress | |
NET_IFTYPE_ETHERNET, // IfType | |
FALSE, // MacAddressChangeable | |
FALSE, // MultipleTxSupported | |
FALSE, // MediaPresentSupported | |
TRUE // MediaPresent | |
}, | |
{ | |
0 | |
} // InterfaceInfo | |
}; | |
/** | |
Initialize the driver's global data. | |
@param This Pointer to the global context data. | |
@retval EFI_SUCCESS The global data is initialized. | |
@retval EFI_NOT_FOUND The required DLL is not found. | |
**/ | |
EFI_STATUS | |
SnpNt32InitializeGlobalData ( | |
IN SNPNT32_GLOBAL_DATA *This | |
) | |
{ | |
EFI_STATUS Status; | |
CHAR16 *DllFileNameU; | |
UINT32 Index; | |
INT32 ReturnValue; | |
BOOLEAN NetUtilityLibInitDone; | |
NT_NET_INTERFACE_INFO NetInterfaceInfoBuffer[MAX_INTERFACE_INFO_NUMBER]; | |
SNPNT32_INSTANCE_DATA *Instance; | |
LIST_ENTRY *Entry; | |
UINT32 InterfaceCount; | |
ASSERT (This != NULL); | |
NetUtilityLibInitDone = FALSE; | |
InterfaceCount = MAX_INTERFACE_INFO_NUMBER; | |
InitializeListHead (&This->InstanceList); | |
EfiInitializeLock (&This->Lock, TPL_CALLBACK); | |
// | |
// Get the WinNT thunk | |
// | |
Status = gBS->LocateProtocol (&gEfiWinNtThunkProtocolGuid, NULL, &This->WinNtThunk); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
ASSERT (This->WinNtThunk != NULL); | |
DllFileNameU = NETWORK_LIBRARY_NAME_U; | |
// | |
// Load network utility library | |
// | |
This->NetworkLibraryHandle = This->WinNtThunk->LoadLibraryEx (DllFileNameU, NULL, 0); | |
if (NULL == This->NetworkLibraryHandle) { | |
return EFI_NOT_FOUND; | |
} | |
This->NtNetUtilityTable.Initialize = (NT_NET_INITIALIZE) This->WinNtThunk->GetProcAddress ( | |
This->NetworkLibraryHandle, | |
NETWORK_LIBRARY_INITIALIZE | |
); | |
if (NULL == This->NtNetUtilityTable.Initialize) { | |
Status = EFI_NOT_FOUND; | |
goto ErrorReturn; | |
} | |
This->NtNetUtilityTable.Finalize = (NT_NET_FINALIZE) This->WinNtThunk->GetProcAddress ( | |
This->NetworkLibraryHandle, | |
NETWORK_LIBRARY_FINALIZE | |
); | |
if (NULL == This->NtNetUtilityTable.Finalize) { | |
Status = EFI_NOT_FOUND; | |
goto ErrorReturn; | |
} | |
This->NtNetUtilityTable.SetReceiveFilter = (NT_NET_SET_RECEIVE_FILTER) This->WinNtThunk->GetProcAddress ( | |
This->NetworkLibraryHandle, | |
NETWORK_LIBRARY_SET_RCV_FILTER | |
); | |
if (NULL == This->NtNetUtilityTable.SetReceiveFilter) { | |
Status = EFI_NOT_FOUND; | |
goto ErrorReturn; | |
} | |
This->NtNetUtilityTable.Receive = (NT_NET_RECEIVE) This->WinNtThunk->GetProcAddress ( | |
This->NetworkLibraryHandle, | |
NETWORK_LIBRARY_RECEIVE | |
); | |
if (NULL == This->NtNetUtilityTable.Receive) { | |
Status = EFI_NOT_FOUND; | |
goto ErrorReturn; | |
} | |
This->NtNetUtilityTable.Transmit = (NT_NET_TRANSMIT) This->WinNtThunk->GetProcAddress ( | |
This->NetworkLibraryHandle, | |
NETWORK_LIBRARY_TRANSMIT | |
); | |
if (NULL == This->NtNetUtilityTable.Transmit) { | |
Status = EFI_NOT_FOUND; | |
goto ErrorReturn; | |
} | |
// | |
// Initialize the network utility library | |
// And enumerate the interfaces in NT32 host | |
// | |
ReturnValue = This->NtNetUtilityTable.Initialize (&InterfaceCount, &NetInterfaceInfoBuffer[0]); | |
if (ReturnValue <= 0) { | |
Status = EFI_DEVICE_ERROR; | |
goto ErrorReturn; | |
} | |
NetUtilityLibInitDone = TRUE; | |
if (InterfaceCount == 0) { | |
Status = EFI_NOT_FOUND; | |
goto ErrorReturn; | |
} | |
// | |
// Create fake SNP instances | |
// | |
for (Index = 0; Index < InterfaceCount; Index++) { | |
Instance = AllocatePool (sizeof (SNPNT32_INSTANCE_DATA)); | |
if (NULL == Instance) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto ErrorReturn; | |
} | |
// | |
// Copy the content from a template | |
// | |
CopyMem (Instance, &gSnpNt32InstanceTemplate, sizeof (SNPNT32_INSTANCE_DATA)); | |
// | |
// Set the interface information. | |
// | |
Instance->InterfaceInfo = NetInterfaceInfoBuffer[Index]; | |
// | |
// Initialize this instance | |
// | |
Status = This->InitializeInstanceData (This, Instance); | |
if (EFI_ERROR (Status)) { | |
gBS->FreePool (Instance); | |
goto ErrorReturn; | |
} | |
// | |
// Insert this instance into the instance list | |
// | |
InsertTailList (&This->InstanceList, &Instance->Entry); | |
} | |
return EFI_SUCCESS; | |
ErrorReturn: | |
while (!IsListEmpty (&This->InstanceList)) { | |
Entry = This->InstanceList.ForwardLink; | |
Instance = NET_LIST_USER_STRUCT_S (Entry, SNPNT32_INSTANCE_DATA, Entry, SNP_NT32_INSTANCE_SIGNATURE); | |
RemoveEntryList (Entry); | |
This->CloseInstance (This, Instance); | |
gBS->FreePool (Instance); | |
} | |
if (NetUtilityLibInitDone) { | |
ASSERT (This->WinNtThunk != NULL); | |
if (This->NtNetUtilityTable.Finalize != NULL) { | |
This->NtNetUtilityTable.Finalize (); | |
This->NtNetUtilityTable.Finalize = NULL; | |
} | |
} | |
return Status; | |
} | |
/** | |
Initialize the snpnt32 driver instance. | |
@param This Pointer to the SnpNt32 global data. | |
@param Instance Pointer to the instance context data. | |
@retval EFI_SUCCESS The driver instance is initialized. | |
**/ | |
EFI_STATUS | |
SnpNt32InitializeInstanceData ( | |
IN SNPNT32_GLOBAL_DATA *This, | |
IN SNPNT32_INSTANCE_DATA *Instance | |
) | |
{ | |
EFI_STATUS Status; | |
EFI_DEV_PATH EndNode; | |
EFI_DEV_PATH Node; | |
Instance->GlobalData = This; | |
Instance->Snp.Mode = &Instance->Mode; | |
// | |
// Set broadcast address | |
// | |
SetMem (&Instance->Mode.BroadcastAddress, sizeof (EFI_MAC_ADDRESS), 0xFF); | |
// | |
// Copy Current/PermanentAddress MAC address | |
// | |
Instance->Mode.CurrentAddress = Instance->InterfaceInfo.MacAddr; | |
Instance->Mode.PermanentAddress = Instance->InterfaceInfo.MacAddr; | |
// | |
// Since the fake SNP is based on a real NIC, to avoid conflict with the host | |
// NIC network stack, we use a different MAC address. | |
// So just change the last byte of the MAC address for the real NIC. | |
// | |
Instance->Mode.CurrentAddress.Addr[NET_ETHER_ADDR_LEN - 1]++; | |
// | |
// Create a fake device path for the instance | |
// | |
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, | |
&Instance->Mode.CurrentAddress, | |
sizeof (EFI_MAC_ADDRESS) | |
); | |
Node.MacAddr.IfType = Instance->Mode.IfType; | |
SetDevicePathEndNode (&EndNode.DevPath); | |
Instance->DevicePath = AppendDevicePathNode ( | |
&EndNode.DevPath, | |
&Node.DevPath | |
); | |
// | |
// Create a fake device handle for the fake SNP | |
// | |
Status = gBS->InstallMultipleProtocolInterfaces ( | |
&Instance->DeviceHandle, | |
&gEfiSimpleNetworkProtocolGuid, | |
&Instance->Snp, | |
&gEfiDevicePathProtocolGuid, | |
Instance->DevicePath, | |
NULL | |
); | |
if (EFI_ERROR (Status)) { | |
goto ErrorReturn; | |
} | |
return EFI_SUCCESS; | |
ErrorReturn: | |
return Status; | |
} | |
/** | |
Close the SnpNt32 driver instance. | |
@param This Pointer to the SnpNt32 global data. | |
@param Instance Pointer to the instance context data. | |
@retval EFI_SUCCESS The instance is closed. | |
**/ | |
EFI_STATUS | |
SnpNt32CloseInstance ( | |
IN SNPNT32_GLOBAL_DATA *This, | |
IN SNPNT32_INSTANCE_DATA *Instance | |
) | |
{ | |
ASSERT (This != NULL); | |
ASSERT (Instance != NULL); | |
gBS->UninstallMultipleProtocolInterfaces ( | |
Instance->DeviceHandle, | |
&gEfiSimpleNetworkProtocolGuid, | |
&Instance->Snp, | |
&gEfiDevicePathProtocolGuid, | |
Instance->DevicePath, | |
NULL | |
); | |
if (Instance->DevicePath != NULL) { | |
gBS->FreePool (Instance->DevicePath); | |
} | |
return EFI_SUCCESS; | |
} | |
/** | |
Unload the SnpNt32 driver. | |
@param ImageHandle The handle of the driver image. | |
@retval EFI_SUCCESS The driver is unloaded. | |
@retval other Some error occurs. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
SnpNt32Unload ( | |
IN EFI_HANDLE ImageHandle | |
) | |
{ | |
EFI_STATUS Status; | |
SNPNT32_GLOBAL_DATA *This; | |
LIST_ENTRY *Entry; | |
SNPNT32_INSTANCE_DATA *Instance; | |
This = &gSnpNt32GlobalData; | |
Status = NetLibDefaultUnload (ImageHandle); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
while (!IsListEmpty (&This->InstanceList)) { | |
// | |
// Walkthrough the interfaces and remove all the SNP instance | |
// | |
Entry = This->InstanceList.ForwardLink; | |
Instance = NET_LIST_USER_STRUCT_S (Entry, SNPNT32_INSTANCE_DATA, Entry, SNP_NT32_INSTANCE_SIGNATURE); | |
RemoveEntryList (Entry); | |
This->CloseInstance (This, Instance); | |
gBS->FreePool (Instance); | |
} | |
if (This->NtNetUtilityTable.Finalize != NULL) { | |
This->NtNetUtilityTable.Finalize (); | |
} | |
This->WinNtThunk->FreeLibrary (This->NetworkLibraryHandle); | |
return EFI_SUCCESS; | |
} | |
EFI_STATUS | |
InitializeSnpNt32river ( | |
IN EFI_HANDLE ImageHandle, | |
IN EFI_SYSTEM_TABLE *SystemTable | |
) | |
/*++ | |
Routine Description: | |
Install DriverBinding Protocol for the Win NT Bus driver on the drivers | |
image handle. | |
Arguments: | |
ImageHandle - The handle of this image. | |
SystemTable - Pointer to the EFI system table. | |
Returns: | |
EFI_SUCEESS - The protocols are installed and the SnpNt32 is initialized. | |
other - Some error occurs. | |
--*/ | |
{ | |
EFI_STATUS Status; | |
// | |
// Install the Driver Protocols | |
// | |
Status = EfiLibInstallDriverBindingComponentName2 ( | |
ImageHandle, | |
SystemTable, | |
&gSnpNt32DriverBinding, | |
ImageHandle, | |
&gSnpNt32DriverComponentName, | |
&gSnpNt32DriverComponentName2 | |
); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
// | |
// Initialize the global data | |
// | |
Status = SnpNt32InitializeGlobalData (&gSnpNt32GlobalData); | |
if (EFI_ERROR (Status)) { | |
SnpNt32Unload (ImageHandle); | |
} | |
return Status; | |
} |