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