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