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