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