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