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