]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/DxeNetLib/DxeNetLib.c
1. Update the UdpIo to a combined UdpIo to support both v4 and v6 stack.
[mirror_edk2.git] / MdeModulePkg / Library / DxeNetLib / DxeNetLib.c
1 /** @file
2 Network library.
3
4 Copyright (c) 2005 - 2009, Intel Corporation.<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 **/
13
14 #include <Uefi.h>
15
16 #include <Protocol/DriverBinding.h>
17 #include <Protocol/ServiceBinding.h>
18 #include <Protocol/SimpleNetwork.h>
19 #include <Protocol/HiiConfigRouting.h>
20 #include <Protocol/ComponentName.h>
21 #include <Protocol/ComponentName2.h>
22
23 #include <Guid/NicIp4ConfigNvData.h>
24
25 #include <Library/NetLib.h>
26 #include <Library/BaseLib.h>
27 #include <Library/DebugLib.h>
28 #include <Library/BaseMemoryLib.h>
29 #include <Library/UefiBootServicesTableLib.h>
30 #include <Library/UefiRuntimeServicesTableLib.h>
31 #include <Library/MemoryAllocationLib.h>
32 #include <Library/DevicePathLib.h>
33 #include <Library/HiiLib.h>
34 #include <Library/PrintLib.h>
35
36 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mNetLibHexStr[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
37
38 #define NIC_ITEM_CONFIG_SIZE sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * MAX_IP4_CONFIG_IN_VARIABLE
39
40 //
41 // All the supported IP4 maskes in host byte order.
42 //
43 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
82 EFI_IPv4_ADDRESS mZeroIp4Addr = {{0, 0, 0, 0}};
83
84 /**
85 Return the length of the mask.
86
87 Return the length of the mask, the correct value is from 0 to 32.
88 If the mask is invalid, return the invalid length 33, which is IP4_MASK_NUM.
89 NetMask is in the host byte order.
90
91 @param[in] NetMask The netmask to get the length from.
92
93 @return The length of the netmask, IP4_MASK_NUM if the mask is invalid.
94
95 **/
96 INTN
97 EFIAPI
98 NetGetMaskLength (
99 IN IP4_ADDR NetMask
100 )
101 {
102 INTN Index;
103
104 for (Index = 0; Index < IP4_MASK_NUM; Index++) {
105 if (NetMask == gIp4AllMasks[Index]) {
106 break;
107 }
108 }
109
110 return Index;
111 }
112
113
114
115 /**
116 Return the class of the IP address, such as class A, B, C.
117 Addr is in host byte order.
118
119 The address of class A starts with 0.
120 If the address belong to class A, return IP4_ADDR_CLASSA.
121 The address of class B starts with 10.
122 If the address belong to class B, return IP4_ADDR_CLASSB.
123 The address of class C starts with 110.
124 If the address belong to class C, return IP4_ADDR_CLASSC.
125 The address of class D starts with 1110.
126 If the address belong to class D, return IP4_ADDR_CLASSD.
127 The address of class E starts with 1111.
128 If the address belong to class E, return IP4_ADDR_CLASSE.
129
130
131 @param[in] Addr The address to get the class from.
132
133 @return IP address class, such as IP4_ADDR_CLASSA.
134
135 **/
136 INTN
137 EFIAPI
138 NetGetIpClass (
139 IN IP4_ADDR Addr
140 )
141 {
142 UINT8 ByteOne;
143
144 ByteOne = (UINT8) (Addr >> 24);
145
146 if ((ByteOne & 0x80) == 0) {
147 return IP4_ADDR_CLASSA;
148
149 } else if ((ByteOne & 0xC0) == 0x80) {
150 return IP4_ADDR_CLASSB;
151
152 } else if ((ByteOne & 0xE0) == 0xC0) {
153 return IP4_ADDR_CLASSC;
154
155 } else if ((ByteOne & 0xF0) == 0xE0) {
156 return IP4_ADDR_CLASSD;
157
158 } else {
159 return IP4_ADDR_CLASSE;
160
161 }
162 }
163
164
165 /**
166 Check whether the IP is a valid unicast address according to
167 the netmask. If NetMask is zero, use the IP address's class to get the default mask.
168
169 If Ip is 0, IP is not a valid unicast address.
170 Class D address is used for multicasting and class E address is reserved for future. If Ip
171 belongs to class D or class E, IP is not a valid unicast address.
172 If all bits of the host address of IP are 0 or 1, IP is also not a valid unicast address.
173
174 @param[in] Ip The IP to check against.
175 @param[in] NetMask The mask of the IP.
176
177 @return TRUE if IP is a valid unicast address on the network, otherwise FALSE.
178
179 **/
180 BOOLEAN
181 EFIAPI
182 Ip4IsUnicast (
183 IN IP4_ADDR Ip,
184 IN IP4_ADDR NetMask
185 )
186 {
187 INTN Class;
188
189 Class = NetGetIpClass (Ip);
190
191 if ((Ip == 0) || (Class >= IP4_ADDR_CLASSD)) {
192 return FALSE;
193 }
194
195 if (NetMask == 0) {
196 NetMask = gIp4AllMasks[Class << 3];
197 }
198
199 if (((Ip &~NetMask) == ~NetMask) || ((Ip &~NetMask) == 0)) {
200 return FALSE;
201 }
202
203 return TRUE;
204 }
205
206 /**
207 Check whether the incoming IPv6 address is a valid unicast address.
208
209 If the address is a multicast address has binary 0xFF at the start, it is not
210 a valid unicast address. If the address is unspecified ::, it is not a valid
211 unicast address to be assigned to any node. If the address is loopback address
212 ::1, it is also not a valid unicast address to be assigned to any physical
213 interface.
214
215 @param[in] Ip6 The IPv6 address to check against.
216
217 @return TRUE if Ip6 is a valid unicast address on the network, otherwise FALSE.
218
219 **/
220 BOOLEAN
221 Ip6IsValidUnicast (
222 IN EFI_IPv6_ADDRESS *Ip6
223 )
224 {
225 UINT8 Byte;
226 UINT8 Index;
227
228 if (Ip6->Addr[0] == 0xFF) {
229 return FALSE;
230 }
231
232 for (Index = 0; Index < 15; Index++) {
233 if (Ip6->Addr[Index] != 0) {
234 return TRUE;
235 }
236 }
237
238 Byte = Ip6->Addr[Index];
239
240 if (Byte == 0x0 || Byte == 0x1) {
241 return FALSE;
242 }
243
244 return TRUE;
245 }
246
247 /**
248 Switches the endianess of an IPv6 address
249
250 This function swaps the bytes in a 128-bit IPv6 address to switch the value
251 from little endian to big endian or vice versa. The byte swapped value is
252 returned.
253
254 @param Ip6 Points to an IPv6 address
255
256 @return The byte swapped IPv6 address.
257
258 **/
259 EFI_IPv6_ADDRESS *
260 Ip6Swap128 (
261 EFI_IPv6_ADDRESS *Ip6
262 )
263 {
264 UINT64 High;
265 UINT64 Low;
266
267 CopyMem (&High, Ip6, sizeof (UINT64));
268 CopyMem (&Low, &Ip6->Addr[8], sizeof (UINT64));
269
270 High = SwapBytes64 (High);
271 Low = SwapBytes64 (Low);
272
273 CopyMem (Ip6, &Low, sizeof (UINT64));
274 CopyMem (&Ip6->Addr[8], &High, sizeof (UINT64));
275
276 return Ip6;
277 }
278
279 /**
280 Initialize a random seed using current time.
281
282 Get current time first. Then initialize a random seed based on some basic
283 mathematics operation on the hour, day, minute, second, nanosecond and year
284 of the current time.
285
286 @return The random seed initialized with current time.
287
288 **/
289 UINT32
290 EFIAPI
291 NetRandomInitSeed (
292 VOID
293 )
294 {
295 EFI_TIME Time;
296 UINT32 Seed;
297
298 gRT->GetTime (&Time, NULL);
299 Seed = (~Time.Hour << 24 | Time.Day << 16 | Time.Minute << 8 | Time.Second);
300 Seed ^= Time.Nanosecond;
301 Seed ^= Time.Year << 7;
302
303 return Seed;
304 }
305
306
307 /**
308 Extract a UINT32 from a byte stream.
309
310 Copy a UINT32 from a byte stream, then converts it from Network
311 byte order to host byte order. Use this function to avoid alignment error.
312
313 @param[in] Buf The buffer to extract the UINT32.
314
315 @return The UINT32 extracted.
316
317 **/
318 UINT32
319 EFIAPI
320 NetGetUint32 (
321 IN UINT8 *Buf
322 )
323 {
324 UINT32 Value;
325
326 CopyMem (&Value, Buf, sizeof (UINT32));
327 return NTOHL (Value);
328 }
329
330
331 /**
332 Put a UINT32 to the byte stream in network byte order.
333
334 Converts a UINT32 from host byte order to network byte order. Then copy it to the
335 byte stream.
336
337 @param[in, out] Buf The buffer to put the UINT32.
338 @param[in] Data The data to put.
339
340 **/
341 VOID
342 EFIAPI
343 NetPutUint32 (
344 IN OUT UINT8 *Buf,
345 IN UINT32 Data
346 )
347 {
348 Data = HTONL (Data);
349 CopyMem (Buf, &Data, sizeof (UINT32));
350 }
351
352
353 /**
354 Remove the first node entry on the list, and return the removed node entry.
355
356 Removes the first node Entry from a doubly linked list. It is up to the caller of
357 this function to release the memory used by the first node if that is required. On
358 exit, the removed node is returned.
359
360 If Head is NULL, then ASSERT().
361 If Head was not initialized, then ASSERT().
362 If PcdMaximumLinkedListLength is not zero, and the number of nodes in the
363 linked list including the head node is greater than or equal to PcdMaximumLinkedListLength,
364 then ASSERT().
365
366 @param[in, out] Head The list header.
367
368 @return The first node entry that is removed from the list, NULL if the list is empty.
369
370 **/
371 LIST_ENTRY *
372 EFIAPI
373 NetListRemoveHead (
374 IN OUT LIST_ENTRY *Head
375 )
376 {
377 LIST_ENTRY *First;
378
379 ASSERT (Head != NULL);
380
381 if (IsListEmpty (Head)) {
382 return NULL;
383 }
384
385 First = Head->ForwardLink;
386 Head->ForwardLink = First->ForwardLink;
387 First->ForwardLink->BackLink = Head;
388
389 DEBUG_CODE (
390 First->ForwardLink = (LIST_ENTRY *) NULL;
391 First->BackLink = (LIST_ENTRY *) NULL;
392 );
393
394 return First;
395 }
396
397
398 /**
399 Remove the last node entry on the list and and return the removed node entry.
400
401 Removes the last node entry from a doubly linked list. It is up to the caller of
402 this function to release the memory used by the first node if that is required. On
403 exit, the removed node is returned.
404
405 If Head is NULL, then ASSERT().
406 If Head was not initialized, then ASSERT().
407 If PcdMaximumLinkedListLength is not zero, and the number of nodes in the
408 linked list including the head node is greater than or equal to PcdMaximumLinkedListLength,
409 then ASSERT().
410
411 @param[in, out] Head The list head.
412
413 @return The last node entry that is removed from the list, NULL if the list is empty.
414
415 **/
416 LIST_ENTRY *
417 EFIAPI
418 NetListRemoveTail (
419 IN OUT LIST_ENTRY *Head
420 )
421 {
422 LIST_ENTRY *Last;
423
424 ASSERT (Head != NULL);
425
426 if (IsListEmpty (Head)) {
427 return NULL;
428 }
429
430 Last = Head->BackLink;
431 Head->BackLink = Last->BackLink;
432 Last->BackLink->ForwardLink = Head;
433
434 DEBUG_CODE (
435 Last->ForwardLink = (LIST_ENTRY *) NULL;
436 Last->BackLink = (LIST_ENTRY *) NULL;
437 );
438
439 return Last;
440 }
441
442
443 /**
444 Insert a new node entry after a designated node entry of a doubly linked list.
445
446 Inserts a new node entry donated by NewEntry after the node entry donated by PrevEntry
447 of the doubly linked list.
448
449 @param[in, out] PrevEntry The previous entry to insert after.
450 @param[in, out] NewEntry The new entry to insert.
451
452 **/
453 VOID
454 EFIAPI
455 NetListInsertAfter (
456 IN OUT LIST_ENTRY *PrevEntry,
457 IN OUT LIST_ENTRY *NewEntry
458 )
459 {
460 NewEntry->BackLink = PrevEntry;
461 NewEntry->ForwardLink = PrevEntry->ForwardLink;
462 PrevEntry->ForwardLink->BackLink = NewEntry;
463 PrevEntry->ForwardLink = NewEntry;
464 }
465
466
467 /**
468 Insert a new node entry before a designated node entry of a doubly linked list.
469
470 Inserts a new node entry donated by NewEntry after the node entry donated by PostEntry
471 of the doubly linked list.
472
473 @param[in, out] PostEntry The entry to insert before.
474 @param[in, out] NewEntry The new entry to insert.
475
476 **/
477 VOID
478 EFIAPI
479 NetListInsertBefore (
480 IN OUT LIST_ENTRY *PostEntry,
481 IN OUT LIST_ENTRY *NewEntry
482 )
483 {
484 NewEntry->ForwardLink = PostEntry;
485 NewEntry->BackLink = PostEntry->BackLink;
486 PostEntry->BackLink->ForwardLink = NewEntry;
487 PostEntry->BackLink = NewEntry;
488 }
489
490
491 /**
492 Initialize the netmap. Netmap is a reposity to keep the <Key, Value> pairs.
493
494 Initialize the forward and backward links of two head nodes donated by Map->Used
495 and Map->Recycled of two doubly linked lists.
496 Initializes the count of the <Key, Value> pairs in the netmap to zero.
497
498 If Map is NULL, then ASSERT().
499 If the address of Map->Used is NULL, then ASSERT().
500 If the address of Map->Recycled is NULl, then ASSERT().
501
502 @param[in, out] Map The netmap to initialize.
503
504 **/
505 VOID
506 EFIAPI
507 NetMapInit (
508 IN OUT NET_MAP *Map
509 )
510 {
511 ASSERT (Map != NULL);
512
513 InitializeListHead (&Map->Used);
514 InitializeListHead (&Map->Recycled);
515 Map->Count = 0;
516 }
517
518
519 /**
520 To clean up the netmap, that is, release allocated memories.
521
522 Removes all nodes of the Used doubly linked list and free memory of all related netmap items.
523 Removes all nodes of the Recycled doubly linked list and free memory of all related netmap items.
524 The number of the <Key, Value> pairs in the netmap is set to be zero.
525
526 If Map is NULL, then ASSERT().
527
528 @param[in, out] Map The netmap to clean up.
529
530 **/
531 VOID
532 EFIAPI
533 NetMapClean (
534 IN OUT NET_MAP *Map
535 )
536 {
537 NET_MAP_ITEM *Item;
538 LIST_ENTRY *Entry;
539 LIST_ENTRY *Next;
540
541 ASSERT (Map != NULL);
542
543 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Map->Used) {
544 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
545
546 RemoveEntryList (&Item->Link);
547 Map->Count--;
548
549 gBS->FreePool (Item);
550 }
551
552 ASSERT ((Map->Count == 0) && IsListEmpty (&Map->Used));
553
554 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Map->Recycled) {
555 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
556
557 RemoveEntryList (&Item->Link);
558 gBS->FreePool (Item);
559 }
560
561 ASSERT (IsListEmpty (&Map->Recycled));
562 }
563
564
565 /**
566 Test whether the netmap is empty and return true if it is.
567
568 If the number of the <Key, Value> pairs in the netmap is zero, return TRUE.
569
570 If Map is NULL, then ASSERT().
571
572
573 @param[in] Map The net map to test.
574
575 @return TRUE if the netmap is empty, otherwise FALSE.
576
577 **/
578 BOOLEAN
579 EFIAPI
580 NetMapIsEmpty (
581 IN NET_MAP *Map
582 )
583 {
584 ASSERT (Map != NULL);
585 return (BOOLEAN) (Map->Count == 0);
586 }
587
588
589 /**
590 Return the number of the <Key, Value> pairs in the netmap.
591
592 @param[in] Map The netmap to get the entry number.
593
594 @return The entry number in the netmap.
595
596 **/
597 UINTN
598 EFIAPI
599 NetMapGetCount (
600 IN NET_MAP *Map
601 )
602 {
603 return Map->Count;
604 }
605
606
607 /**
608 Return one allocated item.
609
610 If the Recycled doubly linked list of the netmap is empty, it will try to allocate
611 a batch of items if there are enough resources and add corresponding nodes to the begining
612 of the Recycled doubly linked list of the netmap. Otherwise, it will directly remove
613 the fist node entry of the Recycled doubly linked list and return the corresponding item.
614
615 If Map is NULL, then ASSERT().
616
617 @param[in, out] Map The netmap to allocate item for.
618
619 @return The allocated item. If NULL, the
620 allocation failed due to resource limit.
621
622 **/
623 NET_MAP_ITEM *
624 NetMapAllocItem (
625 IN OUT NET_MAP *Map
626 )
627 {
628 NET_MAP_ITEM *Item;
629 LIST_ENTRY *Head;
630 UINTN Index;
631
632 ASSERT (Map != NULL);
633
634 Head = &Map->Recycled;
635
636 if (IsListEmpty (Head)) {
637 for (Index = 0; Index < NET_MAP_INCREAMENT; Index++) {
638 Item = AllocatePool (sizeof (NET_MAP_ITEM));
639
640 if (Item == NULL) {
641 if (Index == 0) {
642 return NULL;
643 }
644
645 break;
646 }
647
648 InsertHeadList (Head, &Item->Link);
649 }
650 }
651
652 Item = NET_LIST_HEAD (Head, NET_MAP_ITEM, Link);
653 NetListRemoveHead (Head);
654
655 return Item;
656 }
657
658
659 /**
660 Allocate an item to save the <Key, Value> pair to the head of the netmap.
661
662 Allocate an item to save the <Key, Value> pair and add corresponding node entry
663 to the beginning of the Used doubly linked list. The number of the <Key, Value>
664 pairs in the netmap increase by 1.
665
666 If Map is NULL, then ASSERT().
667
668 @param[in, out] Map The netmap to insert into.
669 @param[in] Key The user's key.
670 @param[in] Value The user's value for the key.
671
672 @retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the item.
673 @retval EFI_SUCCESS The item is inserted to the head.
674
675 **/
676 EFI_STATUS
677 EFIAPI
678 NetMapInsertHead (
679 IN OUT NET_MAP *Map,
680 IN VOID *Key,
681 IN VOID *Value OPTIONAL
682 )
683 {
684 NET_MAP_ITEM *Item;
685
686 ASSERT (Map != NULL);
687
688 Item = NetMapAllocItem (Map);
689
690 if (Item == NULL) {
691 return EFI_OUT_OF_RESOURCES;
692 }
693
694 Item->Key = Key;
695 Item->Value = Value;
696 InsertHeadList (&Map->Used, &Item->Link);
697
698 Map->Count++;
699 return EFI_SUCCESS;
700 }
701
702
703 /**
704 Allocate an item to save the <Key, Value> pair to the tail of the netmap.
705
706 Allocate an item to save the <Key, Value> pair and add corresponding node entry
707 to the tail of the Used doubly linked list. The number of the <Key, Value>
708 pairs in the netmap increase by 1.
709
710 If Map is NULL, then ASSERT().
711
712 @param[in, out] Map The netmap to insert into.
713 @param[in] Key The user's key.
714 @param[in] Value The user's value for the key.
715
716 @retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the item.
717 @retval EFI_SUCCESS The item is inserted to the tail.
718
719 **/
720 EFI_STATUS
721 EFIAPI
722 NetMapInsertTail (
723 IN OUT NET_MAP *Map,
724 IN VOID *Key,
725 IN VOID *Value OPTIONAL
726 )
727 {
728 NET_MAP_ITEM *Item;
729
730 ASSERT (Map != NULL);
731
732 Item = NetMapAllocItem (Map);
733
734 if (Item == NULL) {
735 return EFI_OUT_OF_RESOURCES;
736 }
737
738 Item->Key = Key;
739 Item->Value = Value;
740 InsertTailList (&Map->Used, &Item->Link);
741
742 Map->Count++;
743
744 return EFI_SUCCESS;
745 }
746
747
748 /**
749 Check whether the item is in the Map and return TRUE if it is.
750
751 @param[in] Map The netmap to search within.
752 @param[in] Item The item to search.
753
754 @return TRUE if the item is in the netmap, otherwise FALSE.
755
756 **/
757 BOOLEAN
758 NetItemInMap (
759 IN NET_MAP *Map,
760 IN NET_MAP_ITEM *Item
761 )
762 {
763 LIST_ENTRY *ListEntry;
764
765 NET_LIST_FOR_EACH (ListEntry, &Map->Used) {
766 if (ListEntry == &Item->Link) {
767 return TRUE;
768 }
769 }
770
771 return FALSE;
772 }
773
774
775 /**
776 Find the key in the netmap and returns the point to the item contains the Key.
777
778 Iterate the Used doubly linked list of the netmap to get every item. Compare the key of every
779 item with the key to search. It returns the point to the item contains the Key if found.
780
781 If Map is NULL, then ASSERT().
782
783 @param[in] Map The netmap to search within.
784 @param[in] Key The key to search.
785
786 @return The point to the item contains the Key, or NULL if Key isn't in the map.
787
788 **/
789 NET_MAP_ITEM *
790 EFIAPI
791 NetMapFindKey (
792 IN NET_MAP *Map,
793 IN VOID *Key
794 )
795 {
796 LIST_ENTRY *Entry;
797 NET_MAP_ITEM *Item;
798
799 ASSERT (Map != NULL);
800
801 NET_LIST_FOR_EACH (Entry, &Map->Used) {
802 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
803
804 if (Item->Key == Key) {
805 return Item;
806 }
807 }
808
809 return NULL;
810 }
811
812
813 /**
814 Remove the node entry of the item from the netmap and return the key of the removed item.
815
816 Remove the node entry of the item from the Used doubly linked list of the netmap.
817 The number of the <Key, Value> pairs in the netmap decrease by 1. Then add the node
818 entry of the item to the Recycled doubly linked list of the netmap. If Value is not NULL,
819 Value will point to the value of the item. It returns the key of the removed item.
820
821 If Map is NULL, then ASSERT().
822 If Item is NULL, then ASSERT().
823 if item in not in the netmap, then ASSERT().
824
825 @param[in, out] Map The netmap to remove the item from.
826 @param[in, out] Item The item to remove.
827 @param[out] Value The variable to receive the value if not NULL.
828
829 @return The key of the removed item.
830
831 **/
832 VOID *
833 EFIAPI
834 NetMapRemoveItem (
835 IN OUT NET_MAP *Map,
836 IN OUT NET_MAP_ITEM *Item,
837 OUT VOID **Value OPTIONAL
838 )
839 {
840 ASSERT ((Map != NULL) && (Item != NULL));
841 ASSERT (NetItemInMap (Map, Item));
842
843 RemoveEntryList (&Item->Link);
844 Map->Count--;
845 InsertHeadList (&Map->Recycled, &Item->Link);
846
847 if (Value != NULL) {
848 *Value = Item->Value;
849 }
850
851 return Item->Key;
852 }
853
854
855 /**
856 Remove the first node entry on the netmap and return the key of the removed item.
857
858 Remove the first node entry from the Used doubly linked list of the netmap.
859 The number of the <Key, Value> pairs in the netmap decrease by 1. Then add the node
860 entry to the Recycled doubly linked list of the netmap. If parameter Value is not NULL,
861 parameter Value will point to the value of the item. It returns the key of the removed item.
862
863 If Map is NULL, then ASSERT().
864 If the Used doubly linked list is empty, then ASSERT().
865
866 @param[in, out] Map The netmap to remove the head from.
867 @param[out] Value The variable to receive the value if not NULL.
868
869 @return The key of the item removed.
870
871 **/
872 VOID *
873 EFIAPI
874 NetMapRemoveHead (
875 IN OUT NET_MAP *Map,
876 OUT VOID **Value OPTIONAL
877 )
878 {
879 NET_MAP_ITEM *Item;
880
881 //
882 // Often, it indicates a programming error to remove
883 // the first entry in an empty list
884 //
885 ASSERT (Map && !IsListEmpty (&Map->Used));
886
887 Item = NET_LIST_HEAD (&Map->Used, NET_MAP_ITEM, Link);
888 RemoveEntryList (&Item->Link);
889 Map->Count--;
890 InsertHeadList (&Map->Recycled, &Item->Link);
891
892 if (Value != NULL) {
893 *Value = Item->Value;
894 }
895
896 return Item->Key;
897 }
898
899
900 /**
901 Remove the last node entry on the netmap and return the key of the removed item.
902
903 Remove the last node entry from the Used doubly linked list of the netmap.
904 The number of the <Key, Value> pairs in the netmap decrease by 1. Then add the node
905 entry to the Recycled doubly linked list of the netmap. If parameter Value is not NULL,
906 parameter Value will point to the value of the item. It returns the key of the removed item.
907
908 If Map is NULL, then ASSERT().
909 If the Used doubly linked list is empty, then ASSERT().
910
911 @param[in, out] Map The netmap to remove the tail from.
912 @param[out] Value The variable to receive the value if not NULL.
913
914 @return The key of the item removed.
915
916 **/
917 VOID *
918 EFIAPI
919 NetMapRemoveTail (
920 IN OUT NET_MAP *Map,
921 OUT VOID **Value OPTIONAL
922 )
923 {
924 NET_MAP_ITEM *Item;
925
926 //
927 // Often, it indicates a programming error to remove
928 // the last entry in an empty list
929 //
930 ASSERT (Map && !IsListEmpty (&Map->Used));
931
932 Item = NET_LIST_TAIL (&Map->Used, NET_MAP_ITEM, Link);
933 RemoveEntryList (&Item->Link);
934 Map->Count--;
935 InsertHeadList (&Map->Recycled, &Item->Link);
936
937 if (Value != NULL) {
938 *Value = Item->Value;
939 }
940
941 return Item->Key;
942 }
943
944
945 /**
946 Iterate through the netmap and call CallBack for each item.
947
948 It will contiue the traverse if CallBack returns EFI_SUCCESS, otherwise, break
949 from the loop. It returns the CallBack's last return value. This function is
950 delete safe for the current item.
951
952 If Map is NULL, then ASSERT().
953 If CallBack is NULL, then ASSERT().
954
955 @param[in] Map The Map to iterate through.
956 @param[in] CallBack The callback function to call for each item.
957 @param[in] Arg The opaque parameter to the callback.
958
959 @retval EFI_SUCCESS There is no item in the netmap or CallBack for each item
960 return EFI_SUCCESS.
961 @retval Others It returns the CallBack's last return value.
962
963 **/
964 EFI_STATUS
965 EFIAPI
966 NetMapIterate (
967 IN NET_MAP *Map,
968 IN NET_MAP_CALLBACK CallBack,
969 IN VOID *Arg
970 )
971 {
972
973 LIST_ENTRY *Entry;
974 LIST_ENTRY *Next;
975 LIST_ENTRY *Head;
976 NET_MAP_ITEM *Item;
977 EFI_STATUS Result;
978
979 ASSERT ((Map != NULL) && (CallBack != NULL));
980
981 Head = &Map->Used;
982
983 if (IsListEmpty (Head)) {
984 return EFI_SUCCESS;
985 }
986
987 NET_LIST_FOR_EACH_SAFE (Entry, Next, Head) {
988 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
989 Result = CallBack (Map, Item, Arg);
990
991 if (EFI_ERROR (Result)) {
992 return Result;
993 }
994 }
995
996 return EFI_SUCCESS;
997 }
998
999
1000 /**
1001 This is the default unload handle for all the network drivers.
1002
1003 Disconnect the driver specified by ImageHandle from all the devices in the handle database.
1004 Uninstall all the protocols installed in the driver entry point.
1005
1006 @param[in] ImageHandle The drivers' driver image.
1007
1008 @retval EFI_SUCCESS The image is unloaded.
1009 @retval Others Failed to unload the image.
1010
1011 **/
1012 EFI_STATUS
1013 EFIAPI
1014 NetLibDefaultUnload (
1015 IN EFI_HANDLE ImageHandle
1016 )
1017 {
1018 EFI_STATUS Status;
1019 EFI_HANDLE *DeviceHandleBuffer;
1020 UINTN DeviceHandleCount;
1021 UINTN Index;
1022 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
1023 EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
1024 EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;
1025
1026 //
1027 // Get the list of all the handles in the handle database.
1028 // If there is an error getting the list, then the unload
1029 // operation fails.
1030 //
1031 Status = gBS->LocateHandleBuffer (
1032 AllHandles,
1033 NULL,
1034 NULL,
1035 &DeviceHandleCount,
1036 &DeviceHandleBuffer
1037 );
1038
1039 if (EFI_ERROR (Status)) {
1040 return Status;
1041 }
1042
1043 //
1044 // Disconnect the driver specified by ImageHandle from all
1045 // the devices in the handle database.
1046 //
1047 for (Index = 0; Index < DeviceHandleCount; Index++) {
1048 Status = gBS->DisconnectController (
1049 DeviceHandleBuffer[Index],
1050 ImageHandle,
1051 NULL
1052 );
1053 }
1054
1055 //
1056 // Uninstall all the protocols installed in the driver entry point
1057 //
1058 for (Index = 0; Index < DeviceHandleCount; Index++) {
1059 Status = gBS->HandleProtocol (
1060 DeviceHandleBuffer[Index],
1061 &gEfiDriverBindingProtocolGuid,
1062 (VOID **) &DriverBinding
1063 );
1064
1065 if (EFI_ERROR (Status)) {
1066 continue;
1067 }
1068
1069 if (DriverBinding->ImageHandle != ImageHandle) {
1070 continue;
1071 }
1072
1073 gBS->UninstallProtocolInterface (
1074 ImageHandle,
1075 &gEfiDriverBindingProtocolGuid,
1076 DriverBinding
1077 );
1078 Status = gBS->HandleProtocol (
1079 DeviceHandleBuffer[Index],
1080 &gEfiComponentNameProtocolGuid,
1081 (VOID **) &ComponentName
1082 );
1083 if (!EFI_ERROR (Status)) {
1084 gBS->UninstallProtocolInterface (
1085 ImageHandle,
1086 &gEfiComponentNameProtocolGuid,
1087 ComponentName
1088 );
1089 }
1090
1091 Status = gBS->HandleProtocol (
1092 DeviceHandleBuffer[Index],
1093 &gEfiComponentName2ProtocolGuid,
1094 (VOID **) &ComponentName2
1095 );
1096 if (!EFI_ERROR (Status)) {
1097 gBS->UninstallProtocolInterface (
1098 ImageHandle,
1099 &gEfiComponentName2ProtocolGuid,
1100 ComponentName2
1101 );
1102 }
1103 }
1104
1105 //
1106 // Free the buffer containing the list of handles from the handle database
1107 //
1108 if (DeviceHandleBuffer != NULL) {
1109 gBS->FreePool (DeviceHandleBuffer);
1110 }
1111
1112 return EFI_SUCCESS;
1113 }
1114
1115
1116
1117 /**
1118 Create a child of the service that is identified by ServiceBindingGuid.
1119
1120 Get the ServiceBinding Protocol first, then use it to create a child.
1121
1122 If ServiceBindingGuid is NULL, then ASSERT().
1123 If ChildHandle is NULL, then ASSERT().
1124
1125 @param[in] Controller The controller which has the service installed.
1126 @param[in] Image The image handle used to open service.
1127 @param[in] ServiceBindingGuid The service's Guid.
1128 @param[in, out] ChildHandle The handle to receive the create child.
1129
1130 @retval EFI_SUCCESS The child is successfully created.
1131 @retval Others Failed to create the child.
1132
1133 **/
1134 EFI_STATUS
1135 EFIAPI
1136 NetLibCreateServiceChild (
1137 IN EFI_HANDLE Controller,
1138 IN EFI_HANDLE Image,
1139 IN EFI_GUID *ServiceBindingGuid,
1140 IN OUT EFI_HANDLE *ChildHandle
1141 )
1142 {
1143 EFI_STATUS Status;
1144 EFI_SERVICE_BINDING_PROTOCOL *Service;
1145
1146
1147 ASSERT ((ServiceBindingGuid != NULL) && (ChildHandle != NULL));
1148
1149 //
1150 // Get the ServiceBinding Protocol
1151 //
1152 Status = gBS->OpenProtocol (
1153 Controller,
1154 ServiceBindingGuid,
1155 (VOID **) &Service,
1156 Image,
1157 Controller,
1158 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1159 );
1160
1161 if (EFI_ERROR (Status)) {
1162 return Status;
1163 }
1164
1165 //
1166 // Create a child
1167 //
1168 Status = Service->CreateChild (Service, ChildHandle);
1169 return Status;
1170 }
1171
1172
1173 /**
1174 Destory a child of the service that is identified by ServiceBindingGuid.
1175
1176 Get the ServiceBinding Protocol first, then use it to destroy a child.
1177
1178 If ServiceBindingGuid is NULL, then ASSERT().
1179
1180 @param[in] Controller The controller which has the service installed.
1181 @param[in] Image The image handle used to open service.
1182 @param[in] ServiceBindingGuid The service's Guid.
1183 @param[in] ChildHandle The child to destory.
1184
1185 @retval EFI_SUCCESS The child is successfully destoried.
1186 @retval Others Failed to destory the child.
1187
1188 **/
1189 EFI_STATUS
1190 EFIAPI
1191 NetLibDestroyServiceChild (
1192 IN EFI_HANDLE Controller,
1193 IN EFI_HANDLE Image,
1194 IN EFI_GUID *ServiceBindingGuid,
1195 IN EFI_HANDLE ChildHandle
1196 )
1197 {
1198 EFI_STATUS Status;
1199 EFI_SERVICE_BINDING_PROTOCOL *Service;
1200
1201 ASSERT (ServiceBindingGuid != NULL);
1202
1203 //
1204 // Get the ServiceBinding Protocol
1205 //
1206 Status = gBS->OpenProtocol (
1207 Controller,
1208 ServiceBindingGuid,
1209 (VOID **) &Service,
1210 Image,
1211 Controller,
1212 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1213 );
1214
1215 if (EFI_ERROR (Status)) {
1216 return Status;
1217 }
1218
1219 //
1220 // destory the child
1221 //
1222 Status = Service->DestroyChild (Service, ChildHandle);
1223 return Status;
1224 }
1225
1226
1227 /**
1228 Convert the mac address of the simple network protocol installed on
1229 SnpHandle to a unicode string. Callers are responsible for freeing the
1230 string storage.
1231
1232 Get the mac address of the Simple Network protocol from the SnpHandle. Then convert
1233 the mac address into a unicode string. It takes 2 unicode characters to represent
1234 a 1 byte binary buffer. Plus one unicode character for the null-terminator.
1235
1236
1237 @param[in] SnpHandle The handle where the simple network protocol is
1238 installed on.
1239 @param[in] ImageHandle The image handle used to act as the agent handle to
1240 get the simple network protocol.
1241 @param[out] MacString The pointer to store the address of the string
1242 representation of the mac address.
1243
1244 @retval EFI_SUCCESS Convert the mac address a unicode string successfully.
1245 @retval EFI_OUT_OF_RESOURCES There are not enough memory resource.
1246 @retval Others Failed to open the simple network protocol.
1247
1248 **/
1249 EFI_STATUS
1250 EFIAPI
1251 NetLibGetMacString (
1252 IN EFI_HANDLE SnpHandle,
1253 IN EFI_HANDLE ImageHandle,
1254 OUT CHAR16 **MacString
1255 )
1256 {
1257 EFI_STATUS Status;
1258 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
1259 EFI_SIMPLE_NETWORK_MODE *Mode;
1260 CHAR16 *MacAddress;
1261 UINTN Index;
1262
1263 *MacString = NULL;
1264
1265 //
1266 // Get the Simple Network protocol from the SnpHandle.
1267 //
1268 Status = gBS->OpenProtocol (
1269 SnpHandle,
1270 &gEfiSimpleNetworkProtocolGuid,
1271 (VOID **) &Snp,
1272 ImageHandle,
1273 SnpHandle,
1274 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1275 );
1276 if (EFI_ERROR (Status)) {
1277 return Status;
1278 }
1279
1280 Mode = Snp->Mode;
1281
1282 //
1283 // It takes 2 unicode characters to represent a 1 byte binary buffer.
1284 // Plus one unicode character for the null-terminator.
1285 //
1286 MacAddress = AllocatePool ((2 * Mode->HwAddressSize + 1) * sizeof (CHAR16));
1287 if (MacAddress == NULL) {
1288 return EFI_OUT_OF_RESOURCES;
1289 }
1290
1291 //
1292 // Convert the mac address into a unicode string.
1293 //
1294 for (Index = 0; Index < Mode->HwAddressSize; Index++) {
1295 MacAddress[Index * 2] = (CHAR16) mNetLibHexStr[(Mode->CurrentAddress.Addr[Index] >> 4) & 0x0F];
1296 MacAddress[Index * 2 + 1] = (CHAR16) mNetLibHexStr[Mode->CurrentAddress.Addr[Index] & 0x0F];
1297 }
1298
1299 MacAddress[Mode->HwAddressSize * 2] = L'\0';
1300
1301 *MacString = MacAddress;
1302
1303 return EFI_SUCCESS;
1304 }
1305
1306 /**
1307 Check the default address used by the IPv4 driver is static or dynamic (acquired
1308 from DHCP).
1309
1310 If the controller handle does not have the NIC Ip4 Config Protocol installed, the
1311 default address is static. If the EFI variable to save the configuration is not found,
1312 the default address is static. Otherwise, get the result from the EFI variable which
1313 saving the configuration.
1314
1315 @param[in] Controller The controller handle which has the NIC Ip4 Config Protocol
1316 relative with the default address to judge.
1317
1318 @retval TRUE If the default address is static.
1319 @retval FALSE If the default address is acquired from DHCP.
1320
1321 **/
1322 BOOLEAN
1323 NetLibDefaultAddressIsStatic (
1324 IN EFI_HANDLE Controller
1325 )
1326 {
1327 EFI_STATUS Status;
1328 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
1329 UINTN Len;
1330 NIC_IP4_CONFIG_INFO *ConfigInfo;
1331 BOOLEAN IsStatic;
1332 EFI_STRING ConfigHdr;
1333 EFI_STRING ConfigResp;
1334 EFI_STRING AccessProgress;
1335 EFI_STRING AccessResults;
1336 EFI_STRING String;
1337
1338 ConfigInfo = NULL;
1339 ConfigHdr = NULL;
1340 ConfigResp = NULL;
1341 AccessProgress = NULL;
1342 AccessResults = NULL;
1343 IsStatic = TRUE;
1344
1345 Status = gBS->LocateProtocol (
1346 &gEfiHiiConfigRoutingProtocolGuid,
1347 NULL,
1348 (VOID **) &HiiConfigRouting
1349 );
1350 if (EFI_ERROR (Status)) {
1351 return TRUE;
1352 }
1353
1354 //
1355 // Construct config request string header
1356 //
1357 ConfigHdr = HiiConstructConfigHdr (&gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE, Controller);
1358 if (ConfigHdr == NULL) {
1359 return TRUE;
1360 }
1361
1362 Len = StrLen (ConfigHdr);
1363 ConfigResp = AllocateZeroPool ((Len + NIC_ITEM_CONFIG_SIZE * 2 + 100) * sizeof (CHAR16));
1364 if (ConfigResp == NULL) {
1365 goto ON_EXIT;
1366 }
1367 StrCpy (ConfigResp, ConfigHdr);
1368
1369 String = ConfigResp + Len;
1370 UnicodeSPrint (
1371 String,
1372 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16),
1373 L"&OFFSET=%04X&WIDTH=%04X",
1374 OFFSET_OF (NIC_IP4_CONFIG_INFO, Source),
1375 sizeof (UINT32)
1376 );
1377
1378 Status = HiiConfigRouting->ExtractConfig (
1379 HiiConfigRouting,
1380 ConfigResp,
1381 &AccessProgress,
1382 &AccessResults
1383 );
1384 if (EFI_ERROR (Status)) {
1385 goto ON_EXIT;
1386 }
1387
1388 ConfigInfo = AllocateZeroPool (sizeof (NIC_ITEM_CONFIG_SIZE));
1389 if (ConfigInfo == NULL) {
1390 goto ON_EXIT;
1391 }
1392
1393 ConfigInfo->Source = IP4_CONFIG_SOURCE_STATIC;
1394 Len = NIC_ITEM_CONFIG_SIZE;
1395 Status = HiiConfigRouting->ConfigToBlock (
1396 HiiConfigRouting,
1397 AccessResults,
1398 (UINT8 *) ConfigInfo,
1399 &Len,
1400 &AccessProgress
1401 );
1402 if (EFI_ERROR (Status)) {
1403 goto ON_EXIT;
1404 }
1405
1406 IsStatic = (BOOLEAN) (ConfigInfo->Source == IP4_CONFIG_SOURCE_STATIC);
1407
1408 ON_EXIT:
1409
1410 if (AccessResults != NULL) {
1411 FreePool (AccessResults);
1412 }
1413 if (ConfigInfo != NULL) {
1414 FreePool (ConfigInfo);
1415 }
1416 if (ConfigResp != NULL) {
1417 FreePool (ConfigResp);
1418 }
1419 if (ConfigHdr != NULL) {
1420 FreePool (ConfigHdr);
1421 }
1422
1423 return IsStatic;
1424 }
1425
1426 /**
1427 Create an IPv4 device path node.
1428
1429 The header type of IPv4 device path node is MESSAGING_DEVICE_PATH.
1430 The header subtype of IPv4 device path node is MSG_IPv4_DP.
1431 The length of the IPv4 device path node in bytes is 19.
1432 Get other info from parameters to make up the whole IPv4 device path node.
1433
1434 @param[in, out] Node Pointer to the IPv4 device path node.
1435 @param[in] Controller The handle where the NIC IP4 config protocol resides.
1436 @param[in] LocalIp The local IPv4 address.
1437 @param[in] LocalPort The local port.
1438 @param[in] RemoteIp The remote IPv4 address.
1439 @param[in] RemotePort The remote port.
1440 @param[in] Protocol The protocol type in the IP header.
1441 @param[in] UseDefaultAddress Whether this instance is using default address or not.
1442
1443 **/
1444 VOID
1445 EFIAPI
1446 NetLibCreateIPv4DPathNode (
1447 IN OUT IPv4_DEVICE_PATH *Node,
1448 IN EFI_HANDLE Controller,
1449 IN IP4_ADDR LocalIp,
1450 IN UINT16 LocalPort,
1451 IN IP4_ADDR RemoteIp,
1452 IN UINT16 RemotePort,
1453 IN UINT16 Protocol,
1454 IN BOOLEAN UseDefaultAddress
1455 )
1456 {
1457 Node->Header.Type = MESSAGING_DEVICE_PATH;
1458 Node->Header.SubType = MSG_IPv4_DP;
1459 SetDevicePathNodeLength (&Node->Header, 19);
1460
1461 CopyMem (&Node->LocalIpAddress, &LocalIp, sizeof (EFI_IPv4_ADDRESS));
1462 CopyMem (&Node->RemoteIpAddress, &RemoteIp, sizeof (EFI_IPv4_ADDRESS));
1463
1464 Node->LocalPort = LocalPort;
1465 Node->RemotePort = RemotePort;
1466
1467 Node->Protocol = Protocol;
1468
1469 if (!UseDefaultAddress) {
1470 Node->StaticIpAddress = TRUE;
1471 } else {
1472 Node->StaticIpAddress = NetLibDefaultAddressIsStatic (Controller);
1473 }
1474 }
1475
1476
1477 /**
1478 Find the UNDI/SNP handle from controller and protocol GUID.
1479
1480 For example, IP will open a MNP child to transmit/receive
1481 packets, when MNP is stopped, IP should also be stopped. IP
1482 needs to find its own private data which is related the IP's
1483 service binding instance that is install on UNDI/SNP handle.
1484 Now, the controller is either a MNP or ARP child handle. But
1485 IP opens these handle BY_DRIVER, use that info, we can get the
1486 UNDI/SNP handle.
1487
1488 @param[in] Controller Then protocol handle to check.
1489 @param[in] ProtocolGuid The protocol that is related with the handle.
1490
1491 @return The UNDI/SNP handle or NULL for errors.
1492
1493 **/
1494 EFI_HANDLE
1495 EFIAPI
1496 NetLibGetNicHandle (
1497 IN EFI_HANDLE Controller,
1498 IN EFI_GUID *ProtocolGuid
1499 )
1500 {
1501 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenBuffer;
1502 EFI_HANDLE Handle;
1503 EFI_STATUS Status;
1504 UINTN OpenCount;
1505 UINTN Index;
1506
1507 Status = gBS->OpenProtocolInformation (
1508 Controller,
1509 ProtocolGuid,
1510 &OpenBuffer,
1511 &OpenCount
1512 );
1513
1514 if (EFI_ERROR (Status)) {
1515 return NULL;
1516 }
1517
1518 Handle = NULL;
1519
1520 for (Index = 0; Index < OpenCount; Index++) {
1521 if (OpenBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {
1522 Handle = OpenBuffer[Index].ControllerHandle;
1523 break;
1524 }
1525 }
1526
1527 gBS->FreePool (OpenBuffer);
1528 return Handle;
1529 }