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