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