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