TianoCore EDK2 master
Loading...
Searching...
No Matches
DxeNetLib.c
Go to the documentation of this file.
1
10#include <Uefi.h>
11
13
19#include <Protocol/Ip4Config2.h>
22
23#include <Guid/SmBios.h>
24
25#include <Library/NetLib.h>
26#include <Library/BaseLib.h>
27#include <Library/DebugLib.h>
33#include <Library/PrintLib.h>
34#include <Library/UefiLib.h>
35#include <Protocol/Rng.h>
36
37#define NIC_ITEM_CONFIG_SIZE (sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * MAX_IP4_CONFIG_IN_VARIABLE)
38#define DEFAULT_ZERO_START ((UINTN) ~0)
39
40//
41// All the supported IP4 masks in host byte order.
42//
43GLOBAL_REMOVE_IF_UNREFERENCED IP4_ADDR gIp4AllMasks[IP4_MASK_NUM] = {
44 0x00000000,
45 0x80000000,
46 0xC0000000,
47 0xE0000000,
48 0xF0000000,
49 0xF8000000,
50 0xFC000000,
51 0xFE000000,
52
53 0xFF000000,
54 0xFF800000,
55 0xFFC00000,
56 0xFFE00000,
57 0xFFF00000,
58 0xFFF80000,
59 0xFFFC0000,
60 0xFFFE0000,
61
62 0xFFFF0000,
63 0xFFFF8000,
64 0xFFFFC000,
65 0xFFFFE000,
66 0xFFFFF000,
67 0xFFFFF800,
68 0xFFFFFC00,
69 0xFFFFFE00,
70
71 0xFFFFFF00,
72 0xFFFFFF80,
73 0xFFFFFFC0,
74 0xFFFFFFE0,
75 0xFFFFFFF0,
76 0xFFFFFFF8,
77 0xFFFFFFFC,
78 0xFFFFFFFE,
79 0xFFFFFFFF,
80};
81
83 { 0, 0, 0, 0 }
84};
85
86//
87// Any error level digitally larger than mNetDebugLevelMax
88// will be silently discarded.
89//
90GLOBAL_REMOVE_IF_UNREFERENCED UINTN mNetDebugLevelMax = NETDEBUG_LEVEL_ERROR;
91GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mSyslogPacketSeq = 0xDEADBEEF;
92
93//
94// You can change mSyslogDstMac mSyslogDstIp and mSyslogSrcIp
95// here to direct the syslog packets to the syslog deamon. The
96// default is broadcast to both the ethernet and IP.
97//
98GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mSyslogDstMac[NET_ETHER_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
99GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mSyslogDstIp = 0xffffffff;
100GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mSyslogSrcIp = 0;
101
102GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 *mMonthName[] = {
103 "Jan",
104 "Feb",
105 "Mar",
106 "Apr",
107 "May",
108 "Jun",
109 "Jul",
110 "Aug",
111 "Sep",
112 "Oct",
113 "Nov",
114 "Dec"
115};
116
117//
118// VLAN device path node template
119//
120GLOBAL_REMOVE_IF_UNREFERENCED VLAN_DEVICE_PATH mNetVlanDevicePathTemplate = {
121 {
124 {
125 (UINT8)(sizeof (VLAN_DEVICE_PATH)),
126 (UINT8)((sizeof (VLAN_DEVICE_PATH)) >> 8)
127 }
128 },
129 0
130};
131
132//
133// These represent UEFI SPEC defined algorithms that should be supported by
134// the RNG protocol and are generally considered secure.
135//
136// Assuming that PcdEnforceSecureRngAlgorithms is TRUE (the default) then
137// only the algorithms defined here will be used by the network stack, and
138// none of these being available will result in an error condition (even if
139// some other RNG implementation is available).
140//
141// If PcdEnforceSecureRngAlgorithms is FALSE this list is not consulted,
142// and the first available RNG algorithm is used.
143//
144// If your platform needs to use a specific algorithm for the random number
145// generator, then you should modify this array.
146//
147static GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID *mSecureHashAlgorithms[] = {
148 &gEfiRngAlgorithmSp80090Ctr256Guid, // SP800-90A DRBG CTR using AES-256
149 &gEfiRngAlgorithmSp80090Hmac256Guid, // SP800-90A DRBG HMAC using SHA-256
150 &gEfiRngAlgorithmSp80090Hash256Guid, // SP800-90A DRBG Hash using SHA-256
151 &gEfiRngAlgorithmArmRndr, // unspecified SP800-90A DRBG via ARM RNDR register
152 &gEfiRngAlgorithmRaw, // Raw data from NRBG (or TRNG)
153};
154
155#define SECURE_HASH_ALGORITHMS_SIZE (sizeof (mSecureHashAlgorithms) / sizeof (EFI_GUID *))
156
167 VOID
168 )
169{
171 EFI_STATUS Status;
172 EFI_HANDLE *Handles;
173 UINTN HandleCount;
174 UINTN Index;
175
176 //
177 // Locate the handles which has SNP installed.
178 //
179 Handles = NULL;
180 Status = gBS->LocateHandleBuffer (
182 &gEfiSimpleNetworkProtocolGuid,
183 NULL,
184 &HandleCount,
185 &Handles
186 );
187
188 if (EFI_ERROR (Status) || (HandleCount == 0)) {
189 return NULL;
190 }
191
192 //
193 // Try to open one of the ethernet SNP protocol to send packet
194 //
195 Snp = NULL;
196
197 for (Index = 0; Index < HandleCount; Index++) {
198 Status = gBS->HandleProtocol (
199 Handles[Index],
200 &gEfiSimpleNetworkProtocolGuid,
201 (VOID **)&Snp
202 );
203
204 if ((Status == EFI_SUCCESS) && (Snp != NULL) &&
205 (Snp->Mode->IfType == NET_IFTYPE_ETHERNET) &&
206 (Snp->Mode->MaxPacketSize >= NET_SYSLOG_PACKET_LEN))
207 {
208 break;
209 }
210
211 Snp = NULL;
212 }
213
214 FreePool (Handles);
215 return Snp;
216}
217
236 IN CHAR8 *Packet,
237 IN UINT32 Length
238 )
239{
241 ETHER_HEAD *Ether;
242 EFI_STATUS Status;
243 EFI_EVENT TimeoutEvent;
244 UINT8 *TxBuf;
245
246 ASSERT (Packet != NULL);
247
248 Snp = SyslogLocateSnp ();
249
250 if (Snp == NULL) {
251 return EFI_DEVICE_ERROR;
252 }
253
254 Ether = (ETHER_HEAD *)Packet;
255 CopyMem (Ether->SrcMac, Snp->Mode->CurrentAddress.Addr, NET_ETHER_ADDR_LEN);
256
257 //
258 // Start the timeout event.
259 //
260 Status = gBS->CreateEvent (
261 EVT_TIMER,
262 TPL_NOTIFY,
263 NULL,
264 NULL,
265 &TimeoutEvent
266 );
267
268 if (EFI_ERROR (Status)) {
269 return Status;
270 }
271
272 Status = gBS->SetTimer (TimeoutEvent, TimerRelative, NET_SYSLOG_TX_TIMEOUT);
273
274 if (EFI_ERROR (Status)) {
275 goto ON_EXIT;
276 }
277
278 for ( ; ;) {
279 //
280 // Transmit the packet through SNP.
281 //
282 Status = Snp->Transmit (Snp, 0, Length, Packet, NULL, NULL, NULL);
283
284 if ((Status != EFI_SUCCESS) && (Status != EFI_NOT_READY)) {
285 Status = EFI_DEVICE_ERROR;
286 break;
287 }
288
289 //
290 // If Status is EFI_SUCCESS, the packet is put in the transmit queue.
291 // if Status is EFI_NOT_READY, the transmit engine of the network
292 // interface is busy. Both need to sync SNP.
293 //
294 TxBuf = NULL;
295
296 do {
297 //
298 // Get the recycled transmit buffer status.
299 //
300 Snp->GetStatus (Snp, NULL, (VOID **)&TxBuf);
301
302 if (!EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {
303 Status = EFI_TIMEOUT;
304 break;
305 }
306 } while (TxBuf == NULL);
307
308 if ((Status == EFI_SUCCESS) || (Status == EFI_TIMEOUT)) {
309 break;
310 }
311
312 //
313 // Status is EFI_NOT_READY. Restart the timer event and
314 // call Snp->Transmit again.
315 //
316 gBS->SetTimer (TimeoutEvent, TimerRelative, NET_SYSLOG_TX_TIMEOUT);
317 }
318
319 gBS->SetTimer (TimeoutEvent, TimerCancel, 0);
320
321ON_EXIT:
322 gBS->CloseEvent (TimeoutEvent);
323 return Status;
324}
325
341UINT32
343 IN UINT32 Level,
344 IN UINT8 *Module,
345 IN UINT8 *File,
346 IN UINT32 Line,
347 IN UINT8 *Message,
348 IN UINT32 BufLen,
349 OUT CHAR8 *Buf
350 )
351{
352 EFI_STATUS Status;
353 ETHER_HEAD *Ether;
354 IP4_HEAD *Ip4;
355 EFI_UDP_HEADER *Udp4;
356 EFI_TIME Time;
357 UINT32 Pri;
358 UINT32 Len;
359
360 //
361 // Fill in the Ethernet header. Leave alone the source MAC.
362 // SyslogSendPacket will fill in the address for us.
363 //
364 Ether = (ETHER_HEAD *)Buf;
365 CopyMem (Ether->DstMac, mSyslogDstMac, NET_ETHER_ADDR_LEN);
366 ZeroMem (Ether->SrcMac, NET_ETHER_ADDR_LEN);
367
368 Ether->EtherType = HTONS (0x0800); // IPv4 protocol
369
370 Buf += sizeof (ETHER_HEAD);
371 BufLen -= sizeof (ETHER_HEAD);
372
373 //
374 // Fill in the IP header
375 //
376 Ip4 = (IP4_HEAD *)Buf;
377 Ip4->HeadLen = 5;
378 Ip4->Ver = 4;
379 Ip4->Tos = 0;
380 Ip4->TotalLen = 0;
381 Ip4->Id = (UINT16)mSyslogPacketSeq;
382 Ip4->Fragment = 0;
383 Ip4->Ttl = 16;
384 Ip4->Protocol = 0x11;
385 Ip4->Checksum = 0;
386 Ip4->Src = mSyslogSrcIp;
387 Ip4->Dst = mSyslogDstIp;
388
389 Buf += sizeof (IP4_HEAD);
390 BufLen -= sizeof (IP4_HEAD);
391
392 //
393 // Fill in the UDP header, Udp checksum is optional. Leave it zero.
394 //
395 Udp4 = (EFI_UDP_HEADER *)Buf;
396 Udp4->SrcPort = HTONS (514);
397 Udp4->DstPort = HTONS (514);
398 Udp4->Length = 0;
399 Udp4->Checksum = 0;
400
401 Buf += sizeof (EFI_UDP_HEADER);
402 BufLen -= sizeof (EFI_UDP_HEADER);
403
404 //
405 // Build the syslog message body with <PRI> Timestamp machine module Message
406 //
407 Pri = ((NET_SYSLOG_FACILITY & 31) << 3) | (Level & 7);
408 Status = gRT->GetTime (&Time, NULL);
409 if (EFI_ERROR (Status)) {
410 return 0;
411 }
412
413 //
414 // Use %a to format the ASCII strings, %s to format UNICODE strings
415 //
416 Len = 0;
417 Len += (UINT32)AsciiSPrint (
418 Buf,
419 BufLen,
420 "<%d> %a %d %d:%d:%d ",
421 Pri,
422 mMonthName[Time.Month-1],
423 Time.Day,
424 Time.Hour,
425 Time.Minute,
426 Time.Second
427 );
428
429 Len += (UINT32)AsciiSPrint (
430 Buf + Len,
431 BufLen - Len,
432 "Tiano %a: %a (Line: %d File: %a)",
433 Module,
434 Message,
435 Line,
436 File
437 );
438 Len++;
439
440 //
441 // OK, patch the IP length/checksum and UDP length fields.
442 //
443 Len += sizeof (EFI_UDP_HEADER);
444 Udp4->Length = HTONS ((UINT16)Len);
445
446 Len += sizeof (IP4_HEAD);
447 Ip4->TotalLen = HTONS ((UINT16)Len);
448 Ip4->Checksum = (UINT16)(~NetblockChecksum ((UINT8 *)Ip4, sizeof (IP4_HEAD)));
449
450 return Len + sizeof (ETHER_HEAD);
451}
452
479CHAR8 *
480EFIAPI
482 IN CHAR8 *Format,
483 ...
484 )
485{
486 VA_LIST Marker;
487 CHAR8 *Buf;
488
489 ASSERT (Format != NULL);
490
491 Buf = (CHAR8 *)AllocatePool (NET_DEBUG_MSG_LEN);
492
493 if (Buf == NULL) {
494 return NULL;
495 }
496
497 VA_START (Marker, Format);
498 AsciiVSPrint (Buf, NET_DEBUG_MSG_LEN, Format, Marker);
499 VA_END (Marker);
500
501 return Buf;
502}
503
523EFIAPI
525 IN UINT32 Level,
526 IN UINT8 *Module,
527 IN UINT8 *File,
528 IN UINT32 Line,
529 IN UINT8 *Message
530 )
531{
532 CHAR8 *Packet;
533 UINT32 Len;
534 EFI_STATUS Status;
535
536 //
537 // Check whether the message should be sent out
538 //
539 if ((Message == NULL) || (File == NULL) || (Module == NULL)) {
540 return EFI_INVALID_PARAMETER;
541 }
542
543 if (Level > mNetDebugLevelMax) {
544 Status = EFI_SUCCESS;
545 goto ON_EXIT;
546 }
547
548 //
549 // Allocate a maximum of 1024 bytes, the caller should ensure
550 // that the message plus the ethernet/ip/udp header is shorter
551 // than this
552 //
553 Packet = (CHAR8 *)AllocatePool (NET_SYSLOG_PACKET_LEN);
554
555 if (Packet == NULL) {
556 Status = EFI_OUT_OF_RESOURCES;
557 goto ON_EXIT;
558 }
559
560 //
561 // Build the message: Ethernet header + IP header + Udp Header + user data
562 //
563 Len = SyslogBuildPacket (
564 Level,
565 Module,
566 File,
567 Line,
568 Message,
569 NET_SYSLOG_PACKET_LEN,
570 Packet
571 );
572 if (Len == 0) {
573 Status = EFI_DEVICE_ERROR;
574 } else {
575 mSyslogPacketSeq++;
576 Status = SyslogSendPacket (Packet, Len);
577 }
578
579 FreePool (Packet);
580
581ON_EXIT:
582 FreePool (Message);
583 return Status;
584}
585
598INTN
599EFIAPI
601 IN IP4_ADDR NetMask
602 )
603{
604 INTN Index;
605
606 for (Index = 0; Index <= IP4_MASK_MAX; Index++) {
607 if (NetMask == gIp4AllMasks[Index]) {
608 break;
609 }
610 }
611
612 return Index;
613}
614
641INTN
642EFIAPI
644 IN IP4_ADDR Addr
645 )
646{
647 UINT8 ByteOne;
648
649 ByteOne = (UINT8)(Addr >> 24);
650
651 if ((ByteOne & 0x80) == 0) {
652 return IP4_ADDR_CLASSA;
653 } else if ((ByteOne & 0xC0) == 0x80) {
654 return IP4_ADDR_CLASSB;
655 } else if ((ByteOne & 0xE0) == 0xC0) {
656 return IP4_ADDR_CLASSC;
657 } else if ((ByteOne & 0xF0) == 0xE0) {
658 return IP4_ADDR_CLASSD;
659 } else {
660 return IP4_ADDR_CLASSE;
661 }
662}
663
681BOOLEAN
682EFIAPI
684 IN IP4_ADDR Ip,
685 IN IP4_ADDR NetMask
686 )
687{
688 INTN MaskLength;
689
690 ASSERT (NetMask != 0);
691
692 if ((Ip == 0) || IP4_IS_LOCAL_BROADCAST (Ip)) {
693 return FALSE;
694 }
695
696 MaskLength = NetGetMaskLength (NetMask);
697 ASSERT ((MaskLength >= 0) && (MaskLength <= IP4_MASK_NUM));
698 if (MaskLength < 31) {
699 if (((Ip &~NetMask) == ~NetMask) || ((Ip &~NetMask) == 0)) {
700 return FALSE;
701 }
702 }
703
704 return TRUE;
705}
706
723BOOLEAN
724EFIAPI
727 )
728{
729 UINT8 Byte;
730 UINT8 Index;
731
732 ASSERT (Ip6 != NULL);
733
734 if (Ip6->Addr[0] == 0xFF) {
735 return FALSE;
736 }
737
738 for (Index = 0; Index < 15; Index++) {
739 if (Ip6->Addr[Index] != 0) {
740 return TRUE;
741 }
742 }
743
744 Byte = Ip6->Addr[Index];
745
746 if ((Byte == 0x0) || (Byte == 0x1)) {
747 return FALSE;
748 }
749
750 return TRUE;
751}
752
764BOOLEAN
765EFIAPI
768 )
769{
770 UINT8 Index;
771
772 ASSERT (Ip6 != NULL);
773
774 for (Index = 0; Index < 16; Index++) {
775 if (Ip6->Addr[Index] != 0) {
776 return FALSE;
777 }
778 }
779
780 return TRUE;
781}
782
794BOOLEAN
795EFIAPI
798 )
799{
800 UINT8 Index;
801
802 ASSERT (Ip6 != NULL);
803
804 if (Ip6->Addr[0] != 0xFE) {
805 return FALSE;
806 }
807
808 if (Ip6->Addr[1] != 0x80) {
809 return FALSE;
810 }
811
812 for (Index = 2; Index < 8; Index++) {
813 if (Ip6->Addr[Index] != 0) {
814 return FALSE;
815 }
816 }
817
818 return TRUE;
819}
820
835BOOLEAN
836EFIAPI
838 EFI_IPv6_ADDRESS *Ip1,
839 EFI_IPv6_ADDRESS *Ip2,
840 UINT8 PrefixLength
841 )
842{
843 UINT8 Byte;
844 UINT8 Bit;
845 UINT8 Mask;
846
847 ASSERT ((Ip1 != NULL) && (Ip2 != NULL) && (PrefixLength < IP6_PREFIX_MAX));
848
849 if (PrefixLength == 0) {
850 return TRUE;
851 }
852
853 Byte = (UINT8)(PrefixLength / 8);
854 Bit = (UINT8)(PrefixLength % 8);
855
856 if (CompareMem (Ip1, Ip2, Byte) != 0) {
857 return FALSE;
858 }
859
860 if (Bit > 0) {
861 Mask = (UINT8)(0xFF << (8 - Bit));
862
863 ASSERT (Byte < 16);
864 if (Byte >= 16) {
865 return FALSE;
866 }
867
868 if ((Ip1->Addr[Byte] & Mask) != (Ip2->Addr[Byte] & Mask)) {
869 return FALSE;
870 }
871 }
872
873 return TRUE;
874}
875
891EFIAPI
894 )
895{
896 UINT64 High;
897 UINT64 Low;
898
899 ASSERT (Ip6 != NULL);
900
901 CopyMem (&High, Ip6, sizeof (UINT64));
902 CopyMem (&Low, &Ip6->Addr[8], sizeof (UINT64));
903
904 High = SwapBytes64 (High);
905 Low = SwapBytes64 (Low);
906
907 CopyMem (Ip6, &Low, sizeof (UINT64));
908 CopyMem (&Ip6->Addr[8], &High, sizeof (UINT64));
909
910 return Ip6;
911}
912
927EFIAPI
929 OUT VOID *Output,
930 IN UINTN OutputLength
931 )
932{
933 EFI_RNG_PROTOCOL *RngProtocol;
934 EFI_STATUS Status;
935 UINTN AlgorithmIndex;
936
937 if ((Output == NULL) || (OutputLength == 0)) {
938 return EFI_INVALID_PARAMETER;
939 }
940
941 Status = gBS->LocateProtocol (&gEfiRngProtocolGuid, NULL, (VOID **)&RngProtocol);
942 if (EFI_ERROR (Status)) {
943 DEBUG ((DEBUG_ERROR, "Failed to locate EFI_RNG_PROTOCOL: %r\n", Status));
944 ASSERT_EFI_ERROR (Status);
945 return Status;
946 }
947
948 if (PcdGetBool (PcdEnforceSecureRngAlgorithms)) {
949 for (AlgorithmIndex = 0; AlgorithmIndex < SECURE_HASH_ALGORITHMS_SIZE; AlgorithmIndex++) {
950 Status = RngProtocol->GetRNG (RngProtocol, mSecureHashAlgorithms[AlgorithmIndex], OutputLength, (UINT8 *)Output);
951 if (!EFI_ERROR (Status)) {
952 //
953 // Secure Algorithm was supported on this platform
954 //
955 return EFI_SUCCESS;
956 } else if (Status == EFI_UNSUPPORTED) {
957 //
958 // Secure Algorithm was not supported on this platform
959 //
960 DEBUG ((DEBUG_VERBOSE, "Failed to generate random data using secure algorithm %d: %r\n", AlgorithmIndex, Status));
961
962 //
963 // Try the next secure algorithm
964 //
965 continue;
966 } else {
967 //
968 // Some other error occurred
969 //
970 DEBUG ((DEBUG_ERROR, "Failed to generate random data using secure algorithm %d: %r\n", AlgorithmIndex, Status));
971 ASSERT_EFI_ERROR (Status);
972 return Status;
973 }
974 }
975
976 //
977 // If we get here, we failed to generate random data using any secure algorithm
978 // Platform owner should ensure that at least one secure algorithm is supported
979 //
980 DEBUG ((DEBUG_ERROR, "Failed to generate random data, no supported secure algorithm found\n"));
981 ASSERT_EFI_ERROR (Status);
982 return Status;
983 }
984
985 //
986 // Lets try using the default algorithm (which may not be secure)
987 //
988 Status = RngProtocol->GetRNG (RngProtocol, NULL, OutputLength, (UINT8 *)Output);
989 if (EFI_ERROR (Status)) {
990 DEBUG ((DEBUG_ERROR, "%a failed to generate random data: %r\n", __func__, Status));
991 ASSERT_EFI_ERROR (Status);
992 return Status;
993 }
994
995 return EFI_SUCCESS;
996}
997
1010EFIAPI
1012 OUT UINT32 *Output
1013 )
1014{
1015 return PseudoRandom (Output, sizeof (*Output));
1016}
1017
1031UINT32
1032EFIAPI
1034 IN UINT8 *Buf
1035 )
1036{
1037 UINT32 Value;
1038
1039 ASSERT (Buf != NULL);
1040
1041 CopyMem (&Value, Buf, sizeof (UINT32));
1042 return NTOHL (Value);
1043}
1044
1057VOID
1058EFIAPI
1060 IN OUT UINT8 *Buf,
1061 IN UINT32 Data
1062 )
1063{
1064 ASSERT (Buf != NULL);
1065
1066 Data = HTONL (Data);
1067 CopyMem (Buf, &Data, sizeof (UINT32));
1068}
1069
1088LIST_ENTRY *
1089EFIAPI
1091 IN OUT LIST_ENTRY *Head
1092 )
1093{
1094 LIST_ENTRY *First;
1095
1096 ASSERT (Head != NULL);
1097
1098 if (IsListEmpty (Head)) {
1099 return NULL;
1100 }
1101
1102 First = Head->ForwardLink;
1103 Head->ForwardLink = First->ForwardLink;
1104 First->ForwardLink->BackLink = Head;
1105
1106 DEBUG_CODE (
1107 First->ForwardLink = (LIST_ENTRY *)NULL;
1108 First->BackLink = (LIST_ENTRY *)NULL;
1109 );
1110
1111 return First;
1112}
1113
1132LIST_ENTRY *
1133EFIAPI
1135 IN OUT LIST_ENTRY *Head
1136 )
1137{
1138 LIST_ENTRY *Last;
1139
1140 ASSERT (Head != NULL);
1141
1142 if (IsListEmpty (Head)) {
1143 return NULL;
1144 }
1145
1146 Last = Head->BackLink;
1147 Head->BackLink = Last->BackLink;
1148 Last->BackLink->ForwardLink = Head;
1149
1150 DEBUG_CODE (
1151 Last->ForwardLink = (LIST_ENTRY *)NULL;
1152 Last->BackLink = (LIST_ENTRY *)NULL;
1153 );
1154
1155 return Last;
1156}
1157
1170VOID
1171EFIAPI
1173 IN OUT LIST_ENTRY *PrevEntry,
1174 IN OUT LIST_ENTRY *NewEntry
1175 )
1176{
1177 ASSERT (PrevEntry != NULL && NewEntry != NULL);
1178
1179 NewEntry->BackLink = PrevEntry;
1180 NewEntry->ForwardLink = PrevEntry->ForwardLink;
1181 PrevEntry->ForwardLink->BackLink = NewEntry;
1182 PrevEntry->ForwardLink = NewEntry;
1183}
1184
1197VOID
1198EFIAPI
1200 IN OUT LIST_ENTRY *PostEntry,
1201 IN OUT LIST_ENTRY *NewEntry
1202 )
1203{
1204 ASSERT (PostEntry != NULL && NewEntry != NULL);
1205
1206 NewEntry->ForwardLink = PostEntry;
1207 NewEntry->BackLink = PostEntry->BackLink;
1208 PostEntry->BackLink->ForwardLink = NewEntry;
1209 PostEntry->BackLink = NewEntry;
1210}
1211
1235EFIAPI
1237 IN LIST_ENTRY *List,
1239 IN VOID *Context OPTIONAL,
1240 OUT UINTN *ListLength OPTIONAL
1241 )
1242{
1243 UINTN PreviousLength;
1244 LIST_ENTRY *Entry;
1245 LIST_ENTRY *Ptr;
1246 UINTN Length;
1247 EFI_STATUS Status;
1248
1249 if ((List == NULL) || (CallBack == NULL)) {
1250 return EFI_INVALID_PARAMETER;
1251 }
1252
1253 Length = 0;
1254 do {
1255 PreviousLength = Length;
1256 Entry = GetFirstNode (List);
1257 while (!IsNull (List, Entry)) {
1258 Status = CallBack (Entry, Context);
1259 if (EFI_ERROR (Status)) {
1260 return Status;
1261 }
1262
1263 //
1264 // Walk through the list to see whether the Entry has been removed or not.
1265 // If the Entry still exists, just try to destroy the next one.
1266 // If not, go back to the start point to iterate the list again.
1267 //
1268 for (Ptr = List->ForwardLink; Ptr != List; Ptr = Ptr->ForwardLink) {
1269 if (Ptr == Entry) {
1270 break;
1271 }
1272 }
1273
1274 if (Ptr == Entry) {
1275 Entry = GetNextNode (List, Entry);
1276 } else {
1277 Entry = GetFirstNode (List);
1278 }
1279 }
1280
1281 for (Length = 0, Ptr = List->ForwardLink; Ptr != List; Length++, Ptr = Ptr->ForwardLink) {
1282 }
1283 } while (Length != PreviousLength);
1284
1285 if (ListLength != NULL) {
1286 *ListLength = Length;
1287 }
1288
1289 return EFI_SUCCESS;
1290}
1291
1304BOOLEAN
1305EFIAPI
1307 IN EFI_HANDLE Handle,
1308 IN UINTN NumberOfChildren,
1309 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
1310 )
1311{
1312 UINTN Index;
1313
1314 if ((NumberOfChildren == 0) || (ChildHandleBuffer == NULL)) {
1315 return FALSE;
1316 }
1317
1318 for (Index = 0; Index < NumberOfChildren; Index++) {
1319 if (Handle == ChildHandleBuffer[Index]) {
1320 return TRUE;
1321 }
1322 }
1323
1324 return FALSE;
1325}
1326
1341VOID
1342EFIAPI
1344 IN OUT NET_MAP *Map
1345 )
1346{
1347 ASSERT (Map != NULL);
1348
1349 InitializeListHead (&Map->Used);
1350 InitializeListHead (&Map->Recycled);
1351 Map->Count = 0;
1352}
1353
1366VOID
1367EFIAPI
1369 IN OUT NET_MAP *Map
1370 )
1371{
1372 NET_MAP_ITEM *Item;
1373 LIST_ENTRY *Entry;
1374 LIST_ENTRY *Next;
1375
1376 ASSERT (Map != NULL);
1377
1378 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Map->Used) {
1379 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
1380
1381 RemoveEntryList (&Item->Link);
1382 Map->Count--;
1383
1384 gBS->FreePool (Item);
1385 }
1386
1387 ASSERT ((Map->Count == 0) && IsListEmpty (&Map->Used));
1388
1389 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Map->Recycled) {
1390 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
1391
1392 RemoveEntryList (&Item->Link);
1393 gBS->FreePool (Item);
1394 }
1395
1396 ASSERT (IsListEmpty (&Map->Recycled));
1397}
1398
1411BOOLEAN
1412EFIAPI
1414 IN NET_MAP *Map
1415 )
1416{
1417 ASSERT (Map != NULL);
1418 return (BOOLEAN)(Map->Count == 0);
1419}
1420
1431UINTN
1432EFIAPI
1434 IN NET_MAP *Map
1435 )
1436{
1437 ASSERT (Map != NULL);
1438 return Map->Count;
1439}
1440
1459 IN OUT NET_MAP *Map
1460 )
1461{
1462 NET_MAP_ITEM *Item;
1463 LIST_ENTRY *Head;
1464 UINTN Index;
1465
1466 ASSERT (Map != NULL);
1467
1468 Head = &Map->Recycled;
1469
1470 if (IsListEmpty (Head)) {
1471 for (Index = 0; Index < NET_MAP_INCREAMENT; Index++) {
1472 Item = AllocatePool (sizeof (NET_MAP_ITEM));
1473
1474 if (Item == NULL) {
1475 if (Index == 0) {
1476 return NULL;
1477 }
1478
1479 break;
1480 }
1481
1482 InsertHeadList (Head, &Item->Link);
1483 }
1484 }
1485
1486 Item = NET_LIST_HEAD (Head, NET_MAP_ITEM, Link);
1487 NetListRemoveHead (Head);
1488
1489 return Item;
1490}
1491
1511EFIAPI
1513 IN OUT NET_MAP *Map,
1514 IN VOID *Key,
1515 IN VOID *Value OPTIONAL
1516 )
1517{
1518 NET_MAP_ITEM *Item;
1519
1520 ASSERT (Map != NULL && Key != NULL);
1521
1522 Item = NetMapAllocItem (Map);
1523
1524 if (Item == NULL) {
1525 return EFI_OUT_OF_RESOURCES;
1526 }
1527
1528 Item->Key = Key;
1529 Item->Value = Value;
1530 InsertHeadList (&Map->Used, &Item->Link);
1531
1532 Map->Count++;
1533 return EFI_SUCCESS;
1534}
1535
1555EFIAPI
1557 IN OUT NET_MAP *Map,
1558 IN VOID *Key,
1559 IN VOID *Value OPTIONAL
1560 )
1561{
1562 NET_MAP_ITEM *Item;
1563
1564 ASSERT (Map != NULL && Key != NULL);
1565
1566 Item = NetMapAllocItem (Map);
1567
1568 if (Item == NULL) {
1569 return EFI_OUT_OF_RESOURCES;
1570 }
1571
1572 Item->Key = Key;
1573 Item->Value = Value;
1574 InsertTailList (&Map->Used, &Item->Link);
1575
1576 Map->Count++;
1577
1578 return EFI_SUCCESS;
1579}
1580
1593BOOLEAN
1595 IN NET_MAP *Map,
1596 IN NET_MAP_ITEM *Item
1597 )
1598{
1599 LIST_ENTRY *ListEntry;
1600
1601 ASSERT (Map != NULL && Item != NULL);
1602
1603 NET_LIST_FOR_EACH (ListEntry, &Map->Used) {
1604 if (ListEntry == &Item->Link) {
1605 return TRUE;
1606 }
1607 }
1608
1609 return FALSE;
1610}
1611
1628EFIAPI
1630 IN NET_MAP *Map,
1631 IN VOID *Key
1632 )
1633{
1634 LIST_ENTRY *Entry;
1635 NET_MAP_ITEM *Item;
1636
1637 ASSERT (Map != NULL && Key != NULL);
1638
1639 NET_LIST_FOR_EACH (Entry, &Map->Used) {
1640 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
1641
1642 if (Item->Key == Key) {
1643 return Item;
1644 }
1645 }
1646
1647 return NULL;
1648}
1649
1669VOID *
1670EFIAPI
1672 IN OUT NET_MAP *Map,
1673 IN OUT NET_MAP_ITEM *Item,
1674 OUT VOID **Value OPTIONAL
1675 )
1676{
1677 ASSERT ((Map != NULL) && (Item != NULL));
1678 ASSERT (NetItemInMap (Map, Item));
1679
1680 RemoveEntryList (&Item->Link);
1681 Map->Count--;
1682 InsertHeadList (&Map->Recycled, &Item->Link);
1683
1684 if (Value != NULL) {
1685 *Value = Item->Value;
1686 }
1687
1688 return Item->Key;
1689}
1690
1708VOID *
1709EFIAPI
1711 IN OUT NET_MAP *Map,
1712 OUT VOID **Value OPTIONAL
1713 )
1714{
1715 NET_MAP_ITEM *Item;
1716
1717 //
1718 // Often, it indicates a programming error to remove
1719 // the first entry in an empty list
1720 //
1721 ASSERT (Map && !IsListEmpty (&Map->Used));
1722
1723 Item = NET_LIST_HEAD (&Map->Used, NET_MAP_ITEM, Link);
1724 RemoveEntryList (&Item->Link);
1725 Map->Count--;
1726 InsertHeadList (&Map->Recycled, &Item->Link);
1727
1728 if (Value != NULL) {
1729 *Value = Item->Value;
1730 }
1731
1732 return Item->Key;
1733}
1734
1752VOID *
1753EFIAPI
1755 IN OUT NET_MAP *Map,
1756 OUT VOID **Value OPTIONAL
1757 )
1758{
1759 NET_MAP_ITEM *Item;
1760
1761 //
1762 // Often, it indicates a programming error to remove
1763 // the last entry in an empty list
1764 //
1765 ASSERT (Map && !IsListEmpty (&Map->Used));
1766
1767 Item = NET_LIST_TAIL (&Map->Used, NET_MAP_ITEM, Link);
1768 RemoveEntryList (&Item->Link);
1769 Map->Count--;
1770 InsertHeadList (&Map->Recycled, &Item->Link);
1771
1772 if (Value != NULL) {
1773 *Value = Item->Value;
1774 }
1775
1776 return Item->Key;
1777}
1778
1799EFIAPI
1801 IN NET_MAP *Map,
1802 IN NET_MAP_CALLBACK CallBack,
1803 IN VOID *Arg OPTIONAL
1804 )
1805{
1806 LIST_ENTRY *Entry;
1807 LIST_ENTRY *Next;
1808 LIST_ENTRY *Head;
1809 NET_MAP_ITEM *Item;
1810 EFI_STATUS Result;
1811
1812 ASSERT ((Map != NULL) && (CallBack != NULL));
1813
1814 Head = &Map->Used;
1815
1816 if (IsListEmpty (Head)) {
1817 return EFI_SUCCESS;
1818 }
1819
1820 NET_LIST_FOR_EACH_SAFE (Entry, Next, Head) {
1821 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
1822 Result = CallBack (Map, Item, Arg);
1823
1824 if (EFI_ERROR (Result)) {
1825 return Result;
1826 }
1827 }
1828
1829 return EFI_SUCCESS;
1830}
1831
1845EFIAPI
1847 IN EFI_HANDLE ImageHandle
1848 )
1849{
1850 EFI_STATUS Status;
1851 EFI_HANDLE *DeviceHandleBuffer;
1852 UINTN DeviceHandleCount;
1853 UINTN Index;
1854 UINTN Index2;
1855 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
1856 EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
1857 EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;
1858
1859 //
1860 // Get the list of all the handles in the handle database.
1861 // If there is an error getting the list, then the unload
1862 // operation fails.
1863 //
1864 Status = gBS->LocateHandleBuffer (
1865 AllHandles,
1866 NULL,
1867 NULL,
1868 &DeviceHandleCount,
1869 &DeviceHandleBuffer
1870 );
1871
1872 if (EFI_ERROR (Status)) {
1873 return Status;
1874 }
1875
1876 for (Index = 0; Index < DeviceHandleCount; Index++) {
1877 Status = gBS->HandleProtocol (
1878 DeviceHandleBuffer[Index],
1879 &gEfiDriverBindingProtocolGuid,
1880 (VOID **)&DriverBinding
1881 );
1882 if (EFI_ERROR (Status)) {
1883 continue;
1884 }
1885
1886 if (DriverBinding->ImageHandle != ImageHandle) {
1887 continue;
1888 }
1889
1890 //
1891 // Disconnect the driver specified by ImageHandle from all
1892 // the devices in the handle database.
1893 //
1894 for (Index2 = 0; Index2 < DeviceHandleCount; Index2++) {
1895 Status = gBS->DisconnectController (
1896 DeviceHandleBuffer[Index2],
1897 DriverBinding->DriverBindingHandle,
1898 NULL
1899 );
1900 }
1901
1902 //
1903 // Uninstall all the protocols installed in the driver entry point
1904 //
1905 gBS->UninstallProtocolInterface (
1906 DriverBinding->DriverBindingHandle,
1907 &gEfiDriverBindingProtocolGuid,
1908 DriverBinding
1909 );
1910
1911 Status = gBS->HandleProtocol (
1912 DeviceHandleBuffer[Index],
1913 &gEfiComponentNameProtocolGuid,
1914 (VOID **)&ComponentName
1915 );
1916 if (!EFI_ERROR (Status)) {
1917 gBS->UninstallProtocolInterface (
1918 DriverBinding->DriverBindingHandle,
1919 &gEfiComponentNameProtocolGuid,
1920 ComponentName
1921 );
1922 }
1923
1924 Status = gBS->HandleProtocol (
1925 DeviceHandleBuffer[Index],
1926 &gEfiComponentName2ProtocolGuid,
1927 (VOID **)&ComponentName2
1928 );
1929 if (!EFI_ERROR (Status)) {
1930 gBS->UninstallProtocolInterface (
1931 DriverBinding->DriverBindingHandle,
1932 &gEfiComponentName2ProtocolGuid,
1933 ComponentName2
1934 );
1935 }
1936 }
1937
1938 //
1939 // Free the buffer containing the list of handles from the handle database
1940 //
1941 if (DeviceHandleBuffer != NULL) {
1942 gBS->FreePool (DeviceHandleBuffer);
1943 }
1944
1945 return EFI_SUCCESS;
1946}
1947
1966EFIAPI
1968 IN EFI_HANDLE Controller,
1969 IN EFI_HANDLE Image,
1970 IN EFI_GUID *ServiceBindingGuid,
1971 IN OUT EFI_HANDLE *ChildHandle
1972 )
1973{
1974 EFI_STATUS Status;
1976
1977 ASSERT ((ServiceBindingGuid != NULL) && (ChildHandle != NULL));
1978
1979 //
1980 // Get the ServiceBinding Protocol
1981 //
1982 Status = gBS->OpenProtocol (
1983 Controller,
1984 ServiceBindingGuid,
1985 (VOID **)&Service,
1986 Image,
1987 Controller,
1988 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1989 );
1990
1991 if (EFI_ERROR (Status)) {
1992 return Status;
1993 }
1994
1995 //
1996 // Create a child
1997 //
1998 Status = Service->CreateChild (Service, ChildHandle);
1999 return Status;
2000}
2001
2019EFIAPI
2021 IN EFI_HANDLE Controller,
2022 IN EFI_HANDLE Image,
2023 IN EFI_GUID *ServiceBindingGuid,
2024 IN EFI_HANDLE ChildHandle
2025 )
2026{
2027 EFI_STATUS Status;
2029
2030 ASSERT (ServiceBindingGuid != NULL);
2031
2032 //
2033 // Get the ServiceBinding Protocol
2034 //
2035 Status = gBS->OpenProtocol (
2036 Controller,
2037 ServiceBindingGuid,
2038 (VOID **)&Service,
2039 Image,
2040 Controller,
2041 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2042 );
2043
2044 if (EFI_ERROR (Status)) {
2045 return Status;
2046 }
2047
2048 //
2049 // destroy the child
2050 //
2051 Status = Service->DestroyChild (Service, ChildHandle);
2052 return Status;
2053}
2054
2072EFIAPI
2074 IN EFI_HANDLE ServiceHandle,
2075 OUT EFI_SIMPLE_NETWORK_PROTOCOL **Snp OPTIONAL
2076 )
2077{
2078 EFI_STATUS Status;
2079 EFI_SIMPLE_NETWORK_PROTOCOL *SnpInstance;
2080 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
2081 EFI_HANDLE SnpHandle;
2082
2083 //
2084 // Try to open SNP from ServiceHandle
2085 //
2086 SnpInstance = NULL;
2087 Status = gBS->HandleProtocol (ServiceHandle, &gEfiSimpleNetworkProtocolGuid, (VOID **)&SnpInstance);
2088 if (!EFI_ERROR (Status)) {
2089 if (Snp != NULL) {
2090 *Snp = SnpInstance;
2091 }
2092
2093 return ServiceHandle;
2094 }
2095
2096 //
2097 // Failed to open SNP, try to get SNP handle by LocateDevicePath()
2098 //
2099 DevicePath = DevicePathFromHandle (ServiceHandle);
2100 if (DevicePath == NULL) {
2101 return NULL;
2102 }
2103
2104 SnpHandle = NULL;
2105 Status = gBS->LocateDevicePath (&gEfiSimpleNetworkProtocolGuid, &DevicePath, &SnpHandle);
2106 if (EFI_ERROR (Status)) {
2107 //
2108 // Failed to find SNP handle
2109 //
2110 return NULL;
2111 }
2112
2113 Status = gBS->HandleProtocol (SnpHandle, &gEfiSimpleNetworkProtocolGuid, (VOID **)&SnpInstance);
2114 if (!EFI_ERROR (Status)) {
2115 if (Snp != NULL) {
2116 *Snp = SnpInstance;
2117 }
2118
2119 return SnpHandle;
2120 }
2121
2122 return NULL;
2123}
2124
2138UINT16
2139EFIAPI
2141 IN EFI_HANDLE ServiceHandle
2142 )
2143{
2144 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
2146
2147 DevicePath = DevicePathFromHandle (ServiceHandle);
2148 if (DevicePath == NULL) {
2149 return 0;
2150 }
2151
2152 Node = DevicePath;
2153 while (!IsDevicePathEnd (Node)) {
2154 if ((Node->Type == MESSAGING_DEVICE_PATH) && (Node->SubType == MSG_VLAN_DP)) {
2155 return ((VLAN_DEVICE_PATH *)Node)->VlanId;
2156 }
2157
2158 Node = NextDevicePathNode (Node);
2159 }
2160
2161 return 0;
2162}
2163
2179EFIAPI
2181 IN EFI_HANDLE ControllerHandle,
2182 IN UINT16 VlanId
2183 )
2184{
2185 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
2186 EFI_DEVICE_PATH_PROTOCOL *VlanDevicePath;
2187 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
2188 VLAN_DEVICE_PATH VlanNode;
2189 EFI_HANDLE Handle;
2190
2191 ParentDevicePath = DevicePathFromHandle (ControllerHandle);
2192 if (ParentDevicePath == NULL) {
2193 return NULL;
2194 }
2195
2196 //
2197 // Construct VLAN device path
2198 //
2199 CopyMem (&VlanNode, &mNetVlanDevicePathTemplate, sizeof (VLAN_DEVICE_PATH));
2200 VlanNode.VlanId = VlanId;
2201 VlanDevicePath = AppendDevicePathNode (
2202 ParentDevicePath,
2203 (EFI_DEVICE_PATH_PROTOCOL *)&VlanNode
2204 );
2205 if (VlanDevicePath == NULL) {
2206 return NULL;
2207 }
2208
2209 //
2210 // Find VLAN device handle
2211 //
2212 Handle = NULL;
2213 DevicePath = VlanDevicePath;
2214 gBS->LocateDevicePath (
2215 &gEfiDevicePathProtocolGuid,
2216 &DevicePath,
2217 &Handle
2218 );
2219 if (!IsDevicePathEnd (DevicePath)) {
2220 //
2221 // Device path is not exactly match
2222 //
2223 Handle = NULL;
2224 }
2225
2226 FreePool (VlanDevicePath);
2227 return Handle;
2228}
2229
2250EFIAPI
2252 IN EFI_HANDLE ServiceHandle,
2253 OUT EFI_MAC_ADDRESS *MacAddress,
2254 OUT UINTN *AddressSize
2255 )
2256{
2257 EFI_STATUS Status;
2259 EFI_SIMPLE_NETWORK_MODE *SnpMode;
2260 EFI_SIMPLE_NETWORK_MODE SnpModeData;
2263 EFI_HANDLE SnpHandle;
2264 EFI_HANDLE MnpChildHandle;
2265
2266 ASSERT (MacAddress != NULL);
2267 ASSERT (AddressSize != NULL);
2268
2269 //
2270 // Try to get SNP handle
2271 //
2272 Snp = NULL;
2273 SnpHandle = NetLibGetSnpHandle (ServiceHandle, &Snp);
2274 if (SnpHandle != NULL) {
2275 //
2276 // SNP found, use it directly
2277 //
2278 SnpMode = Snp->Mode;
2279 } else {
2280 //
2281 // Failed to get SNP handle, try to get MAC address from MNP
2282 //
2283 MnpChildHandle = NULL;
2284 Status = gBS->HandleProtocol (
2285 ServiceHandle,
2286 &gEfiManagedNetworkServiceBindingProtocolGuid,
2287 (VOID **)&MnpSb
2288 );
2289 if (EFI_ERROR (Status)) {
2290 return Status;
2291 }
2292
2293 //
2294 // Create a MNP child
2295 //
2296 Status = MnpSb->CreateChild (MnpSb, &MnpChildHandle);
2297 if (EFI_ERROR (Status)) {
2298 return Status;
2299 }
2300
2301 //
2302 // Open MNP protocol
2303 //
2304 Status = gBS->HandleProtocol (
2305 MnpChildHandle,
2306 &gEfiManagedNetworkProtocolGuid,
2307 (VOID **)&Mnp
2308 );
2309 if (EFI_ERROR (Status)) {
2310 MnpSb->DestroyChild (MnpSb, MnpChildHandle);
2311 return Status;
2312 }
2313
2314 //
2315 // Try to get SNP mode from MNP
2316 //
2317 Status = Mnp->GetModeData (Mnp, NULL, &SnpModeData);
2318 if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {
2319 MnpSb->DestroyChild (MnpSb, MnpChildHandle);
2320 return Status;
2321 }
2322
2323 SnpMode = &SnpModeData;
2324
2325 //
2326 // Destroy the MNP child
2327 //
2328 MnpSb->DestroyChild (MnpSb, MnpChildHandle);
2329 }
2330
2331 *AddressSize = SnpMode->HwAddressSize;
2332 CopyMem (MacAddress->Addr, SnpMode->CurrentAddress.Addr, SnpMode->HwAddressSize);
2333
2334 return EFI_SUCCESS;
2335}
2336
2362EFIAPI
2364 IN EFI_HANDLE ServiceHandle,
2365 IN EFI_HANDLE ImageHandle OPTIONAL,
2366 OUT CHAR16 **MacString
2367 )
2368{
2369 EFI_STATUS Status;
2370 EFI_MAC_ADDRESS MacAddress;
2371 UINT8 *HwAddress;
2372 UINTN HwAddressSize;
2373 UINT16 VlanId;
2374 CHAR16 *String;
2375 UINTN Index;
2376 UINTN BufferSize;
2377
2378 ASSERT (MacString != NULL);
2379
2380 //
2381 // Get MAC address of the network device
2382 //
2383 Status = NetLibGetMacAddress (ServiceHandle, &MacAddress, &HwAddressSize);
2384 if (EFI_ERROR (Status)) {
2385 return Status;
2386 }
2387
2388 //
2389 // It takes 2 unicode characters to represent a 1 byte binary buffer.
2390 // If VLAN is configured, it will need extra 5 characters like "\0005".
2391 // Plus one unicode character for the null-terminator.
2392 //
2393 BufferSize = (2 * HwAddressSize + 5 + 1) * sizeof (CHAR16);
2394 String = AllocateZeroPool (BufferSize);
2395 if (String == NULL) {
2396 return EFI_OUT_OF_RESOURCES;
2397 }
2398
2399 *MacString = String;
2400
2401 //
2402 // Convert the MAC address into a unicode string.
2403 //
2404 HwAddress = &MacAddress.Addr[0];
2405 for (Index = 0; Index < HwAddressSize; Index++) {
2407 String,
2408 BufferSize - ((UINTN)String - (UINTN)*MacString),
2409 PREFIX_ZERO | RADIX_HEX,
2410 *(HwAddress++),
2411 2
2412 );
2413 String += StrnLenS (String, (BufferSize - ((UINTN)String - (UINTN)*MacString)) / sizeof (CHAR16));
2414 }
2415
2416 //
2417 // Append VLAN ID if any
2418 //
2419 VlanId = NetLibGetVlanId (ServiceHandle);
2420 if (VlanId != 0) {
2421 *String++ = L'\\';
2423 String,
2424 BufferSize - ((UINTN)String - (UINTN)*MacString),
2425 PREFIX_ZERO | RADIX_HEX,
2426 VlanId,
2427 4
2428 );
2429 String += StrnLenS (String, (BufferSize - ((UINTN)String - (UINTN)*MacString)) / sizeof (CHAR16));
2430 }
2431
2432 //
2433 // Null terminate the Unicode string
2434 //
2435 *String = L'\0';
2436
2437 return EFI_SUCCESS;
2438}
2439
2471EFIAPI
2473 IN EFI_HANDLE ServiceHandle,
2474 OUT BOOLEAN *MediaPresent
2475 )
2476{
2477 EFI_STATUS Status;
2478 EFI_HANDLE SnpHandle;
2480 UINT32 InterruptStatus;
2481 UINT32 OldState;
2482 EFI_MAC_ADDRESS *MCastFilter;
2483 UINT32 MCastFilterCount;
2484 UINT32 EnableFilterBits;
2485 UINT32 DisableFilterBits;
2486 BOOLEAN ResetMCastFilters;
2487
2488 ASSERT (MediaPresent != NULL);
2489
2490 //
2491 // Get SNP handle
2492 //
2493 Snp = NULL;
2494 SnpHandle = NetLibGetSnpHandle (ServiceHandle, &Snp);
2495 if (SnpHandle == NULL) {
2496 return EFI_INVALID_PARAMETER;
2497 }
2498
2499 //
2500 // Check whether SNP support media detection
2501 //
2502 if (!Snp->Mode->MediaPresentSupported) {
2503 return EFI_UNSUPPORTED;
2504 }
2505
2506 //
2507 // Invoke Snp->GetStatus() to refresh MediaPresent field in SNP mode data
2508 //
2509 Status = Snp->GetStatus (Snp, &InterruptStatus, NULL);
2510 if (EFI_ERROR (Status)) {
2511 return Status;
2512 }
2513
2514 if (Snp->Mode->MediaPresent) {
2515 //
2516 // Media is present, return directly
2517 //
2518 *MediaPresent = TRUE;
2519 return EFI_SUCCESS;
2520 }
2521
2522 //
2523 // Till now, GetStatus() report no media; while, in case UNDI not support
2524 // reporting media status from GetStatus(), this media status may be incorrect.
2525 // So, we will stop SNP and then restart it to get the correct media status.
2526 //
2527 OldState = Snp->Mode->State;
2528 if (OldState >= EfiSimpleNetworkMaxState) {
2529 return EFI_DEVICE_ERROR;
2530 }
2531
2532 MCastFilter = NULL;
2533
2534 if (OldState == EfiSimpleNetworkInitialized) {
2535 //
2536 // SNP is already in use, need Shutdown/Stop and then Start/Initialize
2537 //
2538
2539 //
2540 // Backup current SNP receive filter settings
2541 //
2542 EnableFilterBits = Snp->Mode->ReceiveFilterSetting;
2543 DisableFilterBits = Snp->Mode->ReceiveFilterMask ^ EnableFilterBits;
2544
2545 ResetMCastFilters = TRUE;
2546 MCastFilterCount = Snp->Mode->MCastFilterCount;
2547 if (MCastFilterCount != 0) {
2548 MCastFilter = AllocateCopyPool (
2549 MCastFilterCount * sizeof (EFI_MAC_ADDRESS),
2550 Snp->Mode->MCastFilter
2551 );
2552 ASSERT (MCastFilter != NULL);
2553 if (MCastFilter == NULL) {
2554 Status = EFI_OUT_OF_RESOURCES;
2555 goto Exit;
2556 }
2557
2558 ResetMCastFilters = FALSE;
2559 }
2560
2561 //
2562 // Shutdown/Stop the simple network
2563 //
2564 Status = Snp->Shutdown (Snp);
2565 if (!EFI_ERROR (Status)) {
2566 Status = Snp->Stop (Snp);
2567 }
2568
2569 if (EFI_ERROR (Status)) {
2570 goto Exit;
2571 }
2572
2573 //
2574 // Start/Initialize the simple network
2575 //
2576 Status = Snp->Start (Snp);
2577 if (!EFI_ERROR (Status)) {
2578 Status = Snp->Initialize (Snp, 0, 0);
2579 }
2580
2581 if (EFI_ERROR (Status)) {
2582 goto Exit;
2583 }
2584
2585 //
2586 // Here we get the correct media status
2587 //
2588 *MediaPresent = Snp->Mode->MediaPresent;
2589
2590 //
2591 // Restore SNP receive filter settings
2592 //
2593 Status = Snp->ReceiveFilters (
2594 Snp,
2595 EnableFilterBits,
2596 DisableFilterBits,
2597 ResetMCastFilters,
2598 MCastFilterCount,
2599 MCastFilter
2600 );
2601
2602 if (MCastFilter != NULL) {
2603 FreePool (MCastFilter);
2604 }
2605
2606 return Status;
2607 }
2608
2609 //
2610 // SNP is not in use, it's in state of EfiSimpleNetworkStopped or EfiSimpleNetworkStarted
2611 //
2612 if (OldState == EfiSimpleNetworkStopped) {
2613 //
2614 // SNP not start yet, start it
2615 //
2616 Status = Snp->Start (Snp);
2617 if (EFI_ERROR (Status)) {
2618 goto Exit;
2619 }
2620 }
2621
2622 //
2623 // Initialize the simple network
2624 //
2625 Status = Snp->Initialize (Snp, 0, 0);
2626 if (EFI_ERROR (Status)) {
2627 Status = EFI_DEVICE_ERROR;
2628 goto Exit;
2629 }
2630
2631 //
2632 // Here we get the correct media status
2633 //
2634 *MediaPresent = Snp->Mode->MediaPresent;
2635
2636 //
2637 // Shut down the simple network
2638 //
2639 Snp->Shutdown (Snp);
2640
2641Exit:
2642 if (OldState == EfiSimpleNetworkStopped) {
2643 //
2644 // Original SNP sate is Stopped, restore to original state
2645 //
2646 Snp->Stop (Snp);
2647 }
2648
2649 if (MCastFilter != NULL) {
2650 FreePool (MCastFilter);
2651 }
2652
2653 return Status;
2654}
2655
2682EFIAPI
2684 IN EFI_HANDLE ServiceHandle,
2685 IN UINT64 Timeout,
2686 OUT EFI_STATUS *MediaState
2687 )
2688{
2689 EFI_STATUS Status;
2690 EFI_HANDLE SnpHandle;
2694 BOOLEAN MediaPresent;
2695 UINTN DataSize;
2696 EFI_STATUS TimerStatus;
2697 EFI_EVENT Timer;
2698 UINT64 TimeRemained;
2699
2700 if (MediaState == NULL) {
2701 return EFI_INVALID_PARAMETER;
2702 }
2703
2704 *MediaState = EFI_SUCCESS;
2705 MediaInfo = NULL;
2706
2707 //
2708 // Get SNP handle
2709 //
2710 Snp = NULL;
2711 SnpHandle = NetLibGetSnpHandle (ServiceHandle, &Snp);
2712 if (SnpHandle == NULL) {
2713 return EFI_INVALID_PARAMETER;
2714 }
2715
2716 Status = gBS->HandleProtocol (
2717 SnpHandle,
2718 &gEfiAdapterInformationProtocolGuid,
2719 (VOID *)&Aip
2720 );
2721 if (EFI_ERROR (Status)) {
2722 MediaPresent = TRUE;
2723 Status = NetLibDetectMedia (ServiceHandle, &MediaPresent);
2724 if (!EFI_ERROR (Status)) {
2725 if (MediaPresent) {
2726 *MediaState = EFI_SUCCESS;
2727 } else {
2728 *MediaState = EFI_NO_MEDIA;
2729 }
2730 }
2731
2732 //
2733 // NetLibDetectMedia doesn't support EFI_NOT_READY status, return now!
2734 //
2735 return Status;
2736 }
2737
2738 Status = Aip->GetInformation (
2739 Aip,
2740 &gEfiAdapterInfoMediaStateGuid,
2741 (VOID **)&MediaInfo,
2742 &DataSize
2743 );
2744 if (!EFI_ERROR (Status)) {
2745 *MediaState = MediaInfo->MediaState;
2746 FreePool (MediaInfo);
2747 if ((*MediaState != EFI_NOT_READY) || (Timeout < MEDIA_STATE_DETECT_TIME_INTERVAL)) {
2748 return EFI_SUCCESS;
2749 }
2750 } else {
2751 if (MediaInfo != NULL) {
2752 FreePool (MediaInfo);
2753 }
2754
2755 if (Status == EFI_UNSUPPORTED) {
2756 //
2757 // If gEfiAdapterInfoMediaStateGuid is not supported, call NetLibDetectMedia to get media state!
2758 //
2759 MediaPresent = TRUE;
2760 Status = NetLibDetectMedia (ServiceHandle, &MediaPresent);
2761 if (!EFI_ERROR (Status)) {
2762 if (MediaPresent) {
2763 *MediaState = EFI_SUCCESS;
2764 } else {
2765 *MediaState = EFI_NO_MEDIA;
2766 }
2767 }
2768
2769 return Status;
2770 }
2771
2772 return Status;
2773 }
2774
2775 //
2776 // Loop to check media state
2777 //
2778
2779 Timer = NULL;
2780 TimeRemained = Timeout;
2781 Status = gBS->CreateEvent (EVT_TIMER, TPL_CALLBACK, NULL, NULL, &Timer);
2782 if (EFI_ERROR (Status)) {
2783 return EFI_DEVICE_ERROR;
2784 }
2785
2786 do {
2787 Status = gBS->SetTimer (
2788 Timer,
2790 MEDIA_STATE_DETECT_TIME_INTERVAL
2791 );
2792 if (EFI_ERROR (Status)) {
2793 gBS->CloseEvent (Timer);
2794 return EFI_DEVICE_ERROR;
2795 }
2796
2797 do {
2798 TimerStatus = gBS->CheckEvent (Timer);
2799 if (!EFI_ERROR (TimerStatus)) {
2800 TimeRemained -= MEDIA_STATE_DETECT_TIME_INTERVAL;
2801 Status = Aip->GetInformation (
2802 Aip,
2803 &gEfiAdapterInfoMediaStateGuid,
2804 (VOID **)&MediaInfo,
2805 &DataSize
2806 );
2807 if (!EFI_ERROR (Status)) {
2808 *MediaState = MediaInfo->MediaState;
2809 FreePool (MediaInfo);
2810 } else {
2811 if (MediaInfo != NULL) {
2812 FreePool (MediaInfo);
2813 }
2814
2815 gBS->CloseEvent (Timer);
2816 return Status;
2817 }
2818 }
2819 } while (TimerStatus == EFI_NOT_READY);
2820 } while (*MediaState == EFI_NOT_READY && TimeRemained >= MEDIA_STATE_DETECT_TIME_INTERVAL);
2821
2822 gBS->CloseEvent (Timer);
2823 if ((*MediaState == EFI_NOT_READY) && (TimeRemained < MEDIA_STATE_DETECT_TIME_INTERVAL)) {
2824 return EFI_TIMEOUT;
2825 } else {
2826 return EFI_SUCCESS;
2827 }
2828}
2829
2845BOOLEAN
2847 IN EFI_HANDLE Controller
2848 )
2849{
2850 EFI_STATUS Status;
2851 EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2;
2852 UINTN DataSize;
2854 BOOLEAN IsStatic;
2855
2856 Ip4Config2 = NULL;
2857
2858 DataSize = sizeof (EFI_IP4_CONFIG2_POLICY);
2859
2860 IsStatic = TRUE;
2861
2862 //
2863 // Get Ip4Config2 policy.
2864 //
2865 Status = gBS->HandleProtocol (Controller, &gEfiIp4Config2ProtocolGuid, (VOID **)&Ip4Config2);
2866 if (EFI_ERROR (Status)) {
2867 goto ON_EXIT;
2868 }
2869
2870 Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypePolicy, &DataSize, &Policy);
2871 if (EFI_ERROR (Status)) {
2872 goto ON_EXIT;
2873 }
2874
2875 IsStatic = (BOOLEAN)(Policy == Ip4Config2PolicyStatic);
2876
2877ON_EXIT:
2878
2879 return IsStatic;
2880}
2881
2901VOID
2902EFIAPI
2904 IN OUT IPv4_DEVICE_PATH *Node,
2905 IN EFI_HANDLE Controller,
2906 IN IP4_ADDR LocalIp,
2907 IN UINT16 LocalPort,
2908 IN IP4_ADDR RemoteIp,
2909 IN UINT16 RemotePort,
2910 IN UINT16 Protocol,
2911 IN BOOLEAN UseDefaultAddress
2912 )
2913{
2914 ASSERT (Node != NULL);
2915
2916 Node->Header.Type = MESSAGING_DEVICE_PATH;
2917 Node->Header.SubType = MSG_IPv4_DP;
2918 SetDevicePathNodeLength (&Node->Header, sizeof (IPv4_DEVICE_PATH));
2919
2920 CopyMem (&Node->LocalIpAddress, &LocalIp, sizeof (EFI_IPv4_ADDRESS));
2921 CopyMem (&Node->RemoteIpAddress, &RemoteIp, sizeof (EFI_IPv4_ADDRESS));
2922
2923 Node->LocalPort = LocalPort;
2924 Node->RemotePort = RemotePort;
2925
2926 Node->Protocol = Protocol;
2927
2928 if (!UseDefaultAddress) {
2929 Node->StaticIpAddress = TRUE;
2930 } else {
2931 Node->StaticIpAddress = NetLibDefaultAddressIsStatic (Controller);
2932 }
2933
2934 //
2935 // Set the Gateway IP address to default value 0:0:0:0.
2936 // Set the Subnet mask to default value 255:255:255:0.
2937 //
2938 ZeroMem (&Node->GatewayIpAddress, sizeof (EFI_IPv4_ADDRESS));
2939 SetMem (&Node->SubnetMask, sizeof (EFI_IPv4_ADDRESS), 0xff);
2940 Node->SubnetMask.Addr[3] = 0;
2941}
2942
2963VOID
2964EFIAPI
2966 IN OUT IPv6_DEVICE_PATH *Node,
2967 IN EFI_HANDLE Controller,
2968 IN EFI_IPv6_ADDRESS *LocalIp,
2969 IN UINT16 LocalPort,
2970 IN EFI_IPv6_ADDRESS *RemoteIp,
2971 IN UINT16 RemotePort,
2972 IN UINT16 Protocol
2973 )
2974{
2975 ASSERT (Node != NULL && LocalIp != NULL && RemoteIp != NULL);
2976
2977 Node->Header.Type = MESSAGING_DEVICE_PATH;
2978 Node->Header.SubType = MSG_IPv6_DP;
2979 SetDevicePathNodeLength (&Node->Header, sizeof (IPv6_DEVICE_PATH));
2980
2981 CopyMem (&Node->LocalIpAddress, LocalIp, sizeof (EFI_IPv6_ADDRESS));
2982 CopyMem (&Node->RemoteIpAddress, RemoteIp, sizeof (EFI_IPv6_ADDRESS));
2983
2984 Node->LocalPort = LocalPort;
2985 Node->RemotePort = RemotePort;
2986
2987 Node->Protocol = Protocol;
2988
2989 //
2990 // Set default value to IPAddressOrigin, PrefixLength.
2991 // Set the Gateway IP address to unspecified address.
2992 //
2993 Node->IpAddressOrigin = 0;
2994 Node->PrefixLength = IP6_PREFIX_LENGTH;
2995 ZeroMem (&Node->GatewayIpAddress, sizeof (EFI_IPv6_ADDRESS));
2996}
2997
3018EFIAPI
3020 IN EFI_HANDLE Controller,
3021 IN EFI_GUID *ProtocolGuid
3022 )
3023{
3025 EFI_HANDLE Handle;
3026 EFI_STATUS Status;
3027 UINTN OpenCount;
3028 UINTN Index;
3029
3030 ASSERT (ProtocolGuid != NULL);
3031
3032 Status = gBS->OpenProtocolInformation (
3033 Controller,
3034 ProtocolGuid,
3035 &OpenBuffer,
3036 &OpenCount
3037 );
3038
3039 if (EFI_ERROR (Status)) {
3040 return NULL;
3041 }
3042
3043 Handle = NULL;
3044
3045 for (Index = 0; Index < OpenCount; Index++) {
3046 if ((OpenBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
3047 Handle = OpenBuffer[Index].ControllerHandle;
3048 break;
3049 }
3050 }
3051
3052 gBS->FreePool (OpenBuffer);
3053 return Handle;
3054}
3055
3067EFIAPI
3069 IN CONST CHAR8 *String,
3070 OUT EFI_IPv4_ADDRESS *Ip4Address
3071 )
3072{
3073 RETURN_STATUS Status;
3074 CHAR8 *EndPointer;
3075
3076 Status = AsciiStrToIpv4Address (String, &EndPointer, Ip4Address, NULL);
3077 if (RETURN_ERROR (Status) || (*EndPointer != '\0')) {
3078 return EFI_INVALID_PARAMETER;
3079 } else {
3080 return EFI_SUCCESS;
3081 }
3082}
3083
3096EFIAPI
3098 IN CONST CHAR8 *String,
3099 OUT EFI_IPv6_ADDRESS *Ip6Address
3100 )
3101{
3102 RETURN_STATUS Status;
3103 CHAR8 *EndPointer;
3104
3105 Status = AsciiStrToIpv6Address (String, &EndPointer, Ip6Address, NULL);
3106 if (RETURN_ERROR (Status) || (*EndPointer != '\0')) {
3107 return EFI_INVALID_PARAMETER;
3108 } else {
3109 return EFI_SUCCESS;
3110 }
3111}
3112
3124EFIAPI
3126 IN CONST CHAR16 *String,
3127 OUT EFI_IPv4_ADDRESS *Ip4Address
3128 )
3129{
3130 RETURN_STATUS Status;
3131 CHAR16 *EndPointer;
3132
3133 Status = StrToIpv4Address (String, &EndPointer, Ip4Address, NULL);
3134 if (RETURN_ERROR (Status) || (*EndPointer != L'\0')) {
3135 return EFI_INVALID_PARAMETER;
3136 } else {
3137 return EFI_SUCCESS;
3138 }
3139}
3140
3153EFIAPI
3155 IN CONST CHAR16 *String,
3156 OUT EFI_IPv6_ADDRESS *Ip6Address
3157 )
3158{
3159 RETURN_STATUS Status;
3160 CHAR16 *EndPointer;
3161
3162 Status = StrToIpv6Address (String, &EndPointer, Ip6Address, NULL);
3163 if (RETURN_ERROR (Status) || (*EndPointer != L'\0')) {
3164 return EFI_INVALID_PARAMETER;
3165 } else {
3166 return EFI_SUCCESS;
3167 }
3168}
3169
3184EFIAPI
3186 IN CONST CHAR16 *String,
3187 OUT EFI_IPv6_ADDRESS *Ip6Address,
3188 OUT UINT8 *PrefixLength
3189 )
3190{
3191 RETURN_STATUS Status;
3192 CHAR16 *EndPointer;
3193
3194 Status = StrToIpv6Address (String, &EndPointer, Ip6Address, PrefixLength);
3195 if (RETURN_ERROR (Status) || (*EndPointer != L'\0')) {
3196 return EFI_INVALID_PARAMETER;
3197 } else {
3198 return EFI_SUCCESS;
3199 }
3200}
3201
3217EFIAPI
3219 IN EFI_IPv6_ADDRESS *Ip6Address,
3220 OUT CHAR16 *String,
3221 IN UINTN StringSize
3222 )
3223{
3224 UINT16 Ip6Addr[8];
3225 UINTN Index;
3226 UINTN LongestZerosStart;
3227 UINTN LongestZerosLength;
3228 UINTN CurrentZerosStart;
3229 UINTN CurrentZerosLength;
3230 CHAR16 Buffer[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"];
3231 CHAR16 *Ptr;
3232
3233 if ((Ip6Address == NULL) || (String == NULL) || (StringSize == 0)) {
3234 return EFI_INVALID_PARAMETER;
3235 }
3236
3237 //
3238 // Convert the UINT8 array to an UINT16 array for easy handling.
3239 //
3240 ZeroMem (Ip6Addr, sizeof (Ip6Addr));
3241 for (Index = 0; Index < 16; Index++) {
3242 Ip6Addr[Index / 2] |= (Ip6Address->Addr[Index] << ((1 - (Index % 2)) << 3));
3243 }
3244
3245 //
3246 // Find the longest zeros and mark it.
3247 //
3248 CurrentZerosStart = DEFAULT_ZERO_START;
3249 CurrentZerosLength = 0;
3250 LongestZerosStart = DEFAULT_ZERO_START;
3251 LongestZerosLength = 0;
3252 for (Index = 0; Index < 8; Index++) {
3253 if (Ip6Addr[Index] == 0) {
3254 if (CurrentZerosStart == DEFAULT_ZERO_START) {
3255 CurrentZerosStart = Index;
3256 CurrentZerosLength = 1;
3257 } else {
3258 CurrentZerosLength++;
3259 }
3260 } else {
3261 if (CurrentZerosStart != DEFAULT_ZERO_START) {
3262 if ((CurrentZerosLength > 2) && ((LongestZerosStart == (DEFAULT_ZERO_START)) || (CurrentZerosLength > LongestZerosLength))) {
3263 LongestZerosStart = CurrentZerosStart;
3264 LongestZerosLength = CurrentZerosLength;
3265 }
3266
3267 CurrentZerosStart = DEFAULT_ZERO_START;
3268 CurrentZerosLength = 0;
3269 }
3270 }
3271 }
3272
3273 if ((CurrentZerosStart != DEFAULT_ZERO_START) && (CurrentZerosLength > 2)) {
3274 if ((LongestZerosStart == DEFAULT_ZERO_START) || (LongestZerosLength < CurrentZerosLength)) {
3275 LongestZerosStart = CurrentZerosStart;
3276 LongestZerosLength = CurrentZerosLength;
3277 }
3278 }
3279
3280 Ptr = Buffer;
3281 for (Index = 0; Index < 8; Index++) {
3282 if ((LongestZerosStart != DEFAULT_ZERO_START) && (Index >= LongestZerosStart) && (Index < LongestZerosStart + LongestZerosLength)) {
3283 if (Index == LongestZerosStart) {
3284 *Ptr++ = L':';
3285 }
3286
3287 continue;
3288 }
3289
3290 if (Index != 0) {
3291 *Ptr++ = L':';
3292 }
3293
3294 Ptr += UnicodeSPrint (Ptr, 10, L"%x", Ip6Addr[Index]);
3295 }
3296
3297 if ((LongestZerosStart != DEFAULT_ZERO_START) && (LongestZerosStart + LongestZerosLength == 8)) {
3298 *Ptr++ = L':';
3299 }
3300
3301 *Ptr = L'\0';
3302
3303 if ((UINTN)Ptr - (UINTN)Buffer > StringSize) {
3304 return EFI_BUFFER_TOO_SMALL;
3305 }
3306
3307 StrCpyS (String, StringSize / sizeof (CHAR16), Buffer);
3308
3309 return EFI_SUCCESS;
3310}
3311
3324EFIAPI
3326 OUT EFI_GUID *SystemGuid
3327 )
3328{
3329 EFI_STATUS Status;
3330 SMBIOS_TABLE_ENTRY_POINT *SmbiosTable;
3331 SMBIOS_TABLE_3_0_ENTRY_POINT *Smbios30Table;
3333 SMBIOS_STRUCTURE_POINTER SmbiosEnd;
3334 CHAR8 *String;
3335
3336 ASSERT (SystemGuid != NULL);
3337
3338 SmbiosTable = NULL;
3339 Status = EfiGetSystemConfigurationTable (&gEfiSmbios3TableGuid, (VOID **)&Smbios30Table);
3340 if (!(EFI_ERROR (Status) || (Smbios30Table == NULL))) {
3341 Smbios.Hdr = (SMBIOS_STRUCTURE *)(UINTN)Smbios30Table->TableAddress;
3342 SmbiosEnd.Raw = (UINT8 *)(UINTN)(Smbios30Table->TableAddress + Smbios30Table->TableMaximumSize);
3343 } else {
3344 Status = EfiGetSystemConfigurationTable (&gEfiSmbiosTableGuid, (VOID **)&SmbiosTable);
3345 if (EFI_ERROR (Status) || (SmbiosTable == NULL)) {
3346 return EFI_NOT_FOUND;
3347 }
3348
3349 Smbios.Hdr = (SMBIOS_STRUCTURE *)(UINTN)SmbiosTable->TableAddress;
3350 SmbiosEnd.Raw = (UINT8 *)((UINTN)SmbiosTable->TableAddress + SmbiosTable->TableLength);
3351 }
3352
3353 do {
3354 if (Smbios.Hdr->Type == 1) {
3355 if (Smbios.Hdr->Length < 0x19) {
3356 //
3357 // Older version did not support UUID.
3358 //
3359 return EFI_NOT_FOUND;
3360 }
3361
3362 //
3363 // SMBIOS tables are byte packed so we need to do a byte copy to
3364 // prevend alignment faults on Itanium-based platform.
3365 //
3366 CopyMem (SystemGuid, &Smbios.Type1->Uuid, sizeof (EFI_GUID));
3367 return EFI_SUCCESS;
3368 }
3369
3370 //
3371 // Go to the next SMBIOS structure. Each SMBIOS structure may include 2 parts:
3372 // 1. Formatted section; 2. Unformatted string section. So, 2 steps are needed
3373 // to skip one SMBIOS structure.
3374 //
3375
3376 //
3377 // Step 1: Skip over formatted section.
3378 //
3379 String = (CHAR8 *)(Smbios.Raw + Smbios.Hdr->Length);
3380
3381 //
3382 // Step 2: Skip over unformatted string section.
3383 //
3384 do {
3385 //
3386 // Each string is terminated with a NULL(00h) BYTE and the sets of strings
3387 // is terminated with an additional NULL(00h) BYTE.
3388 //
3389 for ( ; *String != 0; String++) {
3390 }
3391
3392 if (*(UINT8 *)++String == 0) {
3393 //
3394 // Pointer to the next SMBIOS structure.
3395 //
3396 Smbios.Raw = (UINT8 *)++String;
3397 break;
3398 }
3399 } while (TRUE);
3400 } while (Smbios.Raw < SmbiosEnd.Raw);
3401
3402 return EFI_NOT_FOUND;
3403}
3404
3422CHAR8 *
3423EFIAPI
3425 IN CHAR16 *DomainName
3426 )
3427{
3428 CHAR8 *QueryName;
3429 UINTN QueryNameSize;
3430 CHAR8 *Header;
3431 CHAR8 *Tail;
3432 UINTN Len;
3433 UINTN Index;
3434
3435 ASSERT (DomainName != NULL);
3436
3437 QueryName = NULL;
3438 QueryNameSize = 0;
3439 Header = NULL;
3440 Tail = NULL;
3441
3442 //
3443 // One byte for first label length, one byte for terminated length zero.
3444 //
3445 QueryNameSize = StrLen (DomainName) + 2;
3446
3447 if (QueryNameSize > DNS_MAX_NAME_SIZE) {
3448 return NULL;
3449 }
3450
3451 QueryName = AllocateZeroPool (QueryNameSize);
3452 if (QueryName == NULL) {
3453 return NULL;
3454 }
3455
3456 Header = QueryName;
3457 Tail = Header + 1;
3458 Len = 0;
3459 for (Index = 0; DomainName[Index] != 0; Index++) {
3460 *Tail = (CHAR8)DomainName[Index];
3461 if (*Tail == '.') {
3462 *Header = (CHAR8)Len;
3463 Header = Tail;
3464 Tail++;
3465 Len = 0;
3466 } else {
3467 Tail++;
3468 Len++;
3469 }
3470 }
3471
3472 *Header = (CHAR8)Len;
3473 *Tail = 0;
3474
3475 return QueryName;
3476}
UINT64 UINTN
INT64 INTN
BOOLEAN EFIAPI IsNull(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:443
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
RETURN_STATUS EFIAPI StrCpyS(OUT CHAR16 *Destination, IN UINTN DestMax, IN CONST CHAR16 *Source)
Definition: SafeString.c:226
LIST_ENTRY *EFIAPI GetNextNode(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:333
LIST_ENTRY *EFIAPI InsertHeadList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:218
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
Definition: LinkedList.c:298
UINTN EFIAPI StrnLenS(IN CONST CHAR16 *String, IN UINTN MaxSize)
Definition: SafeString.c:119
RETURN_STATUS EFIAPI StrToIpv6Address(IN CONST CHAR16 *String, OUT CHAR16 **EndPointer OPTIONAL, OUT IPv6_ADDRESS *Address, OUT UINT8 *PrefixLength OPTIONAL)
Definition: SafeString.c:1129
RETURN_STATUS EFIAPI StrToIpv4Address(IN CONST CHAR16 *String, OUT CHAR16 **EndPointer OPTIONAL, OUT IPv4_ADDRESS *Address, OUT UINT8 *PrefixLength OPTIONAL)
Definition: SafeString.c:1351
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
RETURN_STATUS EFIAPI AsciiStrToIpv4Address(IN CONST CHAR8 *String, OUT CHAR8 **EndPointer OPTIONAL, OUT IPv4_ADDRESS *Address, OUT UINT8 *PrefixLength OPTIONAL)
Definition: SafeString.c:3313
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
RETURN_STATUS EFIAPI AsciiStrToIpv6Address(IN CONST CHAR8 *String, OUT CHAR8 **EndPointer OPTIONAL, OUT IPv6_ADDRESS *Address, OUT UINT8 *PrefixLength OPTIONAL)
Definition: SafeString.c:3095
UINT64 EFIAPI SwapBytes64(IN UINT64 Value)
Definition: SwapBytes64.c:25
UINTN EFIAPI StrLen(IN CONST CHAR16 *String)
Definition: String.c:30
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI SetMem(OUT VOID *Buffer, IN UINTN Length, IN UINT8 Value)
Definition: SetMemWrapper.c:38
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
#define MSG_IPv6_DP
Definition: DevicePath.h:607
#define MSG_IPv4_DP
Definition: DevicePath.h:566
#define MSG_VLAN_DP
Definition: DevicePath.h:964
#define MESSAGING_DEVICE_PATH
Definition: DevicePath.h:321
UINT16 EFIAPI SetDevicePathNodeLength(IN OUT VOID *Node, IN UINTN Length)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI AppendDevicePathNode(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL, IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL)
BOOLEAN EFIAPI IsDevicePathEnd(IN CONST VOID *Node)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI NextDevicePathNode(IN CONST VOID *Node)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI DevicePathFromHandle(IN EFI_HANDLE Handle)
VOID *EFIAPI NetMapRemoveTail(IN OUT NET_MAP *Map, OUT VOID **Value OPTIONAL)
Definition: DxeNetLib.c:1754
LIST_ENTRY *EFIAPI NetListRemoveHead(IN OUT LIST_ENTRY *Head)
Definition: DxeNetLib.c:1090
LIST_ENTRY *EFIAPI NetListRemoveTail(IN OUT LIST_ENTRY *Head)
Definition: DxeNetLib.c:1134
EFI_STATUS EFIAPI NetLibGetMacAddress(IN EFI_HANDLE ServiceHandle, OUT EFI_MAC_ADDRESS *MacAddress, OUT UINTN *AddressSize)
Definition: DxeNetLib.c:2251
EFI_STATUS EFIAPI NetLibGetMacString(IN EFI_HANDLE ServiceHandle, IN EFI_HANDLE ImageHandle OPTIONAL, OUT CHAR16 **MacString)
Definition: DxeNetLib.c:2363
BOOLEAN EFIAPI NetIp4IsUnicast(IN IP4_ADDR Ip, IN IP4_ADDR NetMask)
Definition: DxeNetLib.c:683
BOOLEAN EFIAPI NetIp6IsValidUnicast(IN EFI_IPv6_ADDRESS *Ip6)
Definition: DxeNetLib.c:725
VOID EFIAPI NetMapClean(IN OUT NET_MAP *Map)
Definition: DxeNetLib.c:1368
EFI_HANDLE EFIAPI NetLibGetVlanHandle(IN EFI_HANDLE ControllerHandle, IN UINT16 VlanId)
Definition: DxeNetLib.c:2180
EFI_STATUS EFIAPI NetLibCreateServiceChild(IN EFI_HANDLE Controller, IN EFI_HANDLE Image, IN EFI_GUID *ServiceBindingGuid, IN OUT EFI_HANDLE *ChildHandle)
Definition: DxeNetLib.c:1967
NET_MAP_ITEM * NetMapAllocItem(IN OUT NET_MAP *Map)
Definition: DxeNetLib.c:1458
BOOLEAN NetItemInMap(IN NET_MAP *Map, IN NET_MAP_ITEM *Item)
Definition: DxeNetLib.c:1594
VOID EFIAPI NetLibCreateIPv6DPathNode(IN OUT IPv6_DEVICE_PATH *Node, IN EFI_HANDLE Controller, IN EFI_IPv6_ADDRESS *LocalIp, IN UINT16 LocalPort, IN EFI_IPv6_ADDRESS *RemoteIp, IN UINT16 RemotePort, IN UINT16 Protocol)
Definition: DxeNetLib.c:2965
EFI_STATUS EFIAPI NetLibAsciiStrToIp4(IN CONST CHAR8 *String, OUT EFI_IPv4_ADDRESS *Ip4Address)
Definition: DxeNetLib.c:3068
CHAR8 *EFIAPI NetLibCreateDnsQName(IN CHAR16 *DomainName)
Definition: DxeNetLib.c:3424
BOOLEAN EFIAPI NetIp6IsNetEqual(EFI_IPv6_ADDRESS *Ip1, EFI_IPv6_ADDRESS *Ip2, UINT8 PrefixLength)
Definition: DxeNetLib.c:837
NET_MAP_ITEM *EFIAPI NetMapFindKey(IN NET_MAP *Map, IN VOID *Key)
Definition: DxeNetLib.c:1629
EFI_STATUS EFIAPI NetMapInsertHead(IN OUT NET_MAP *Map, IN VOID *Key, IN VOID *Value OPTIONAL)
Definition: DxeNetLib.c:1512
BOOLEAN EFIAPI NetIp6IsLinkLocalAddr(IN EFI_IPv6_ADDRESS *Ip6)
Definition: DxeNetLib.c:796
EFI_IPv6_ADDRESS *EFIAPI Ip6Swap128(EFI_IPv6_ADDRESS *Ip6)
Definition: DxeNetLib.c:892
VOID EFIAPI NetListInsertAfter(IN OUT LIST_ENTRY *PrevEntry, IN OUT LIST_ENTRY *NewEntry)
Definition: DxeNetLib.c:1172
EFI_STATUS EFIAPI NetLibDestroyServiceChild(IN EFI_HANDLE Controller, IN EFI_HANDLE Image, IN EFI_GUID *ServiceBindingGuid, IN EFI_HANDLE ChildHandle)
Definition: DxeNetLib.c:2020
VOID EFIAPI NetMapInit(IN OUT NET_MAP *Map)
Definition: DxeNetLib.c:1343
EFI_STATUS EFIAPI NetLibDetectMedia(IN EFI_HANDLE ServiceHandle, OUT BOOLEAN *MediaPresent)
Definition: DxeNetLib.c:2472
UINT32 EFIAPI NetGetUint32(IN UINT8 *Buf)
Definition: DxeNetLib.c:1033
CHAR8 *EFIAPI NetDebugASPrint(IN CHAR8 *Format,...)
Definition: DxeNetLib.c:481
VOID EFIAPI NetLibCreateIPv4DPathNode(IN OUT IPv4_DEVICE_PATH *Node, IN EFI_HANDLE Controller, IN IP4_ADDR LocalIp, IN UINT16 LocalPort, IN IP4_ADDR RemoteIp, IN UINT16 RemotePort, IN UINT16 Protocol, IN BOOLEAN UseDefaultAddress)
Definition: DxeNetLib.c:2903
EFI_STATUS EFIAPI NetLibDefaultUnload(IN EFI_HANDLE ImageHandle)
Definition: DxeNetLib.c:1846
BOOLEAN EFIAPI NetIsInHandleBuffer(IN EFI_HANDLE Handle, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer OPTIONAL)
Definition: DxeNetLib.c:1306
BOOLEAN EFIAPI NetIp6IsUnspecifiedAddr(IN EFI_IPv6_ADDRESS *Ip6)
Definition: DxeNetLib.c:766
VOID EFIAPI NetPutUint32(IN OUT UINT8 *Buf, IN UINT32 Data)
Definition: DxeNetLib.c:1059
EFI_STATUS EFIAPI NetLibDetectMediaWaitTimeout(IN EFI_HANDLE ServiceHandle, IN UINT64 Timeout, OUT EFI_STATUS *MediaState)
Definition: DxeNetLib.c:2683
EFI_STATUS EFIAPI NetLibGetSystemGuid(OUT EFI_GUID *SystemGuid)
Definition: DxeNetLib.c:3325
EFI_STATUS EFIAPI NetLibStrToIp4(IN CONST CHAR16 *String, OUT EFI_IPv4_ADDRESS *Ip4Address)
Definition: DxeNetLib.c:3125
INTN EFIAPI NetGetIpClass(IN IP4_ADDR Addr)
Definition: DxeNetLib.c:643
EFI_HANDLE EFIAPI NetLibGetSnpHandle(IN EFI_HANDLE ServiceHandle, OUT EFI_SIMPLE_NETWORK_PROTOCOL **Snp OPTIONAL)
Definition: DxeNetLib.c:2073
EFI_STATUS EFIAPI NetLibStrToIp6andPrefix(IN CONST CHAR16 *String, OUT EFI_IPv6_ADDRESS *Ip6Address, OUT UINT8 *PrefixLength)
Definition: DxeNetLib.c:3185
BOOLEAN EFIAPI NetMapIsEmpty(IN NET_MAP *Map)
Definition: DxeNetLib.c:1413
EFI_STATUS EFIAPI NetLibAsciiStrToIp6(IN CONST CHAR8 *String, OUT EFI_IPv6_ADDRESS *Ip6Address)
Definition: DxeNetLib.c:3097
INTN EFIAPI NetGetMaskLength(IN IP4_ADDR NetMask)
Definition: DxeNetLib.c:600
EFI_STATUS EFIAPI NetLibStrToIp6(IN CONST CHAR16 *String, OUT EFI_IPv6_ADDRESS *Ip6Address)
Definition: DxeNetLib.c:3154
EFI_STATUS EFIAPI PseudoRandomU32(OUT UINT32 *Output)
Definition: DxeNetLib.c:1011
EFI_SIMPLE_NETWORK_PROTOCOL * SyslogLocateSnp(VOID)
Definition: DxeNetLib.c:166
EFI_STATUS EFIAPI NetLibIp6ToStr(IN EFI_IPv6_ADDRESS *Ip6Address, OUT CHAR16 *String, IN UINTN StringSize)
Definition: DxeNetLib.c:3218
VOID *EFIAPI NetMapRemoveItem(IN OUT NET_MAP *Map, IN OUT NET_MAP_ITEM *Item, OUT VOID **Value OPTIONAL)
Definition: DxeNetLib.c:1671
VOID *EFIAPI NetMapRemoveHead(IN OUT NET_MAP *Map, OUT VOID **Value OPTIONAL)
Definition: DxeNetLib.c:1710
BOOLEAN NetLibDefaultAddressIsStatic(IN EFI_HANDLE Controller)
Definition: DxeNetLib.c:2846
EFI_HANDLE EFIAPI NetLibGetNicHandle(IN EFI_HANDLE Controller, IN EFI_GUID *ProtocolGuid)
Definition: DxeNetLib.c:3019
EFI_STATUS EFIAPI NetMapInsertTail(IN OUT NET_MAP *Map, IN VOID *Key, IN VOID *Value OPTIONAL)
Definition: DxeNetLib.c:1556
EFI_STATUS SyslogSendPacket(IN CHAR8 *Packet, IN UINT32 Length)
Definition: DxeNetLib.c:235
EFI_STATUS EFIAPI NetDestroyLinkList(IN LIST_ENTRY *List, IN NET_DESTROY_LINK_LIST_CALLBACK CallBack, IN VOID *Context OPTIONAL, OUT UINTN *ListLength OPTIONAL)
Definition: DxeNetLib.c:1236
UINT32 SyslogBuildPacket(IN UINT32 Level, IN UINT8 *Module, IN UINT8 *File, IN UINT32 Line, IN UINT8 *Message, IN UINT32 BufLen, OUT CHAR8 *Buf)
Definition: DxeNetLib.c:342
EFI_STATUS EFIAPI NetMapIterate(IN NET_MAP *Map, IN NET_MAP_CALLBACK CallBack, IN VOID *Arg OPTIONAL)
Definition: DxeNetLib.c:1800
VOID EFIAPI NetListInsertBefore(IN OUT LIST_ENTRY *PostEntry, IN OUT LIST_ENTRY *NewEntry)
Definition: DxeNetLib.c:1199
EFI_STATUS EFIAPI PseudoRandom(OUT VOID *Output, IN UINTN OutputLength)
Definition: DxeNetLib.c:928
UINT16 EFIAPI NetLibGetVlanId(IN EFI_HANDLE ServiceHandle)
Definition: DxeNetLib.c:2140
EFI_STATUS EFIAPI NetDebugOutput(IN UINT32 Level, IN UINT8 *Module, IN UINT8 *File, IN UINT32 Line, IN UINT8 *Message)
Definition: DxeNetLib.c:524
UINTN EFIAPI NetMapGetCount(IN NET_MAP *Map)
Definition: DxeNetLib.c:1433
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
EFI_IP4_CONFIG2_POLICY
Definition: Ip4Config2.h:127
@ Ip4Config2PolicyStatic
Definition: Ip4Config2.h:135
@ Ip4Config2DataTypePolicy
Definition: Ip4Config2.h:43
RETURN_STATUS EFIAPI UnicodeValueToStringS(IN OUT CHAR16 *Buffer, IN UINTN BufferSize, IN UINTN Flags, IN INT64 Value, IN UINTN Width)
Definition: PrintLib.c:652
UINTN EFIAPI UnicodeSPrint(OUT CHAR16 *StartOfBuffer, IN UINTN BufferSize, IN CONST CHAR16 *FormatString,...)
Definition: PrintLib.c:408
UINTN EFIAPI AsciiVSPrint(OUT CHAR8 *StartOfBuffer, IN UINTN BufferSize, IN CONST CHAR8 *FormatString, IN VA_LIST Marker)
Definition: PrintLib.c:702
UINTN EFIAPI AsciiSPrint(OUT CHAR8 *StartOfBuffer, IN UINTN BufferSize, IN CONST CHAR8 *FormatString,...)
Definition: PrintLib.c:813
EFI_RUNTIME_SERVICES * gRT
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define RETURN_ERROR(StatusCode)
Definition: Base.h:1061
#define VA_START(Marker, Parameter)
Definition: Base.h:661
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
CHAR8 * VA_LIST
Definition: Base.h:643
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define GLOBAL_REMOVE_IF_UNREFERENCED
Definition: Base.h:48
#define VA_END(Marker)
Definition: Base.h:691
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define DEBUG_CODE(Expression)
Definition: DebugLib.h:590
UINT16 EFIAPI NetblockChecksum(IN UINT8 *Bulk, IN UINT32 Len)
Definition: NetBuffer.c:1615
EFI_STATUS(EFIAPI * NET_DESTROY_LINK_LIST_CALLBACK)(IN LIST_ENTRY *Entry, IN VOID *Context OPTIONAL)
Definition: NetLib.h:749
#define PcdGetBool(TokenName)
Definition: PcdLib.h:401
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
VOID EFIAPI Exit(IN EFI_STATUS Status)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_STATUS EFIAPI EfiGetSystemConfigurationTable(IN EFI_GUID *TableGuid, OUT VOID **Table)
Definition: UefiLib.c:82
@ TimerCancel
Definition: UefiSpec.h:531
@ TimerRelative
Definition: UefiSpec.h:539
@ ByProtocol
Definition: UefiSpec.h:1518
@ AllHandles
Definition: UefiSpec.h:1509
EFI_SIMPLE_NETWORK_MODE * Mode
EFI_MAC_ADDRESS CurrentAddress
EFI_MAC_ADDRESS MCastFilter[MAX_MCAST_FILTER_CNT]
Definition: Base.h:213