arpimpl.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,698 行 · 第 1/3 页
C
1,698 行
//
NetCopyMem (TmpPtr, &SnpMode->CurrentAddress, SnpMode->HwAddressSize);
TmpPtr += SnpMode->HwAddressSize;
//
// The ethernet protocol type.
//
*(UINT16 *)TmpPtr = HTONS (ARP_ETHER_PROTO_TYPE);
TmpPtr += 2;
//
// The ARP Head.
//
ArpHead = (ARP_HEAD *) TmpPtr;
ArpHead->HwType = HTONS ((UINT16)SnpMode->IfType);
ArpHead->ProtoType = HTONS (ConfigData->SwAddressType);
ArpHead->HwAddrLen = (UINT8)SnpMode->HwAddressSize;
ArpHead->ProtoAddrLen = ConfigData->SwAddressLength;
ArpHead->OpCode = HTONS (ArpOpCode);
TmpPtr += sizeof (ARP_HEAD);
//
// The sender hardware address.
//
NetCopyMem (TmpPtr, &SnpMode->CurrentAddress, SnpMode->HwAddressSize);
TmpPtr += SnpMode->HwAddressSize;
//
// The sender protocol address.
//
NetCopyMem (TmpPtr, ConfigData->StationAddress, ConfigData->SwAddressLength);
TmpPtr += ConfigData->SwAddressLength;
//
// The target hardware address.
//
NetCopyMem (
TmpPtr,
CacheEntry->Addresses[Hardware].AddressPtr,
SnpMode->HwAddressSize
);
TmpPtr += SnpMode->HwAddressSize;
//
// The target protocol address.
//
NetCopyMem (
TmpPtr,
CacheEntry->Addresses[Protocol].AddressPtr,
ConfigData->SwAddressLength
);
//
// Set all the fields of the TxData.
//
TxData->DestinationAddress = NULL;
TxData->SourceAddress = NULL;
TxData->ProtocolType = 0;
TxData->DataLength = TotalLength - SnpMode->MediaHeaderSize;
TxData->HeaderLength = (UINT16) SnpMode->MediaHeaderSize;
TxData->FragmentCount = 1;
TxData->FragmentTable[0].FragmentBuffer = Packet;
TxData->FragmentTable[0].FragmentLength = TotalLength;
//
// Associate the TxData with the TxToken.
//
TxToken->Packet.TxData = TxData;
TxToken->Status = EFI_NOT_READY;
//
// Send out this arp packet by Mnp.
//
Status = ArpService->Mnp->Transmit (ArpService->Mnp, TxToken);
if (EFI_ERROR (Status)) {
ARP_DEBUG_ERROR (("Mnp->Transmit failed, %r.\n", Status));
goto CLEAN_EXIT;
}
return;
CLEAN_EXIT:
if (Packet != NULL) {
NetFreePool (Packet);
}
if (TxData != NULL) {
NetFreePool (TxData);
}
if (TxToken->Event != NULL) {
gBS->CloseEvent (TxToken->Event);
}
NetFreePool (TxToken);
}
STATIC
UINTN
ArpDeleteCacheEntryInTable (
IN NET_LIST_ENTRY *CacheTable,
IN BOOLEAN BySwAddress,
IN UINT16 SwAddressType,
IN UINT8 *AddressBuffer OPTIONAL,
IN BOOLEAN Force
)
/*++
Routine Description:
Delete the cache entries in the specified CacheTable, using the BySwAddress,
SwAddressType, AddressBuffer combination as the matching key, if Force is TRUE,
the cache is deleted event it's a static entry.
Arguments:
CacheTable - Pointer to the cache table to do the deletion.
BySwAddress - Delete the cache entry by software address or by hardware address.
SwAddressType - The software address used to do the deletion.
AddressBuffer - Pointer to the buffer containing the address to match for the deletion.
Force - This deletion is forced or not.
Returns:
The count of the deleted cache entries.
--*/
{
NET_LIST_ENTRY *Entry;
NET_LIST_ENTRY *NextEntry;
ARP_CACHE_ENTRY *CacheEntry;
UINTN Count;
Count = 0;
NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, CacheTable) {
CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);
if ((CacheEntry->DefaultDecayTime == 0) && !Force) {
//
// It's a static entry and we are not forced to delete it, skip.
//
continue;
}
if (BySwAddress) {
if (SwAddressType == CacheEntry->Addresses[Protocol].Type) {
//
// Protocol address type matched. Check the address.
//
if ((AddressBuffer == NULL) ||
(NetCompareMem (
AddressBuffer,
CacheEntry->Addresses[Protocol].AddressPtr,
CacheEntry->Addresses[Protocol].Length
) == 0)) {
//
// Address matched.
//
goto MATCHED;
}
}
} else {
if ((AddressBuffer == NULL) ||
(NetCompareMem (
AddressBuffer,
CacheEntry->Addresses[Hardware].AddressPtr,
CacheEntry->Addresses[Hardware].Length
) == 0)) {
//
// Address matched.
//
goto MATCHED;
}
}
continue;
MATCHED:
//
// Delete this entry.
//
NetListRemoveEntry (&CacheEntry->List);
ASSERT (NetListIsEmpty (&CacheEntry->UserRequestList));
NetFreePool (CacheEntry);
Count++;
}
return Count;
}
UINTN
ArpDeleteCacheEntry (
IN ARP_INSTANCE_DATA *Instance,
IN BOOLEAN BySwAddress,
IN UINT8 *AddressBuffer OPTIONAL,
IN BOOLEAN Force
)
/*++
Routine Description:
Delete cache entries in all the cache tables.
Arguments:
Instance - Pointer to the instance context data.
BySwAddress - Delete the cache entry by software address or by hardware address.
AddressBuffer - Pointer to the buffer containing the address to match for the deletion.
Force - This deletion is forced or not.
Returns:
The count of the deleted cache entries.
--*/
{
ARP_SERVICE_DATA *ArpService;
UINTN Count;
NET_CHECK_SIGNATURE (Instance, ARP_INSTANCE_DATA_SIGNATURE);
ArpService = Instance->ArpService;
//
// Delete the cache entries in the DeniedCacheTable.
//
Count = ArpDeleteCacheEntryInTable (
&ArpService->DeniedCacheTable,
BySwAddress,
Instance->ConfigData.SwAddressType,
AddressBuffer,
Force
);
//
// Delete the cache entries inthe ResolvedCacheTable.
//
Count += ArpDeleteCacheEntryInTable (
&ArpService->ResolvedCacheTable,
BySwAddress,
Instance->ConfigData.SwAddressType,
AddressBuffer,
Force
);
return Count;
}
UINTN
ArpCancelRequest (
IN ARP_INSTANCE_DATA *Instance,
IN VOID *TargetSwAddress OPTIONAL,
IN EFI_EVENT UserEvent OPTIONAL
)
/*++
Routine Description:
Cancel the arp request.
Arguments:
Instance - Pointer to the instance context data.
TargetSwAddress - Pointer to the buffer containing the target software address to
match the arp request.
UserEvent - The user event used to notify this request cancellation.
Returns:
The count of the cancelled requests.
--*/
{
ARP_SERVICE_DATA *ArpService;
NET_LIST_ENTRY *Entry;
NET_LIST_ENTRY *NextEntry;
ARP_CACHE_ENTRY *CacheEntry;
UINTN Count;
NET_CHECK_SIGNATURE (Instance, ARP_INSTANCE_DATA_SIGNATURE);
ArpService = Instance->ArpService;
Count = 0;
NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &ArpService->PendingRequestTable) {
CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);
if ((TargetSwAddress == NULL) ||
(NetCompareMem (
TargetSwAddress,
CacheEntry->Addresses[Protocol].AddressPtr,
CacheEntry->Addresses[Protocol].Length
) == 0)) {
//
// This request entry matches the TargetSwAddress or all requests are to be
// cancelled as TargetSwAddress is NULL.
//
Count += ArpAddressResolved (CacheEntry, Instance, UserEvent);
if (NetListIsEmpty (&CacheEntry->UserRequestList)) {
//
// No user requests any more, remove this request cache entry.
//
NetListRemoveEntry (&CacheEntry->List);
NetFreePool (CacheEntry);
}
}
}
return Count;
}
EFI_STATUS
ArpFindCacheEntry (
IN ARP_INSTANCE_DATA *Instance,
IN BOOLEAN BySwAddress,
IN VOID *AddressBuffer OPTIONAL,
OUT UINT32 *EntryLength OPTIONAL,
OUT UINT32 *EntryCount OPTIONAL,
OUT EFI_ARP_FIND_DATA **Entries OPTIONAL,
IN BOOLEAN Refresh
)
/*++
Routine Description:
Find the cache entry in the cache table.
Arguments:
Instance - Pointer to the instance context data.
BySwAddress - Set to TRUE to look for matching software protocol addresses.
Set to FALSE to look for matching hardware protocol addresses.
AddressBuffer - Pointer to address buffer. Set to NULL to match all addresses.
EntryLength - The size of an entry in the entries buffer.
EntryCount - The number of ARP cache entries that are found by the specified
criteria.
Entries - Pointer to the buffer that will receive the ARP cache entries.
Refresh - Set to TRUE to refresh the timeout value of the matching ARP
cache entry.
Returns:
EFI_SUCCESS - The requested ARP cache entries are copied into the buffer.
EFI_NOT_FOUND - No matching entries found.
EFI_OUT_OF_RESOURCE - There is a memory allocation failure.
--*/
{
EFI_STATUS Status;
ARP_SERVICE_DATA *ArpService;
NET_ARP_ADDRESS MatchAddress;
FIND_OPTYPE FindOpType;
NET_LIST_ENTRY *StartEntry;
ARP_CACHE_ENTRY *CacheEntry;
NET_MAP FoundEntries;
UINT32 FoundCount;
EFI_ARP_FIND_DATA *FindData;
NET_LIST_ENTRY *CacheTable;
ArpService = Instance->ArpService;
//
// Init the FounEntries used to hold the found cache entries.
//
NetMapInit (&FoundEntries);
//
// Set the MatchAddress.
//
if (BySwAddress) {
MatchAddress.Type = Instance->ConfigData.SwAddressType;
MatchAddress.Length = Instance->ConfigData.SwAddressLength;
FindOpType = ByProtoAddress;
} else {
MatchAddress.Type = ArpService->SnpMode.IfType;
MatchAddress.Length = (UINT8)ArpService->SnpMode.HwAddressSize;
FindOpType = ByHwAddress;
}
MatchAddress.AddressPtr = AddressBuffer;
//
// Search the DeniedCacheTable
//
StartEntry = NULL;
while (TRUE) {
//
// Try to find the matched entries in the DeniedCacheTable.
//
CacheEntry = ArpFindNextCacheEntryInTable (
&ArpService->DeniedCacheTable,
StartEntry,
FindOpType,
&MatchAddress,
&MatchAddress
);
if (CacheEntry == NULL) {
//
// Once the CacheEntry is NULL, there are no more matches.
//
break;
}
//
// Insert the found entry into the map.
//
NetMapInsertTail (
&FoundEntries,
(VOID *)CacheEntry,
(VOID *)&ArpService->DeniedCacheTable
);
//
// Let the next search start from this cache entry.
//
StartEntry = &CacheEntry->List;
if (Refresh) {
//
// Refresh the DecayTime if needed.
//
CacheEntry->DecayTime = CacheEntry->DefaultDecayTime;
}
}
//
// Search the ResolvedCacheTable
//
StartEntry = NULL;
while (TRUE) {
CacheEntry = ArpFindNextCacheEntryInTable (
&ArpService->ResolvedCacheTable,
StartEntry,
FindOpType,
&MatchAddress,
&MatchAddress
);
if (CacheEntry == NULL) {
//
// Once the CacheEntry is NULL, there are no more matches.
//
break;
}
//
// Insert the found entry into the map.
//
NetMapInsertTail (
&FoundEntries,
(VOID *)CacheEntry,
(VOID *)&ArpService->ResolvedCacheTable
);
//
// Let the next search start from this cache entry.
//
StartEntry = &CacheEntry->List;
if (Refresh) {
//
// Refresh the DecayTime if needed.
//
CacheEntry->DecayTime = CacheEntry->DefaultDecayTime;
}
}
Status = EFI_SUCCESS;
FoundCount = (UINT32) NetMapGetCount (&FoundEntries);
if (FoundCount == 0) {
Status = EFI_NOT_FOUND;
goto CLEAN_EXIT;
}
if (EntryLength != NULL) {
//
// Return the entry length.
//
*EntryLength = sizeof (EFI_ARP_FIND_DATA) + Instance->ConfigData.SwAddressLength +
ArpService->SnpMode.HwAddressSize;
}
if (EntryCount != NULL) {
//
// Return the found entry count.
//
*EntryCount = FoundCount;
}
if (Entries == NULL) {
goto CLEAN_EXIT;
}
//
// Allocate buffer to copy the found entries.
//
FindData = NetAllocatePool (FoundCount * (*EntryLength));
if (FindData == NULL) {
ARP_DEBUG_ERROR (("ArpFindCacheEntry: Failed to allocate memory.\n"));
Status = EFI_OUT_OF_RESOURCES;
goto CLEAN_EXIT;
}
//
// Return the address to the user.
//
*Entries = FindData;
//
// Dump the entries.
//
while (!NetMapIsEmpty (&FoundEntries)) {
//
// Get a cache entry from the map.
//
CacheEntry = NetMapRemoveHead (&FoundEntries, (VOID **)&CacheTable);
//
// Set the fields in FindData.
//
FindData->Size = *EntryLength;
FindData->DenyFlag = (BOOLEAN)(CacheTable == &ArpService->DeniedCacheTable);
FindData->StaticFlag = (BOOLEAN)(CacheEntry->DefaultDecayTime == 0);
FindData->HwAddressType = ArpService->SnpMode.IfType;
FindData->SwAddressType = Instance->ConfigData.SwAddressType;
FindData->HwAddressLength = (UINT8)ArpService->SnpMode.HwAddressSize;
FindData->SwAddressLength = Instance->ConfigData.SwAddressLength;
//
// Copy the software address.
//
NetCopyMem (
FindData + 1,
CacheEntry->Addresses[Protocol].AddressPtr,
FindData->SwAddressLength
);
//
// Copy the hardware address.
//
NetCopyMem (
(UINT8 *)(FindData + 1) + FindData->SwAddressLength,
CacheEntry->Addresses[Hardware].AddressPtr,
FindData->HwAddressLength
);
//
// Slip to the next FindData.
//
FindData = (EFI_ARP_FIND_DATA *)((UINT8 *)FindData + *EntryLength);
}
CLEAN_EXIT:
NetMapClean (&FoundEntries);
return Status;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?