4 Copyright (c) 2006 - 2008, Intel Corporation.<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at<BR>
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 EFI_ARP_PROTOCOL mEfiArpProtocolTemplate
= {
29 Initialize the instance context data.
31 @param[in] ArpService Pointer to the arp service context data this
33 @param[in] Instance Pointer to the instance context data.
40 IN ARP_SERVICE_DATA
*ArpService
,
41 IN ARP_INSTANCE_DATA
*Instance
44 NET_CHECK_SIGNATURE (ArpService
, ARP_SERVICE_DATA_SIGNATURE
);
46 Instance
->Signature
= ARP_INSTANCE_DATA_SIGNATURE
;
47 Instance
->ArpService
= ArpService
;
49 CopyMem (&Instance
->ArpProto
, &mEfiArpProtocolTemplate
, sizeof (Instance
->ArpProto
));
51 Instance
->Configured
= FALSE
;
52 Instance
->Destroyed
= FALSE
;
54 InitializeListHead (&Instance
->List
);
59 Process the Arp packets received from Mnp, the procedure conforms to RFC826.
61 @param[in] Context Pointer to the context data registerd to the
74 ARP_SERVICE_DATA
*ArpService
;
75 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*RxToken
;
76 EFI_MANAGED_NETWORK_RECEIVE_DATA
*RxData
;
78 ARP_ADDRESS ArpAddress
;
79 ARP_CACHE_ENTRY
*CacheEntry
;
81 ARP_INSTANCE_DATA
*Instance
;
82 EFI_ARP_CONFIG_DATA
*ConfigData
;
83 NET_ARP_ADDRESS SenderAddress
[2];
88 ArpService
= (ARP_SERVICE_DATA
*)Context
;
89 NET_CHECK_SIGNATURE (ArpService
, ARP_SERVICE_DATA_SIGNATURE
);
91 RxToken
= &ArpService
->RxToken
;
93 if (RxToken
->Status
== EFI_ABORTED
) {
95 // The Token is aborted, possibly by arp itself, just return and the receiving
96 // process is stopped.
101 if (EFI_ERROR (RxToken
->Status
)) {
103 // Restart the receiving if any other error Status occurs.
105 goto RESTART_RECEIVE
;
109 // Status is EFI_SUCCESS, process the received frame.
111 RxData
= RxToken
->Packet
.RxData
;
112 Head
= (ARP_HEAD
*) RxData
->PacketData
;
115 // Convert the byte order of the multi-byte fields.
117 Head
->HwType
= NTOHS (Head
->HwType
);
118 Head
->ProtoType
= NTOHS (Head
->ProtoType
);
119 Head
->OpCode
= NTOHS (Head
->OpCode
);
121 if ((Head
->HwType
!= ArpService
->SnpMode
.IfType
) ||
122 (Head
->HwAddrLen
!= ArpService
->SnpMode
.HwAddressSize
) ||
123 (RxData
->ProtocolType
!= ARP_ETHER_PROTO_TYPE
)) {
125 // The hardware type or the hardware address length doesn't match.
126 // There is a sanity check for the protocol type too.
132 // Set the pointers to the addresses contained in the arp packet.
134 ArpAddress
.SenderHwAddr
= (UINT8
*)(Head
+ 1);
135 ArpAddress
.SenderProtoAddr
= ArpAddress
.SenderHwAddr
+ Head
->HwAddrLen
;
136 ArpAddress
.TargetHwAddr
= ArpAddress
.SenderProtoAddr
+ Head
->ProtoAddrLen
;
137 ArpAddress
.TargetProtoAddr
= ArpAddress
.TargetHwAddr
+ Head
->HwAddrLen
;
139 SenderAddress
[Hardware
].Type
= Head
->HwType
;
140 SenderAddress
[Hardware
].Length
= Head
->HwAddrLen
;
141 SenderAddress
[Hardware
].AddressPtr
= ArpAddress
.SenderHwAddr
;
143 SenderAddress
[Protocol
].Type
= Head
->ProtoType
;
144 SenderAddress
[Protocol
].Length
= Head
->ProtoAddrLen
;
145 SenderAddress
[Protocol
].AddressPtr
= ArpAddress
.SenderProtoAddr
;
148 // First, check the denied cache table.
150 CacheEntry
= ArpFindDeniedCacheEntry (
152 &SenderAddress
[Protocol
],
153 &SenderAddress
[Hardware
]
155 if (CacheEntry
!= NULL
) {
157 // This address (either hardware or protocol address, or both) is configured to
158 // be a deny entry, silently skip the normal process.
163 ProtoMatched
= FALSE
;
166 NET_LIST_FOR_EACH (Entry
, &ArpService
->ChildrenList
) {
168 // Iterate all the children.
170 Instance
= NET_LIST_USER_STRUCT (Entry
, ARP_INSTANCE_DATA
, List
);
171 NET_CHECK_SIGNATURE (Instance
, ARP_INSTANCE_DATA_SIGNATURE
);
172 ConfigData
= &Instance
->ConfigData
;
174 if ((Instance
->Configured
) &&
175 (Head
->ProtoType
== ConfigData
->SwAddressType
) &&
176 (Head
->ProtoAddrLen
== ConfigData
->SwAddressLength
)) {
178 // The protocol type is matched for the received arp packet.
181 if (0 == CompareMem (
182 (VOID
*)ArpAddress
.TargetProtoAddr
,
183 ConfigData
->StationAddress
,
184 ConfigData
->SwAddressLength
187 // The arp driver has the target address required by the received arp packet.
197 // Protocol type unmatchable, skip.
203 // Check whether the sender's address information is already in the cache.
206 CacheEntry
= ArpFindNextCacheEntryInTable (
207 &ArpService
->ResolvedCacheTable
,
210 &SenderAddress
[Protocol
],
213 if (CacheEntry
!= NULL
) {
215 // Update the entry with the new information.
217 ArpFillAddressInCacheEntry (CacheEntry
, &SenderAddress
[Hardware
], NULL
);
218 CacheEntry
->DecayTime
= CacheEntry
->DefaultDecayTime
;
224 // This arp packet isn't targeted to us, skip now.
231 // Add the triplet <protocol type, sender protocol address, sender hardware address>
232 // to the translation table.
234 CacheEntry
= ArpFindNextCacheEntryInTable (
235 &ArpService
->PendingRequestTable
,
238 &SenderAddress
[Protocol
],
241 if (CacheEntry
== NULL
) {
243 // Allocate a new CacheEntry.
245 CacheEntry
= ArpAllocCacheEntry (NULL
);
246 if (CacheEntry
== NULL
) {
251 if (!IsListEmpty (&CacheEntry
->List
)) {
252 RemoveEntryList (&CacheEntry
->List
);
256 // Fill the addresses into the CacheEntry.
258 ArpFillAddressInCacheEntry (
260 &SenderAddress
[Hardware
],
261 &SenderAddress
[Protocol
]
267 ArpAddressResolved (CacheEntry
, NULL
, NULL
);
270 // Add this entry into the ResolvedCacheTable
272 InsertHeadList (&ArpService
->ResolvedCacheTable
, &CacheEntry
->List
);
275 if (Head
->OpCode
== ARP_OPCODE_REQUEST
) {
277 // Send back the ARP Reply. If we reach here, Instance is not NULL and CacheEntry
280 ArpSendFrame (Instance
, CacheEntry
, ARP_OPCODE_REPLY
);
286 // Signal Mnp to recycle the RxData.
288 gBS
->SignalEvent (RxData
->RecycleEvent
);
293 // Continue to receive packets from Mnp.
295 Status
= ArpService
->Mnp
->Receive (ArpService
->Mnp
, RxToken
);
298 if (EFI_ERROR (Status
)) {
299 DEBUG ((EFI_D_ERROR
, "ArpOnFrameRcvd: ArpService->Mnp->Receive "
300 "failed, %r\n.", Status
));
306 Queue ArpOnFrameRcvdDpc as a DPC at TPL_CALLBACK.
308 @param[in] Event The Event this notify function registered to.
309 @param[in] Context Pointer to the context data registerd to the
323 // Request ArpOnFrameRcvdDpc as a DPC at TPL_CALLBACK
325 NetLibQueueDpc (TPL_CALLBACK
, ArpOnFrameRcvdDpc
, Context
);
329 Process the already sent arp packets.
331 @param[in] Context Pointer to the context data registerd to the
343 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*TxToken
;
344 EFI_MANAGED_NETWORK_TRANSMIT_DATA
*TxData
;
346 ASSERT (Context
!= NULL
);
348 TxToken
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*)Context
;
349 TxData
= TxToken
->Packet
.TxData
;
352 if (EFI_ERROR (TxToken
->Status
)) {
353 DEBUG ((EFI_D_ERROR
, "ArpOnFrameSent: TxToken->Status, %r.\n", TxToken
->Status
));
358 // Free the allocated memory and close the event.
360 gBS
->FreePool (TxData
->FragmentTable
[0].FragmentBuffer
);
361 gBS
->FreePool (TxData
);
362 gBS
->CloseEvent (TxToken
->Event
);
363 gBS
->FreePool (TxToken
);
367 Request ArpOnFrameSentDpc as a DPC at TPL_CALLBACK.
369 @param[in] Event The Event this notify function registered to.
370 @param[in] Context Pointer to the context data registerd to the
384 // Request ArpOnFrameSentDpc as a DPC at TPL_CALLBACK
386 NetLibQueueDpc (TPL_CALLBACK
, ArpOnFrameSentDpc
, Context
);
391 Process the arp cache olding and drive the retrying arp requests.
393 @param[in] Event The Event this notify function registered to.
394 @param[in] Context Pointer to the context data registerd to the
407 ARP_SERVICE_DATA
*ArpService
;
409 LIST_ENTRY
*NextEntry
;
410 LIST_ENTRY
*ContextEntry
;
411 ARP_CACHE_ENTRY
*CacheEntry
;
412 USER_REQUEST_CONTEXT
*RequestContext
;
414 ASSERT (Context
!= NULL
);
415 ArpService
= (ARP_SERVICE_DATA
*)Context
;
418 // Iterate all the pending requests to see whether a retry is needed to send out
419 // or the request finally fails because the retry time reaches the limitation.
421 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &ArpService
->PendingRequestTable
) {
422 CacheEntry
= NET_LIST_USER_STRUCT (Entry
, ARP_CACHE_ENTRY
, List
);
424 if (CacheEntry
->NextRetryTime
<= ARP_PERIODIC_TIMER_INTERVAL
) {
426 // Timeout, if we can retry more, send out the request again, otherwise abort
429 if (CacheEntry
->RetryCount
== 0) {
431 // Abort this request.
433 ArpAddressResolved (CacheEntry
, NULL
, NULL
);
434 ASSERT (IsListEmpty (&CacheEntry
->UserRequestList
));
436 RemoveEntryList (&CacheEntry
->List
);
437 gBS
->FreePool (CacheEntry
);
440 // resend the ARP request.
442 ASSERT (!IsListEmpty(&CacheEntry
->UserRequestList
));
444 ContextEntry
= CacheEntry
->UserRequestList
.ForwardLink
;
445 RequestContext
= NET_LIST_USER_STRUCT (ContextEntry
, USER_REQUEST_CONTEXT
, List
);
447 ArpSendFrame (RequestContext
->Instance
, CacheEntry
, ARP_OPCODE_REQUEST
);
449 CacheEntry
->RetryCount
--;
450 CacheEntry
->NextRetryTime
= RequestContext
->Instance
->ConfigData
.RetryTimeOut
;
454 // Update the NextRetryTime.
456 CacheEntry
->NextRetryTime
-= ARP_PERIODIC_TIMER_INTERVAL
;
461 // Check the timeouts for the DeniedCacheTable.
463 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &ArpService
->DeniedCacheTable
) {
464 CacheEntry
= NET_LIST_USER_STRUCT (Entry
, ARP_CACHE_ENTRY
, List
);
465 ASSERT (IsListEmpty (&CacheEntry
->UserRequestList
));
467 if (CacheEntry
->DefaultDecayTime
== 0) {
469 // It's a static entry, skip it.
474 if (CacheEntry
->DecayTime
<= ARP_PERIODIC_TIMER_INTERVAL
) {
476 // Time out, remove it.
478 RemoveEntryList (&CacheEntry
->List
);
479 gBS
->FreePool (CacheEntry
);
482 // Update the DecayTime.
484 CacheEntry
->DecayTime
-= ARP_PERIODIC_TIMER_INTERVAL
;
489 // Check the timeouts for the ResolvedCacheTable.
491 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &ArpService
->ResolvedCacheTable
) {
492 CacheEntry
= NET_LIST_USER_STRUCT (Entry
, ARP_CACHE_ENTRY
, List
);
493 ASSERT (IsListEmpty (&CacheEntry
->UserRequestList
));
495 if (CacheEntry
->DefaultDecayTime
== 0) {
497 // It's a static entry, skip it.
502 if (CacheEntry
->DecayTime
<= ARP_PERIODIC_TIMER_INTERVAL
) {
504 // Time out, remove it.
506 RemoveEntryList (&CacheEntry
->List
);
507 gBS
->FreePool (CacheEntry
);
510 // Update the DecayTime.
512 CacheEntry
->DecayTime
-= ARP_PERIODIC_TIMER_INTERVAL
;
519 Match the two NET_ARP_ADDRESSes.
521 @param[in] AddressOne Pointer to the first address to match.
522 @param[in] AddressTwo Pointer to the second address to match.
524 @return The two addresses match or not.
529 IN NET_ARP_ADDRESS
*AddressOne
,
530 IN NET_ARP_ADDRESS
*AddressTwo
533 if ((AddressOne
->Type
!= AddressTwo
->Type
) ||
534 (AddressOne
->Length
!= AddressTwo
->Length
)) {
536 // Either Type or Length doesn't match.
541 if ((AddressOne
->AddressPtr
!= NULL
) &&
543 AddressOne
->AddressPtr
,
544 AddressTwo
->AddressPtr
,
548 // The address is not the same.
558 Find the CacheEntry which matches the requirements in the specified CacheTable.
560 @param[in] CacheTable Pointer to the arp cache table.
561 @param[in] StartEntry Pointer to the start entry this search begins with
563 @param[in] FindOpType The search type.
564 @param[in] ProtocolAddress Pointer to the protocol address to match.
565 @param[in] HardwareAddress Pointer to the hardware address to match.
567 @return Pointer to the matched arp cache entry, if NULL, no match is found.
571 ArpFindNextCacheEntryInTable (
572 IN LIST_ENTRY
*CacheTable
,
573 IN LIST_ENTRY
*StartEntry
,
574 IN FIND_OPTYPE FindOpType
,
575 IN NET_ARP_ADDRESS
*ProtocolAddress OPTIONAL
,
576 IN NET_ARP_ADDRESS
*HardwareAddress OPTIONAL
580 ARP_CACHE_ENTRY
*CacheEntry
;
582 if (StartEntry
== NULL
) {
584 // Start from the beginning of the table if no StartEntry is specified.
586 StartEntry
= CacheTable
;
589 for (Entry
= StartEntry
->ForwardLink
; Entry
!= CacheTable
; Entry
= Entry
->ForwardLink
) {
590 CacheEntry
= NET_LIST_USER_STRUCT (Entry
, ARP_CACHE_ENTRY
, List
);
592 if ((FindOpType
& MATCH_SW_ADDRESS
) != 0) {
594 // Find by the software address.
596 if (!ArpMatchAddress (ProtocolAddress
, &CacheEntry
->Addresses
[Protocol
])) {
598 // The ProtocolAddress doesn't match, continue to the next cache entry.
604 if ((FindOpType
& MATCH_HW_ADDRESS
) != 0) {
606 // Find by the hardware address.
608 if (!ArpMatchAddress (HardwareAddress
, &CacheEntry
->Addresses
[Hardware
])) {
610 // The HardwareAddress doesn't match, continue to the next cache entry.
617 // The CacheEntry meets the requirements now, return this entry.
630 Find the CacheEntry, using ProtocolAddress or HardwareAddress or both, as the keyword,
631 in the DeniedCacheTable.
633 @param[in] ArpService Pointer to the arp service context data.
634 @param[in] ProtocolAddress Pointer to the protocol address.
635 @param[in] HardwareAddress Pointer to the hardware address.
637 @return Pointer to the matched cache entry, if NULL no match is found.
641 ArpFindDeniedCacheEntry (
642 IN ARP_SERVICE_DATA
*ArpService
,
643 IN NET_ARP_ADDRESS
*ProtocolAddress OPTIONAL
,
644 IN NET_ARP_ADDRESS
*HardwareAddress OPTIONAL
647 ARP_CACHE_ENTRY
*CacheEntry
;
649 ASSERT ((ProtocolAddress
!= NULL
) || (HardwareAddress
!= NULL
));
650 NET_CHECK_SIGNATURE (ArpService
, ARP_SERVICE_DATA_SIGNATURE
);
654 if ((ProtocolAddress
!= NULL
) && (ProtocolAddress
->AddressPtr
!= NULL
)) {
656 // Find the cache entry in the DeniedCacheTable by the protocol address.
658 CacheEntry
= ArpFindNextCacheEntryInTable (
659 &ArpService
->DeniedCacheTable
,
665 if (CacheEntry
!= NULL
) {
673 if ((HardwareAddress
!= NULL
) && (HardwareAddress
->AddressPtr
!= NULL
)) {
675 // Find the cache entry in the DeniedCacheTable by the hardware address.
677 CacheEntry
= ArpFindNextCacheEntryInTable (
678 &ArpService
->DeniedCacheTable
,
691 Allocate a cache entry and initialize it.
693 @param[in] Instance Pointer to the instance context data.
695 @return Pointer to the new created cache entry.
700 IN ARP_INSTANCE_DATA
*Instance
703 ARP_CACHE_ENTRY
*CacheEntry
;
704 NET_ARP_ADDRESS
*Address
;
708 // Allocate memory for the cache entry.
710 CacheEntry
= AllocatePool (sizeof (ARP_CACHE_ENTRY
));
711 if (CacheEntry
== NULL
) {
718 InitializeListHead (&CacheEntry
->List
);
719 InitializeListHead (&CacheEntry
->UserRequestList
);
721 for (Index
= 0; Index
< 2; Index
++) {
723 // Init the address pointers to point to the concrete buffer.
725 Address
= &CacheEntry
->Addresses
[Index
];
726 Address
->AddressPtr
= Address
->Buffer
.ProtoAddress
;
730 // Zero the hardware address first.
732 ZeroMem (CacheEntry
->Addresses
[Hardware
].AddressPtr
, ARP_MAX_HARDWARE_ADDRESS_LEN
);
734 if (Instance
!= NULL
) {
736 // Inherit the parameters from the instance configuration.
738 CacheEntry
->RetryCount
= Instance
->ConfigData
.RetryCount
;
739 CacheEntry
->NextRetryTime
= Instance
->ConfigData
.RetryTimeOut
;
740 CacheEntry
->DefaultDecayTime
= Instance
->ConfigData
.EntryTimeOut
;
741 CacheEntry
->DecayTime
= Instance
->ConfigData
.EntryTimeOut
;
744 // Use the default parameters if this cache entry isn't allocate in a
747 CacheEntry
->RetryCount
= ARP_DEFAULT_RETRY_COUNT
;
748 CacheEntry
->NextRetryTime
= ARP_DEFAULT_RETRY_INTERVAL
;
749 CacheEntry
->DefaultDecayTime
= ARP_DEFAULT_TIMEOUT_VALUE
;
750 CacheEntry
->DecayTime
= ARP_DEFAULT_TIMEOUT_VALUE
;
758 Turn the CacheEntry into the resolved status.
760 @param[in] CacheEntry Pointer to the resolved cache entry.
761 @param[in] Instance Pointer to the instance context data.
762 @param[in] UserEvent Pointer to the UserEvent to notify.
764 @return The count of notifications sent to the instance.
769 IN ARP_CACHE_ENTRY
*CacheEntry
,
770 IN ARP_INSTANCE_DATA
*Instance OPTIONAL
,
771 IN EFI_EVENT UserEvent OPTIONAL
775 LIST_ENTRY
*NextEntry
;
776 USER_REQUEST_CONTEXT
*Context
;
782 // Iterate all the linked user requests to notify them.
784 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &CacheEntry
->UserRequestList
) {
785 Context
= NET_LIST_USER_STRUCT (Entry
, USER_REQUEST_CONTEXT
, List
);
787 if (((Instance
== NULL
) || (Context
->Instance
== Instance
)) &&
788 ((UserEvent
== NULL
) || (Context
->UserRequestEvent
== UserEvent
))) {
790 // Copy the address to the user-provided buffer and notify the user.
793 Context
->UserHwAddrBuffer
,
794 CacheEntry
->Addresses
[Hardware
].AddressPtr
,
795 CacheEntry
->Addresses
[Hardware
].Length
797 gBS
->SignalEvent (Context
->UserRequestEvent
);
800 // Remove this user request and free the context data.
802 RemoveEntryList (&Context
->List
);
803 gBS
->FreePool (Context
);
810 // Dispatch the DPCs queued by the NotifyFunction of the Context->UserRequestEvent.
812 NetLibDispatchDpc ();
819 Fill the addresses in the CacheEntry using the information passed in by
822 @param[in] CacheEntry Pointer to the cache entry.
823 @param[in] HwAddr Pointer to the software address.
824 @param[in] SwAddr Pointer to the hardware address.
830 ArpFillAddressInCacheEntry (
831 IN ARP_CACHE_ENTRY
*CacheEntry
,
832 IN NET_ARP_ADDRESS
*HwAddr OPTIONAL
,
833 IN NET_ARP_ADDRESS
*SwAddr OPTIONAL
836 NET_ARP_ADDRESS
*Address
[2];
837 NET_ARP_ADDRESS
*CacheAddress
;
840 Address
[Hardware
] = HwAddr
;
841 Address
[Protocol
] = SwAddr
;
843 for (Index
= 0; Index
< 2; Index
++) {
844 if (Address
[Index
] != NULL
) {
846 // Fill the address if the passed in pointer is not NULL.
848 CacheAddress
= &CacheEntry
->Addresses
[Index
];
850 CacheAddress
->Type
= Address
[Index
]->Type
;
851 CacheAddress
->Length
= Address
[Index
]->Length
;
853 if (Address
[Index
]->AddressPtr
!= NULL
) {
855 // Copy it if the AddressPtr points to some buffer.
858 CacheAddress
->AddressPtr
,
859 Address
[Index
]->AddressPtr
,
864 // Zero the corresponding address buffer in the CacheEntry.
866 ZeroMem (CacheAddress
->AddressPtr
, CacheAddress
->Length
);
874 Configure the instance using the ConfigData. ConfigData is already validated.
876 @param[in] Instance Pointer to the instance context data to be
878 @param[in] ConfigData Pointer to the configuration data used to
879 configure the instance.
881 @retval EFI_SUCCESS The instance is configured with the ConfigData.
882 @retval EFI_ACCESS_DENIED The instance is already configured and the
883 ConfigData tries to reset some unchangeable
885 @retval EFI_INVALID_PARAMETER The ConfigData provides a non-unicast IPv4 address
886 when the SwAddressType is IPv4.
887 @retval EFI_OUT_OF_RESOURCES The instance fails to configure due to memory
892 ArpConfigureInstance (
893 IN ARP_INSTANCE_DATA
*Instance
,
894 IN EFI_ARP_CONFIG_DATA
*ConfigData OPTIONAL
897 EFI_ARP_CONFIG_DATA
*OldConfigData
;
900 OldConfigData
= &Instance
->ConfigData
;
902 if (ConfigData
!= NULL
) {
904 if (Instance
->Configured
) {
906 // The instance is configured, check the unchangeable fields.
908 if ((OldConfigData
->SwAddressType
!= ConfigData
->SwAddressType
) ||
909 (OldConfigData
->SwAddressLength
!= ConfigData
->SwAddressLength
) ||
911 OldConfigData
->StationAddress
,
912 ConfigData
->StationAddress
,
913 OldConfigData
->SwAddressLength
916 // Deny the unallowed changes.
918 return EFI_ACCESS_DENIED
;
922 // The instance is not configured.
925 if (ConfigData
->SwAddressType
== IPV4_ETHER_PROTO_TYPE
) {
926 CopyMem (&Ip
, ConfigData
->StationAddress
, sizeof (IP4_ADDR
));
928 if (!Ip4IsUnicast (NTOHL (Ip
), 0)) {
930 // The station address is not a valid IPv4 unicast address.
932 return EFI_INVALID_PARAMETER
;
937 // Save the configuration.
939 CopyMem (OldConfigData
, ConfigData
, sizeof (*OldConfigData
));
941 OldConfigData
->StationAddress
= AllocatePool (OldConfigData
->SwAddressLength
);
942 if (OldConfigData
->StationAddress
== NULL
) {
943 DEBUG ((EFI_D_ERROR
, "ArpConfigInstance: AllocatePool for the StationAddress "
945 return EFI_OUT_OF_RESOURCES
;
949 // Save the StationAddress.
952 OldConfigData
->StationAddress
,
953 ConfigData
->StationAddress
,
954 OldConfigData
->SwAddressLength
958 // Set the state to configured.
960 Instance
->Configured
= TRUE
;
964 // Use the implementation specific values if the following field is zero.
966 OldConfigData
->EntryTimeOut
= (ConfigData
->EntryTimeOut
== 0) ?
967 ARP_DEFAULT_TIMEOUT_VALUE
: ConfigData
->EntryTimeOut
;
969 OldConfigData
->RetryCount
= (ConfigData
->RetryCount
== 0) ?
970 ARP_DEFAULT_RETRY_COUNT
: ConfigData
->RetryCount
;
972 OldConfigData
->RetryTimeOut
= (ConfigData
->RetryTimeOut
== 0) ?
973 ARP_DEFAULT_RETRY_INTERVAL
: ConfigData
->RetryTimeOut
;
976 // Reset the configuration.
979 if (Instance
->Configured
) {
981 // Cancel the arp requests issued by this instance.
983 Instance
->ArpProto
.Cancel (&Instance
->ArpProto
, NULL
, NULL
);
986 // Free the buffer previously allocated to hold the station address.
988 gBS
->FreePool (OldConfigData
->StationAddress
);
991 Instance
->Configured
= FALSE
;
999 Send out an arp frame using the CachEntry and the ArpOpCode.
1001 @param[in] Instance Pointer to the instance context data.
1002 @param[in] CacheEntry Pointer to the configuration data used to
1003 configure the instance.
1004 @param[in] ArpOpCode The opcode used to send out this Arp frame, either
1012 IN ARP_INSTANCE_DATA
*Instance
,
1013 IN ARP_CACHE_ENTRY
*CacheEntry
,
1018 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*TxToken
;
1019 EFI_MANAGED_NETWORK_TRANSMIT_DATA
*TxData
;
1022 ARP_SERVICE_DATA
*ArpService
;
1023 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
1024 EFI_ARP_CONFIG_DATA
*ConfigData
;
1028 ASSERT ((Instance
!= NULL
) && (CacheEntry
!= NULL
));
1031 // Allocate memory for the TxToken.
1033 TxToken
= AllocatePool (sizeof(EFI_MANAGED_NETWORK_COMPLETION_TOKEN
));
1034 if (TxToken
== NULL
) {
1035 DEBUG ((EFI_D_ERROR
, "ArpSendFrame: Allocate memory for TxToken failed.\n"));
1039 TxToken
->Event
= NULL
;
1044 // Create the event for this TxToken.
1046 Status
= gBS
->CreateEvent (
1053 if (EFI_ERROR (Status
)) {
1054 DEBUG ((EFI_D_ERROR
, "ArpSendFrame: CreateEvent failed for TxToken->Event.\n"));
1059 // Allocate memory for the TxData used in the TxToken.
1061 TxData
= AllocatePool (sizeof(EFI_MANAGED_NETWORK_TRANSMIT_DATA
));
1062 if (TxData
== NULL
) {
1063 DEBUG ((EFI_D_ERROR
, "ArpSendFrame: Allocate memory for TxData failed.\n"));
1067 ArpService
= Instance
->ArpService
;
1068 SnpMode
= &ArpService
->SnpMode
;
1069 ConfigData
= &Instance
->ConfigData
;
1072 // Calculate the buffer length for this arp frame.
1074 TotalLength
= SnpMode
->MediaHeaderSize
+ sizeof (ARP_HEAD
) +
1075 2 * (ConfigData
->SwAddressLength
+ SnpMode
->HwAddressSize
);
1078 // Allocate buffer for the arp frame.
1080 Packet
= AllocatePool (TotalLength
);
1081 if (Packet
== NULL
) {
1082 DEBUG ((EFI_D_ERROR
, "ArpSendFrame: Allocate memory for Packet failed.\n"));
1088 // The destination MAC address.
1090 if (ArpOpCode
== ARP_OPCODE_REQUEST
) {
1091 CopyMem (TmpPtr
, &SnpMode
->BroadcastAddress
, SnpMode
->HwAddressSize
);
1095 CacheEntry
->Addresses
[Hardware
].AddressPtr
,
1096 SnpMode
->HwAddressSize
1099 TmpPtr
+= SnpMode
->HwAddressSize
;
1102 // The source MAC address.
1104 CopyMem (TmpPtr
, &SnpMode
->CurrentAddress
, SnpMode
->HwAddressSize
);
1105 TmpPtr
+= SnpMode
->HwAddressSize
;
1108 // The ethernet protocol type.
1110 *(UINT16
*)TmpPtr
= HTONS (ARP_ETHER_PROTO_TYPE
);
1116 ArpHead
= (ARP_HEAD
*) TmpPtr
;
1117 ArpHead
->HwType
= HTONS ((UINT16
)SnpMode
->IfType
);
1118 ArpHead
->ProtoType
= HTONS (ConfigData
->SwAddressType
);
1119 ArpHead
->HwAddrLen
= (UINT8
)SnpMode
->HwAddressSize
;
1120 ArpHead
->ProtoAddrLen
= ConfigData
->SwAddressLength
;
1121 ArpHead
->OpCode
= HTONS (ArpOpCode
);
1122 TmpPtr
+= sizeof (ARP_HEAD
);
1125 // The sender hardware address.
1127 CopyMem (TmpPtr
, &SnpMode
->CurrentAddress
, SnpMode
->HwAddressSize
);
1128 TmpPtr
+= SnpMode
->HwAddressSize
;
1131 // The sender protocol address.
1133 CopyMem (TmpPtr
, ConfigData
->StationAddress
, ConfigData
->SwAddressLength
);
1134 TmpPtr
+= ConfigData
->SwAddressLength
;
1137 // The target hardware address.
1141 CacheEntry
->Addresses
[Hardware
].AddressPtr
,
1142 SnpMode
->HwAddressSize
1144 TmpPtr
+= SnpMode
->HwAddressSize
;
1147 // The target protocol address.
1151 CacheEntry
->Addresses
[Protocol
].AddressPtr
,
1152 ConfigData
->SwAddressLength
1156 // Set all the fields of the TxData.
1158 TxData
->DestinationAddress
= NULL
;
1159 TxData
->SourceAddress
= NULL
;
1160 TxData
->ProtocolType
= 0;
1161 TxData
->DataLength
= TotalLength
- SnpMode
->MediaHeaderSize
;
1162 TxData
->HeaderLength
= (UINT16
) SnpMode
->MediaHeaderSize
;
1163 TxData
->FragmentCount
= 1;
1165 TxData
->FragmentTable
[0].FragmentBuffer
= Packet
;
1166 TxData
->FragmentTable
[0].FragmentLength
= TotalLength
;
1169 // Associate the TxData with the TxToken.
1171 TxToken
->Packet
.TxData
= TxData
;
1172 TxToken
->Status
= EFI_NOT_READY
;
1175 // Send out this arp packet by Mnp.
1177 Status
= ArpService
->Mnp
->Transmit (ArpService
->Mnp
, TxToken
);
1178 if (EFI_ERROR (Status
)) {
1179 DEBUG ((EFI_D_ERROR
, "Mnp->Transmit failed, %r.\n", Status
));
1187 if (Packet
!= NULL
) {
1188 gBS
->FreePool (Packet
);
1191 if (TxData
!= NULL
) {
1192 gBS
->FreePool (TxData
);
1195 if (TxToken
->Event
!= NULL
) {
1196 gBS
->CloseEvent (TxToken
->Event
);
1199 gBS
->FreePool (TxToken
);
1204 Delete the cache entries in the specified CacheTable, using the BySwAddress,
1205 SwAddressType, AddressBuffer combination as the matching key, if Force is TRUE,
1206 the cache is deleted event it's a static entry.
1208 @param[in] CacheTable Pointer to the cache table to do the deletion.
1209 @param[in] BySwAddress Delete the cache entry by software address or by
1211 @param[in] SwAddressType The software address used to do the deletion.
1212 @param[in] AddressBuffer Pointer to the buffer containing the address to
1213 match for the deletion.
1214 @param[in] Force This deletion is forced or not.
1216 @return The count of the deleted cache entries.
1220 ArpDeleteCacheEntryInTable (
1221 IN LIST_ENTRY
*CacheTable
,
1222 IN BOOLEAN BySwAddress
,
1223 IN UINT16 SwAddressType
,
1224 IN UINT8
*AddressBuffer OPTIONAL
,
1229 LIST_ENTRY
*NextEntry
;
1230 ARP_CACHE_ENTRY
*CacheEntry
;
1235 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, CacheTable
) {
1236 CacheEntry
= NET_LIST_USER_STRUCT (Entry
, ARP_CACHE_ENTRY
, List
);
1238 if ((CacheEntry
->DefaultDecayTime
== 0) && !Force
) {
1240 // It's a static entry and we are not forced to delete it, skip.
1246 if (SwAddressType
== CacheEntry
->Addresses
[Protocol
].Type
) {
1248 // Protocol address type matched. Check the address.
1250 if ((AddressBuffer
== NULL
) ||
1253 CacheEntry
->Addresses
[Protocol
].AddressPtr
,
1254 CacheEntry
->Addresses
[Protocol
].Length
1263 if ((AddressBuffer
== NULL
) ||
1266 CacheEntry
->Addresses
[Hardware
].AddressPtr
,
1267 CacheEntry
->Addresses
[Hardware
].Length
1281 // Delete this entry.
1283 RemoveEntryList (&CacheEntry
->List
);
1284 ASSERT (IsListEmpty (&CacheEntry
->UserRequestList
));
1285 gBS
->FreePool (CacheEntry
);
1295 Delete cache entries in all the cache tables.
1297 @param[in] Instance Pointer to the instance context data.
1298 @param[in] BySwAddress Delete the cache entry by software address or by
1300 @param[in] AddressBuffer Pointer to the buffer containing the address to
1301 match for the deletion.
1302 @param[in] Force This deletion is forced or not.
1304 @return The count of the deleted cache entries.
1308 ArpDeleteCacheEntry (
1309 IN ARP_INSTANCE_DATA
*Instance
,
1310 IN BOOLEAN BySwAddress
,
1311 IN UINT8
*AddressBuffer OPTIONAL
,
1315 ARP_SERVICE_DATA
*ArpService
;
1318 NET_CHECK_SIGNATURE (Instance
, ARP_INSTANCE_DATA_SIGNATURE
);
1320 ArpService
= Instance
->ArpService
;
1323 // Delete the cache entries in the DeniedCacheTable.
1325 Count
= ArpDeleteCacheEntryInTable (
1326 &ArpService
->DeniedCacheTable
,
1328 Instance
->ConfigData
.SwAddressType
,
1334 // Delete the cache entries inthe ResolvedCacheTable.
1336 Count
+= ArpDeleteCacheEntryInTable (
1337 &ArpService
->ResolvedCacheTable
,
1339 Instance
->ConfigData
.SwAddressType
,
1349 Cancel the arp request.
1351 @param[in] Instance Pointer to the instance context data.
1352 @param[in] TargetSwAddress Pointer to the buffer containing the target
1353 software address to match the arp request.
1354 @param[in] UserEvent The user event used to notify this request
1357 @return The count of the cancelled requests.
1362 IN ARP_INSTANCE_DATA
*Instance
,
1363 IN VOID
*TargetSwAddress OPTIONAL
,
1364 IN EFI_EVENT UserEvent OPTIONAL
1367 ARP_SERVICE_DATA
*ArpService
;
1369 LIST_ENTRY
*NextEntry
;
1370 ARP_CACHE_ENTRY
*CacheEntry
;
1373 NET_CHECK_SIGNATURE (Instance
, ARP_INSTANCE_DATA_SIGNATURE
);
1375 ArpService
= Instance
->ArpService
;
1378 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &ArpService
->PendingRequestTable
) {
1379 CacheEntry
= NET_LIST_USER_STRUCT (Entry
, ARP_CACHE_ENTRY
, List
);
1381 if ((TargetSwAddress
== NULL
) ||
1384 CacheEntry
->Addresses
[Protocol
].AddressPtr
,
1385 CacheEntry
->Addresses
[Protocol
].Length
1388 // This request entry matches the TargetSwAddress or all requests are to be
1389 // cancelled as TargetSwAddress is NULL.
1391 Count
+= ArpAddressResolved (CacheEntry
, Instance
, UserEvent
);
1393 if (IsListEmpty (&CacheEntry
->UserRequestList
)) {
1395 // No user requests any more, remove this request cache entry.
1397 RemoveEntryList (&CacheEntry
->List
);
1398 gBS
->FreePool (CacheEntry
);
1408 Find the cache entry in the cache table.
1410 @param[in] Instance Pointer to the instance context data.
1411 @param[in] BySwAddress Set to TRUE to look for matching software protocol
1412 addresses. Set to FALSE to look for matching
1413 hardware protocol addresses.
1414 @param[in] AddressBuffer Pointer to address buffer. Set to NULL to match
1416 @param[out] EntryLength The size of an entry in the entries buffer.
1417 @param[out] EntryCount The number of ARP cache entries that are found by
1418 the specified criteria.
1419 @param[out] Entries Pointer to the buffer that will receive the ARP
1421 @param[in] Refresh Set to TRUE to refresh the timeout value of the
1422 matching ARP cache entry.
1424 @retval EFI_SUCCESS The requested ARP cache entries are copied into
1426 @retval EFI_NOT_FOUND No matching entries found.
1427 @retval EFI_OUT_OF_RESOURCE There is a memory allocation failure.
1432 IN ARP_INSTANCE_DATA
*Instance
,
1433 IN BOOLEAN BySwAddress
,
1434 IN VOID
*AddressBuffer OPTIONAL
,
1435 OUT UINT32
*EntryLength OPTIONAL
,
1436 OUT UINT32
*EntryCount OPTIONAL
,
1437 OUT EFI_ARP_FIND_DATA
**Entries OPTIONAL
,
1442 ARP_SERVICE_DATA
*ArpService
;
1443 NET_ARP_ADDRESS MatchAddress
;
1444 FIND_OPTYPE FindOpType
;
1445 LIST_ENTRY
*StartEntry
;
1446 ARP_CACHE_ENTRY
*CacheEntry
;
1447 NET_MAP FoundEntries
;
1449 EFI_ARP_FIND_DATA
*FindData
;
1450 LIST_ENTRY
*CacheTable
;
1452 ArpService
= Instance
->ArpService
;
1455 // Init the FounEntries used to hold the found cache entries.
1457 NetMapInit (&FoundEntries
);
1460 // Set the MatchAddress.
1463 MatchAddress
.Type
= Instance
->ConfigData
.SwAddressType
;
1464 MatchAddress
.Length
= Instance
->ConfigData
.SwAddressLength
;
1465 FindOpType
= ByProtoAddress
;
1467 MatchAddress
.Type
= ArpService
->SnpMode
.IfType
;
1468 MatchAddress
.Length
= (UINT8
)ArpService
->SnpMode
.HwAddressSize
;
1469 FindOpType
= ByHwAddress
;
1472 MatchAddress
.AddressPtr
= AddressBuffer
;
1475 // Search the DeniedCacheTable
1480 // Try to find the matched entries in the DeniedCacheTable.
1482 CacheEntry
= ArpFindNextCacheEntryInTable (
1483 &ArpService
->DeniedCacheTable
,
1489 if (CacheEntry
== NULL
) {
1491 // Once the CacheEntry is NULL, there are no more matches.
1497 // Insert the found entry into the map.
1502 (VOID
*)&ArpService
->DeniedCacheTable
1506 // Let the next search start from this cache entry.
1508 StartEntry
= &CacheEntry
->List
;
1512 // Refresh the DecayTime if needed.
1514 CacheEntry
->DecayTime
= CacheEntry
->DefaultDecayTime
;
1519 // Search the ResolvedCacheTable
1523 CacheEntry
= ArpFindNextCacheEntryInTable (
1524 &ArpService
->ResolvedCacheTable
,
1530 if (CacheEntry
== NULL
) {
1532 // Once the CacheEntry is NULL, there are no more matches.
1538 // Insert the found entry into the map.
1543 (VOID
*)&ArpService
->ResolvedCacheTable
1547 // Let the next search start from this cache entry.
1549 StartEntry
= &CacheEntry
->List
;
1553 // Refresh the DecayTime if needed.
1555 CacheEntry
->DecayTime
= CacheEntry
->DefaultDecayTime
;
1559 Status
= EFI_SUCCESS
;
1561 FoundCount
= (UINT32
) NetMapGetCount (&FoundEntries
);
1562 if (FoundCount
== 0) {
1563 Status
= EFI_NOT_FOUND
;
1567 if (EntryLength
!= NULL
) {
1569 // Return the entry length, make sure its 8 bytes alignment.
1571 *EntryLength
= (((sizeof (EFI_ARP_FIND_DATA
) + Instance
->ConfigData
.SwAddressLength
+
1572 ArpService
->SnpMode
.HwAddressSize
) + 3) & ~(0x3));
1575 if (EntryCount
!= NULL
) {
1577 // Return the found entry count.
1579 *EntryCount
= FoundCount
;
1582 if (Entries
== NULL
) {
1587 // Allocate buffer to copy the found entries.
1589 FindData
= AllocatePool (FoundCount
* (*EntryLength
));
1590 if (FindData
== NULL
) {
1591 DEBUG ((EFI_D_ERROR
, "ArpFindCacheEntry: Failed to allocate memory.\n"));
1592 Status
= EFI_OUT_OF_RESOURCES
;
1597 // Return the address to the user.
1599 *Entries
= FindData
;
1602 // Dump the entries.
1604 while (!NetMapIsEmpty (&FoundEntries
)) {
1606 // Get a cache entry from the map.
1608 CacheEntry
= NetMapRemoveHead (&FoundEntries
, (VOID
**)&CacheTable
);
1611 // Set the fields in FindData.
1613 FindData
->Size
= *EntryLength
;
1614 FindData
->DenyFlag
= (BOOLEAN
)(CacheTable
== &ArpService
->DeniedCacheTable
);
1615 FindData
->StaticFlag
= (BOOLEAN
)(CacheEntry
->DefaultDecayTime
== 0);
1616 FindData
->HwAddressType
= ArpService
->SnpMode
.IfType
;
1617 FindData
->SwAddressType
= Instance
->ConfigData
.SwAddressType
;
1618 FindData
->HwAddressLength
= (UINT8
)ArpService
->SnpMode
.HwAddressSize
;
1619 FindData
->SwAddressLength
= Instance
->ConfigData
.SwAddressLength
;
1622 // Copy the software address.
1626 CacheEntry
->Addresses
[Protocol
].AddressPtr
,
1627 FindData
->SwAddressLength
1631 // Copy the hardware address.
1634 (UINT8
*)(FindData
+ 1) + FindData
->SwAddressLength
,
1635 CacheEntry
->Addresses
[Hardware
].AddressPtr
,
1636 FindData
->HwAddressLength
1640 // Slip to the next FindData.
1642 FindData
= (EFI_ARP_FIND_DATA
*)((UINT8
*)FindData
+ *EntryLength
);
1647 NetMapClean (&FoundEntries
);