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