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