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