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