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