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