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