0dff772b7ae73ec916f0a98baa901d0cb9f319de
[people/mcb30/edk2.git] / edk2 / 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>\r
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 /**\r
83   Converts the low nibble of a byte  to hex unicode character.\r
84 \r
85   @param  Nibble  lower nibble of a byte.\r
86 \r
87   @return Hex unicode character.\r
88 \r
89 **/\r
90 CHAR16\r
91 NibbleToHexChar (\r
92   IN UINT8      Nibble\r
93   )\r
94 {\r
95   //\r
96   // Porting Guide:\r
97   // This library interface is simply obsolete.\r
98   // Include the source code to user code.\r
99   //\r
100 \r
101   Nibble &= 0x0F;\r
102   if (Nibble <= 0x9) {\r
103     return (CHAR16)(Nibble + L'0');\r
104   }\r
105 \r
106   return (CHAR16)(Nibble - 0xA + L'A');\r
107 }\r
108 \r
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