]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/DxeNetLib/DxeNetLib.c
1) Add BufToHexString, HexStringToBuf and IsHexDigit to BaseLib.
[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 mIp4AllMasks[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 == mIp4AllMasks[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 = mIp4AllMasks[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 STATIC
490 NET_MAP_ITEM *
491 NetMapAllocItem (
492 IN NET_MAP *Map
493 )
494 {
495 NET_MAP_ITEM *Item;
496 LIST_ENTRY *Head;
497 UINTN Index;
498
499 ASSERT (Map != NULL);
500
501 Head = &Map->Recycled;
502
503 if (IsListEmpty (Head)) {
504 for (Index = 0; Index < NET_MAP_INCREAMENT; Index++) {
505 Item = AllocatePool (sizeof (NET_MAP_ITEM));
506
507 if (Item == NULL) {
508 if (Index == 0) {
509 return NULL;
510 }
511
512 break;
513 }
514
515 InsertHeadList (Head, &Item->Link);
516 }
517 }
518
519 Item = NET_LIST_HEAD (Head, NET_MAP_ITEM, Link);
520 NetListRemoveHead (Head);
521
522 return Item;
523 }
524
525
526 /**
527 Allocate an item to save the <Key, Value> pair to the head of the netmap.
528
529 @param Map The netmap to insert into
530 @param Key The user's key
531 @param Value The user's value for the key
532
533 @retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the item
534 @retval EFI_SUCCESS The item is inserted to the head
535
536 **/
537 EFI_STATUS
538 EFIAPI
539 NetMapInsertHead (
540 IN NET_MAP *Map,
541 IN VOID *Key,
542 IN VOID *Value OPTIONAL
543 )
544 {
545 NET_MAP_ITEM *Item;
546
547 ASSERT (Map != NULL);
548
549 Item = NetMapAllocItem (Map);
550
551 if (Item == NULL) {
552 return EFI_OUT_OF_RESOURCES;
553 }
554
555 Item->Key = Key;
556 Item->Value = Value;
557 InsertHeadList (&Map->Used, &Item->Link);
558
559 Map->Count++;
560 return EFI_SUCCESS;
561 }
562
563
564 /**
565 Allocate an item to save the <Key, Value> pair to the tail of the netmap.
566
567 @param Map The netmap to insert into
568 @param Key The user's key
569 @param Value The user's value for the key
570
571 @retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the item
572 @retval EFI_SUCCESS The item is inserted to the tail
573
574 **/
575 EFI_STATUS
576 EFIAPI
577 NetMapInsertTail (
578 IN NET_MAP *Map,
579 IN VOID *Key,
580 IN VOID *Value OPTIONAL
581 )
582 {
583 NET_MAP_ITEM *Item;
584
585 ASSERT (Map != NULL);
586
587 Item = NetMapAllocItem (Map);
588
589 if (Item == NULL) {
590 return EFI_OUT_OF_RESOURCES;
591 }
592
593 Item->Key = Key;
594 Item->Value = Value;
595 InsertTailList (&Map->Used, &Item->Link);
596
597 Map->Count++;
598
599 return EFI_SUCCESS;
600 }
601
602
603 /**
604 Check whther the item is in the Map
605
606 @param Map The netmap to search within
607 @param Item The item to search
608
609 @return TRUE if the item is in the netmap, otherwise FALSE.
610
611 **/
612 STATIC
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 STATIC
1120 BOOLEAN
1121 NetLibDefaultAddressIsStatic (
1122 IN EFI_HANDLE Controller
1123 )
1124 {
1125 EFI_STATUS Status;
1126 EFI_NIC_IP4_CONFIG_PROTOCOL *NicIp4;
1127 UINTN Len;
1128 NIC_IP4_CONFIG_INFO *ConfigInfo;
1129 BOOLEAN IsStatic;
1130
1131 Status = gBS->HandleProtocol (
1132 Controller,
1133 &gEfiNicIp4ConfigProtocolGuid,
1134 (VOID **) &NicIp4
1135 );
1136 if (EFI_ERROR (Status)) {
1137 return TRUE;
1138 }
1139
1140 Len = 0;
1141 Status = NicIp4->GetInfo (NicIp4, &Len, NULL);
1142 if (Status != EFI_BUFFER_TOO_SMALL) {
1143 return TRUE;
1144 }
1145
1146 ConfigInfo = AllocatePool (Len);
1147 if (ConfigInfo == NULL) {
1148 return TRUE;
1149 }
1150
1151 IsStatic = TRUE;
1152 Status = NicIp4->GetInfo (NicIp4, &Len, ConfigInfo);
1153 if (EFI_ERROR (Status)) {
1154 goto ON_EXIT;
1155 }
1156
1157 IsStatic = (BOOLEAN) (ConfigInfo->Source == IP4_CONFIG_SOURCE_STATIC);
1158
1159 ON_EXIT:
1160
1161 gBS->FreePool (ConfigInfo);
1162
1163 return IsStatic;
1164 }
1165
1166 /**
1167 Create an IPv4 device path node.
1168
1169 @param Node Pointer to the IPv4 device path node.
1170 @param Controller The handle where the NIC IP4 config protocol resides.
1171 @param LocalIp The local IPv4 address.
1172 @param LocalPort The local port.
1173 @param RemoteIp The remote IPv4 address.
1174 @param RemotePort The remote port.
1175 @param Protocol The protocol type in the IP header.
1176 @param UseDefaultAddress Whether this instance is using default address or not.
1177
1178 @retval None
1179 **/
1180 VOID
1181 EFIAPI
1182 NetLibCreateIPv4DPathNode (
1183 IN OUT IPv4_DEVICE_PATH *Node,
1184 IN EFI_HANDLE Controller,
1185 IN IP4_ADDR LocalIp,
1186 IN UINT16 LocalPort,
1187 IN IP4_ADDR RemoteIp,
1188 IN UINT16 RemotePort,
1189 IN UINT16 Protocol,
1190 IN BOOLEAN UseDefaultAddress
1191 )
1192 {
1193 Node->Header.Type = MESSAGING_DEVICE_PATH;
1194 Node->Header.SubType = MSG_IPv4_DP;
1195 SetDevicePathNodeLength (&Node->Header, 19);
1196
1197 CopyMem (&Node->LocalIpAddress, &LocalIp, sizeof (EFI_IPv4_ADDRESS));
1198 CopyMem (&Node->RemoteIpAddress, &RemoteIp, sizeof (EFI_IPv4_ADDRESS));
1199
1200 Node->LocalPort = LocalPort;
1201 Node->RemotePort = RemotePort;
1202
1203 Node->Protocol = Protocol;
1204
1205 if (!UseDefaultAddress) {
1206 Node->StaticIpAddress = TRUE;
1207 } else {
1208 Node->StaticIpAddress = NetLibDefaultAddressIsStatic (Controller);
1209 }
1210 }
1211
1212
1213 /**
1214 Find the UNDI/SNP handle from controller and protocol GUID.
1215 For example, IP will open a MNP child to transmit/receive
1216 packets, when MNP is stopped, IP should also be stopped. IP
1217 needs to find its own private data which is related the IP's
1218 service binding instance that is install on UNDI/SNP handle.
1219 Now, the controller is either a MNP or ARP child handle. But
1220 IP opens these handle BY_DRIVER, use that info, we can get the
1221 UNDI/SNP handle.
1222
1223 @param Controller Then protocol handle to check
1224 @param ProtocolGuid The protocol that is related with the handle.
1225
1226 @return The UNDI/SNP handle or NULL.
1227
1228 **/
1229 EFI_HANDLE
1230 EFIAPI
1231 NetLibGetNicHandle (
1232 IN EFI_HANDLE Controller,
1233 IN EFI_GUID *ProtocolGuid
1234 )
1235 {
1236 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenBuffer;
1237 EFI_HANDLE Handle;
1238 EFI_STATUS Status;
1239 UINTN OpenCount;
1240 UINTN Index;
1241
1242 Status = gBS->OpenProtocolInformation (
1243 Controller,
1244 ProtocolGuid,
1245 &OpenBuffer,
1246 &OpenCount
1247 );
1248
1249 if (EFI_ERROR (Status)) {
1250 return NULL;
1251 }
1252
1253 Handle = NULL;
1254
1255 for (Index = 0; Index < OpenCount; Index++) {
1256 if (OpenBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {
1257 Handle = OpenBuffer[Index].ControllerHandle;
1258 break;
1259 }
1260 }
1261
1262 gBS->FreePool (OpenBuffer);
1263 return Handle;
1264 }
1265
1266 /**
1267 Add a Deferred Procedure Call to the end of the DPC queue.
1268
1269 @DpcTpl The EFI_TPL that the DPC should be invoked.
1270 @DpcProcedure Pointer to the DPC's function.
1271 @DpcContext Pointer to the DPC's context. Passed to DpcProcedure
1272 when DpcProcedure is invoked.
1273
1274 @retval EFI_SUCCESS The DPC was queued.
1275 @retval EFI_INVALID_PARAMETER DpcTpl is not a valid EFI_TPL.
1276 DpcProcedure is NULL.
1277 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to
1278 add the DPC to the queue.
1279
1280 **/
1281 EFI_STATUS
1282 EFIAPI
1283 NetLibQueueDpc (
1284 IN EFI_TPL DpcTpl,
1285 IN EFI_DPC_PROCEDURE DpcProcedure,
1286 IN VOID *DpcContext OPTIONAL
1287 )
1288 {
1289 return mDpc->QueueDpc (mDpc, DpcTpl, DpcProcedure, DpcContext);
1290 }
1291
1292 /**
1293 Add a Deferred Procedure Call to the end of the DPC queue.
1294
1295 @retval EFI_SUCCESS One or more DPCs were invoked.
1296 @retval EFI_NOT_FOUND No DPCs were invoked.
1297
1298 **/
1299 EFI_STATUS
1300 EFIAPI
1301 NetLibDispatchDpc (
1302 VOID
1303 )
1304 {
1305 return mDpc->DispatchDpc(mDpc);
1306 }
1307
1308
1309 /**
1310 The constructor function caches the pointer to DPC protocol.
1311
1312 The constructor function locates DPC protocol from protocol database.
1313 It will ASSERT() if that operation fails and it will always return EFI_SUCCESS.
1314
1315 @param ImageHandle The firmware allocated handle for the EFI image.
1316 @param SystemTable A pointer to the EFI System Table.
1317
1318 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
1319
1320 **/
1321 EFI_STATUS
1322 EFIAPI
1323 NetLibConstructor (
1324 IN EFI_HANDLE ImageHandle,
1325 IN EFI_SYSTEM_TABLE *SystemTable
1326 )
1327 {
1328 EFI_STATUS Status;
1329
1330 Status = gBS->LocateProtocol (&gEfiDpcProtocolGuid, NULL, (VOID**) &mDpc);
1331 ASSERT_EFI_ERROR (Status);
1332 ASSERT (mDpc != NULL);
1333
1334 return Status;
1335 }