arpimpl.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,698 行 · 第 1/3 页
C
1,698 行
)
/*++
Routine Description:
Find the CacheEntry which matches the requirements in the specified CacheTable.
Arguments:
CacheTable - Pointer to the arp cache table.
StartEntry - Pointer to the start entry this search begins with in the cache table.
FindOpType - The search type.
ProtocolAddress - Pointer to the protocol address to match.
HardwareAddress - Pointer to the hardware address to match.
Returns:
Pointer to the matched arp cache entry, if NULL, no match is found.
--*/
{
NET_LIST_ENTRY *Entry;
ARP_CACHE_ENTRY *CacheEntry;
if (StartEntry == NULL) {
//
// Start from the beginning of the table if no StartEntry is specified.
//
StartEntry = CacheTable;
}
for (Entry = StartEntry->ForwardLink; Entry != CacheTable; Entry = Entry->ForwardLink) {
CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);
if (FindOpType & MATCH_SW_ADDRESS) {
//
// Find by the software address.
//
if (!ArpMatchAddress (ProtocolAddress, &CacheEntry->Addresses[Protocol])) {
//
// The ProtocolAddress doesn't match, continue to the next cache entry.
//
continue;
}
}
if (FindOpType & MATCH_HW_ADDRESS) {
//
// Find by the hardware address.
//
if (!ArpMatchAddress (HardwareAddress, &CacheEntry->Addresses[Hardware])) {
//
// The HardwareAddress doesn't match, continue to the next cache entry.
//
continue;
}
}
//
// The CacheEntry meets the requirements now, return this entry.
//
return CacheEntry;
}
//
// No matching.
//
return NULL;
}
ARP_CACHE_ENTRY *
ArpFindDeniedCacheEntry (
IN ARP_SERVICE_DATA *ArpService,
IN NET_ARP_ADDRESS *ProtocolAddress OPTIONAL,
IN NET_ARP_ADDRESS *HardwareAddress OPTIONAL
)
/*++
Routine Description:
Find the CacheEntry, using ProtocolAddress or HardwareAddress or both, as the keyword,
in the DeniedCacheTable.
Arguments:
ArpService - Pointer to the arp service context data.
ProtocolAddress - Pointer to the protocol address.
HardwareAddress - Pointer to the hardware address.
Returns:
Pointer to the matched cache entry, if NULL no match is found.
--*/
{
ARP_CACHE_ENTRY *CacheEntry;
ASSERT ((ProtocolAddress != NULL) || (HardwareAddress != NULL));
NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);
CacheEntry = NULL;
if ((ProtocolAddress != NULL) && (ProtocolAddress->AddressPtr != NULL)) {
//
// Find the cache entry in the DeniedCacheTable by the protocol address.
//
CacheEntry = ArpFindNextCacheEntryInTable (
&ArpService->DeniedCacheTable,
NULL,
ByProtoAddress,
ProtocolAddress,
NULL
);
if (CacheEntry != NULL) {
//
// There is a match.
//
return CacheEntry;
}
}
if ((HardwareAddress != NULL) && (HardwareAddress->AddressPtr != NULL)) {
//
// Find the cache entry in the DeniedCacheTable by the hardware address.
//
CacheEntry = ArpFindNextCacheEntryInTable (
&ArpService->DeniedCacheTable,
NULL,
ByHwAddress,
NULL,
HardwareAddress
);
}
return CacheEntry;
}
ARP_CACHE_ENTRY *
ArpAllocCacheEntry (
IN ARP_INSTANCE_DATA *Instance
)
/*++
Routine Description:
Allocate a cache entry and initialize it.
Arguments:
Instance - Pointer to the instance context data.
Returns:
Pointer to the new created cache entry.
--*/
{
ARP_CACHE_ENTRY *CacheEntry;
NET_ARP_ADDRESS *Address;
UINT16 Index;
//
// Allocate memory for the cache entry.
//
CacheEntry = NetAllocatePool (sizeof (ARP_CACHE_ENTRY));
if (CacheEntry == NULL) {
return NULL;
}
//
// Init the lists.
//
NetListInit (&CacheEntry->List);
NetListInit (&CacheEntry->UserRequestList);
for (Index = 0; Index < 2; Index++) {
//
// Init the address pointers to point to the concrete buffer.
//
Address = &CacheEntry->Addresses[Index];
Address->AddressPtr = Address->Buffer.ProtoAddress;
}
//
// Zero the hardware address first.
//
NetZeroMem (CacheEntry->Addresses[Hardware].AddressPtr, ARP_MAX_HARDWARE_ADDRESS_LEN);
if (Instance != NULL) {
//
// Inherit the parameters from the instance configuration.
//
CacheEntry->RetryCount = Instance->ConfigData.RetryCount;
CacheEntry->NextRetryTime = Instance->ConfigData.RetryTimeOut;
CacheEntry->DefaultDecayTime = Instance->ConfigData.EntryTimeOut;
CacheEntry->DecayTime = Instance->ConfigData.EntryTimeOut;
} else {
//
// Use the default parameters if this cache entry isn't allocate in a
// instance's scope.
//
CacheEntry->RetryCount = ARP_DEFAULT_RETRY_COUNT;
CacheEntry->NextRetryTime = ARP_DEFAULT_RETRY_INTERVAL;
CacheEntry->DefaultDecayTime = ARP_DEFAULT_TIMEOUT_VALUE;
CacheEntry->DecayTime = ARP_DEFAULT_TIMEOUT_VALUE;
}
return CacheEntry;
}
UINTN
ArpAddressResolved (
IN ARP_CACHE_ENTRY *CacheEntry,
IN ARP_INSTANCE_DATA *Instance OPTIONAL,
IN EFI_EVENT UserEvent OPTIONAL
)
/*++
Routine Description:
Turn the CacheEntry into the resolved status.
Arguments:
CacheEntry - Pointer to the resolved cache entry.
Instance - Pointer to the instance context data.
UserEvent - Pointer to the UserEvent to notify.
Returns:
The count of notifications sent to the instance.
--*/
{
NET_LIST_ENTRY *Entry;
NET_LIST_ENTRY *NextEntry;
USER_REQUEST_CONTEXT *Context;
UINTN Count;
Count = 0;
//
// Iterate all the linked user requests to notify them.
//
NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &CacheEntry->UserRequestList) {
Context = NET_LIST_USER_STRUCT (Entry, USER_REQUEST_CONTEXT, List);
if (((Instance == NULL) || (Context->Instance == Instance)) &&
((UserEvent == NULL) || (Context->UserRequestEvent == UserEvent))) {
//
// Copy the address to the user-provided buffer and notify the user.
//
NetCopyMem (
Context->UserHwAddrBuffer,
CacheEntry->Addresses[Hardware].AddressPtr,
CacheEntry->Addresses[Hardware].Length
);
gBS->SignalEvent (Context->UserRequestEvent);
//
// Remove this user request and free the context data.
//
NetListRemoveEntry (&Context->List);
NetFreePool (Context);
Count++;
}
}
return Count;
}
VOID
ArpFillAddressInCacheEntry (
IN ARP_CACHE_ENTRY *CacheEntry,
IN NET_ARP_ADDRESS *HwAddr OPTIONAL,
IN NET_ARP_ADDRESS *SwAddr OPTIONAL
)
/*++
Routine Description:
Fill the addresses in the CacheEntry using the information passed in by
HwAddr and SwAddr.
Arguments:
CacheEntry - Pointer to the cache entry.
HwAddr - Pointer to the software address.
SwAddr - Pointer to the hardware address.
Returns:
None.
--*/
{
NET_ARP_ADDRESS *Address[2];
NET_ARP_ADDRESS *CacheAddress;
UINT32 Index;
Address[Hardware] = HwAddr;
Address[Protocol] = SwAddr;
for (Index = 0; Index < 2; Index++) {
if (Address[Index] != NULL) {
//
// Fill the address if the passed in pointer is not NULL.
//
CacheAddress = &CacheEntry->Addresses[Index];
CacheAddress->Type = Address[Index]->Type;
CacheAddress->Length = Address[Index]->Length;
if (Address[Index]->AddressPtr != NULL) {
//
// Copy it if the AddressPtr points to some buffer.
//
NetCopyMem (
CacheAddress->AddressPtr,
Address[Index]->AddressPtr,
CacheAddress->Length
);
} else {
//
// Zero the corresponding address buffer in the CacheEntry.
//
NetZeroMem (CacheAddress->AddressPtr, CacheAddress->Length);
}
}
}
}
EFI_STATUS
ArpConfigureInstance (
IN ARP_INSTANCE_DATA *Instance,
IN EFI_ARP_CONFIG_DATA *ConfigData OPTIONAL
)
/*++
Routine Description:
Configure the instance using the ConfigData. ConfigData is already validated.
Arguments:
Instance - Pointer to the instance context data to be configured.
ConfigData - Pointer to the configuration data used to configure the instance.
Returns:
EFI_SUCCESS - The instance is configured with the ConfigData.
EFI_ACCESS_DENIED - The instance is already configured and the ConfigData tries to
reset some unchangeable fields.
EFI_INVALID_PARAMETER - The ConfigData provides a non-unicast IPv4 address when the
SwAddressType is IPv4.
EFI_OUT_OF_RESOURCES - The instance fails to configure due to memory limitation.
--*/
{
EFI_ARP_CONFIG_DATA *OldConfigData;
OldConfigData = &Instance->ConfigData;
if (ConfigData != NULL) {
if (Instance->Configured) {
//
// The instance is configured, check the unchangeable fields.
//
if ((OldConfigData->SwAddressType != ConfigData->SwAddressType) ||
(OldConfigData->SwAddressLength != ConfigData->SwAddressLength) ||
(NetCompareMem (
OldConfigData->StationAddress,
ConfigData->StationAddress,
OldConfigData->SwAddressLength
) != 0)) {
//
// Deny the unallowed changes.
//
return EFI_ACCESS_DENIED;
}
} else {
//
// The instance is not configured.
//
if ((ConfigData->SwAddressType == IPv4_ETHER_PROTO_TYPE) &&
(!Ip4IsUnicast (EFI_IP4 (*((EFI_IPv4_ADDRESS *)ConfigData->StationAddress)), 0))) {
//
// The station address is not a valid IPv4 unicast address.
//
return EFI_INVALID_PARAMETER;
}
//
// Save the configuration.
//
*OldConfigData = *ConfigData;
OldConfigData->StationAddress = NetAllocatePool (OldConfigData->SwAddressLength);
if (OldConfigData->StationAddress == NULL) {
ARP_DEBUG_ERROR (("ArpConfigInstance: NetAllocatePool for the StationAddress "
"failed.\n"));
return EFI_OUT_OF_RESOURCES;
}
//
// Save the StationAddress.
//
NetCopyMem (
OldConfigData->StationAddress,
ConfigData->StationAddress,
OldConfigData->SwAddressLength
);
//
// Set the state to configured.
//
Instance->Configured = TRUE;
}
//
// Use the implementation specific values if the following field is zero.
//
OldConfigData->EntryTimeOut = (ConfigData->EntryTimeOut == 0) ?
ARP_DEFAULT_TIMEOUT_VALUE : ConfigData->EntryTimeOut;
OldConfigData->RetryCount = (ConfigData->RetryCount == 0) ?
ARP_DEFAULT_RETRY_COUNT : ConfigData->RetryCount;
OldConfigData->RetryTimeOut = (ConfigData->RetryTimeOut == 0) ?
ARP_DEFAULT_RETRY_INTERVAL : ConfigData->RetryTimeOut;
} else {
//
// Reset the configuration.
//
if (Instance->Configured) {
//
// Cancel the arp requests issued by this instance.
//
ArpCancelRequest (Instance, NULL, NULL);
//
// Free the buffer previously allocated to hold the station address.
//
NetFreePool (OldConfigData->StationAddress);
}
Instance->Configured = FALSE;
}
return EFI_SUCCESS;
}
VOID
ArpSendFrame (
IN ARP_INSTANCE_DATA *Instance,
IN ARP_CACHE_ENTRY *CacheEntry,
IN UINT16 ArpOpCode
)
/*++
Routine Description:
Send out an arp frame using the CachEntry and the ArpOpCode.
Arguments:
Instance - Pointer to the instance context data.
CacheEntry - Pointer to the configuration data used to configure the instance.
ArpOpCode - The opcode used to send out this Arp frame, either request or reply.
Returns:
None.
--*/
{
EFI_STATUS Status;
EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TxToken;
EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData;
UINT32 TotalLength;
UINT8 *Packet;
ARP_SERVICE_DATA *ArpService;
EFI_SIMPLE_NETWORK_MODE *SnpMode;
EFI_ARP_CONFIG_DATA *ConfigData;
UINT8 *TmpPtr;
ARP_HEAD *ArpHead;
ASSERT ((Instance != NULL) && (CacheEntry != NULL));
//
// Allocate memory for the TxToken.
//
TxToken = NetAllocatePool (sizeof(EFI_MANAGED_NETWORK_COMPLETION_TOKEN));
if (TxToken == NULL) {
ARP_DEBUG_ERROR (("ArpSendFrame: Allocate memory for TxToken failed.\n"));
return;
}
TxToken->Event = NULL;
TxData = NULL;
Packet = NULL;
//
// Create the event for this TxToken.
//
Status = gBS->CreateEvent (
EFI_EVENT_NOTIFY_SIGNAL,
NET_TPL_EVENT,
ArpOnFrameSent,
(VOID *)TxToken,
&TxToken->Event
);
if (EFI_ERROR (Status)) {
ARP_DEBUG_ERROR (("ArpSendFrame: CreateEvent failed for TxToken->Event.\n"));
goto CLEAN_EXIT;
}
//
// Allocate memory for the TxData used in the TxToken.
//
TxData = NetAllocatePool (sizeof(EFI_MANAGED_NETWORK_TRANSMIT_DATA));
if (TxData == NULL) {
ARP_DEBUG_ERROR (("ArpSendFrame: Allocate memory for TxData failed.\n"));
goto CLEAN_EXIT;
}
ArpService = Instance->ArpService;
SnpMode = &ArpService->SnpMode;
ConfigData = &Instance->ConfigData;
//
// Calculate the buffer length for this arp frame.
//
TotalLength = SnpMode->MediaHeaderSize + sizeof (ARP_HEAD) +
2 * (ConfigData->SwAddressLength + SnpMode->HwAddressSize);
//
// Allocate buffer for the arp frame.
//
Packet = NetAllocatePool (TotalLength);
if (Packet == NULL) {
ARP_DEBUG_ERROR (("ArpSendFrame: Allocate memory for Packet failed.\n"));
}
TmpPtr = Packet;
//
// The destination MAC address.
//
if (ArpOpCode == ARP_OPCODE_REQUEST) {
NetCopyMem (TmpPtr, &SnpMode->BroadcastAddress, SnpMode->HwAddressSize);
} else {
NetCopyMem (
TmpPtr,
CacheEntry->Addresses[Hardware].AddressPtr,
SnpMode->HwAddressSize
);
}
TmpPtr += SnpMode->HwAddressSize;
//
// The source MAC address.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?