]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/DxeNetLib/DxeNetLib.c
ffcd70ca844109d3171ef01b10e11d5d2bf4efdd
[mirror_edk2.git] / MdeModulePkg / Library / DxeNetLib / DxeNetLib.c
1 /** @file
2 Network library.
3
4 Copyright (c) 2005 - 2009, 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
8 http://opensource.org/licenses/bsd-license.php
9
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.
12 **/
13
14 #include <Uefi.h>
15
16 #include <Protocol/DriverBinding.h>
17 #include <Protocol/ServiceBinding.h>
18 #include <Protocol/SimpleNetwork.h>
19 #include <Protocol/ManagedNetwork.h>
20 #include <Protocol/HiiConfigRouting.h>
21 #include <Protocol/ComponentName.h>
22 #include <Protocol/ComponentName2.h>
23
24 #include <Guid/NicIp4ConfigNvData.h>
25
26 #include <Library/NetLib.h>
27 #include <Library/BaseLib.h>
28 #include <Library/DebugLib.h>
29 #include <Library/BaseMemoryLib.h>
30 #include <Library/UefiBootServicesTableLib.h>
31 #include <Library/UefiRuntimeServicesTableLib.h>
32 #include <Library/MemoryAllocationLib.h>
33 #include <Library/DevicePathLib.h>
34 #include <Library/HiiLib.h>
35 #include <Library/PrintLib.h>
36
37 #define NIC_ITEM_CONFIG_SIZE sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * MAX_IP4_CONFIG_IN_VARIABLE
38
39 //
40 // All the supported IP4 maskes in host byte order.
41 //
42 GLOBAL_REMOVE_IF_UNREFERENCED IP4_ADDR gIp4AllMasks[IP4_MASK_NUM] = {
43 0x00000000,
44 0x80000000,
45 0xC0000000,
46 0xE0000000,
47 0xF0000000,
48 0xF8000000,
49 0xFC000000,
50 0xFE000000,
51
52 0xFF000000,
53 0xFF800000,
54 0xFFC00000,
55 0xFFE00000,
56 0xFFF00000,
57 0xFFF80000,
58 0xFFFC0000,
59 0xFFFE0000,
60
61 0xFFFF0000,
62 0xFFFF8000,
63 0xFFFFC000,
64 0xFFFFE000,
65 0xFFFFF000,
66 0xFFFFF800,
67 0xFFFFFC00,
68 0xFFFFFE00,
69
70 0xFFFFFF00,
71 0xFFFFFF80,
72 0xFFFFFFC0,
73 0xFFFFFFE0,
74 0xFFFFFFF0,
75 0xFFFFFFF8,
76 0xFFFFFFFC,
77 0xFFFFFFFE,
78 0xFFFFFFFF,
79 };
80
81 GLOBAL_REMOVE_IF_UNREFERENCED EFI_IPv4_ADDRESS mZeroIp4Addr = {{0, 0, 0, 0}};
82
83 //
84 // Any error level digitally larger than mNetDebugLevelMax
85 // will be silently discarded.
86 //
87 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mNetDebugLevelMax = NETDEBUG_LEVEL_ERROR;
88 GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mSyslogPacketSeq = 0xDEADBEEF;
89
90 //
91 // You can change mSyslogDstMac mSyslogDstIp and mSyslogSrcIp
92 // here to direct the syslog packets to the syslog deamon. The
93 // default is broadcast to both the ethernet and IP.
94 //
95 GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mSyslogDstMac[NET_ETHER_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
96 GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mSyslogDstIp = 0xffffffff;
97 GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mSyslogSrcIp = 0;
98
99 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 *mMonthName[] = {
100 "Jan",
101 "Feb",
102 "Mar",
103 "Apr",
104 "May",
105 "Jun",
106 "Jul",
107 "Aug",
108 "Sep",
109 "Oct",
110 "Nov",
111 "Dec"
112 };
113
114 /**
115 Locate the handles that support SNP, then open one of them
116 to send the syslog packets. The caller isn't required to close
117 the SNP after use because the SNP is opened by HandleProtocol.
118
119 @return The point to SNP if one is properly openned. Otherwise NULL
120
121 **/
122 EFI_SIMPLE_NETWORK_PROTOCOL *
123 SyslogLocateSnp (
124 VOID
125 )
126 {
127 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
128 EFI_STATUS Status;
129 EFI_HANDLE *Handles;
130 UINTN HandleCount;
131 UINTN Index;
132
133 //
134 // Locate the handles which has SNP installed.
135 //
136 Handles = NULL;
137 Status = gBS->LocateHandleBuffer (
138 ByProtocol,
139 &gEfiSimpleNetworkProtocolGuid,
140 NULL,
141 &HandleCount,
142 &Handles
143 );
144
145 if (EFI_ERROR (Status) || (HandleCount == 0)) {
146 return NULL;
147 }
148
149 //
150 // Try to open one of the ethernet SNP protocol to send packet
151 //
152 Snp = NULL;
153
154 for (Index = 0; Index < HandleCount; Index++) {
155 Status = gBS->HandleProtocol (
156 Handles[Index],
157 &gEfiSimpleNetworkProtocolGuid,
158 (VOID **) &Snp
159 );
160
161 if ((Status == EFI_SUCCESS) && (Snp != NULL) &&
162 (Snp->Mode->IfType == NET_IFTYPE_ETHERNET) &&
163 (Snp->Mode->MaxPacketSize >= NET_SYSLOG_PACKET_LEN)) {
164
165 break;
166 }
167
168 Snp = NULL;
169 }
170
171 FreePool (Handles);
172 return Snp;
173 }
174
175 /**
176 Transmit a syslog packet synchronously through SNP. The Packet
177 already has the ethernet header prepended. This function should
178 fill in the source MAC because it will try to locate a SNP each
179 time it is called to avoid the problem if SNP is unloaded.
180 This code snip is copied from MNP.
181
182 @param[in] Packet The Syslog packet
183 @param[in] Length The length of the packet
184
185 @retval EFI_DEVICE_ERROR Failed to locate a usable SNP protocol
186 @retval EFI_TIMEOUT Timeout happened to send the packet.
187 @retval EFI_SUCCESS Packet is sent.
188
189 **/
190 EFI_STATUS
191 SyslogSendPacket (
192 IN CHAR8 *Packet,
193 IN UINT32 Length
194 )
195 {
196 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
197 ETHER_HEAD *Ether;
198 EFI_STATUS Status;
199 EFI_EVENT TimeoutEvent;
200 UINT8 *TxBuf;
201
202 Snp = SyslogLocateSnp ();
203
204 if (Snp == NULL) {
205 return EFI_DEVICE_ERROR;
206 }
207
208 Ether = (ETHER_HEAD *) Packet;
209 CopyMem (Ether->SrcMac, Snp->Mode->CurrentAddress.Addr, NET_ETHER_ADDR_LEN);
210
211 //
212 // Start the timeout event.
213 //
214 Status = gBS->CreateEvent (
215 EVT_TIMER,
216 TPL_NOTIFY,
217 NULL,
218 NULL,
219 &TimeoutEvent
220 );
221
222 if (EFI_ERROR (Status)) {
223 return Status;
224 }
225
226 Status = gBS->SetTimer (TimeoutEvent, TimerRelative, NET_SYSLOG_TX_TIMEOUT);
227
228 if (EFI_ERROR (Status)) {
229 goto ON_EXIT;
230 }
231
232 for (;;) {
233 //
234 // Transmit the packet through SNP.
235 //
236 Status = Snp->Transmit (Snp, 0, Length, Packet, NULL, NULL, NULL);
237
238 if ((Status != EFI_SUCCESS) && (Status != EFI_NOT_READY)) {
239 Status = EFI_DEVICE_ERROR;
240 break;
241 }
242
243 //
244 // If Status is EFI_SUCCESS, the packet is put in the transmit queue.
245 // if Status is EFI_NOT_READY, the transmit engine of the network
246 // interface is busy. Both need to sync SNP.
247 //
248 TxBuf = NULL;
249
250 do {
251 //
252 // Get the recycled transmit buffer status.
253 //
254 Snp->GetStatus (Snp, NULL, (VOID **) &TxBuf);
255
256 if (!EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {
257 Status = EFI_TIMEOUT;
258 break;
259 }
260
261 } while (TxBuf == NULL);
262
263 if ((Status == EFI_SUCCESS) || (Status == EFI_TIMEOUT)) {
264 break;
265 }
266
267 //
268 // Status is EFI_NOT_READY. Restart the timer event and
269 // call Snp->Transmit again.
270 //
271 gBS->SetTimer (TimeoutEvent, TimerRelative, NET_SYSLOG_TX_TIMEOUT);
272 }
273
274 gBS->SetTimer (TimeoutEvent, TimerCancel, 0);
275
276 ON_EXIT:
277 gBS->CloseEvent (TimeoutEvent);
278 return Status;
279 }
280
281 /**
282 Build a syslog packet, including the Ethernet/Ip/Udp headers
283 and user's message.
284
285 @param[in] Level Syslog servity level
286 @param[in] Module The module that generates the log
287 @param[in] File The file that contains the current log
288 @param[in] Line The line of code in the File that contains the current log
289 @param[in] Message The log message
290 @param[in] BufLen The lenght of the Buf
291 @param[out] Buf The buffer to put the packet data
292
293 @return The length of the syslog packet built.
294
295 **/
296 UINT32
297 SyslogBuildPacket (
298 IN UINT32 Level,
299 IN UINT8 *Module,
300 IN UINT8 *File,
301 IN UINT32 Line,
302 IN UINT8 *Message,
303 IN UINT32 BufLen,
304 OUT CHAR8 *Buf
305 )
306 {
307 ETHER_HEAD *Ether;
308 IP4_HEAD *Ip4;
309 EFI_UDP_HEADER *Udp4;
310 EFI_TIME Time;
311 UINT32 Pri;
312 UINT32 Len;
313
314 //
315 // Fill in the Ethernet header. Leave alone the source MAC.
316 // SyslogSendPacket will fill in the address for us.
317 //
318 Ether = (ETHER_HEAD *) Buf;
319 CopyMem (Ether->DstMac, mSyslogDstMac, NET_ETHER_ADDR_LEN);
320 ZeroMem (Ether->SrcMac, NET_ETHER_ADDR_LEN);
321
322 Ether->EtherType = HTONS (0x0800); // IPv4 protocol
323
324 Buf += sizeof (ETHER_HEAD);
325 BufLen -= sizeof (ETHER_HEAD);
326
327 //
328 // Fill in the IP header
329 //
330 Ip4 = (IP4_HEAD *) Buf;
331 Ip4->HeadLen = 5;
332 Ip4->Ver = 4;
333 Ip4->Tos = 0;
334 Ip4->TotalLen = 0;
335 Ip4->Id = (UINT16) mSyslogPacketSeq;
336 Ip4->Fragment = 0;
337 Ip4->Ttl = 16;
338 Ip4->Protocol = 0x11;
339 Ip4->Checksum = 0;
340 Ip4->Src = mSyslogSrcIp;
341 Ip4->Dst = mSyslogDstIp;
342
343 Buf += sizeof (IP4_HEAD);
344 BufLen -= sizeof (IP4_HEAD);
345
346 //
347 // Fill in the UDP header, Udp checksum is optional. Leave it zero.
348 //
349 Udp4 = (EFI_UDP_HEADER *) Buf;
350 Udp4->SrcPort = HTONS (514);
351 Udp4->DstPort = HTONS (514);
352 Udp4->Length = 0;
353 Udp4->Checksum = 0;
354
355 Buf += sizeof (EFI_UDP_HEADER);
356 BufLen -= sizeof (EFI_UDP_HEADER);
357
358 //
359 // Build the syslog message body with <PRI> Timestamp machine module Message
360 //
361 Pri = ((NET_SYSLOG_FACILITY & 31) << 3) | (Level & 7);
362 gRT->GetTime (&Time, NULL);
363
364 //
365 // Use %a to format the ASCII strings, %s to format UNICODE strings
366 //
367 Len = 0;
368 Len += (UINT32) AsciiSPrint (
369 Buf,
370 BufLen,
371 "<%d> %a %d %d:%d:%d ",
372 Pri,
373 mMonthName [Time.Month-1],
374 Time.Day,
375 Time.Hour,
376 Time.Minute,
377 Time.Second
378 );
379 Len--;
380
381 Len += (UINT32) AsciiSPrint (
382 Buf + Len,
383 BufLen - Len,
384 "Tiano %a: %a (Line: %d File: %a)",
385 Module,
386 Message,
387 Line,
388 File
389 );
390 Len--;
391
392 //
393 // OK, patch the IP length/checksum and UDP length fields.
394 //
395 Len += sizeof (EFI_UDP_HEADER);
396 Udp4->Length = HTONS ((UINT16) Len);
397
398 Len += sizeof (IP4_HEAD);
399 Ip4->TotalLen = HTONS ((UINT16) Len);
400 Ip4->Checksum = (UINT16) (~NetblockChecksum ((UINT8 *) Ip4, sizeof (IP4_HEAD)));
401
402 return Len + sizeof (ETHER_HEAD);
403 }
404
405 /**
406 Allocate a buffer, then format the message to it. This is a
407 help function for the NET_DEBUG_XXX macros. The PrintArg of
408 these macros treats the variable length print parameters as a
409 single parameter, and pass it to the NetDebugASPrint. For
410 example, NET_DEBUG_TRACE ("Tcp", ("State transit to %a\n", Name))
411 if extracted to:
412
413 NetDebugOutput (
414 NETDEBUG_LEVEL_TRACE,
415 "Tcp",
416 __FILE__,
417 __LINE__,
418 NetDebugASPrint ("State transit to %a\n", Name)
419 )
420
421 @param Format The ASCII format string.
422 @param ... The variable length parameter whose format is determined
423 by the Format string.
424
425 @return The buffer containing the formatted message,
426 or NULL if failed to allocate memory.
427
428 **/
429 CHAR8 *
430 NetDebugASPrint (
431 IN CHAR8 *Format,
432 ...
433 )
434 {
435 VA_LIST Marker;
436 CHAR8 *Buf;
437
438 Buf = (CHAR8 *) AllocatePool (NET_DEBUG_MSG_LEN);
439
440 if (Buf == NULL) {
441 return NULL;
442 }
443
444 VA_START (Marker, Format);
445 AsciiVSPrint (Buf, NET_DEBUG_MSG_LEN, Format, Marker);
446 VA_END (Marker);
447
448 return Buf;
449 }
450
451 /**
452 Builds an UDP4 syslog packet and send it using SNP.
453
454 This function will locate a instance of SNP then send the message through it.
455 Because it isn't open the SNP BY_DRIVER, apply caution when using it.
456
457 @param Level The servity level of the message.
458 @param Module The Moudle that generates the log.
459 @param File The file that contains the log.
460 @param Line The exact line that contains the log.
461 @param Message The user message to log.
462
463 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
464 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the packet
465 @retval EFI_SUCCESS The log is discard because that it is more verbose
466 than the mNetDebugLevelMax. Or, it has been sent out.
467 **/
468 EFI_STATUS
469 NetDebugOutput (
470 IN UINT32 Level,
471 IN UINT8 *Module,
472 IN UINT8 *File,
473 IN UINT32 Line,
474 IN UINT8 *Message
475 )
476 {
477 CHAR8 *Packet;
478 UINT32 Len;
479 EFI_STATUS Status;
480
481 //
482 // Check whether the message should be sent out
483 //
484 if (Message == NULL) {
485 return EFI_INVALID_PARAMETER;
486 }
487
488 if (Level > mNetDebugLevelMax) {
489 Status = EFI_SUCCESS;
490 goto ON_EXIT;
491 }
492
493 //
494 // Allocate a maxium of 1024 bytes, the caller should ensure
495 // that the message plus the ethernet/ip/udp header is shorter
496 // than this
497 //
498 Packet = (CHAR8 *) AllocatePool (NET_SYSLOG_PACKET_LEN);
499
500 if (Packet == NULL) {
501 Status = EFI_OUT_OF_RESOURCES;
502 goto ON_EXIT;
503 }
504
505 //
506 // Build the message: Ethernet header + IP header + Udp Header + user data
507 //
508 Len = SyslogBuildPacket (
509 Level,
510 Module,
511 File,
512 Line,
513 Message,
514 NET_SYSLOG_PACKET_LEN,
515 Packet
516 );
517
518 mSyslogPacketSeq++;
519 Status = SyslogSendPacket (Packet, Len);
520 FreePool (Packet);
521
522 ON_EXIT:
523 FreePool (Message);
524 return Status;
525 }
526 /**
527 Return the length of the mask.
528
529 Return the length of the mask, the correct value is from 0 to 32.
530 If the mask is invalid, return the invalid length 33, which is IP4_MASK_NUM.
531 NetMask is in the host byte order.
532
533 @param[in] NetMask The netmask to get the length from.
534
535 @return The length of the netmask, IP4_MASK_NUM if the mask is invalid.
536
537 **/
538 INTN
539 EFIAPI
540 NetGetMaskLength (
541 IN IP4_ADDR NetMask
542 )
543 {
544 INTN Index;
545
546 for (Index = 0; Index < IP4_MASK_NUM; Index++) {
547 if (NetMask == gIp4AllMasks[Index]) {
548 break;
549 }
550 }
551
552 return Index;
553 }
554
555
556
557 /**
558 Return the class of the IP address, such as class A, B, C.
559 Addr is in host byte order.
560
561 The address of class A starts with 0.
562 If the address belong to class A, return IP4_ADDR_CLASSA.
563 The address of class B starts with 10.
564 If the address belong to class B, return IP4_ADDR_CLASSB.
565 The address of class C starts with 110.
566 If the address belong to class C, return IP4_ADDR_CLASSC.
567 The address of class D starts with 1110.
568 If the address belong to class D, return IP4_ADDR_CLASSD.
569 The address of class E starts with 1111.
570 If the address belong to class E, return IP4_ADDR_CLASSE.
571
572
573 @param[in] Addr The address to get the class from.
574
575 @return IP address class, such as IP4_ADDR_CLASSA.
576
577 **/
578 INTN
579 EFIAPI
580 NetGetIpClass (
581 IN IP4_ADDR Addr
582 )
583 {
584 UINT8 ByteOne;
585
586 ByteOne = (UINT8) (Addr >> 24);
587
588 if ((ByteOne & 0x80) == 0) {
589 return IP4_ADDR_CLASSA;
590
591 } else if ((ByteOne & 0xC0) == 0x80) {
592 return IP4_ADDR_CLASSB;
593
594 } else if ((ByteOne & 0xE0) == 0xC0) {
595 return IP4_ADDR_CLASSC;
596
597 } else if ((ByteOne & 0xF0) == 0xE0) {
598 return IP4_ADDR_CLASSD;
599
600 } else {
601 return IP4_ADDR_CLASSE;
602
603 }
604 }
605
606
607 /**
608 Check whether the IP is a valid unicast address according to
609 the netmask. If NetMask is zero, use the IP address's class to get the default mask.
610
611 If Ip is 0, IP is not a valid unicast address.
612 Class D address is used for multicasting and class E address is reserved for future. If Ip
613 belongs to class D or class E, IP is not a valid unicast address.
614 If all bits of the host address of IP are 0 or 1, IP is also not a valid unicast address.
615
616 @param[in] Ip The IP to check against.
617 @param[in] NetMask The mask of the IP.
618
619 @return TRUE if IP is a valid unicast address on the network, otherwise FALSE.
620
621 **/
622 BOOLEAN
623 EFIAPI
624 NetIp4IsUnicast (
625 IN IP4_ADDR Ip,
626 IN IP4_ADDR NetMask
627 )
628 {
629 INTN Class;
630
631 Class = NetGetIpClass (Ip);
632
633 if ((Ip == 0) || (Class >= IP4_ADDR_CLASSD)) {
634 return FALSE;
635 }
636
637 if (NetMask == 0) {
638 NetMask = gIp4AllMasks[Class << 3];
639 }
640
641 if (((Ip &~NetMask) == ~NetMask) || ((Ip &~NetMask) == 0)) {
642 return FALSE;
643 }
644
645 return TRUE;
646 }
647
648 /**
649 Check whether the incoming IPv6 address is a valid unicast address.
650
651 If the address is a multicast address has binary 0xFF at the start, it is not
652 a valid unicast address. If the address is unspecified ::, it is not a valid
653 unicast address to be assigned to any node. If the address is loopback address
654 ::1, it is also not a valid unicast address to be assigned to any physical
655 interface.
656
657 @param[in] Ip6 The IPv6 address to check against.
658
659 @return TRUE if Ip6 is a valid unicast address on the network, otherwise FALSE.
660
661 **/
662 BOOLEAN
663 NetIp6IsValidUnicast (
664 IN EFI_IPv6_ADDRESS *Ip6
665 )
666 {
667 UINT8 Byte;
668 UINT8 Index;
669
670 if (Ip6->Addr[0] == 0xFF) {
671 return FALSE;
672 }
673
674 for (Index = 0; Index < 15; Index++) {
675 if (Ip6->Addr[Index] != 0) {
676 return TRUE;
677 }
678 }
679
680 Byte = Ip6->Addr[Index];
681
682 if (Byte == 0x0 || Byte == 0x1) {
683 return FALSE;
684 }
685
686 return TRUE;
687 }
688
689 /**
690 Check whether the incoming Ipv6 address is the unspecified address or not.
691
692 @param[in] Ip6 - Ip6 address, in network order.
693
694 @retval TRUE - Yes, unspecified
695 @retval FALSE - No
696
697 **/
698 BOOLEAN
699 NetIp6IsUnspecifiedAddr (
700 IN EFI_IPv6_ADDRESS *Ip6
701 )
702 {
703 UINT8 Index;
704
705 for (Index = 0; Index < 16; Index++) {
706 if (Ip6->Addr[Index] != 0) {
707 return FALSE;
708 }
709 }
710
711 return TRUE;
712 }
713
714 /**
715 Check whether the incoming Ipv6 address is a link-local address.
716
717 @param[in] Ip6 - Ip6 address, in network order.
718
719 @retval TRUE - Yes, link-local address
720 @retval FALSE - No
721
722 **/
723 BOOLEAN
724 NetIp6IsLinkLocalAddr (
725 IN EFI_IPv6_ADDRESS *Ip6
726 )
727 {
728 UINT8 Index;
729
730 ASSERT (Ip6 != NULL);
731
732 if (Ip6->Addr[0] != 0xFE) {
733 return FALSE;
734 }
735
736 if (Ip6->Addr[1] != 0x80) {
737 return FALSE;
738 }
739
740 for (Index = 2; Index < 8; Index++) {
741 if (Ip6->Addr[Index] != 0) {
742 return FALSE;
743 }
744 }
745
746 return TRUE;
747 }
748
749 /**
750 Check whether the Ipv6 address1 and address2 are on the connected network.
751
752 @param[in] Ip1 - Ip6 address1, in network order.
753 @param[in] Ip2 - Ip6 address2, in network order.
754 @param[in] PrefixLength - The prefix length of the checking net.
755
756 @retval TRUE - Yes, connected.
757 @retval FALSE - No.
758
759 **/
760 BOOLEAN
761 NetIp6IsNetEqual (
762 EFI_IPv6_ADDRESS *Ip1,
763 EFI_IPv6_ADDRESS *Ip2,
764 UINT8 PrefixLength
765 )
766 {
767 UINT8 Byte;
768 UINT8 Bit;
769 UINT8 Mask;
770
771 ASSERT (Ip1 != NULL && Ip2 != NULL);
772
773 if (PrefixLength == 0) {
774 return TRUE;
775 }
776
777 Byte = (UINT8) (PrefixLength / 8);
778 Bit = (UINT8) (PrefixLength % 8);
779
780 if (CompareMem (Ip1, Ip2, Byte) != 0) {
781 return FALSE;
782 }
783
784 if (Bit > 0) {
785 Mask = (UINT8) (0xFF << (8 - Bit));
786
787 if ((Ip1->Addr[Byte] & Mask) != (Ip2->Addr[Byte] & Mask)) {
788 return FALSE;
789 }
790 }
791
792 return TRUE;
793 }
794
795
796 /**
797 Switches the endianess of an IPv6 address
798
799 This function swaps the bytes in a 128-bit IPv6 address to switch the value
800 from little endian to big endian or vice versa. The byte swapped value is
801 returned.
802
803 @param Ip6 Points to an IPv6 address
804
805 @return The byte swapped IPv6 address.
806
807 **/
808 EFI_IPv6_ADDRESS *
809 Ip6Swap128 (
810 EFI_IPv6_ADDRESS *Ip6
811 )
812 {
813 UINT64 High;
814 UINT64 Low;
815
816 CopyMem (&High, Ip6, sizeof (UINT64));
817 CopyMem (&Low, &Ip6->Addr[8], sizeof (UINT64));
818
819 High = SwapBytes64 (High);
820 Low = SwapBytes64 (Low);
821
822 CopyMem (Ip6, &Low, sizeof (UINT64));
823 CopyMem (&Ip6->Addr[8], &High, sizeof (UINT64));
824
825 return Ip6;
826 }
827
828 /**
829 Initialize a random seed using current time.
830
831 Get current time first. Then initialize a random seed based on some basic
832 mathematics operation on the hour, day, minute, second, nanosecond and year
833 of the current time.
834
835 @return The random seed initialized with current time.
836
837 **/
838 UINT32
839 EFIAPI
840 NetRandomInitSeed (
841 VOID
842 )
843 {
844 EFI_TIME Time;
845 UINT32 Seed;
846
847 gRT->GetTime (&Time, NULL);
848 Seed = (~Time.Hour << 24 | Time.Day << 16 | Time.Minute << 8 | Time.Second);
849 Seed ^= Time.Nanosecond;
850 Seed ^= Time.Year << 7;
851
852 return Seed;
853 }
854
855
856 /**
857 Extract a UINT32 from a byte stream.
858
859 Copy a UINT32 from a byte stream, then converts it from Network
860 byte order to host byte order. Use this function to avoid alignment error.
861
862 @param[in] Buf The buffer to extract the UINT32.
863
864 @return The UINT32 extracted.
865
866 **/
867 UINT32
868 EFIAPI
869 NetGetUint32 (
870 IN UINT8 *Buf
871 )
872 {
873 UINT32 Value;
874
875 CopyMem (&Value, Buf, sizeof (UINT32));
876 return NTOHL (Value);
877 }
878
879
880 /**
881 Put a UINT32 to the byte stream in network byte order.
882
883 Converts a UINT32 from host byte order to network byte order. Then copy it to the
884 byte stream.
885
886 @param[in, out] Buf The buffer to put the UINT32.
887 @param[in] Data The data to put.
888
889 **/
890 VOID
891 EFIAPI
892 NetPutUint32 (
893 IN OUT UINT8 *Buf,
894 IN UINT32 Data
895 )
896 {
897 Data = HTONL (Data);
898 CopyMem (Buf, &Data, sizeof (UINT32));
899 }
900
901
902 /**
903 Remove the first node entry on the list, and return the removed node entry.
904
905 Removes the first node Entry from a doubly linked list. It is up to the caller of
906 this function to release the memory used by the first node if that is required. On
907 exit, the removed node is returned.
908
909 If Head is NULL, then ASSERT().
910 If Head was not initialized, then ASSERT().
911 If PcdMaximumLinkedListLength is not zero, and the number of nodes in the
912 linked list including the head node is greater than or equal to PcdMaximumLinkedListLength,
913 then ASSERT().
914
915 @param[in, out] Head The list header.
916
917 @return The first node entry that is removed from the list, NULL if the list is empty.
918
919 **/
920 LIST_ENTRY *
921 EFIAPI
922 NetListRemoveHead (
923 IN OUT LIST_ENTRY *Head
924 )
925 {
926 LIST_ENTRY *First;
927
928 ASSERT (Head != NULL);
929
930 if (IsListEmpty (Head)) {
931 return NULL;
932 }
933
934 First = Head->ForwardLink;
935 Head->ForwardLink = First->ForwardLink;
936 First->ForwardLink->BackLink = Head;
937
938 DEBUG_CODE (
939 First->ForwardLink = (LIST_ENTRY *) NULL;
940 First->BackLink = (LIST_ENTRY *) NULL;
941 );
942
943 return First;
944 }
945
946
947 /**
948 Remove the last node entry on the list and and return the removed node entry.
949
950 Removes the last node entry from a doubly linked list. It is up to the caller of
951 this function to release the memory used by the first node if that is required. On
952 exit, the removed node is returned.
953
954 If Head is NULL, then ASSERT().
955 If Head was not initialized, then ASSERT().
956 If PcdMaximumLinkedListLength is not zero, and the number of nodes in the
957 linked list including the head node is greater than or equal to PcdMaximumLinkedListLength,
958 then ASSERT().
959
960 @param[in, out] Head The list head.
961
962 @return The last node entry that is removed from the list, NULL if the list is empty.
963
964 **/
965 LIST_ENTRY *
966 EFIAPI
967 NetListRemoveTail (
968 IN OUT LIST_ENTRY *Head
969 )
970 {
971 LIST_ENTRY *Last;
972
973 ASSERT (Head != NULL);
974
975 if (IsListEmpty (Head)) {
976 return NULL;
977 }
978
979 Last = Head->BackLink;
980 Head->BackLink = Last->BackLink;
981 Last->BackLink->ForwardLink = Head;
982
983 DEBUG_CODE (
984 Last->ForwardLink = (LIST_ENTRY *) NULL;
985 Last->BackLink = (LIST_ENTRY *) NULL;
986 );
987
988 return Last;
989 }
990
991
992 /**
993 Insert a new node entry after a designated node entry of a doubly linked list.
994
995 Inserts a new node entry donated by NewEntry after the node entry donated by PrevEntry
996 of the doubly linked list.
997
998 @param[in, out] PrevEntry The previous entry to insert after.
999 @param[in, out] NewEntry The new entry to insert.
1000
1001 **/
1002 VOID
1003 EFIAPI
1004 NetListInsertAfter (
1005 IN OUT LIST_ENTRY *PrevEntry,
1006 IN OUT LIST_ENTRY *NewEntry
1007 )
1008 {
1009 NewEntry->BackLink = PrevEntry;
1010 NewEntry->ForwardLink = PrevEntry->ForwardLink;
1011 PrevEntry->ForwardLink->BackLink = NewEntry;
1012 PrevEntry->ForwardLink = NewEntry;
1013 }
1014
1015
1016 /**
1017 Insert a new node entry before a designated node entry of a doubly linked list.
1018
1019 Inserts a new node entry donated by NewEntry after the node entry donated by PostEntry
1020 of the doubly linked list.
1021
1022 @param[in, out] PostEntry The entry to insert before.
1023 @param[in, out] NewEntry The new entry to insert.
1024
1025 **/
1026 VOID
1027 EFIAPI
1028 NetListInsertBefore (
1029 IN OUT LIST_ENTRY *PostEntry,
1030 IN OUT LIST_ENTRY *NewEntry
1031 )
1032 {
1033 NewEntry->ForwardLink = PostEntry;
1034 NewEntry->BackLink = PostEntry->BackLink;
1035 PostEntry->BackLink->ForwardLink = NewEntry;
1036 PostEntry->BackLink = NewEntry;
1037 }
1038
1039
1040 /**
1041 Initialize the netmap. Netmap is a reposity to keep the <Key, Value> pairs.
1042
1043 Initialize the forward and backward links of two head nodes donated by Map->Used
1044 and Map->Recycled of two doubly linked lists.
1045 Initializes the count of the <Key, Value> pairs in the netmap to zero.
1046
1047 If Map is NULL, then ASSERT().
1048 If the address of Map->Used is NULL, then ASSERT().
1049 If the address of Map->Recycled is NULl, then ASSERT().
1050
1051 @param[in, out] Map The netmap to initialize.
1052
1053 **/
1054 VOID
1055 EFIAPI
1056 NetMapInit (
1057 IN OUT NET_MAP *Map
1058 )
1059 {
1060 ASSERT (Map != NULL);
1061
1062 InitializeListHead (&Map->Used);
1063 InitializeListHead (&Map->Recycled);
1064 Map->Count = 0;
1065 }
1066
1067
1068 /**
1069 To clean up the netmap, that is, release allocated memories.
1070
1071 Removes all nodes of the Used doubly linked list and free memory of all related netmap items.
1072 Removes all nodes of the Recycled doubly linked list and free memory of all related netmap items.
1073 The number of the <Key, Value> pairs in the netmap is set to be zero.
1074
1075 If Map is NULL, then ASSERT().
1076
1077 @param[in, out] Map The netmap to clean up.
1078
1079 **/
1080 VOID
1081 EFIAPI
1082 NetMapClean (
1083 IN OUT NET_MAP *Map
1084 )
1085 {
1086 NET_MAP_ITEM *Item;
1087 LIST_ENTRY *Entry;
1088 LIST_ENTRY *Next;
1089
1090 ASSERT (Map != NULL);
1091
1092 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Map->Used) {
1093 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
1094
1095 RemoveEntryList (&Item->Link);
1096 Map->Count--;
1097
1098 gBS->FreePool (Item);
1099 }
1100
1101 ASSERT ((Map->Count == 0) && IsListEmpty (&Map->Used));
1102
1103 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Map->Recycled) {
1104 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
1105
1106 RemoveEntryList (&Item->Link);
1107 gBS->FreePool (Item);
1108 }
1109
1110 ASSERT (IsListEmpty (&Map->Recycled));
1111 }
1112
1113
1114 /**
1115 Test whether the netmap is empty and return true if it is.
1116
1117 If the number of the <Key, Value> pairs in the netmap is zero, return TRUE.
1118
1119 If Map is NULL, then ASSERT().
1120
1121
1122 @param[in] Map The net map to test.
1123
1124 @return TRUE if the netmap is empty, otherwise FALSE.
1125
1126 **/
1127 BOOLEAN
1128 EFIAPI
1129 NetMapIsEmpty (
1130 IN NET_MAP *Map
1131 )
1132 {
1133 ASSERT (Map != NULL);
1134 return (BOOLEAN) (Map->Count == 0);
1135 }
1136
1137
1138 /**
1139 Return the number of the <Key, Value> pairs in the netmap.
1140
1141 @param[in] Map The netmap to get the entry number.
1142
1143 @return The entry number in the netmap.
1144
1145 **/
1146 UINTN
1147 EFIAPI
1148 NetMapGetCount (
1149 IN NET_MAP *Map
1150 )
1151 {
1152 return Map->Count;
1153 }
1154
1155
1156 /**
1157 Return one allocated item.
1158
1159 If the Recycled doubly linked list of the netmap is empty, it will try to allocate
1160 a batch of items if there are enough resources and add corresponding nodes to the begining
1161 of the Recycled doubly linked list of the netmap. Otherwise, it will directly remove
1162 the fist node entry of the Recycled doubly linked list and return the corresponding item.
1163
1164 If Map is NULL, then ASSERT().
1165
1166 @param[in, out] Map The netmap to allocate item for.
1167
1168 @return The allocated item. If NULL, the
1169 allocation failed due to resource limit.
1170
1171 **/
1172 NET_MAP_ITEM *
1173 NetMapAllocItem (
1174 IN OUT NET_MAP *Map
1175 )
1176 {
1177 NET_MAP_ITEM *Item;
1178 LIST_ENTRY *Head;
1179 UINTN Index;
1180
1181 ASSERT (Map != NULL);
1182
1183 Head = &Map->Recycled;
1184
1185 if (IsListEmpty (Head)) {
1186 for (Index = 0; Index < NET_MAP_INCREAMENT; Index++) {
1187 Item = AllocatePool (sizeof (NET_MAP_ITEM));
1188
1189 if (Item == NULL) {
1190 if (Index == 0) {
1191 return NULL;
1192 }
1193
1194 break;
1195 }
1196
1197 InsertHeadList (Head, &Item->Link);
1198 }
1199 }
1200
1201 Item = NET_LIST_HEAD (Head, NET_MAP_ITEM, Link);
1202 NetListRemoveHead (Head);
1203
1204 return Item;
1205 }
1206
1207
1208 /**
1209 Allocate an item to save the <Key, Value> pair to the head of the netmap.
1210
1211 Allocate an item to save the <Key, Value> pair and add corresponding node entry
1212 to the beginning of the Used doubly linked list. The number of the <Key, Value>
1213 pairs in the netmap increase by 1.
1214
1215 If Map is NULL, then ASSERT().
1216
1217 @param[in, out] Map The netmap to insert into.
1218 @param[in] Key The user's key.
1219 @param[in] Value The user's value for the key.
1220
1221 @retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the item.
1222 @retval EFI_SUCCESS The item is inserted to the head.
1223
1224 **/
1225 EFI_STATUS
1226 EFIAPI
1227 NetMapInsertHead (
1228 IN OUT NET_MAP *Map,
1229 IN VOID *Key,
1230 IN VOID *Value OPTIONAL
1231 )
1232 {
1233 NET_MAP_ITEM *Item;
1234
1235 ASSERT (Map != NULL);
1236
1237 Item = NetMapAllocItem (Map);
1238
1239 if (Item == NULL) {
1240 return EFI_OUT_OF_RESOURCES;
1241 }
1242
1243 Item->Key = Key;
1244 Item->Value = Value;
1245 InsertHeadList (&Map->Used, &Item->Link);
1246
1247 Map->Count++;
1248 return EFI_SUCCESS;
1249 }
1250
1251
1252 /**
1253 Allocate an item to save the <Key, Value> pair to the tail of the netmap.
1254
1255 Allocate an item to save the <Key, Value> pair and add corresponding node entry
1256 to the tail of the Used doubly linked list. The number of the <Key, Value>
1257 pairs in the netmap increase by 1.
1258
1259 If Map is NULL, then ASSERT().
1260
1261 @param[in, out] Map The netmap to insert into.
1262 @param[in] Key The user's key.
1263 @param[in] Value The user's value for the key.
1264
1265 @retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the item.
1266 @retval EFI_SUCCESS The item is inserted to the tail.
1267
1268 **/
1269 EFI_STATUS
1270 EFIAPI
1271 NetMapInsertTail (
1272 IN OUT NET_MAP *Map,
1273 IN VOID *Key,
1274 IN VOID *Value OPTIONAL
1275 )
1276 {
1277 NET_MAP_ITEM *Item;
1278
1279 ASSERT (Map != NULL);
1280
1281 Item = NetMapAllocItem (Map);
1282
1283 if (Item == NULL) {
1284 return EFI_OUT_OF_RESOURCES;
1285 }
1286
1287 Item->Key = Key;
1288 Item->Value = Value;
1289 InsertTailList (&Map->Used, &Item->Link);
1290
1291 Map->Count++;
1292
1293 return EFI_SUCCESS;
1294 }
1295
1296
1297 /**
1298 Check whether the item is in the Map and return TRUE if it is.
1299
1300 @param[in] Map The netmap to search within.
1301 @param[in] Item The item to search.
1302
1303 @return TRUE if the item is in the netmap, otherwise FALSE.
1304
1305 **/
1306 BOOLEAN
1307 NetItemInMap (
1308 IN NET_MAP *Map,
1309 IN NET_MAP_ITEM *Item
1310 )
1311 {
1312 LIST_ENTRY *ListEntry;
1313
1314 NET_LIST_FOR_EACH (ListEntry, &Map->Used) {
1315 if (ListEntry == &Item->Link) {
1316 return TRUE;
1317 }
1318 }
1319
1320 return FALSE;
1321 }
1322
1323
1324 /**
1325 Find the key in the netmap and returns the point to the item contains the Key.
1326
1327 Iterate the Used doubly linked list of the netmap to get every item. Compare the key of every
1328 item with the key to search. It returns the point to the item contains the Key if found.
1329
1330 If Map is NULL, then ASSERT().
1331
1332 @param[in] Map The netmap to search within.
1333 @param[in] Key The key to search.
1334
1335 @return The point to the item contains the Key, or NULL if Key isn't in the map.
1336
1337 **/
1338 NET_MAP_ITEM *
1339 EFIAPI
1340 NetMapFindKey (
1341 IN NET_MAP *Map,
1342 IN VOID *Key
1343 )
1344 {
1345 LIST_ENTRY *Entry;
1346 NET_MAP_ITEM *Item;
1347
1348 ASSERT (Map != NULL);
1349
1350 NET_LIST_FOR_EACH (Entry, &Map->Used) {
1351 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
1352
1353 if (Item->Key == Key) {
1354 return Item;
1355 }
1356 }
1357
1358 return NULL;
1359 }
1360
1361
1362 /**
1363 Remove the node entry of the item from the netmap and return the key of the removed item.
1364
1365 Remove the node entry of the item from the Used doubly linked list of the netmap.
1366 The number of the <Key, Value> pairs in the netmap decrease by 1. Then add the node
1367 entry of the item to the Recycled doubly linked list of the netmap. If Value is not NULL,
1368 Value will point to the value of the item. It returns the key of the removed item.
1369
1370 If Map is NULL, then ASSERT().
1371 If Item is NULL, then ASSERT().
1372 if item in not in the netmap, then ASSERT().
1373
1374 @param[in, out] Map The netmap to remove the item from.
1375 @param[in, out] Item The item to remove.
1376 @param[out] Value The variable to receive the value if not NULL.
1377
1378 @return The key of the removed item.
1379
1380 **/
1381 VOID *
1382 EFIAPI
1383 NetMapRemoveItem (
1384 IN OUT NET_MAP *Map,
1385 IN OUT NET_MAP_ITEM *Item,
1386 OUT VOID **Value OPTIONAL
1387 )
1388 {
1389 ASSERT ((Map != NULL) && (Item != NULL));
1390 ASSERT (NetItemInMap (Map, Item));
1391
1392 RemoveEntryList (&Item->Link);
1393 Map->Count--;
1394 InsertHeadList (&Map->Recycled, &Item->Link);
1395
1396 if (Value != NULL) {
1397 *Value = Item->Value;
1398 }
1399
1400 return Item->Key;
1401 }
1402
1403
1404 /**
1405 Remove the first node entry on the netmap and return the key of the removed item.
1406
1407 Remove the first node entry from the Used doubly linked list of the netmap.
1408 The number of the <Key, Value> pairs in the netmap decrease by 1. Then add the node
1409 entry to the Recycled doubly linked list of the netmap. If parameter Value is not NULL,
1410 parameter Value will point to the value of the item. It returns the key of the removed item.
1411
1412 If Map is NULL, then ASSERT().
1413 If the Used doubly linked list is empty, then ASSERT().
1414
1415 @param[in, out] Map The netmap to remove the head from.
1416 @param[out] Value The variable to receive the value if not NULL.
1417
1418 @return The key of the item removed.
1419
1420 **/
1421 VOID *
1422 EFIAPI
1423 NetMapRemoveHead (
1424 IN OUT NET_MAP *Map,
1425 OUT VOID **Value OPTIONAL
1426 )
1427 {
1428 NET_MAP_ITEM *Item;
1429
1430 //
1431 // Often, it indicates a programming error to remove
1432 // the first entry in an empty list
1433 //
1434 ASSERT (Map && !IsListEmpty (&Map->Used));
1435
1436 Item = NET_LIST_HEAD (&Map->Used, NET_MAP_ITEM, Link);
1437 RemoveEntryList (&Item->Link);
1438 Map->Count--;
1439 InsertHeadList (&Map->Recycled, &Item->Link);
1440
1441 if (Value != NULL) {
1442 *Value = Item->Value;
1443 }
1444
1445 return Item->Key;
1446 }
1447
1448
1449 /**
1450 Remove the last node entry on the netmap and return the key of the removed item.
1451
1452 Remove the last node entry from the Used doubly linked list of the netmap.
1453 The number of the <Key, Value> pairs in the netmap decrease by 1. Then add the node
1454 entry to the Recycled doubly linked list of the netmap. If parameter Value is not NULL,
1455 parameter Value will point to the value of the item. It returns the key of the removed item.
1456
1457 If Map is NULL, then ASSERT().
1458 If the Used doubly linked list is empty, then ASSERT().
1459
1460 @param[in, out] Map The netmap to remove the tail from.
1461 @param[out] Value The variable to receive the value if not NULL.
1462
1463 @return The key of the item removed.
1464
1465 **/
1466 VOID *
1467 EFIAPI
1468 NetMapRemoveTail (
1469 IN OUT NET_MAP *Map,
1470 OUT VOID **Value OPTIONAL
1471 )
1472 {
1473 NET_MAP_ITEM *Item;
1474
1475 //
1476 // Often, it indicates a programming error to remove
1477 // the last entry in an empty list
1478 //
1479 ASSERT (Map && !IsListEmpty (&Map->Used));
1480
1481 Item = NET_LIST_TAIL (&Map->Used, NET_MAP_ITEM, Link);
1482 RemoveEntryList (&Item->Link);
1483 Map->Count--;
1484 InsertHeadList (&Map->Recycled, &Item->Link);
1485
1486 if (Value != NULL) {
1487 *Value = Item->Value;
1488 }
1489
1490 return Item->Key;
1491 }
1492
1493
1494 /**
1495 Iterate through the netmap and call CallBack for each item.
1496
1497 It will contiue the traverse if CallBack returns EFI_SUCCESS, otherwise, break
1498 from the loop. It returns the CallBack's last return value. This function is
1499 delete safe for the current item.
1500
1501 If Map is NULL, then ASSERT().
1502 If CallBack is NULL, then ASSERT().
1503
1504 @param[in] Map The Map to iterate through.
1505 @param[in] CallBack The callback function to call for each item.
1506 @param[in] Arg The opaque parameter to the callback.
1507
1508 @retval EFI_SUCCESS There is no item in the netmap or CallBack for each item
1509 return EFI_SUCCESS.
1510 @retval Others It returns the CallBack's last return value.
1511
1512 **/
1513 EFI_STATUS
1514 EFIAPI
1515 NetMapIterate (
1516 IN NET_MAP *Map,
1517 IN NET_MAP_CALLBACK CallBack,
1518 IN VOID *Arg
1519 )
1520 {
1521
1522 LIST_ENTRY *Entry;
1523 LIST_ENTRY *Next;
1524 LIST_ENTRY *Head;
1525 NET_MAP_ITEM *Item;
1526 EFI_STATUS Result;
1527
1528 ASSERT ((Map != NULL) && (CallBack != NULL));
1529
1530 Head = &Map->Used;
1531
1532 if (IsListEmpty (Head)) {
1533 return EFI_SUCCESS;
1534 }
1535
1536 NET_LIST_FOR_EACH_SAFE (Entry, Next, Head) {
1537 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
1538 Result = CallBack (Map, Item, Arg);
1539
1540 if (EFI_ERROR (Result)) {
1541 return Result;
1542 }
1543 }
1544
1545 return EFI_SUCCESS;
1546 }
1547
1548
1549 /**
1550 This is the default unload handle for all the network drivers.
1551
1552 Disconnect the driver specified by ImageHandle from all the devices in the handle database.
1553 Uninstall all the protocols installed in the driver entry point.
1554
1555 @param[in] ImageHandle The drivers' driver image.
1556
1557 @retval EFI_SUCCESS The image is unloaded.
1558 @retval Others Failed to unload the image.
1559
1560 **/
1561 EFI_STATUS
1562 EFIAPI
1563 NetLibDefaultUnload (
1564 IN EFI_HANDLE ImageHandle
1565 )
1566 {
1567 EFI_STATUS Status;
1568 EFI_HANDLE *DeviceHandleBuffer;
1569 UINTN DeviceHandleCount;
1570 UINTN Index;
1571 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
1572 EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
1573 EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;
1574
1575 //
1576 // Get the list of all the handles in the handle database.
1577 // If there is an error getting the list, then the unload
1578 // operation fails.
1579 //
1580 Status = gBS->LocateHandleBuffer (
1581 AllHandles,
1582 NULL,
1583 NULL,
1584 &DeviceHandleCount,
1585 &DeviceHandleBuffer
1586 );
1587
1588 if (EFI_ERROR (Status)) {
1589 return Status;
1590 }
1591
1592 //
1593 // Disconnect the driver specified by ImageHandle from all
1594 // the devices in the handle database.
1595 //
1596 for (Index = 0; Index < DeviceHandleCount; Index++) {
1597 Status = gBS->DisconnectController (
1598 DeviceHandleBuffer[Index],
1599 ImageHandle,
1600 NULL
1601 );
1602 }
1603
1604 //
1605 // Uninstall all the protocols installed in the driver entry point
1606 //
1607 for (Index = 0; Index < DeviceHandleCount; Index++) {
1608 Status = gBS->HandleProtocol (
1609 DeviceHandleBuffer[Index],
1610 &gEfiDriverBindingProtocolGuid,
1611 (VOID **) &DriverBinding
1612 );
1613
1614 if (EFI_ERROR (Status)) {
1615 continue;
1616 }
1617
1618 if (DriverBinding->ImageHandle != ImageHandle) {
1619 continue;
1620 }
1621
1622 gBS->UninstallProtocolInterface (
1623 ImageHandle,
1624 &gEfiDriverBindingProtocolGuid,
1625 DriverBinding
1626 );
1627 Status = gBS->HandleProtocol (
1628 DeviceHandleBuffer[Index],
1629 &gEfiComponentNameProtocolGuid,
1630 (VOID **) &ComponentName
1631 );
1632 if (!EFI_ERROR (Status)) {
1633 gBS->UninstallProtocolInterface (
1634 ImageHandle,
1635 &gEfiComponentNameProtocolGuid,
1636 ComponentName
1637 );
1638 }
1639
1640 Status = gBS->HandleProtocol (
1641 DeviceHandleBuffer[Index],
1642 &gEfiComponentName2ProtocolGuid,
1643 (VOID **) &ComponentName2
1644 );
1645 if (!EFI_ERROR (Status)) {
1646 gBS->UninstallProtocolInterface (
1647 ImageHandle,
1648 &gEfiComponentName2ProtocolGuid,
1649 ComponentName2
1650 );
1651 }
1652 }
1653
1654 //
1655 // Free the buffer containing the list of handles from the handle database
1656 //
1657 if (DeviceHandleBuffer != NULL) {
1658 gBS->FreePool (DeviceHandleBuffer);
1659 }
1660
1661 return EFI_SUCCESS;
1662 }
1663
1664
1665
1666 /**
1667 Create a child of the service that is identified by ServiceBindingGuid.
1668
1669 Get the ServiceBinding Protocol first, then use it to create a child.
1670
1671 If ServiceBindingGuid is NULL, then ASSERT().
1672 If ChildHandle is NULL, then ASSERT().
1673
1674 @param[in] Controller The controller which has the service installed.
1675 @param[in] Image The image handle used to open service.
1676 @param[in] ServiceBindingGuid The service's Guid.
1677 @param[in, out] ChildHandle The handle to receive the create child.
1678
1679 @retval EFI_SUCCESS The child is successfully created.
1680 @retval Others Failed to create the child.
1681
1682 **/
1683 EFI_STATUS
1684 EFIAPI
1685 NetLibCreateServiceChild (
1686 IN EFI_HANDLE Controller,
1687 IN EFI_HANDLE Image,
1688 IN EFI_GUID *ServiceBindingGuid,
1689 IN OUT EFI_HANDLE *ChildHandle
1690 )
1691 {
1692 EFI_STATUS Status;
1693 EFI_SERVICE_BINDING_PROTOCOL *Service;
1694
1695
1696 ASSERT ((ServiceBindingGuid != NULL) && (ChildHandle != NULL));
1697
1698 //
1699 // Get the ServiceBinding Protocol
1700 //
1701 Status = gBS->OpenProtocol (
1702 Controller,
1703 ServiceBindingGuid,
1704 (VOID **) &Service,
1705 Image,
1706 Controller,
1707 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1708 );
1709
1710 if (EFI_ERROR (Status)) {
1711 return Status;
1712 }
1713
1714 //
1715 // Create a child
1716 //
1717 Status = Service->CreateChild (Service, ChildHandle);
1718 return Status;
1719 }
1720
1721
1722 /**
1723 Destory a child of the service that is identified by ServiceBindingGuid.
1724
1725 Get the ServiceBinding Protocol first, then use it to destroy a child.
1726
1727 If ServiceBindingGuid is NULL, then ASSERT().
1728
1729 @param[in] Controller The controller which has the service installed.
1730 @param[in] Image The image handle used to open service.
1731 @param[in] ServiceBindingGuid The service's Guid.
1732 @param[in] ChildHandle The child to destory.
1733
1734 @retval EFI_SUCCESS The child is successfully destoried.
1735 @retval Others Failed to destory the child.
1736
1737 **/
1738 EFI_STATUS
1739 EFIAPI
1740 NetLibDestroyServiceChild (
1741 IN EFI_HANDLE Controller,
1742 IN EFI_HANDLE Image,
1743 IN EFI_GUID *ServiceBindingGuid,
1744 IN EFI_HANDLE ChildHandle
1745 )
1746 {
1747 EFI_STATUS Status;
1748 EFI_SERVICE_BINDING_PROTOCOL *Service;
1749
1750 ASSERT (ServiceBindingGuid != NULL);
1751
1752 //
1753 // Get the ServiceBinding Protocol
1754 //
1755 Status = gBS->OpenProtocol (
1756 Controller,
1757 ServiceBindingGuid,
1758 (VOID **) &Service,
1759 Image,
1760 Controller,
1761 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1762 );
1763
1764 if (EFI_ERROR (Status)) {
1765 return Status;
1766 }
1767
1768 //
1769 // destory the child
1770 //
1771 Status = Service->DestroyChild (Service, ChildHandle);
1772 return Status;
1773 }
1774
1775
1776 /**
1777 Convert the mac address of the simple network protocol installed on
1778 SnpHandle to a unicode string. Callers are responsible for freeing the
1779 string storage.
1780
1781 Get the mac address of the Simple Network protocol from the SnpHandle. Then convert
1782 the mac address into a unicode string. It takes 2 unicode characters to represent
1783 a 1 byte binary buffer. Plus one unicode character for the null-terminator.
1784
1785
1786 @param[in] SnpHandle The handle where the simple network protocol is
1787 installed on.
1788 @param[in] ImageHandle The image handle used to act as the agent handle to
1789 get the simple network protocol.
1790 @param[out] MacString The pointer to store the address of the string
1791 representation of the mac address.
1792
1793 @retval EFI_SUCCESS Convert the mac address a unicode string successfully.
1794 @retval EFI_OUT_OF_RESOURCES There are not enough memory resource.
1795 @retval Others Failed to open the simple network protocol.
1796
1797 **/
1798 EFI_STATUS
1799 EFIAPI
1800 NetLibGetMacString (
1801 IN EFI_HANDLE SnpHandle,
1802 IN EFI_HANDLE ImageHandle,
1803 OUT CHAR16 **MacString
1804 )
1805 {
1806 EFI_STATUS Status;
1807 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
1808 EFI_SIMPLE_NETWORK_MODE *Mode;
1809 CHAR16 *MacAddress;
1810 UINT8 *HwAddress;
1811 UINTN Index;
1812
1813 *MacString = NULL;
1814
1815 //
1816 // Get the Simple Network protocol from the SnpHandle.
1817 //
1818 Status = gBS->OpenProtocol (
1819 SnpHandle,
1820 &gEfiSimpleNetworkProtocolGuid,
1821 (VOID **) &Snp,
1822 ImageHandle,
1823 SnpHandle,
1824 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1825 );
1826 if (EFI_ERROR (Status)) {
1827 return Status;
1828 }
1829
1830 Mode = Snp->Mode;
1831
1832 //
1833 // It takes 2 unicode characters to represent a 1 byte binary buffer.
1834 // Plus one unicode character for the null-terminator.
1835 //
1836 MacAddress = AllocatePool ((2 * Mode->HwAddressSize + 1) * sizeof (CHAR16));
1837 if (MacAddress == NULL) {
1838 return EFI_OUT_OF_RESOURCES;
1839 }
1840 *MacString = MacAddress;
1841
1842 //
1843 // Convert the mac address into a unicode string.
1844 //
1845 HwAddress = Mode->CurrentAddress.Addr;
1846 for (Index = 0; Index < Mode->HwAddressSize; Index++) {
1847 MacAddress += UnicodeValueToString (MacAddress, PREFIX_ZERO | RADIX_HEX, *(HwAddress++), 2);
1848 }
1849
1850 MacAddress[Mode->HwAddressSize * 2] = L'\0';
1851
1852
1853 return EFI_SUCCESS;
1854 }
1855
1856 /**
1857 Check the default address used by the IPv4 driver is static or dynamic (acquired
1858 from DHCP).
1859
1860 If the controller handle does not have the NIC Ip4 Config Protocol installed, the
1861 default address is static. If the EFI variable to save the configuration is not found,
1862 the default address is static. Otherwise, get the result from the EFI variable which
1863 saving the configuration.
1864
1865 @param[in] Controller The controller handle which has the NIC Ip4 Config Protocol
1866 relative with the default address to judge.
1867
1868 @retval TRUE If the default address is static.
1869 @retval FALSE If the default address is acquired from DHCP.
1870
1871 **/
1872 BOOLEAN
1873 NetLibDefaultAddressIsStatic (
1874 IN EFI_HANDLE Controller
1875 )
1876 {
1877 EFI_STATUS Status;
1878 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
1879 UINTN Len;
1880 NIC_IP4_CONFIG_INFO *ConfigInfo;
1881 BOOLEAN IsStatic;
1882 EFI_STRING ConfigHdr;
1883 EFI_STRING ConfigResp;
1884 EFI_STRING AccessProgress;
1885 EFI_STRING AccessResults;
1886 EFI_STRING String;
1887
1888 ConfigInfo = NULL;
1889 ConfigHdr = NULL;
1890 ConfigResp = NULL;
1891 AccessProgress = NULL;
1892 AccessResults = NULL;
1893 IsStatic = TRUE;
1894
1895 Status = gBS->LocateProtocol (
1896 &gEfiHiiConfigRoutingProtocolGuid,
1897 NULL,
1898 (VOID **) &HiiConfigRouting
1899 );
1900 if (EFI_ERROR (Status)) {
1901 return TRUE;
1902 }
1903
1904 //
1905 // Construct config request string header
1906 //
1907 ConfigHdr = HiiConstructConfigHdr (&gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE, Controller);
1908 if (ConfigHdr == NULL) {
1909 return TRUE;
1910 }
1911
1912 Len = StrLen (ConfigHdr);
1913 ConfigResp = AllocateZeroPool ((Len + NIC_ITEM_CONFIG_SIZE * 2 + 100) * sizeof (CHAR16));
1914 if (ConfigResp == NULL) {
1915 goto ON_EXIT;
1916 }
1917 StrCpy (ConfigResp, ConfigHdr);
1918
1919 String = ConfigResp + Len;
1920 UnicodeSPrint (
1921 String,
1922 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16),
1923 L"&OFFSET=%04X&WIDTH=%04X",
1924 OFFSET_OF (NIC_IP4_CONFIG_INFO, Source),
1925 sizeof (UINT32)
1926 );
1927
1928 Status = HiiConfigRouting->ExtractConfig (
1929 HiiConfigRouting,
1930 ConfigResp,
1931 &AccessProgress,
1932 &AccessResults
1933 );
1934 if (EFI_ERROR (Status)) {
1935 goto ON_EXIT;
1936 }
1937
1938 ConfigInfo = AllocateZeroPool (sizeof (NIC_ITEM_CONFIG_SIZE));
1939 if (ConfigInfo == NULL) {
1940 goto ON_EXIT;
1941 }
1942
1943 ConfigInfo->Source = IP4_CONFIG_SOURCE_STATIC;
1944 Len = NIC_ITEM_CONFIG_SIZE;
1945 Status = HiiConfigRouting->ConfigToBlock (
1946 HiiConfigRouting,
1947 AccessResults,
1948 (UINT8 *) ConfigInfo,
1949 &Len,
1950 &AccessProgress
1951 );
1952 if (EFI_ERROR (Status)) {
1953 goto ON_EXIT;
1954 }
1955
1956 IsStatic = (BOOLEAN) (ConfigInfo->Source == IP4_CONFIG_SOURCE_STATIC);
1957
1958 ON_EXIT:
1959
1960 if (AccessResults != NULL) {
1961 FreePool (AccessResults);
1962 }
1963 if (ConfigInfo != NULL) {
1964 FreePool (ConfigInfo);
1965 }
1966 if (ConfigResp != NULL) {
1967 FreePool (ConfigResp);
1968 }
1969 if (ConfigHdr != NULL) {
1970 FreePool (ConfigHdr);
1971 }
1972
1973 return IsStatic;
1974 }
1975
1976 /**
1977 Create an IPv4 device path node.
1978
1979 The header type of IPv4 device path node is MESSAGING_DEVICE_PATH.
1980 The header subtype of IPv4 device path node is MSG_IPv4_DP.
1981 The length of the IPv4 device path node in bytes is 19.
1982 Get other info from parameters to make up the whole IPv4 device path node.
1983
1984 @param[in, out] Node Pointer to the IPv4 device path node.
1985 @param[in] Controller The controller handle.
1986 @param[in] LocalIp The local IPv4 address.
1987 @param[in] LocalPort The local port.
1988 @param[in] RemoteIp The remote IPv4 address.
1989 @param[in] RemotePort The remote port.
1990 @param[in] Protocol The protocol type in the IP header.
1991 @param[in] UseDefaultAddress Whether this instance is using default address or not.
1992
1993 **/
1994 VOID
1995 EFIAPI
1996 NetLibCreateIPv4DPathNode (
1997 IN OUT IPv4_DEVICE_PATH *Node,
1998 IN EFI_HANDLE Controller,
1999 IN IP4_ADDR LocalIp,
2000 IN UINT16 LocalPort,
2001 IN IP4_ADDR RemoteIp,
2002 IN UINT16 RemotePort,
2003 IN UINT16 Protocol,
2004 IN BOOLEAN UseDefaultAddress
2005 )
2006 {
2007 Node->Header.Type = MESSAGING_DEVICE_PATH;
2008 Node->Header.SubType = MSG_IPv4_DP;
2009 SetDevicePathNodeLength (&Node->Header, 19);
2010
2011 CopyMem (&Node->LocalIpAddress, &LocalIp, sizeof (EFI_IPv4_ADDRESS));
2012 CopyMem (&Node->RemoteIpAddress, &RemoteIp, sizeof (EFI_IPv4_ADDRESS));
2013
2014 Node->LocalPort = LocalPort;
2015 Node->RemotePort = RemotePort;
2016
2017 Node->Protocol = Protocol;
2018
2019 if (!UseDefaultAddress) {
2020 Node->StaticIpAddress = TRUE;
2021 } else {
2022 Node->StaticIpAddress = NetLibDefaultAddressIsStatic (Controller);
2023 }
2024 }
2025
2026 /**
2027 Create an IPv6 device path node.
2028
2029 The header type of IPv6 device path node is MESSAGING_DEVICE_PATH.
2030 The header subtype of IPv6 device path node is MSG_IPv6_DP.
2031 Get other info from parameters to make up the whole IPv6 device path node.
2032
2033 @param[in, out] Node Pointer to the IPv6 device path node.
2034 @param[in] Controller The controller handle.
2035 @param[in] LocalIp The local IPv6 address.
2036 @param[in] LocalPort The local port.
2037 @param[in] RemoteIp The remote IPv6 address.
2038 @param[in] RemotePort The remote port.
2039 @param[in] Protocol The protocol type in the IP header.
2040
2041 **/
2042 VOID
2043 EFIAPI
2044 NetLibCreateIPv6DPathNode (
2045 IN OUT IPv6_DEVICE_PATH *Node,
2046 IN EFI_HANDLE Controller,
2047 IN EFI_IPv6_ADDRESS *LocalIp,
2048 IN UINT16 LocalPort,
2049 IN EFI_IPv6_ADDRESS *RemoteIp,
2050 IN UINT16 RemotePort,
2051 IN UINT16 Protocol
2052 )
2053 {
2054 Node->Header.Type = MESSAGING_DEVICE_PATH;
2055 Node->Header.SubType = MSG_IPv6_DP;
2056 SetDevicePathNodeLength (&Node->Header, sizeof (IPv6_DEVICE_PATH));
2057
2058 CopyMem (&Node->LocalIpAddress, LocalIp, sizeof (EFI_IPv6_ADDRESS));
2059 CopyMem (&Node->RemoteIpAddress, RemoteIp, sizeof (EFI_IPv6_ADDRESS));
2060
2061 Node->LocalPort = LocalPort;
2062 Node->RemotePort = RemotePort;
2063
2064 Node->Protocol = Protocol;
2065 Node->StaticIpAddress = FALSE;
2066 }
2067
2068 /**
2069 Find the UNDI/SNP handle from controller and protocol GUID.
2070
2071 For example, IP will open a MNP child to transmit/receive
2072 packets, when MNP is stopped, IP should also be stopped. IP
2073 needs to find its own private data which is related the IP's
2074 service binding instance that is install on UNDI/SNP handle.
2075 Now, the controller is either a MNP or ARP child handle. But
2076 IP opens these handle BY_DRIVER, use that info, we can get the
2077 UNDI/SNP handle.
2078
2079 @param[in] Controller Then protocol handle to check.
2080 @param[in] ProtocolGuid The protocol that is related with the handle.
2081
2082 @return The UNDI/SNP handle or NULL for errors.
2083
2084 **/
2085 EFI_HANDLE
2086 EFIAPI
2087 NetLibGetNicHandle (
2088 IN EFI_HANDLE Controller,
2089 IN EFI_GUID *ProtocolGuid
2090 )
2091 {
2092 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenBuffer;
2093 EFI_HANDLE Handle;
2094 EFI_STATUS Status;
2095 UINTN OpenCount;
2096 UINTN Index;
2097
2098 Status = gBS->OpenProtocolInformation (
2099 Controller,
2100 ProtocolGuid,
2101 &OpenBuffer,
2102 &OpenCount
2103 );
2104
2105 if (EFI_ERROR (Status)) {
2106 return NULL;
2107 }
2108
2109 Handle = NULL;
2110
2111 for (Index = 0; Index < OpenCount; Index++) {
2112 if (OpenBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {
2113 Handle = OpenBuffer[Index].ControllerHandle;
2114 break;
2115 }
2116 }
2117
2118 gBS->FreePool (OpenBuffer);
2119 return Handle;
2120 }