]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/ArpDxe/ArpImpl.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / NetworkPkg / ArpDxe / ArpImpl.c
1 /** @file
2 The implementation of the ARP protocol.
3
4 Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "ArpImpl.h"
10
11 //
12 // Global variable of EFI ARP Protocol Interface.
13 //
14 EFI_ARP_PROTOCOL mEfiArpProtocolTemplate = {
15 ArpConfigure,
16 ArpAdd,
17 ArpFind,
18 ArpDelete,
19 ArpFlush,
20 ArpRequest,
21 ArpCancel
22 };
23
24 /**
25 Initialize the instance context data.
26
27 @param[in] ArpService Pointer to the arp service context data this
28 instance belongs to.
29 @param[out] Instance Pointer to the instance context data.
30
31 @return None.
32
33 **/
34 VOID
35 ArpInitInstance (
36 IN ARP_SERVICE_DATA *ArpService,
37 OUT ARP_INSTANCE_DATA *Instance
38 )
39 {
40 NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);
41
42 Instance->Signature = ARP_INSTANCE_DATA_SIGNATURE;
43 Instance->ArpService = ArpService;
44
45 CopyMem (&Instance->ArpProto, &mEfiArpProtocolTemplate, sizeof (Instance->ArpProto));
46
47 Instance->Configured = FALSE;
48 Instance->InDestroy = FALSE;
49
50 InitializeListHead (&Instance->List);
51 }
52
53 /**
54 Process the Arp packets received from Mnp, the procedure conforms to RFC826.
55
56 @param[in] Context Pointer to the context data registered to the
57 Event.
58
59 @return None.
60
61 **/
62 VOID
63 EFIAPI
64 ArpOnFrameRcvdDpc (
65 IN VOID *Context
66 )
67 {
68 EFI_STATUS Status;
69 ARP_SERVICE_DATA *ArpService;
70 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *RxToken;
71 EFI_MANAGED_NETWORK_RECEIVE_DATA *RxData;
72 ARP_HEAD *Head;
73 ARP_ADDRESS ArpAddress;
74 ARP_CACHE_ENTRY *CacheEntry;
75 LIST_ENTRY *Entry;
76 ARP_INSTANCE_DATA *Instance;
77 EFI_ARP_CONFIG_DATA *ConfigData;
78 NET_ARP_ADDRESS SenderAddress[2];
79 BOOLEAN ProtoMatched;
80 BOOLEAN IsTarget;
81 BOOLEAN MergeFlag;
82
83 ArpService = (ARP_SERVICE_DATA *)Context;
84 NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);
85
86 RxToken = &ArpService->RxToken;
87
88 if (RxToken->Status == EFI_ABORTED) {
89 //
90 // The Token is aborted, possibly by arp itself, just return and the receiving
91 // process is stopped.
92 //
93 return;
94 }
95
96 if (EFI_ERROR (RxToken->Status)) {
97 //
98 // Restart the receiving if any other error Status occurs.
99 //
100 goto RESTART_RECEIVE;
101 }
102
103 //
104 // Status is EFI_SUCCESS, process the received frame.
105 //
106 RxData = RxToken->Packet.RxData;
107 //
108 // Sanity check.
109 //
110 if (RxData->DataLength < sizeof (ARP_HEAD)) {
111 //
112 // Restart the receiving if packet size is not correct.
113 //
114 goto RECYCLE_RXDATA;
115 }
116
117 //
118 // Convert the byte order of the multi-byte fields.
119 //
120 Head = (ARP_HEAD *)RxData->PacketData;
121 Head->HwType = NTOHS (Head->HwType);
122 Head->ProtoType = NTOHS (Head->ProtoType);
123 Head->OpCode = NTOHS (Head->OpCode);
124
125 if (RxData->DataLength < (sizeof (ARP_HEAD) + 2 * Head->HwAddrLen + 2 * Head->ProtoAddrLen)) {
126 goto RECYCLE_RXDATA;
127 }
128
129 if ((Head->HwType != ArpService->SnpMode.IfType) ||
130 (Head->HwAddrLen != ArpService->SnpMode.HwAddressSize) ||
131 (RxData->ProtocolType != ARP_ETHER_PROTO_TYPE))
132 {
133 //
134 // The hardware type or the hardware address length doesn't match.
135 // There is a sanity check for the protocol type too.
136 //
137 goto RECYCLE_RXDATA;
138 }
139
140 //
141 // Set the pointers to the addresses contained in the arp packet.
142 //
143 ArpAddress.SenderHwAddr = (UINT8 *)(Head + 1);
144 ArpAddress.SenderProtoAddr = ArpAddress.SenderHwAddr + Head->HwAddrLen;
145 ArpAddress.TargetHwAddr = ArpAddress.SenderProtoAddr + Head->ProtoAddrLen;
146 ArpAddress.TargetProtoAddr = ArpAddress.TargetHwAddr + Head->HwAddrLen;
147
148 SenderAddress[Hardware].Type = Head->HwType;
149 SenderAddress[Hardware].Length = Head->HwAddrLen;
150 SenderAddress[Hardware].AddressPtr = ArpAddress.SenderHwAddr;
151
152 SenderAddress[Protocol].Type = Head->ProtoType;
153 SenderAddress[Protocol].Length = Head->ProtoAddrLen;
154 SenderAddress[Protocol].AddressPtr = ArpAddress.SenderProtoAddr;
155
156 //
157 // First, check the denied cache table.
158 //
159 CacheEntry = ArpFindDeniedCacheEntry (
160 ArpService,
161 &SenderAddress[Protocol],
162 &SenderAddress[Hardware]
163 );
164 if (CacheEntry != NULL) {
165 //
166 // This address (either hardware or protocol address, or both) is configured to
167 // be a deny entry, silently skip the normal process.
168 //
169 goto RECYCLE_RXDATA;
170 }
171
172 ProtoMatched = FALSE;
173 IsTarget = FALSE;
174 Instance = NULL;
175 NET_LIST_FOR_EACH (Entry, &ArpService->ChildrenList) {
176 //
177 // Iterate all the children.
178 //
179 Instance = NET_LIST_USER_STRUCT (Entry, ARP_INSTANCE_DATA, List);
180 NET_CHECK_SIGNATURE (Instance, ARP_INSTANCE_DATA_SIGNATURE);
181 ConfigData = &Instance->ConfigData;
182
183 if ((Instance->Configured) &&
184 (Head->ProtoType == ConfigData->SwAddressType) &&
185 (Head->ProtoAddrLen == ConfigData->SwAddressLength))
186 {
187 //
188 // The protocol type is matched for the received arp packet.
189 //
190 ProtoMatched = TRUE;
191 if (0 == CompareMem (
192 (VOID *)ArpAddress.TargetProtoAddr,
193 ConfigData->StationAddress,
194 ConfigData->SwAddressLength
195 ))
196 {
197 //
198 // The arp driver has the target address required by the received arp packet.
199 //
200 IsTarget = TRUE;
201 break;
202 }
203 }
204 }
205
206 if (!ProtoMatched) {
207 //
208 // Protocol type unmatchable, skip.
209 //
210 goto RECYCLE_RXDATA;
211 }
212
213 //
214 // Check whether the sender's address information is already in the cache.
215 //
216 MergeFlag = FALSE;
217 CacheEntry = ArpFindNextCacheEntryInTable (
218 &ArpService->ResolvedCacheTable,
219 NULL,
220 ByProtoAddress,
221 &SenderAddress[Protocol],
222 NULL
223 );
224 if (CacheEntry != NULL) {
225 //
226 // Update the entry with the new information.
227 //
228 ArpFillAddressInCacheEntry (CacheEntry, &SenderAddress[Hardware], NULL);
229 CacheEntry->DecayTime = CacheEntry->DefaultDecayTime;
230 MergeFlag = TRUE;
231 }
232
233 if (!IsTarget) {
234 //
235 // This arp packet isn't targeted to us, skip now.
236 //
237 goto RECYCLE_RXDATA;
238 }
239
240 if (!MergeFlag) {
241 //
242 // Add the triplet <protocol type, sender protocol address, sender hardware address>
243 // to the translation table.
244 //
245 CacheEntry = ArpFindNextCacheEntryInTable (
246 &ArpService->PendingRequestTable,
247 NULL,
248 ByProtoAddress,
249 &SenderAddress[Protocol],
250 NULL
251 );
252 if (CacheEntry == NULL) {
253 //
254 // Allocate a new CacheEntry.
255 //
256 CacheEntry = ArpAllocCacheEntry (NULL);
257 if (CacheEntry == NULL) {
258 goto RECYCLE_RXDATA;
259 }
260 }
261
262 if (!IsListEmpty (&CacheEntry->List)) {
263 RemoveEntryList (&CacheEntry->List);
264 }
265
266 //
267 // Fill the addresses into the CacheEntry.
268 //
269 ArpFillAddressInCacheEntry (
270 CacheEntry,
271 &SenderAddress[Hardware],
272 &SenderAddress[Protocol]
273 );
274
275 //
276 // Inform the user.
277 //
278 ArpAddressResolved (CacheEntry, NULL, NULL);
279
280 //
281 // Add this entry into the ResolvedCacheTable
282 //
283 InsertHeadList (&ArpService->ResolvedCacheTable, &CacheEntry->List);
284 }
285
286 if (Head->OpCode == ARP_OPCODE_REQUEST) {
287 //
288 // Send back the ARP Reply. If we reach here, Instance is not NULL and CacheEntry
289 // is not NULL.
290 //
291 ArpSendFrame (Instance, CacheEntry, ARP_OPCODE_REPLY);
292 }
293
294 RECYCLE_RXDATA:
295
296 //
297 // Signal Mnp to recycle the RxData.
298 //
299 gBS->SignalEvent (RxData->RecycleEvent);
300
301 RESTART_RECEIVE:
302
303 //
304 // Continue to receive packets from Mnp.
305 //
306 Status = ArpService->Mnp->Receive (ArpService->Mnp, RxToken);
307
308 DEBUG_CODE_BEGIN ();
309 if (EFI_ERROR (Status)) {
310 DEBUG ((
311 DEBUG_ERROR,
312 "ArpOnFrameRcvd: ArpService->Mnp->Receive "
313 "failed, %r\n.",
314 Status
315 ));
316 }
317
318 DEBUG_CODE_END ();
319 }
320
321 /**
322 Queue ArpOnFrameRcvdDpc as a DPC at TPL_CALLBACK.
323
324 @param[in] Event The Event this notify function registered to.
325 @param[in] Context Pointer to the context data registered to the
326 Event.
327
328 @return None.
329
330 **/
331 VOID
332 EFIAPI
333 ArpOnFrameRcvd (
334 IN EFI_EVENT Event,
335 IN VOID *Context
336 )
337 {
338 //
339 // Request ArpOnFrameRcvdDpc as a DPC at TPL_CALLBACK
340 //
341 QueueDpc (TPL_CALLBACK, ArpOnFrameRcvdDpc, Context);
342 }
343
344 /**
345 Process the already sent arp packets.
346
347 @param[in] Context Pointer to the context data registered to the
348 Event.
349
350 @return None.
351
352 **/
353 VOID
354 EFIAPI
355 ArpOnFrameSentDpc (
356 IN VOID *Context
357 )
358 {
359 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TxToken;
360 EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData;
361
362 ASSERT (Context != NULL);
363
364 TxToken = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *)Context;
365 TxData = TxToken->Packet.TxData;
366
367 DEBUG_CODE_BEGIN ();
368 if (EFI_ERROR (TxToken->Status)) {
369 DEBUG ((DEBUG_ERROR, "ArpOnFrameSent: TxToken->Status, %r.\n", TxToken->Status));
370 }
371
372 DEBUG_CODE_END ();
373
374 //
375 // Free the allocated memory and close the event.
376 //
377 FreePool (TxData->FragmentTable[0].FragmentBuffer);
378 FreePool (TxData);
379 gBS->CloseEvent (TxToken->Event);
380 FreePool (TxToken);
381 }
382
383 /**
384 Request ArpOnFrameSentDpc as a DPC at TPL_CALLBACK.
385
386 @param[in] Event The Event this notify function registered to.
387 @param[in] Context Pointer to the context data registered to the
388 Event.
389
390 @return None.
391
392 **/
393 VOID
394 EFIAPI
395 ArpOnFrameSent (
396 IN EFI_EVENT Event,
397 IN VOID *Context
398 )
399 {
400 //
401 // Request ArpOnFrameSentDpc as a DPC at TPL_CALLBACK
402 //
403 QueueDpc (TPL_CALLBACK, ArpOnFrameSentDpc, Context);
404 }
405
406 /**
407 Process the arp cache olding and drive the retrying arp requests.
408
409 @param[in] Event The Event this notify function registered to.
410 @param[in] Context Pointer to the context data registered to the
411 Event.
412
413 @return None.
414
415 **/
416 VOID
417 EFIAPI
418 ArpTimerHandler (
419 IN EFI_EVENT Event,
420 IN VOID *Context
421 )
422 {
423 ARP_SERVICE_DATA *ArpService;
424 LIST_ENTRY *Entry;
425 LIST_ENTRY *NextEntry;
426 LIST_ENTRY *ContextEntry;
427 ARP_CACHE_ENTRY *CacheEntry;
428 USER_REQUEST_CONTEXT *RequestContext;
429
430 ASSERT (Context != NULL);
431 ArpService = (ARP_SERVICE_DATA *)Context;
432
433 //
434 // Iterate all the pending requests to see whether a retry is needed to send out
435 // or the request finally fails because the retry time reaches the limitation.
436 //
437 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &ArpService->PendingRequestTable) {
438 CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);
439
440 if (CacheEntry->NextRetryTime <= ARP_PERIODIC_TIMER_INTERVAL) {
441 //
442 // Timeout, if we can retry more, send out the request again, otherwise abort
443 // this request.
444 //
445 if (CacheEntry->RetryCount == 0) {
446 //
447 // Abort this request.
448 //
449 ArpAddressResolved (CacheEntry, NULL, NULL);
450 ASSERT (IsListEmpty (&CacheEntry->UserRequestList));
451
452 RemoveEntryList (&CacheEntry->List);
453 FreePool (CacheEntry);
454 } else {
455 //
456 // resend the ARP request.
457 //
458 ASSERT (!IsListEmpty (&CacheEntry->UserRequestList));
459
460 ContextEntry = CacheEntry->UserRequestList.ForwardLink;
461 RequestContext = NET_LIST_USER_STRUCT (ContextEntry, USER_REQUEST_CONTEXT, List);
462
463 ArpSendFrame (RequestContext->Instance, CacheEntry, ARP_OPCODE_REQUEST);
464
465 CacheEntry->RetryCount--;
466 CacheEntry->NextRetryTime = RequestContext->Instance->ConfigData.RetryTimeOut;
467 }
468 } else {
469 //
470 // Update the NextRetryTime.
471 //
472 CacheEntry->NextRetryTime -= ARP_PERIODIC_TIMER_INTERVAL;
473 }
474 }
475
476 //
477 // Check the timeouts for the DeniedCacheTable.
478 //
479 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &ArpService->DeniedCacheTable) {
480 CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);
481 ASSERT (IsListEmpty (&CacheEntry->UserRequestList));
482
483 if (CacheEntry->DefaultDecayTime == 0) {
484 //
485 // It's a static entry, skip it.
486 //
487 continue;
488 }
489
490 if (CacheEntry->DecayTime <= ARP_PERIODIC_TIMER_INTERVAL) {
491 //
492 // Time out, remove it.
493 //
494 RemoveEntryList (&CacheEntry->List);
495 FreePool (CacheEntry);
496 } else {
497 //
498 // Update the DecayTime.
499 //
500 CacheEntry->DecayTime -= ARP_PERIODIC_TIMER_INTERVAL;
501 }
502 }
503
504 //
505 // Check the timeouts for the ResolvedCacheTable.
506 //
507 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &ArpService->ResolvedCacheTable) {
508 CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);
509 ASSERT (IsListEmpty (&CacheEntry->UserRequestList));
510
511 if (CacheEntry->DefaultDecayTime == 0) {
512 //
513 // It's a static entry, skip it.
514 //
515 continue;
516 }
517
518 if (CacheEntry->DecayTime <= ARP_PERIODIC_TIMER_INTERVAL) {
519 //
520 // Time out, remove it.
521 //
522 RemoveEntryList (&CacheEntry->List);
523 FreePool (CacheEntry);
524 } else {
525 //
526 // Update the DecayTime.
527 //
528 CacheEntry->DecayTime -= ARP_PERIODIC_TIMER_INTERVAL;
529 }
530 }
531 }
532
533 /**
534 Match the two NET_ARP_ADDRESSes.
535
536 @param[in] AddressOne Pointer to the first address to match.
537 @param[in] AddressTwo Pointer to the second address to match.
538
539 @return The two addresses match or not.
540
541 **/
542 BOOLEAN
543 ArpMatchAddress (
544 IN NET_ARP_ADDRESS *AddressOne,
545 IN NET_ARP_ADDRESS *AddressTwo
546 )
547 {
548 ASSERT (AddressOne != NULL && AddressTwo != NULL);
549
550 if ((AddressOne->Type != AddressTwo->Type) ||
551 (AddressOne->Length != AddressTwo->Length))
552 {
553 //
554 // Either Type or Length doesn't match.
555 //
556 return FALSE;
557 }
558
559 if ((AddressOne->AddressPtr != NULL) &&
560 (CompareMem (
561 AddressOne->AddressPtr,
562 AddressTwo->AddressPtr,
563 AddressOne->Length
564 ) != 0))
565 {
566 //
567 // The address is not the same.
568 //
569 return FALSE;
570 }
571
572 return TRUE;
573 }
574
575 /**
576 Find the CacheEntry which matches the requirements in the specified CacheTable.
577
578 @param[in] CacheTable Pointer to the arp cache table.
579 @param[in] StartEntry Pointer to the start entry this search begins with
580 in the cache table.
581 @param[in] FindOpType The search type.
582 @param[in] ProtocolAddress Pointer to the protocol address to match.
583 @param[in] HardwareAddress Pointer to the hardware address to match.
584
585 @return Pointer to the matched arp cache entry, if NULL, no match is found.
586
587 **/
588 ARP_CACHE_ENTRY *
589 ArpFindNextCacheEntryInTable (
590 IN LIST_ENTRY *CacheTable,
591 IN LIST_ENTRY *StartEntry,
592 IN FIND_OPTYPE FindOpType,
593 IN NET_ARP_ADDRESS *ProtocolAddress OPTIONAL,
594 IN NET_ARP_ADDRESS *HardwareAddress OPTIONAL
595 )
596 {
597 LIST_ENTRY *Entry;
598 ARP_CACHE_ENTRY *CacheEntry;
599
600 if (StartEntry == NULL) {
601 //
602 // Start from the beginning of the table if no StartEntry is specified.
603 //
604 StartEntry = CacheTable;
605 }
606
607 for (Entry = StartEntry->ForwardLink; Entry != CacheTable; Entry = Entry->ForwardLink) {
608 CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);
609
610 if ((FindOpType & MATCH_SW_ADDRESS) != 0) {
611 //
612 // Find by the software address.
613 //
614 if (!ArpMatchAddress (ProtocolAddress, &CacheEntry->Addresses[Protocol])) {
615 //
616 // The ProtocolAddress doesn't match, continue to the next cache entry.
617 //
618 continue;
619 }
620 }
621
622 if ((FindOpType & MATCH_HW_ADDRESS) != 0) {
623 //
624 // Find by the hardware address.
625 //
626 if (!ArpMatchAddress (HardwareAddress, &CacheEntry->Addresses[Hardware])) {
627 //
628 // The HardwareAddress doesn't match, continue to the next cache entry.
629 //
630 continue;
631 }
632 }
633
634 //
635 // The CacheEntry meets the requirements now, return this entry.
636 //
637 return CacheEntry;
638 }
639
640 //
641 // No matching.
642 //
643 return NULL;
644 }
645
646 /**
647 Find the CacheEntry, using ProtocolAddress or HardwareAddress or both, as the keyword,
648 in the DeniedCacheTable.
649
650 @param[in] ArpService Pointer to the arp service context data.
651 @param[in] ProtocolAddress Pointer to the protocol address.
652 @param[in] HardwareAddress Pointer to the hardware address.
653
654 @return Pointer to the matched cache entry, if NULL no match is found.
655
656 **/
657 ARP_CACHE_ENTRY *
658 ArpFindDeniedCacheEntry (
659 IN ARP_SERVICE_DATA *ArpService,
660 IN NET_ARP_ADDRESS *ProtocolAddress OPTIONAL,
661 IN NET_ARP_ADDRESS *HardwareAddress OPTIONAL
662 )
663 {
664 ARP_CACHE_ENTRY *CacheEntry;
665
666 ASSERT ((ProtocolAddress != NULL) || (HardwareAddress != NULL));
667 NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);
668
669 CacheEntry = NULL;
670
671 if ((ProtocolAddress != NULL) && (ProtocolAddress->AddressPtr != NULL)) {
672 //
673 // Find the cache entry in the DeniedCacheTable by the protocol address.
674 //
675 CacheEntry = ArpFindNextCacheEntryInTable (
676 &ArpService->DeniedCacheTable,
677 NULL,
678 ByProtoAddress,
679 ProtocolAddress,
680 NULL
681 );
682 if (CacheEntry != NULL) {
683 //
684 // There is a match.
685 //
686 return CacheEntry;
687 }
688 }
689
690 if ((HardwareAddress != NULL) && (HardwareAddress->AddressPtr != NULL)) {
691 //
692 // Find the cache entry in the DeniedCacheTable by the hardware address.
693 //
694 CacheEntry = ArpFindNextCacheEntryInTable (
695 &ArpService->DeniedCacheTable,
696 NULL,
697 ByHwAddress,
698 NULL,
699 HardwareAddress
700 );
701 }
702
703 return CacheEntry;
704 }
705
706 /**
707 Allocate a cache entry and initialize it.
708
709 @param[in] Instance Pointer to the instance context data.
710
711 @return Pointer to the new created cache entry.
712
713 **/
714 ARP_CACHE_ENTRY *
715 ArpAllocCacheEntry (
716 IN ARP_INSTANCE_DATA *Instance
717 )
718 {
719 ARP_CACHE_ENTRY *CacheEntry;
720 NET_ARP_ADDRESS *Address;
721 UINT16 Index;
722
723 //
724 // Allocate memory for the cache entry.
725 //
726 CacheEntry = AllocatePool (sizeof (ARP_CACHE_ENTRY));
727 if (CacheEntry == NULL) {
728 return NULL;
729 }
730
731 //
732 // Init the lists.
733 //
734 InitializeListHead (&CacheEntry->List);
735 InitializeListHead (&CacheEntry->UserRequestList);
736
737 for (Index = 0; Index < 2; Index++) {
738 //
739 // Init the address pointers to point to the concrete buffer.
740 //
741 Address = &CacheEntry->Addresses[Index];
742 Address->AddressPtr = Address->Buffer.ProtoAddress;
743 }
744
745 //
746 // Zero the hardware address first.
747 //
748 ZeroMem (CacheEntry->Addresses[Hardware].AddressPtr, ARP_MAX_HARDWARE_ADDRESS_LEN);
749
750 if (Instance != NULL) {
751 //
752 // Inherit the parameters from the instance configuration.
753 //
754 CacheEntry->RetryCount = Instance->ConfigData.RetryCount;
755 CacheEntry->NextRetryTime = Instance->ConfigData.RetryTimeOut;
756 CacheEntry->DefaultDecayTime = Instance->ConfigData.EntryTimeOut;
757 CacheEntry->DecayTime = Instance->ConfigData.EntryTimeOut;
758 } else {
759 //
760 // Use the default parameters if this cache entry isn't allocate in a
761 // instance's scope.
762 //
763 CacheEntry->RetryCount = ARP_DEFAULT_RETRY_COUNT;
764 CacheEntry->NextRetryTime = ARP_DEFAULT_RETRY_INTERVAL;
765 CacheEntry->DefaultDecayTime = ARP_DEFAULT_TIMEOUT_VALUE;
766 CacheEntry->DecayTime = ARP_DEFAULT_TIMEOUT_VALUE;
767 }
768
769 return CacheEntry;
770 }
771
772 /**
773 Turn the CacheEntry into the resolved status.
774
775 @param[in] CacheEntry Pointer to the resolved cache entry.
776 @param[in] Instance Pointer to the instance context data.
777 @param[in] UserEvent Pointer to the UserEvent to notify.
778
779 @return The count of notifications sent to the instance.
780
781 **/
782 UINTN
783 ArpAddressResolved (
784 IN ARP_CACHE_ENTRY *CacheEntry,
785 IN ARP_INSTANCE_DATA *Instance OPTIONAL,
786 IN EFI_EVENT UserEvent OPTIONAL
787 )
788 {
789 LIST_ENTRY *Entry;
790 LIST_ENTRY *NextEntry;
791 USER_REQUEST_CONTEXT *Context;
792 UINTN Count;
793
794 Count = 0;
795
796 //
797 // Iterate all the linked user requests to notify them.
798 //
799 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &CacheEntry->UserRequestList) {
800 Context = NET_LIST_USER_STRUCT (Entry, USER_REQUEST_CONTEXT, List);
801
802 if (((Instance == NULL) || (Context->Instance == Instance)) &&
803 ((UserEvent == NULL) || (Context->UserRequestEvent == UserEvent)))
804 {
805 //
806 // Copy the address to the user-provided buffer and notify the user.
807 //
808 CopyMem (
809 Context->UserHwAddrBuffer,
810 CacheEntry->Addresses[Hardware].AddressPtr,
811 CacheEntry->Addresses[Hardware].Length
812 );
813 gBS->SignalEvent (Context->UserRequestEvent);
814
815 //
816 // Remove this user request and free the context data.
817 //
818 RemoveEntryList (&Context->List);
819 FreePool (Context);
820
821 Count++;
822 }
823 }
824
825 //
826 // Dispatch the DPCs queued by the NotifyFunction of the Context->UserRequestEvent.
827 //
828 DispatchDpc ();
829
830 return Count;
831 }
832
833 /**
834 Fill the addresses in the CacheEntry using the information passed in by
835 HwAddr and SwAddr.
836
837 @param[in] CacheEntry Pointer to the cache entry.
838 @param[in] HwAddr Pointer to the software address.
839 @param[in] SwAddr Pointer to the hardware address.
840
841 @return None.
842
843 **/
844 VOID
845 ArpFillAddressInCacheEntry (
846 IN ARP_CACHE_ENTRY *CacheEntry,
847 IN NET_ARP_ADDRESS *HwAddr OPTIONAL,
848 IN NET_ARP_ADDRESS *SwAddr OPTIONAL
849 )
850 {
851 NET_ARP_ADDRESS *Address[2];
852 NET_ARP_ADDRESS *CacheAddress;
853 UINT32 Index;
854
855 Address[Hardware] = HwAddr;
856 Address[Protocol] = SwAddr;
857
858 for (Index = 0; Index < 2; Index++) {
859 if (Address[Index] != NULL) {
860 //
861 // Fill the address if the passed in pointer is not NULL.
862 //
863 CacheAddress = &CacheEntry->Addresses[Index];
864
865 CacheAddress->Type = Address[Index]->Type;
866 CacheAddress->Length = Address[Index]->Length;
867
868 if (Address[Index]->AddressPtr != NULL) {
869 //
870 // Copy it if the AddressPtr points to some buffer.
871 //
872 CopyMem (
873 CacheAddress->AddressPtr,
874 Address[Index]->AddressPtr,
875 CacheAddress->Length
876 );
877 } else {
878 //
879 // Zero the corresponding address buffer in the CacheEntry.
880 //
881 ZeroMem (CacheAddress->AddressPtr, CacheAddress->Length);
882 }
883 }
884 }
885 }
886
887 /**
888 Configure the instance using the ConfigData. ConfigData is already validated.
889
890 @param[in] Instance Pointer to the instance context data to be
891 configured.
892 @param[in] ConfigData Pointer to the configuration data used to
893 configure the instance.
894
895 @retval EFI_SUCCESS The instance is configured with the ConfigData.
896 @retval EFI_ACCESS_DENIED The instance is already configured and the
897 ConfigData tries to reset some unchangeable
898 fields.
899 @retval EFI_INVALID_PARAMETER The ConfigData provides a non-unicast IPv4 address
900 when the SwAddressType is IPv4.
901 @retval EFI_OUT_OF_RESOURCES The instance fails to configure due to memory
902 limitation.
903
904 **/
905 EFI_STATUS
906 ArpConfigureInstance (
907 IN ARP_INSTANCE_DATA *Instance,
908 IN EFI_ARP_CONFIG_DATA *ConfigData OPTIONAL
909 )
910 {
911 EFI_ARP_CONFIG_DATA *OldConfigData;
912 IP4_ADDR Ip;
913
914 OldConfigData = &Instance->ConfigData;
915
916 if (ConfigData != NULL) {
917 if (Instance->Configured) {
918 //
919 // The instance is configured, check the unchangeable fields.
920 //
921 if ((OldConfigData->SwAddressType != ConfigData->SwAddressType) ||
922 (OldConfigData->SwAddressLength != ConfigData->SwAddressLength) ||
923 (CompareMem (
924 OldConfigData->StationAddress,
925 ConfigData->StationAddress,
926 OldConfigData->SwAddressLength
927 ) != 0))
928 {
929 //
930 // Deny the unallowed changes.
931 //
932 return EFI_ACCESS_DENIED;
933 }
934 } else {
935 //
936 // The instance is not configured.
937 //
938
939 if (ConfigData->SwAddressType == IPV4_ETHER_PROTO_TYPE) {
940 CopyMem (&Ip, ConfigData->StationAddress, sizeof (IP4_ADDR));
941
942 if (IP4_IS_UNSPECIFIED (Ip) || IP4_IS_LOCAL_BROADCAST (Ip)) {
943 //
944 // The station address should not be zero or broadcast address.
945 //
946 return EFI_INVALID_PARAMETER;
947 }
948 }
949
950 //
951 // Save the configuration.
952 //
953 CopyMem (OldConfigData, ConfigData, sizeof (*OldConfigData));
954
955 OldConfigData->StationAddress = AllocatePool (OldConfigData->SwAddressLength);
956 if (OldConfigData->StationAddress == NULL) {
957 DEBUG ((
958 DEBUG_ERROR,
959 "ArpConfigInstance: AllocatePool for the StationAddress "
960 "failed.\n"
961 ));
962 return EFI_OUT_OF_RESOURCES;
963 }
964
965 //
966 // Save the StationAddress.
967 //
968 CopyMem (
969 OldConfigData->StationAddress,
970 ConfigData->StationAddress,
971 OldConfigData->SwAddressLength
972 );
973
974 //
975 // Set the state to configured.
976 //
977 Instance->Configured = TRUE;
978 }
979
980 //
981 // Use the implementation specific values if the following field is zero.
982 //
983 OldConfigData->EntryTimeOut = (ConfigData->EntryTimeOut == 0) ?
984 ARP_DEFAULT_TIMEOUT_VALUE : ConfigData->EntryTimeOut;
985
986 OldConfigData->RetryCount = (ConfigData->RetryCount == 0) ?
987 ARP_DEFAULT_RETRY_COUNT : ConfigData->RetryCount;
988
989 OldConfigData->RetryTimeOut = (ConfigData->RetryTimeOut == 0) ?
990 ARP_DEFAULT_RETRY_INTERVAL : ConfigData->RetryTimeOut;
991 } else {
992 //
993 // Reset the configuration.
994 //
995
996 if (Instance->Configured) {
997 //
998 // Cancel the arp requests issued by this instance.
999 //
1000 Instance->ArpProto.Cancel (&Instance->ArpProto, NULL, NULL);
1001
1002 //
1003 // Free the buffer previously allocated to hold the station address.
1004 //
1005 FreePool (OldConfigData->StationAddress);
1006 }
1007
1008 Instance->Configured = FALSE;
1009 }
1010
1011 return EFI_SUCCESS;
1012 }
1013
1014 /**
1015 Send out an arp frame using the CacheEntry and the ArpOpCode.
1016
1017 @param[in] Instance Pointer to the instance context data.
1018 @param[in] CacheEntry Pointer to the configuration data used to
1019 configure the instance.
1020 @param[in] ArpOpCode The opcode used to send out this Arp frame, either
1021 request or reply.
1022
1023 @return None.
1024
1025 **/
1026 VOID
1027 ArpSendFrame (
1028 IN ARP_INSTANCE_DATA *Instance,
1029 IN ARP_CACHE_ENTRY *CacheEntry,
1030 IN UINT16 ArpOpCode
1031 )
1032 {
1033 EFI_STATUS Status;
1034 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TxToken;
1035 EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData;
1036 UINT32 TotalLength;
1037 UINT8 *Packet;
1038 ARP_SERVICE_DATA *ArpService;
1039 EFI_SIMPLE_NETWORK_MODE *SnpMode;
1040 EFI_ARP_CONFIG_DATA *ConfigData;
1041 UINT8 *TmpPtr;
1042 ARP_HEAD *ArpHead;
1043
1044 ASSERT ((Instance != NULL) && (CacheEntry != NULL));
1045
1046 //
1047 // Allocate memory for the TxToken.
1048 //
1049 TxToken = AllocatePool (sizeof (EFI_MANAGED_NETWORK_COMPLETION_TOKEN));
1050 if (TxToken == NULL) {
1051 DEBUG ((DEBUG_ERROR, "ArpSendFrame: Allocate memory for TxToken failed.\n"));
1052 return;
1053 }
1054
1055 TxToken->Event = NULL;
1056 TxData = NULL;
1057 Packet = NULL;
1058
1059 //
1060 // Create the event for this TxToken.
1061 //
1062 Status = gBS->CreateEvent (
1063 EVT_NOTIFY_SIGNAL,
1064 TPL_NOTIFY,
1065 ArpOnFrameSent,
1066 (VOID *)TxToken,
1067 &TxToken->Event
1068 );
1069 if (EFI_ERROR (Status)) {
1070 DEBUG ((DEBUG_ERROR, "ArpSendFrame: CreateEvent failed for TxToken->Event.\n"));
1071 goto CLEAN_EXIT;
1072 }
1073
1074 //
1075 // Allocate memory for the TxData used in the TxToken.
1076 //
1077 TxData = AllocatePool (sizeof (EFI_MANAGED_NETWORK_TRANSMIT_DATA));
1078 if (TxData == NULL) {
1079 DEBUG ((DEBUG_ERROR, "ArpSendFrame: Allocate memory for TxData failed.\n"));
1080 goto CLEAN_EXIT;
1081 }
1082
1083 ArpService = Instance->ArpService;
1084 SnpMode = &ArpService->SnpMode;
1085 ConfigData = &Instance->ConfigData;
1086
1087 //
1088 // Calculate the buffer length for this arp frame.
1089 //
1090 TotalLength = SnpMode->MediaHeaderSize + sizeof (ARP_HEAD) +
1091 2 * (ConfigData->SwAddressLength + SnpMode->HwAddressSize);
1092
1093 //
1094 // Allocate buffer for the arp frame.
1095 //
1096 Packet = AllocatePool (TotalLength);
1097 if (Packet == NULL) {
1098 DEBUG ((DEBUG_ERROR, "ArpSendFrame: Allocate memory for Packet failed.\n"));
1099 ASSERT (Packet != NULL);
1100 }
1101
1102 TmpPtr = Packet;
1103
1104 //
1105 // The destination MAC address.
1106 //
1107 if (ArpOpCode == ARP_OPCODE_REQUEST) {
1108 CopyMem (TmpPtr, &SnpMode->BroadcastAddress, SnpMode->HwAddressSize);
1109 } else {
1110 CopyMem (
1111 TmpPtr,
1112 CacheEntry->Addresses[Hardware].AddressPtr,
1113 SnpMode->HwAddressSize
1114 );
1115 }
1116
1117 TmpPtr += SnpMode->HwAddressSize;
1118
1119 //
1120 // The source MAC address.
1121 //
1122 CopyMem (TmpPtr, &SnpMode->CurrentAddress, SnpMode->HwAddressSize);
1123 TmpPtr += SnpMode->HwAddressSize;
1124
1125 //
1126 // The ethernet protocol type.
1127 //
1128 *(UINT16 *)TmpPtr = HTONS (ARP_ETHER_PROTO_TYPE);
1129 TmpPtr += 2;
1130
1131 //
1132 // The ARP Head.
1133 //
1134 ArpHead = (ARP_HEAD *)TmpPtr;
1135 ArpHead->HwType = HTONS ((UINT16)SnpMode->IfType);
1136 ArpHead->ProtoType = HTONS (ConfigData->SwAddressType);
1137 ArpHead->HwAddrLen = (UINT8)SnpMode->HwAddressSize;
1138 ArpHead->ProtoAddrLen = ConfigData->SwAddressLength;
1139 ArpHead->OpCode = HTONS (ArpOpCode);
1140 TmpPtr += sizeof (ARP_HEAD);
1141
1142 //
1143 // The sender hardware address.
1144 //
1145 CopyMem (TmpPtr, &SnpMode->CurrentAddress, SnpMode->HwAddressSize);
1146 TmpPtr += SnpMode->HwAddressSize;
1147
1148 //
1149 // The sender protocol address.
1150 //
1151 CopyMem (TmpPtr, ConfigData->StationAddress, ConfigData->SwAddressLength);
1152 TmpPtr += ConfigData->SwAddressLength;
1153
1154 //
1155 // The target hardware address.
1156 //
1157 CopyMem (
1158 TmpPtr,
1159 CacheEntry->Addresses[Hardware].AddressPtr,
1160 SnpMode->HwAddressSize
1161 );
1162 TmpPtr += SnpMode->HwAddressSize;
1163
1164 //
1165 // The target protocol address.
1166 //
1167 CopyMem (
1168 TmpPtr,
1169 CacheEntry->Addresses[Protocol].AddressPtr,
1170 ConfigData->SwAddressLength
1171 );
1172
1173 //
1174 // Set all the fields of the TxData.
1175 //
1176 TxData->DestinationAddress = NULL;
1177 TxData->SourceAddress = NULL;
1178 TxData->ProtocolType = 0;
1179 TxData->DataLength = TotalLength - SnpMode->MediaHeaderSize;
1180 TxData->HeaderLength = (UINT16)SnpMode->MediaHeaderSize;
1181 TxData->FragmentCount = 1;
1182
1183 TxData->FragmentTable[0].FragmentBuffer = Packet;
1184 TxData->FragmentTable[0].FragmentLength = TotalLength;
1185
1186 //
1187 // Associate the TxData with the TxToken.
1188 //
1189 TxToken->Packet.TxData = TxData;
1190 TxToken->Status = EFI_NOT_READY;
1191
1192 //
1193 // Send out this arp packet by Mnp.
1194 //
1195 Status = ArpService->Mnp->Transmit (ArpService->Mnp, TxToken);
1196 if (EFI_ERROR (Status)) {
1197 DEBUG ((DEBUG_ERROR, "Mnp->Transmit failed, %r.\n", Status));
1198 goto CLEAN_EXIT;
1199 }
1200
1201 return;
1202
1203 CLEAN_EXIT:
1204
1205 if (Packet != NULL) {
1206 FreePool (Packet);
1207 }
1208
1209 if (TxData != NULL) {
1210 FreePool (TxData);
1211 }
1212
1213 if (TxToken->Event != NULL) {
1214 gBS->CloseEvent (TxToken->Event);
1215 }
1216
1217 FreePool (TxToken);
1218 }
1219
1220 /**
1221 Delete the cache entries in the specified CacheTable, using the BySwAddress,
1222 SwAddressType, AddressBuffer combination as the matching key, if Force is TRUE,
1223 the cache is deleted event it's a static entry.
1224
1225 @param[in] CacheTable Pointer to the cache table to do the deletion.
1226 @param[in] BySwAddress Delete the cache entry by software address or by
1227 hardware address.
1228 @param[in] SwAddressType The software address used to do the deletion.
1229 @param[in] AddressBuffer Pointer to the buffer containing the address to
1230 match for the deletion.
1231 @param[in] Force This deletion is forced or not.
1232
1233 @return The count of the deleted cache entries.
1234
1235 **/
1236 UINTN
1237 ArpDeleteCacheEntryInTable (
1238 IN LIST_ENTRY *CacheTable,
1239 IN BOOLEAN BySwAddress,
1240 IN UINT16 SwAddressType,
1241 IN UINT8 *AddressBuffer OPTIONAL,
1242 IN BOOLEAN Force
1243 )
1244 {
1245 LIST_ENTRY *Entry;
1246 LIST_ENTRY *NextEntry;
1247 ARP_CACHE_ENTRY *CacheEntry;
1248 UINTN Count;
1249
1250 Count = 0;
1251
1252 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, CacheTable) {
1253 CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);
1254
1255 if ((CacheEntry->DefaultDecayTime == 0) && !Force) {
1256 //
1257 // It's a static entry and we are not forced to delete it, skip.
1258 //
1259 continue;
1260 }
1261
1262 if (BySwAddress) {
1263 if (SwAddressType == CacheEntry->Addresses[Protocol].Type) {
1264 //
1265 // Protocol address type matched. Check the address.
1266 //
1267 if ((AddressBuffer == NULL) ||
1268 (CompareMem (
1269 AddressBuffer,
1270 CacheEntry->Addresses[Protocol].AddressPtr,
1271 CacheEntry->Addresses[Protocol].Length
1272 ) == 0))
1273 {
1274 //
1275 // Address matched.
1276 //
1277 goto MATCHED;
1278 }
1279 }
1280 } else {
1281 if ((AddressBuffer == NULL) ||
1282 (CompareMem (
1283 AddressBuffer,
1284 CacheEntry->Addresses[Hardware].AddressPtr,
1285 CacheEntry->Addresses[Hardware].Length
1286 ) == 0))
1287 {
1288 //
1289 // Address matched.
1290 //
1291 goto MATCHED;
1292 }
1293 }
1294
1295 continue;
1296
1297 MATCHED:
1298
1299 //
1300 // Delete this entry.
1301 //
1302 RemoveEntryList (&CacheEntry->List);
1303 ASSERT (IsListEmpty (&CacheEntry->UserRequestList));
1304 FreePool (CacheEntry);
1305
1306 Count++;
1307 }
1308
1309 return Count;
1310 }
1311
1312 /**
1313 Delete cache entries in all the cache tables.
1314
1315 @param[in] Instance Pointer to the instance context data.
1316 @param[in] BySwAddress Delete the cache entry by software address or by
1317 hardware address.
1318 @param[in] AddressBuffer Pointer to the buffer containing the address to
1319 match for the deletion.
1320 @param[in] Force This deletion is forced or not.
1321
1322 @return The count of the deleted cache entries.
1323
1324 **/
1325 UINTN
1326 ArpDeleteCacheEntry (
1327 IN ARP_INSTANCE_DATA *Instance,
1328 IN BOOLEAN BySwAddress,
1329 IN UINT8 *AddressBuffer OPTIONAL,
1330 IN BOOLEAN Force
1331 )
1332 {
1333 ARP_SERVICE_DATA *ArpService;
1334 UINTN Count;
1335
1336 NET_CHECK_SIGNATURE (Instance, ARP_INSTANCE_DATA_SIGNATURE);
1337
1338 ArpService = Instance->ArpService;
1339
1340 //
1341 // Delete the cache entries in the DeniedCacheTable.
1342 //
1343 Count = ArpDeleteCacheEntryInTable (
1344 &ArpService->DeniedCacheTable,
1345 BySwAddress,
1346 Instance->ConfigData.SwAddressType,
1347 AddressBuffer,
1348 Force
1349 );
1350
1351 //
1352 // Delete the cache entries in the ResolvedCacheTable.
1353 //
1354 Count += ArpDeleteCacheEntryInTable (
1355 &ArpService->ResolvedCacheTable,
1356 BySwAddress,
1357 Instance->ConfigData.SwAddressType,
1358 AddressBuffer,
1359 Force
1360 );
1361
1362 return Count;
1363 }
1364
1365 /**
1366 Cancel the arp request.
1367
1368 @param[in] Instance Pointer to the instance context data.
1369 @param[in] TargetSwAddress Pointer to the buffer containing the target
1370 software address to match the arp request.
1371 @param[in] UserEvent The user event used to notify this request
1372 cancellation.
1373
1374 @return The count of the cancelled requests.
1375
1376 **/
1377 UINTN
1378 ArpCancelRequest (
1379 IN ARP_INSTANCE_DATA *Instance,
1380 IN VOID *TargetSwAddress OPTIONAL,
1381 IN EFI_EVENT UserEvent OPTIONAL
1382 )
1383 {
1384 ARP_SERVICE_DATA *ArpService;
1385 LIST_ENTRY *Entry;
1386 LIST_ENTRY *NextEntry;
1387 ARP_CACHE_ENTRY *CacheEntry;
1388 UINTN Count;
1389
1390 NET_CHECK_SIGNATURE (Instance, ARP_INSTANCE_DATA_SIGNATURE);
1391
1392 ArpService = Instance->ArpService;
1393
1394 Count = 0;
1395 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &ArpService->PendingRequestTable) {
1396 CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);
1397
1398 if ((TargetSwAddress == NULL) ||
1399 (CompareMem (
1400 TargetSwAddress,
1401 CacheEntry->Addresses[Protocol].AddressPtr,
1402 CacheEntry->Addresses[Protocol].Length
1403 ) == 0))
1404 {
1405 //
1406 // This request entry matches the TargetSwAddress or all requests are to be
1407 // cancelled as TargetSwAddress is NULL.
1408 //
1409 Count += ArpAddressResolved (CacheEntry, Instance, UserEvent);
1410
1411 if (IsListEmpty (&CacheEntry->UserRequestList)) {
1412 //
1413 // No user requests any more, remove this request cache entry.
1414 //
1415 RemoveEntryList (&CacheEntry->List);
1416 FreePool (CacheEntry);
1417 }
1418 }
1419 }
1420
1421 return Count;
1422 }
1423
1424 /**
1425 Find the cache entry in the cache table.
1426
1427 @param[in] Instance Pointer to the instance context data.
1428 @param[in] BySwAddress Set to TRUE to look for matching software protocol
1429 addresses. Set to FALSE to look for matching
1430 hardware protocol addresses.
1431 @param[in] AddressBuffer Pointer to address buffer. Set to NULL to match
1432 all addresses.
1433 @param[out] EntryLength The size of an entry in the entries buffer.
1434 @param[out] EntryCount The number of ARP cache entries that are found by
1435 the specified criteria.
1436 @param[out] Entries Pointer to the buffer that will receive the ARP
1437 cache entries.
1438 @param[in] Refresh Set to TRUE to refresh the timeout value of the
1439 matching ARP cache entry.
1440
1441 @retval EFI_SUCCESS The requested ARP cache entries are copied into
1442 the buffer.
1443 @retval EFI_NOT_FOUND No matching entries found.
1444 @retval EFI_OUT_OF_RESOURCE There is a memory allocation failure.
1445
1446 **/
1447 EFI_STATUS
1448 ArpFindCacheEntry (
1449 IN ARP_INSTANCE_DATA *Instance,
1450 IN BOOLEAN BySwAddress,
1451 IN VOID *AddressBuffer OPTIONAL,
1452 OUT UINT32 *EntryLength OPTIONAL,
1453 OUT UINT32 *EntryCount OPTIONAL,
1454 OUT EFI_ARP_FIND_DATA **Entries OPTIONAL,
1455 IN BOOLEAN Refresh
1456 )
1457 {
1458 EFI_STATUS Status;
1459 ARP_SERVICE_DATA *ArpService;
1460 NET_ARP_ADDRESS MatchAddress;
1461 FIND_OPTYPE FindOpType;
1462 LIST_ENTRY *StartEntry;
1463 ARP_CACHE_ENTRY *CacheEntry;
1464 NET_MAP FoundEntries;
1465 UINT32 FoundCount;
1466 EFI_ARP_FIND_DATA *FindData;
1467 LIST_ENTRY *CacheTable;
1468 UINT32 FoundEntryLength;
1469
1470 ArpService = Instance->ArpService;
1471
1472 //
1473 // Init the FoundEntries used to hold the found cache entries.
1474 //
1475 NetMapInit (&FoundEntries);
1476
1477 //
1478 // Set the MatchAddress.
1479 //
1480 if (BySwAddress) {
1481 MatchAddress.Type = Instance->ConfigData.SwAddressType;
1482 MatchAddress.Length = Instance->ConfigData.SwAddressLength;
1483 FindOpType = ByProtoAddress;
1484 } else {
1485 MatchAddress.Type = ArpService->SnpMode.IfType;
1486 MatchAddress.Length = (UINT8)ArpService->SnpMode.HwAddressSize;
1487 FindOpType = ByHwAddress;
1488 }
1489
1490 MatchAddress.AddressPtr = AddressBuffer;
1491
1492 //
1493 // Search the DeniedCacheTable
1494 //
1495 StartEntry = NULL;
1496 while (TRUE) {
1497 //
1498 // Try to find the matched entries in the DeniedCacheTable.
1499 //
1500 CacheEntry = ArpFindNextCacheEntryInTable (
1501 &ArpService->DeniedCacheTable,
1502 StartEntry,
1503 FindOpType,
1504 &MatchAddress,
1505 &MatchAddress
1506 );
1507 if (CacheEntry == NULL) {
1508 //
1509 // Once the CacheEntry is NULL, there are no more matches.
1510 //
1511 break;
1512 }
1513
1514 //
1515 // Insert the found entry into the map.
1516 //
1517 NetMapInsertTail (
1518 &FoundEntries,
1519 (VOID *)CacheEntry,
1520 (VOID *)&ArpService->DeniedCacheTable
1521 );
1522
1523 //
1524 // Let the next search start from this cache entry.
1525 //
1526 StartEntry = &CacheEntry->List;
1527
1528 if (Refresh) {
1529 //
1530 // Refresh the DecayTime if needed.
1531 //
1532 CacheEntry->DecayTime = CacheEntry->DefaultDecayTime;
1533 }
1534 }
1535
1536 //
1537 // Search the ResolvedCacheTable
1538 //
1539 StartEntry = NULL;
1540 while (TRUE) {
1541 CacheEntry = ArpFindNextCacheEntryInTable (
1542 &ArpService->ResolvedCacheTable,
1543 StartEntry,
1544 FindOpType,
1545 &MatchAddress,
1546 &MatchAddress
1547 );
1548 if (CacheEntry == NULL) {
1549 //
1550 // Once the CacheEntry is NULL, there are no more matches.
1551 //
1552 break;
1553 }
1554
1555 //
1556 // Insert the found entry into the map.
1557 //
1558 NetMapInsertTail (
1559 &FoundEntries,
1560 (VOID *)CacheEntry,
1561 (VOID *)&ArpService->ResolvedCacheTable
1562 );
1563
1564 //
1565 // Let the next search start from this cache entry.
1566 //
1567 StartEntry = &CacheEntry->List;
1568
1569 if (Refresh) {
1570 //
1571 // Refresh the DecayTime if needed.
1572 //
1573 CacheEntry->DecayTime = CacheEntry->DefaultDecayTime;
1574 }
1575 }
1576
1577 Status = EFI_SUCCESS;
1578
1579 FoundCount = (UINT32)NetMapGetCount (&FoundEntries);
1580 if (FoundCount == 0) {
1581 Status = EFI_NOT_FOUND;
1582 goto CLEAN_EXIT;
1583 }
1584
1585 //
1586 // Found the entry length, make sure its 8 bytes alignment.
1587 //
1588 FoundEntryLength = (((sizeof (EFI_ARP_FIND_DATA) + Instance->ConfigData.SwAddressLength +
1589 ArpService->SnpMode.HwAddressSize) + 3) & ~(0x3));
1590
1591 if (EntryLength != NULL) {
1592 *EntryLength = FoundEntryLength;
1593 }
1594
1595 if (EntryCount != NULL) {
1596 //
1597 // Return the found entry count.
1598 //
1599 *EntryCount = FoundCount;
1600 }
1601
1602 if (Entries == NULL) {
1603 goto CLEAN_EXIT;
1604 }
1605
1606 //
1607 // Allocate buffer to copy the found entries.
1608 //
1609 FindData = AllocatePool (FoundCount * FoundEntryLength);
1610 if (FindData == NULL) {
1611 DEBUG ((DEBUG_ERROR, "ArpFindCacheEntry: Failed to allocate memory.\n"));
1612 Status = EFI_OUT_OF_RESOURCES;
1613 goto CLEAN_EXIT;
1614 }
1615
1616 //
1617 // Return the address to the user.
1618 //
1619 *Entries = FindData;
1620
1621 //
1622 // Dump the entries.
1623 //
1624 while (!NetMapIsEmpty (&FoundEntries)) {
1625 //
1626 // Get a cache entry from the map.
1627 //
1628 CacheEntry = NetMapRemoveHead (&FoundEntries, (VOID **)&CacheTable);
1629
1630 //
1631 // Set the fields in FindData.
1632 //
1633 FindData->Size = FoundEntryLength;
1634 FindData->DenyFlag = (BOOLEAN)(CacheTable == &ArpService->DeniedCacheTable);
1635 FindData->StaticFlag = (BOOLEAN)(CacheEntry->DefaultDecayTime == 0);
1636 FindData->HwAddressType = ArpService->SnpMode.IfType;
1637 FindData->SwAddressType = Instance->ConfigData.SwAddressType;
1638 FindData->HwAddressLength = (UINT8)ArpService->SnpMode.HwAddressSize;
1639 FindData->SwAddressLength = Instance->ConfigData.SwAddressLength;
1640
1641 //
1642 // Copy the software address.
1643 //
1644 CopyMem (
1645 FindData + 1,
1646 CacheEntry->Addresses[Protocol].AddressPtr,
1647 FindData->SwAddressLength
1648 );
1649
1650 //
1651 // Copy the hardware address.
1652 //
1653 CopyMem (
1654 (UINT8 *)(FindData + 1) + FindData->SwAddressLength,
1655 CacheEntry->Addresses[Hardware].AddressPtr,
1656 FindData->HwAddressLength
1657 );
1658
1659 //
1660 // Slip to the next FindData.
1661 //
1662 FindData = (EFI_ARP_FIND_DATA *)((UINT8 *)FindData + FoundEntryLength);
1663 }
1664
1665 CLEAN_EXIT:
1666
1667 NetMapClean (&FoundEntries);
1668
1669 return Status;
1670 }