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