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