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