4 Copyright (c) 2005 - 2010, 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
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.
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>
24 #include <Guid/NicIp4ConfigNvData.h>
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>
37 #define NIC_ITEM_CONFIG_SIZE sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * MAX_IP4_CONFIG_IN_VARIABLE
40 // All the supported IP4 maskes in host byte order.
42 GLOBAL_REMOVE_IF_UNREFERENCED IP4_ADDR gIp4AllMasks
[IP4_MASK_NUM
] = {
81 GLOBAL_REMOVE_IF_UNREFERENCED EFI_IPv4_ADDRESS mZeroIp4Addr
= {{0, 0, 0, 0}};
84 // Any error level digitally larger than mNetDebugLevelMax
85 // will be silently discarded.
87 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mNetDebugLevelMax
= NETDEBUG_LEVEL_ERROR
;
88 GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mSyslogPacketSeq
= 0xDEADBEEF;
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.
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;
99 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8
*mMonthName
[] = {
115 // VLAN device path node template
117 GLOBAL_REMOVE_IF_UNREFERENCED VLAN_DEVICE_PATH mNetVlanDevicePathTemplate
= {
119 MESSAGING_DEVICE_PATH
,
122 (UINT8
) (sizeof (VLAN_DEVICE_PATH
)),
123 (UINT8
) ((sizeof (VLAN_DEVICE_PATH
)) >> 8)
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.
134 @return The point to SNP if one is properly openned. Otherwise NULL
137 EFI_SIMPLE_NETWORK_PROTOCOL
*
142 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
149 // Locate the handles which has SNP installed.
152 Status
= gBS
->LocateHandleBuffer (
154 &gEfiSimpleNetworkProtocolGuid
,
160 if (EFI_ERROR (Status
) || (HandleCount
== 0)) {
165 // Try to open one of the ethernet SNP protocol to send packet
169 for (Index
= 0; Index
< HandleCount
; Index
++) {
170 Status
= gBS
->HandleProtocol (
172 &gEfiSimpleNetworkProtocolGuid
,
176 if ((Status
== EFI_SUCCESS
) && (Snp
!= NULL
) &&
177 (Snp
->Mode
->IfType
== NET_IFTYPE_ETHERNET
) &&
178 (Snp
->Mode
->MaxPacketSize
>= NET_SYSLOG_PACKET_LEN
)) {
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.
197 @param[in] Packet The Syslog packet
198 @param[in] Length The length of the packet
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.
211 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
214 EFI_EVENT TimeoutEvent
;
217 Snp
= SyslogLocateSnp ();
220 return EFI_DEVICE_ERROR
;
223 Ether
= (ETHER_HEAD
*) Packet
;
224 CopyMem (Ether
->SrcMac
, Snp
->Mode
->CurrentAddress
.Addr
, NET_ETHER_ADDR_LEN
);
227 // Start the timeout event.
229 Status
= gBS
->CreateEvent (
237 if (EFI_ERROR (Status
)) {
241 Status
= gBS
->SetTimer (TimeoutEvent
, TimerRelative
, NET_SYSLOG_TX_TIMEOUT
);
243 if (EFI_ERROR (Status
)) {
249 // Transmit the packet through SNP.
251 Status
= Snp
->Transmit (Snp
, 0, Length
, Packet
, NULL
, NULL
, NULL
);
253 if ((Status
!= EFI_SUCCESS
) && (Status
!= EFI_NOT_READY
)) {
254 Status
= EFI_DEVICE_ERROR
;
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.
267 // Get the recycled transmit buffer status.
269 Snp
->GetStatus (Snp
, NULL
, (VOID
**) &TxBuf
);
271 if (!EFI_ERROR (gBS
->CheckEvent (TimeoutEvent
))) {
272 Status
= EFI_TIMEOUT
;
276 } while (TxBuf
== NULL
);
278 if ((Status
== EFI_SUCCESS
) || (Status
== EFI_TIMEOUT
)) {
283 // Status is EFI_NOT_READY. Restart the timer event and
284 // call Snp->Transmit again.
286 gBS
->SetTimer (TimeoutEvent
, TimerRelative
, NET_SYSLOG_TX_TIMEOUT
);
289 gBS
->SetTimer (TimeoutEvent
, TimerCancel
, 0);
292 gBS
->CloseEvent (TimeoutEvent
);
297 Build a syslog packet, including the Ethernet/Ip/Udp headers
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
308 @return The length of the syslog packet built.
324 EFI_UDP_HEADER
*Udp4
;
330 // Fill in the Ethernet header. Leave alone the source MAC.
331 // SyslogSendPacket will fill in the address for us.
333 Ether
= (ETHER_HEAD
*) Buf
;
334 CopyMem (Ether
->DstMac
, mSyslogDstMac
, NET_ETHER_ADDR_LEN
);
335 ZeroMem (Ether
->SrcMac
, NET_ETHER_ADDR_LEN
);
337 Ether
->EtherType
= HTONS (0x0800); // IPv4 protocol
339 Buf
+= sizeof (ETHER_HEAD
);
340 BufLen
-= sizeof (ETHER_HEAD
);
343 // Fill in the IP header
345 Ip4
= (IP4_HEAD
*) Buf
;
350 Ip4
->Id
= (UINT16
) mSyslogPacketSeq
;
353 Ip4
->Protocol
= 0x11;
355 Ip4
->Src
= mSyslogSrcIp
;
356 Ip4
->Dst
= mSyslogDstIp
;
358 Buf
+= sizeof (IP4_HEAD
);
359 BufLen
-= sizeof (IP4_HEAD
);
362 // Fill in the UDP header, Udp checksum is optional. Leave it zero.
364 Udp4
= (EFI_UDP_HEADER
*) Buf
;
365 Udp4
->SrcPort
= HTONS (514);
366 Udp4
->DstPort
= HTONS (514);
370 Buf
+= sizeof (EFI_UDP_HEADER
);
371 BufLen
-= sizeof (EFI_UDP_HEADER
);
374 // Build the syslog message body with <PRI> Timestamp machine module Message
376 Pri
= ((NET_SYSLOG_FACILITY
& 31) << 3) | (Level
& 7);
377 gRT
->GetTime (&Time
, NULL
);
380 // Use %a to format the ASCII strings, %s to format UNICODE strings
383 Len
+= (UINT32
) AsciiSPrint (
386 "<%d> %a %d %d:%d:%d ",
388 mMonthName
[Time
.Month
-1],
396 Len
+= (UINT32
) AsciiSPrint (
399 "Tiano %a: %a (Line: %d File: %a)",
408 // OK, patch the IP length/checksum and UDP length fields.
410 Len
+= sizeof (EFI_UDP_HEADER
);
411 Udp4
->Length
= HTONS ((UINT16
) Len
);
413 Len
+= sizeof (IP4_HEAD
);
414 Ip4
->TotalLen
= HTONS ((UINT16
) Len
);
415 Ip4
->Checksum
= (UINT16
) (~NetblockChecksum ((UINT8
*) Ip4
, sizeof (IP4_HEAD
)));
417 return Len
+ sizeof (ETHER_HEAD
);
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))
429 NETDEBUG_LEVEL_TRACE,
433 NetDebugASPrint ("State transit to %a\n", Name)
436 @param Format The ASCII format string.
437 @param ... The variable length parameter whose format is determined
438 by the Format string.
440 @return The buffer containing the formatted message,
441 or NULL if failed to allocate memory.
453 Buf
= (CHAR8
*) AllocatePool (NET_DEBUG_MSG_LEN
);
459 VA_START (Marker
, Format
);
460 AsciiVSPrint (Buf
, NET_DEBUG_MSG_LEN
, Format
, Marker
);
467 Builds an UDP4 syslog packet and send it using SNP.
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.
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.
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.
497 // Check whether the message should be sent out
499 if (Message
== NULL
) {
500 return EFI_INVALID_PARAMETER
;
503 if (Level
> mNetDebugLevelMax
) {
504 Status
= EFI_SUCCESS
;
509 // Allocate a maxium of 1024 bytes, the caller should ensure
510 // that the message plus the ethernet/ip/udp header is shorter
513 Packet
= (CHAR8
*) AllocatePool (NET_SYSLOG_PACKET_LEN
);
515 if (Packet
== NULL
) {
516 Status
= EFI_OUT_OF_RESOURCES
;
521 // Build the message: Ethernet header + IP header + Udp Header + user data
523 Len
= SyslogBuildPacket (
529 NET_SYSLOG_PACKET_LEN
,
534 Status
= SyslogSendPacket (Packet
, Len
);
542 Return the length of the mask.
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.
548 @param[in] NetMask The netmask to get the length from.
550 @return The length of the netmask, IP4_MASK_NUM if the mask is invalid.
561 for (Index
= 0; Index
< IP4_MASK_NUM
; Index
++) {
562 if (NetMask
== gIp4AllMasks
[Index
]) {
573 Return the class of the IP address, such as class A, B, C.
574 Addr is in host byte order.
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.
588 @param[in] Addr The address to get the class from.
590 @return IP address class, such as IP4_ADDR_CLASSA.
601 ByteOne
= (UINT8
) (Addr
>> 24);
603 if ((ByteOne
& 0x80) == 0) {
604 return IP4_ADDR_CLASSA
;
606 } else if ((ByteOne
& 0xC0) == 0x80) {
607 return IP4_ADDR_CLASSB
;
609 } else if ((ByteOne
& 0xE0) == 0xC0) {
610 return IP4_ADDR_CLASSC
;
612 } else if ((ByteOne
& 0xF0) == 0xE0) {
613 return IP4_ADDR_CLASSD
;
616 return IP4_ADDR_CLASSE
;
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.
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.
631 @param[in] Ip The IP to check against.
632 @param[in] NetMask The mask of the IP.
634 @return TRUE if IP is a valid unicast address on the network, otherwise FALSE.
646 Class
= NetGetIpClass (Ip
);
648 if ((Ip
== 0) || (Class
>= IP4_ADDR_CLASSD
)) {
653 NetMask
= gIp4AllMasks
[Class
<< 3];
656 if (((Ip
&~NetMask
) == ~NetMask
) || ((Ip
&~NetMask
) == 0)) {
664 Check whether the incoming IPv6 address is a valid unicast address.
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
672 @param[in] Ip6 The IPv6 address to check against.
674 @return TRUE if Ip6 is a valid unicast address on the network, otherwise FALSE.
678 NetIp6IsValidUnicast (
679 IN EFI_IPv6_ADDRESS
*Ip6
685 if (Ip6
->Addr
[0] == 0xFF) {
689 for (Index
= 0; Index
< 15; Index
++) {
690 if (Ip6
->Addr
[Index
] != 0) {
695 Byte
= Ip6
->Addr
[Index
];
697 if (Byte
== 0x0 || Byte
== 0x1) {
705 Check whether the incoming Ipv6 address is the unspecified address or not.
707 @param[in] Ip6 - Ip6 address, in network order.
709 @retval TRUE - Yes, unspecified
714 NetIp6IsUnspecifiedAddr (
715 IN EFI_IPv6_ADDRESS
*Ip6
720 for (Index
= 0; Index
< 16; Index
++) {
721 if (Ip6
->Addr
[Index
] != 0) {
730 Check whether the incoming Ipv6 address is a link-local address.
732 @param[in] Ip6 - Ip6 address, in network order.
734 @retval TRUE - Yes, link-local address
739 NetIp6IsLinkLocalAddr (
740 IN EFI_IPv6_ADDRESS
*Ip6
745 ASSERT (Ip6
!= NULL
);
747 if (Ip6
->Addr
[0] != 0xFE) {
751 if (Ip6
->Addr
[1] != 0x80) {
755 for (Index
= 2; Index
< 8; Index
++) {
756 if (Ip6
->Addr
[Index
] != 0) {
765 Check whether the Ipv6 address1 and address2 are on the connected network.
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.
771 @retval TRUE - Yes, connected.
777 EFI_IPv6_ADDRESS
*Ip1
,
778 EFI_IPv6_ADDRESS
*Ip2
,
786 ASSERT (Ip1
!= NULL
&& Ip2
!= NULL
);
788 if (PrefixLength
== 0) {
792 Byte
= (UINT8
) (PrefixLength
/ 8);
793 Bit
= (UINT8
) (PrefixLength
% 8);
795 if (CompareMem (Ip1
, Ip2
, Byte
) != 0) {
800 Mask
= (UINT8
) (0xFF << (8 - Bit
));
802 if ((Ip1
->Addr
[Byte
] & Mask
) != (Ip2
->Addr
[Byte
] & Mask
)) {
812 Switches the endianess of an IPv6 address
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
818 @param Ip6 Points to an IPv6 address
820 @return The byte swapped IPv6 address.
825 EFI_IPv6_ADDRESS
*Ip6
831 CopyMem (&High
, Ip6
, sizeof (UINT64
));
832 CopyMem (&Low
, &Ip6
->Addr
[8], sizeof (UINT64
));
834 High
= SwapBytes64 (High
);
835 Low
= SwapBytes64 (Low
);
837 CopyMem (Ip6
, &Low
, sizeof (UINT64
));
838 CopyMem (&Ip6
->Addr
[8], &High
, sizeof (UINT64
));
844 Initialize a random seed using current time.
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
850 @return The random seed initialized with current time.
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;
872 Extract a UINT32 from a byte stream.
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.
877 @param[in] Buf The buffer to extract the UINT32.
879 @return The UINT32 extracted.
890 CopyMem (&Value
, Buf
, sizeof (UINT32
));
891 return NTOHL (Value
);
896 Put a UINT32 to the byte stream in network byte order.
898 Converts a UINT32 from host byte order to network byte order. Then copy it to the
901 @param[in, out] Buf The buffer to put the UINT32.
902 @param[in] Data The data to put.
913 CopyMem (Buf
, &Data
, sizeof (UINT32
));
918 Remove the first node entry on the list, and return the removed node entry.
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.
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,
930 @param[in, out] Head The list header.
932 @return The first node entry that is removed from the list, NULL if the list is empty.
938 IN OUT LIST_ENTRY
*Head
943 ASSERT (Head
!= NULL
);
945 if (IsListEmpty (Head
)) {
949 First
= Head
->ForwardLink
;
950 Head
->ForwardLink
= First
->ForwardLink
;
951 First
->ForwardLink
->BackLink
= Head
;
954 First
->ForwardLink
= (LIST_ENTRY
*) NULL
;
955 First
->BackLink
= (LIST_ENTRY
*) NULL
;
963 Remove the last node entry on the list and and return the removed node entry.
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.
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,
975 @param[in, out] Head The list head.
977 @return The last node entry that is removed from the list, NULL if the list is empty.
983 IN OUT LIST_ENTRY
*Head
988 ASSERT (Head
!= NULL
);
990 if (IsListEmpty (Head
)) {
994 Last
= Head
->BackLink
;
995 Head
->BackLink
= Last
->BackLink
;
996 Last
->BackLink
->ForwardLink
= Head
;
999 Last
->ForwardLink
= (LIST_ENTRY
*) NULL
;
1000 Last
->BackLink
= (LIST_ENTRY
*) NULL
;
1008 Insert a new node entry after a designated node entry of a doubly linked list.
1010 Inserts a new node entry donated by NewEntry after the node entry donated by PrevEntry
1011 of the doubly linked list.
1013 @param[in, out] PrevEntry The previous entry to insert after.
1014 @param[in, out] NewEntry The new entry to insert.
1019 NetListInsertAfter (
1020 IN OUT LIST_ENTRY
*PrevEntry
,
1021 IN OUT LIST_ENTRY
*NewEntry
1024 NewEntry
->BackLink
= PrevEntry
;
1025 NewEntry
->ForwardLink
= PrevEntry
->ForwardLink
;
1026 PrevEntry
->ForwardLink
->BackLink
= NewEntry
;
1027 PrevEntry
->ForwardLink
= NewEntry
;
1032 Insert a new node entry before a designated node entry of a doubly linked list.
1034 Inserts a new node entry donated by NewEntry after the node entry donated by PostEntry
1035 of the doubly linked list.
1037 @param[in, out] PostEntry The entry to insert before.
1038 @param[in, out] NewEntry The new entry to insert.
1043 NetListInsertBefore (
1044 IN OUT LIST_ENTRY
*PostEntry
,
1045 IN OUT LIST_ENTRY
*NewEntry
1048 NewEntry
->ForwardLink
= PostEntry
;
1049 NewEntry
->BackLink
= PostEntry
->BackLink
;
1050 PostEntry
->BackLink
->ForwardLink
= NewEntry
;
1051 PostEntry
->BackLink
= NewEntry
;
1056 Initialize the netmap. Netmap is a reposity to keep the <Key, Value> pairs.
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.
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().
1066 @param[in, out] Map The netmap to initialize.
1075 ASSERT (Map
!= NULL
);
1077 InitializeListHead (&Map
->Used
);
1078 InitializeListHead (&Map
->Recycled
);
1084 To clean up the netmap, that is, release allocated memories.
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.
1090 If Map is NULL, then ASSERT().
1092 @param[in, out] Map The netmap to clean up.
1105 ASSERT (Map
!= NULL
);
1107 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Map
->Used
) {
1108 Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
1110 RemoveEntryList (&Item
->Link
);
1113 gBS
->FreePool (Item
);
1116 ASSERT ((Map
->Count
== 0) && IsListEmpty (&Map
->Used
));
1118 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Map
->Recycled
) {
1119 Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
1121 RemoveEntryList (&Item
->Link
);
1122 gBS
->FreePool (Item
);
1125 ASSERT (IsListEmpty (&Map
->Recycled
));
1130 Test whether the netmap is empty and return true if it is.
1132 If the number of the <Key, Value> pairs in the netmap is zero, return TRUE.
1134 If Map is NULL, then ASSERT().
1137 @param[in] Map The net map to test.
1139 @return TRUE if the netmap is empty, otherwise FALSE.
1148 ASSERT (Map
!= NULL
);
1149 return (BOOLEAN
) (Map
->Count
== 0);
1154 Return the number of the <Key, Value> pairs in the netmap.
1156 @param[in] Map The netmap to get the entry number.
1158 @return The entry number in the netmap.
1172 Return one allocated item.
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.
1179 If Map is NULL, then ASSERT().
1181 @param[in, out] Map The netmap to allocate item for.
1183 @return The allocated item. If NULL, the
1184 allocation failed due to resource limit.
1196 ASSERT (Map
!= NULL
);
1198 Head
= &Map
->Recycled
;
1200 if (IsListEmpty (Head
)) {
1201 for (Index
= 0; Index
< NET_MAP_INCREAMENT
; Index
++) {
1202 Item
= AllocatePool (sizeof (NET_MAP_ITEM
));
1212 InsertHeadList (Head
, &Item
->Link
);
1216 Item
= NET_LIST_HEAD (Head
, NET_MAP_ITEM
, Link
);
1217 NetListRemoveHead (Head
);
1224 Allocate an item to save the <Key, Value> pair to the head of the netmap.
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.
1230 If Map is NULL, then ASSERT().
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.
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.
1243 IN OUT NET_MAP
*Map
,
1245 IN VOID
*Value OPTIONAL
1250 ASSERT (Map
!= NULL
);
1252 Item
= NetMapAllocItem (Map
);
1255 return EFI_OUT_OF_RESOURCES
;
1259 Item
->Value
= Value
;
1260 InsertHeadList (&Map
->Used
, &Item
->Link
);
1268 Allocate an item to save the <Key, Value> pair to the tail of the netmap.
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.
1274 If Map is NULL, then ASSERT().
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.
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.
1287 IN OUT NET_MAP
*Map
,
1289 IN VOID
*Value OPTIONAL
1294 ASSERT (Map
!= NULL
);
1296 Item
= NetMapAllocItem (Map
);
1299 return EFI_OUT_OF_RESOURCES
;
1303 Item
->Value
= Value
;
1304 InsertTailList (&Map
->Used
, &Item
->Link
);
1313 Check whether the item is in the Map and return TRUE if it is.
1315 @param[in] Map The netmap to search within.
1316 @param[in] Item The item to search.
1318 @return TRUE if the item is in the netmap, otherwise FALSE.
1324 IN NET_MAP_ITEM
*Item
1327 LIST_ENTRY
*ListEntry
;
1329 NET_LIST_FOR_EACH (ListEntry
, &Map
->Used
) {
1330 if (ListEntry
== &Item
->Link
) {
1340 Find the key in the netmap and returns the point to the item contains the Key.
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.
1345 If Map is NULL, then ASSERT().
1347 @param[in] Map The netmap to search within.
1348 @param[in] Key The key to search.
1350 @return The point to the item contains the Key, or NULL if Key isn't in the map.
1363 ASSERT (Map
!= NULL
);
1365 NET_LIST_FOR_EACH (Entry
, &Map
->Used
) {
1366 Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
1368 if (Item
->Key
== Key
) {
1378 Remove the node entry of the item from the netmap and return the key of the removed item.
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.
1385 If Map is NULL, then ASSERT().
1386 If Item is NULL, then ASSERT().
1387 if item in not in the netmap, then ASSERT().
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.
1393 @return The key of the removed item.
1399 IN OUT NET_MAP
*Map
,
1400 IN OUT NET_MAP_ITEM
*Item
,
1401 OUT VOID
**Value OPTIONAL
1404 ASSERT ((Map
!= NULL
) && (Item
!= NULL
));
1405 ASSERT (NetItemInMap (Map
, Item
));
1407 RemoveEntryList (&Item
->Link
);
1409 InsertHeadList (&Map
->Recycled
, &Item
->Link
);
1411 if (Value
!= NULL
) {
1412 *Value
= Item
->Value
;
1420 Remove the first node entry on the netmap and return the key of the removed item.
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.
1427 If Map is NULL, then ASSERT().
1428 If the Used doubly linked list is empty, then ASSERT().
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.
1433 @return The key of the item removed.
1439 IN OUT NET_MAP
*Map
,
1440 OUT VOID
**Value OPTIONAL
1446 // Often, it indicates a programming error to remove
1447 // the first entry in an empty list
1449 ASSERT (Map
&& !IsListEmpty (&Map
->Used
));
1451 Item
= NET_LIST_HEAD (&Map
->Used
, NET_MAP_ITEM
, Link
);
1452 RemoveEntryList (&Item
->Link
);
1454 InsertHeadList (&Map
->Recycled
, &Item
->Link
);
1456 if (Value
!= NULL
) {
1457 *Value
= Item
->Value
;
1465 Remove the last node entry on the netmap and return the key of the removed item.
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.
1472 If Map is NULL, then ASSERT().
1473 If the Used doubly linked list is empty, then ASSERT().
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.
1478 @return The key of the item removed.
1484 IN OUT NET_MAP
*Map
,
1485 OUT VOID
**Value OPTIONAL
1491 // Often, it indicates a programming error to remove
1492 // the last entry in an empty list
1494 ASSERT (Map
&& !IsListEmpty (&Map
->Used
));
1496 Item
= NET_LIST_TAIL (&Map
->Used
, NET_MAP_ITEM
, Link
);
1497 RemoveEntryList (&Item
->Link
);
1499 InsertHeadList (&Map
->Recycled
, &Item
->Link
);
1501 if (Value
!= NULL
) {
1502 *Value
= Item
->Value
;
1510 Iterate through the netmap and call CallBack for each item.
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.
1516 If Map is NULL, then ASSERT().
1517 If CallBack is NULL, then ASSERT().
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.
1523 @retval EFI_SUCCESS There is no item in the netmap or CallBack for each item
1525 @retval Others It returns the CallBack's last return value.
1532 IN NET_MAP_CALLBACK CallBack
,
1533 IN VOID
*Arg OPTIONAL
1543 ASSERT ((Map
!= NULL
) && (CallBack
!= NULL
));
1547 if (IsListEmpty (Head
)) {
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
);
1555 if (EFI_ERROR (Result
)) {
1565 This is the default unload handle for all the network drivers.
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.
1570 @param[in] ImageHandle The drivers' driver image.
1572 @retval EFI_SUCCESS The image is unloaded.
1573 @retval Others Failed to unload the image.
1578 NetLibDefaultUnload (
1579 IN EFI_HANDLE ImageHandle
1583 EFI_HANDLE
*DeviceHandleBuffer
;
1584 UINTN DeviceHandleCount
;
1586 EFI_DRIVER_BINDING_PROTOCOL
*DriverBinding
;
1587 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
1588 EFI_COMPONENT_NAME2_PROTOCOL
*ComponentName2
;
1591 // Get the list of all the handles in the handle database.
1592 // If there is an error getting the list, then the unload
1595 Status
= gBS
->LocateHandleBuffer (
1603 if (EFI_ERROR (Status
)) {
1608 // Disconnect the driver specified by ImageHandle from all
1609 // the devices in the handle database.
1611 for (Index
= 0; Index
< DeviceHandleCount
; Index
++) {
1612 Status
= gBS
->DisconnectController (
1613 DeviceHandleBuffer
[Index
],
1620 // Uninstall all the protocols installed in the driver entry point
1622 for (Index
= 0; Index
< DeviceHandleCount
; Index
++) {
1623 Status
= gBS
->HandleProtocol (
1624 DeviceHandleBuffer
[Index
],
1625 &gEfiDriverBindingProtocolGuid
,
1626 (VOID
**) &DriverBinding
1629 if (EFI_ERROR (Status
)) {
1633 if (DriverBinding
->ImageHandle
!= ImageHandle
) {
1637 gBS
->UninstallProtocolInterface (
1639 &gEfiDriverBindingProtocolGuid
,
1642 Status
= gBS
->HandleProtocol (
1643 DeviceHandleBuffer
[Index
],
1644 &gEfiComponentNameProtocolGuid
,
1645 (VOID
**) &ComponentName
1647 if (!EFI_ERROR (Status
)) {
1648 gBS
->UninstallProtocolInterface (
1650 &gEfiComponentNameProtocolGuid
,
1655 Status
= gBS
->HandleProtocol (
1656 DeviceHandleBuffer
[Index
],
1657 &gEfiComponentName2ProtocolGuid
,
1658 (VOID
**) &ComponentName2
1660 if (!EFI_ERROR (Status
)) {
1661 gBS
->UninstallProtocolInterface (
1663 &gEfiComponentName2ProtocolGuid
,
1670 // Free the buffer containing the list of handles from the handle database
1672 if (DeviceHandleBuffer
!= NULL
) {
1673 gBS
->FreePool (DeviceHandleBuffer
);
1682 Create a child of the service that is identified by ServiceBindingGuid.
1684 Get the ServiceBinding Protocol first, then use it to create a child.
1686 If ServiceBindingGuid is NULL, then ASSERT().
1687 If ChildHandle is NULL, then ASSERT().
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.
1694 @retval EFI_SUCCESS The child is successfully created.
1695 @retval Others Failed to create the child.
1700 NetLibCreateServiceChild (
1701 IN EFI_HANDLE Controller
,
1702 IN EFI_HANDLE Image
,
1703 IN EFI_GUID
*ServiceBindingGuid
,
1704 IN OUT EFI_HANDLE
*ChildHandle
1708 EFI_SERVICE_BINDING_PROTOCOL
*Service
;
1711 ASSERT ((ServiceBindingGuid
!= NULL
) && (ChildHandle
!= NULL
));
1714 // Get the ServiceBinding Protocol
1716 Status
= gBS
->OpenProtocol (
1722 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1725 if (EFI_ERROR (Status
)) {
1732 Status
= Service
->CreateChild (Service
, ChildHandle
);
1738 Destory a child of the service that is identified by ServiceBindingGuid.
1740 Get the ServiceBinding Protocol first, then use it to destroy a child.
1742 If ServiceBindingGuid is NULL, then ASSERT().
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.
1749 @retval EFI_SUCCESS The child is successfully destoried.
1750 @retval Others Failed to destory the child.
1755 NetLibDestroyServiceChild (
1756 IN EFI_HANDLE Controller
,
1757 IN EFI_HANDLE Image
,
1758 IN EFI_GUID
*ServiceBindingGuid
,
1759 IN EFI_HANDLE ChildHandle
1763 EFI_SERVICE_BINDING_PROTOCOL
*Service
;
1765 ASSERT (ServiceBindingGuid
!= NULL
);
1768 // Get the ServiceBinding Protocol
1770 Status
= gBS
->OpenProtocol (
1776 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1779 if (EFI_ERROR (Status
)) {
1784 // destory the child
1786 Status
= Service
->DestroyChild (Service
, ChildHandle
);
1791 Get handle with Simple Network Protocol installed on it.
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.
1798 @param[in] ServiceHandle The handle where network service binding protocols are
1800 @param[out] Snp The pointer to store the address of the SNP instance.
1801 This is an optional parameter that may be NULL.
1803 @return The SNP handle, or NULL if not found.
1808 NetLibGetSnpHandle (
1809 IN EFI_HANDLE ServiceHandle
,
1810 OUT EFI_SIMPLE_NETWORK_PROTOCOL
**Snp OPTIONAL
1814 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpInstance
;
1815 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1816 EFI_HANDLE SnpHandle
;
1819 // Try to open SNP from ServiceHandle
1822 Status
= gBS
->HandleProtocol (ServiceHandle
, &gEfiSimpleNetworkProtocolGuid
, (VOID
**) &SnpInstance
);
1823 if (!EFI_ERROR (Status
)) {
1827 return ServiceHandle
;
1831 // Failed to open SNP, try to get SNP handle by LocateDevicePath()
1833 DevicePath
= DevicePathFromHandle (ServiceHandle
);
1834 if (DevicePath
== NULL
) {
1839 Status
= gBS
->LocateDevicePath (&gEfiSimpleNetworkProtocolGuid
, &DevicePath
, &SnpHandle
);
1840 if (EFI_ERROR (Status
)) {
1842 // Failed to find SNP handle
1847 Status
= gBS
->HandleProtocol (SnpHandle
, &gEfiSimpleNetworkProtocolGuid
, (VOID
**) &SnpInstance
);
1848 if (!EFI_ERROR (Status
)) {
1859 Retrieve VLAN ID of a VLAN device handle.
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.
1865 @param[in] ServiceHandle The handle where network service binding protocols are
1868 @return VLAN ID of the device handle, or 0 if not a VLAN device.
1874 IN EFI_HANDLE ServiceHandle
1877 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1878 EFI_DEVICE_PATH_PROTOCOL
*Node
;
1880 DevicePath
= DevicePathFromHandle (ServiceHandle
);
1881 if (DevicePath
== NULL
) {
1886 while (!IsDevicePathEnd (Node
)) {
1887 if (Node
->Type
== MESSAGING_DEVICE_PATH
&& Node
->SubType
== MSG_VLAN_DP
) {
1888 return ((VLAN_DEVICE_PATH
*) Node
)->VlanId
;
1890 Node
= NextDevicePathNode (Node
);
1897 Find VLAN device handle with specified VLAN ID.
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.
1903 @param[in] ControllerHandle The handle where network service binding protocols are
1905 @param[in] VlanId The configured VLAN ID for the VLAN device.
1907 @return The VLAN device handle, or NULL if not found.
1912 NetLibGetVlanHandle (
1913 IN EFI_HANDLE ControllerHandle
,
1917 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
1918 EFI_DEVICE_PATH_PROTOCOL
*VlanDevicePath
;
1919 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1920 VLAN_DEVICE_PATH VlanNode
;
1923 ParentDevicePath
= DevicePathFromHandle (ControllerHandle
);
1924 if (ParentDevicePath
== NULL
) {
1929 // Construct VLAN device path
1931 CopyMem (&VlanNode
, &mNetVlanDevicePathTemplate
, sizeof (VLAN_DEVICE_PATH
));
1932 VlanNode
.VlanId
= VlanId
;
1933 VlanDevicePath
= AppendDevicePathNode (
1935 (EFI_DEVICE_PATH_PROTOCOL
*) &VlanNode
1937 if (VlanDevicePath
== NULL
) {
1942 // Find VLAN device handle
1945 DevicePath
= VlanDevicePath
;
1946 gBS
->LocateDevicePath (
1947 &gEfiDevicePathProtocolGuid
,
1951 if (!IsDevicePathEnd (DevicePath
)) {
1953 // Device path is not exactly match
1958 FreePool (VlanDevicePath
);
1963 Get MAC address associated with the network service handle.
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.
1969 @param[in] ServiceHandle The handle where network service binding protocols are
1971 @param[out] MacAddress The pointer to store the returned MAC address.
1972 @param[out] AddressSize The length of returned MAC address.
1974 @retval EFI_SUCCESS MAC address is returned successfully.
1975 @retval Others Failed to get SNP mode data.
1980 NetLibGetMacAddress (
1981 IN EFI_HANDLE ServiceHandle
,
1982 OUT EFI_MAC_ADDRESS
*MacAddress
,
1983 OUT UINTN
*AddressSize
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
;
1995 ASSERT (MacAddress
!= NULL
);
1996 ASSERT (AddressSize
!= NULL
);
1999 // Try to get SNP handle
2002 SnpHandle
= NetLibGetSnpHandle (ServiceHandle
, &Snp
);
2003 if (SnpHandle
!= NULL
) {
2005 // SNP found, use it directly
2007 SnpMode
= Snp
->Mode
;
2010 // Failed to get SNP handle, try to get MAC address from MNP
2012 MnpChildHandle
= NULL
;
2013 Status
= gBS
->HandleProtocol (
2015 &gEfiManagedNetworkServiceBindingProtocolGuid
,
2018 if (EFI_ERROR (Status
)) {
2023 // Create a MNP child
2025 Status
= MnpSb
->CreateChild (MnpSb
, &MnpChildHandle
);
2026 if (EFI_ERROR (Status
)) {
2031 // Open MNP protocol
2033 Status
= gBS
->HandleProtocol (
2035 &gEfiManagedNetworkProtocolGuid
,
2038 if (EFI_ERROR (Status
)) {
2043 // Try to get SNP mode from MNP
2045 Status
= Mnp
->GetModeData (Mnp
, NULL
, &SnpModeData
);
2046 if (EFI_ERROR (Status
)) {
2049 SnpMode
= &SnpModeData
;
2052 // Destroy the MNP child
2054 MnpSb
->DestroyChild (MnpSb
, MnpChildHandle
);
2057 *AddressSize
= SnpMode
->HwAddressSize
;
2058 CopyMem (MacAddress
->Addr
, SnpMode
->CurrentAddress
.Addr
, SnpMode
->HwAddressSize
);
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.
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.
2072 @param[in] ServiceHandle The handle where network service binding protocol is
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.
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.
2086 NetLibGetMacString (
2087 IN EFI_HANDLE ServiceHandle
,
2088 IN EFI_HANDLE ImageHandle
,
2089 OUT CHAR16
**MacString
2093 EFI_MAC_ADDRESS MacAddress
;
2095 UINTN HwAddressSize
;
2100 ASSERT (MacString
!= NULL
);
2103 // Get MAC address of the network device
2105 Status
= NetLibGetMacAddress (ServiceHandle
, &MacAddress
, &HwAddressSize
);
2106 if (EFI_ERROR (Status
)) {
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.
2115 String
= AllocateZeroPool ((2 * HwAddressSize
+ 5 + 1) * sizeof (CHAR16
));
2116 if (String
== NULL
) {
2117 return EFI_OUT_OF_RESOURCES
;
2119 *MacString
= String
;
2122 // Convert the MAC address into a unicode string.
2124 HwAddress
= &MacAddress
.Addr
[0];
2125 for (Index
= 0; Index
< HwAddressSize
; Index
++) {
2126 String
+= UnicodeValueToString (String
, PREFIX_ZERO
| RADIX_HEX
, *(HwAddress
++), 2);
2130 // Append VLAN ID if any
2132 VlanId
= NetLibGetVlanId (ServiceHandle
);
2135 String
+= UnicodeValueToString (String
, PREFIX_ZERO
| RADIX_HEX
, VlanId
, 4);
2139 // Null terminate the Unicode string
2147 Check the default address used by the IPv4 driver is static or dynamic (acquired
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.
2155 @param[in] Controller The controller handle which has the NIC Ip4 Config Protocol
2156 relative with the default address to judge.
2158 @retval TRUE If the default address is static.
2159 @retval FALSE If the default address is acquired from DHCP.
2163 NetLibDefaultAddressIsStatic (
2164 IN EFI_HANDLE Controller
2168 EFI_HII_CONFIG_ROUTING_PROTOCOL
*HiiConfigRouting
;
2170 NIC_IP4_CONFIG_INFO
*ConfigInfo
;
2172 EFI_STRING ConfigHdr
;
2173 EFI_STRING ConfigResp
;
2174 EFI_STRING AccessProgress
;
2175 EFI_STRING AccessResults
;
2181 AccessProgress
= NULL
;
2182 AccessResults
= NULL
;
2185 Status
= gBS
->LocateProtocol (
2186 &gEfiHiiConfigRoutingProtocolGuid
,
2188 (VOID
**) &HiiConfigRouting
2190 if (EFI_ERROR (Status
)) {
2195 // Construct config request string header
2197 ConfigHdr
= HiiConstructConfigHdr (&gEfiNicIp4ConfigVariableGuid
, EFI_NIC_IP4_CONFIG_VARIABLE
, Controller
);
2198 if (ConfigHdr
== NULL
) {
2202 Len
= StrLen (ConfigHdr
);
2203 ConfigResp
= AllocateZeroPool ((Len
+ NIC_ITEM_CONFIG_SIZE
* 2 + 100) * sizeof (CHAR16
));
2204 if (ConfigResp
== NULL
) {
2207 StrCpy (ConfigResp
, ConfigHdr
);
2209 String
= ConfigResp
+ Len
;
2212 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
2213 L
"&OFFSET=%04X&WIDTH=%04X",
2214 OFFSET_OF (NIC_IP4_CONFIG_INFO
, Source
),
2218 Status
= HiiConfigRouting
->ExtractConfig (
2224 if (EFI_ERROR (Status
)) {
2228 ConfigInfo
= AllocateZeroPool (sizeof (NIC_ITEM_CONFIG_SIZE
));
2229 if (ConfigInfo
== NULL
) {
2233 ConfigInfo
->Source
= IP4_CONFIG_SOURCE_STATIC
;
2234 Len
= NIC_ITEM_CONFIG_SIZE
;
2235 Status
= HiiConfigRouting
->ConfigToBlock (
2238 (UINT8
*) ConfigInfo
,
2242 if (EFI_ERROR (Status
)) {
2246 IsStatic
= (BOOLEAN
) (ConfigInfo
->Source
== IP4_CONFIG_SOURCE_STATIC
);
2250 if (AccessResults
!= NULL
) {
2251 FreePool (AccessResults
);
2253 if (ConfigInfo
!= NULL
) {
2254 FreePool (ConfigInfo
);
2256 if (ConfigResp
!= NULL
) {
2257 FreePool (ConfigResp
);
2259 if (ConfigHdr
!= NULL
) {
2260 FreePool (ConfigHdr
);
2267 Create an IPv4 device path node.
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.
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.
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
,
2294 IN BOOLEAN UseDefaultAddress
2297 Node
->Header
.Type
= MESSAGING_DEVICE_PATH
;
2298 Node
->Header
.SubType
= MSG_IPv4_DP
;
2299 SetDevicePathNodeLength (&Node
->Header
, 19);
2301 CopyMem (&Node
->LocalIpAddress
, &LocalIp
, sizeof (EFI_IPv4_ADDRESS
));
2302 CopyMem (&Node
->RemoteIpAddress
, &RemoteIp
, sizeof (EFI_IPv4_ADDRESS
));
2304 Node
->LocalPort
= LocalPort
;
2305 Node
->RemotePort
= RemotePort
;
2307 Node
->Protocol
= Protocol
;
2309 if (!UseDefaultAddress
) {
2310 Node
->StaticIpAddress
= TRUE
;
2312 Node
->StaticIpAddress
= NetLibDefaultAddressIsStatic (Controller
);
2317 Create an IPv6 device path node.
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.
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.
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
,
2344 Node
->Header
.Type
= MESSAGING_DEVICE_PATH
;
2345 Node
->Header
.SubType
= MSG_IPv6_DP
;
2346 SetDevicePathNodeLength (&Node
->Header
, sizeof (IPv6_DEVICE_PATH
));
2348 CopyMem (&Node
->LocalIpAddress
, LocalIp
, sizeof (EFI_IPv6_ADDRESS
));
2349 CopyMem (&Node
->RemoteIpAddress
, RemoteIp
, sizeof (EFI_IPv6_ADDRESS
));
2351 Node
->LocalPort
= LocalPort
;
2352 Node
->RemotePort
= RemotePort
;
2354 Node
->Protocol
= Protocol
;
2355 Node
->StaticIpAddress
= FALSE
;
2359 Find the UNDI/SNP handle from controller and protocol GUID.
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
2369 @param[in] Controller Then protocol handle to check.
2370 @param[in] ProtocolGuid The protocol that is related with the handle.
2372 @return The UNDI/SNP handle or NULL for errors.
2377 NetLibGetNicHandle (
2378 IN EFI_HANDLE Controller
,
2379 IN EFI_GUID
*ProtocolGuid
2382 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenBuffer
;
2388 Status
= gBS
->OpenProtocolInformation (
2395 if (EFI_ERROR (Status
)) {
2401 for (Index
= 0; Index
< OpenCount
; Index
++) {
2402 if ((OpenBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
2403 Handle
= OpenBuffer
[Index
].ControllerHandle
;
2408 gBS
->FreePool (OpenBuffer
);