1 /** @file 2 The implementation of EFI IPv4 Configuration II Protocol. 3 4 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR> 5 (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR> 6 7 SPDX-License-Identifier: BSD-2-Clause-Patent 8 9 **/ 10 11 #include "Ip4Impl.h" 12 13 LIST_ENTRY mIp4Config2InstanceList = {&mIp4Config2InstanceList, &mIp4Config2InstanceList}; 14 15 /** 16 The event process routine when the DHCPv4 service binding protocol is installed 17 in the system. 18 19 @param[in] Event Not used. 20 @param[in] Context Pointer to the IP4 config2 instance data. 21 22 **/ 23 VOID 24 EFIAPI 25 Ip4Config2OnDhcp4SbInstalled ( 26 IN EFI_EVENT Event, 27 IN VOID *Context 28 ); 29 30 /** 31 Destroy the Dhcp4 child in IP4_CONFIG2_INSTANCE and release the resources. 32 33 @param[in, out] Instance The buffer of IP4 config2 instance to be freed. 34 35 @retval EFI_SUCCESS The child was successfully destroyed. 36 @retval Others Failed to destroy the child. 37 38 **/ 39 EFI_STATUS 40 Ip4Config2DestroyDhcp4 ( 41 IN OUT IP4_CONFIG2_INSTANCE *Instance 42 ) 43 { 44 IP4_SERVICE *IpSb; 45 EFI_STATUS Status; 46 EFI_DHCP4_PROTOCOL *Dhcp4; 47 48 Dhcp4 = Instance->Dhcp4; 49 ASSERT (Dhcp4 != NULL); 50 51 Dhcp4->Stop (Dhcp4); 52 Dhcp4->Configure (Dhcp4, NULL); 53 Instance->Dhcp4 = NULL; 54 55 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance); 56 57 // 58 // Close DHCPv4 protocol and destroy the child. 59 // 60 Status = gBS->CloseProtocol ( 61 Instance->Dhcp4Handle, 62 &gEfiDhcp4ProtocolGuid, 63 IpSb->Image, 64 IpSb->Controller 65 ); 66 if (EFI_ERROR (Status)) { 67 return Status; 68 } 69 70 Status = NetLibDestroyServiceChild ( 71 IpSb->Controller, 72 IpSb->Image, 73 &gEfiDhcp4ServiceBindingProtocolGuid, 74 Instance->Dhcp4Handle 75 ); 76 77 Instance->Dhcp4Handle = NULL; 78 79 return Status; 80 } 81 82 /** 83 Update the current policy to NewPolicy. During the transition 84 period, the default router list 85 and address list in all interfaces will be released. 86 87 @param[in] IpSb The IP4 service binding instance. 88 @param[in] NewPolicy The new policy to be updated to. 89 90 **/ 91 VOID 92 Ip4Config2OnPolicyChanged ( 93 IN IP4_SERVICE *IpSb, 94 IN EFI_IP4_CONFIG2_POLICY NewPolicy 95 ) 96 { 97 IP4_INTERFACE *IpIf; 98 IP4_ROUTE_TABLE *RouteTable; 99 100 // 101 // Currently there are only two policies: static and dhcp. Regardless of 102 // what transition is going on, i.e., static -> dhcp and dhcp -> 103 // static, we have to free default router table and all addresses. 104 // 105 106 if (IpSb->DefaultInterface != NULL) { 107 if (IpSb->DefaultRouteTable != NULL) { 108 Ip4FreeRouteTable (IpSb->DefaultRouteTable); 109 IpSb->DefaultRouteTable = NULL; 110 } 111 112 Ip4CancelReceive (IpSb->DefaultInterface); 113 114 Ip4FreeInterface (IpSb->DefaultInterface, NULL); 115 IpSb->DefaultInterface = NULL; 116 } 117 118 Ip4CleanAssembleTable (&IpSb->Assemble); 119 120 // 121 // Create new default interface and route table. 122 // 123 IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image); 124 if (IpIf == NULL) { 125 return ; 126 } 127 128 RouteTable = Ip4CreateRouteTable (); 129 if (RouteTable == NULL) { 130 Ip4FreeInterface (IpIf, NULL); 131 return ; 132 } 133 134 IpSb->DefaultInterface = IpIf; 135 InsertHeadList (&IpSb->Interfaces, &IpIf->Link); 136 IpSb->DefaultRouteTable = RouteTable; 137 Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb); 138 139 if (IpSb->State == IP4_SERVICE_CONFIGED || IpSb->State == IP4_SERVICE_STARTED) { 140 IpSb->State = IP4_SERVICE_UNSTARTED; 141 } 142 143 // 144 // Start the dhcp configuration. 145 // 146 if (NewPolicy == Ip4Config2PolicyDhcp) { 147 Ip4StartAutoConfig (&IpSb->Ip4Config2Instance); 148 } 149 150 } 151 152 /** 153 Signal the registered event. It is the callback routine for NetMapIterate. 154 155 @param[in] Map Points to the list of registered event. 156 @param[in] Item The registered event. 157 @param[in] Arg Not used. 158 159 @retval EFI_SUCCESS The event was signaled successfully. 160 **/ 161 EFI_STATUS 162 EFIAPI 163 Ip4Config2SignalEvent ( 164 IN NET_MAP *Map, 165 IN NET_MAP_ITEM *Item, 166 IN VOID *Arg 167 ) 168 { 169 gBS->SignalEvent ((EFI_EVENT) Item->Key); 170 171 return EFI_SUCCESS; 172 } 173 174 /** 175 Read the configuration data from variable storage according to the VarName and 176 gEfiIp4Config2ProtocolGuid. It checks the integrity of variable data. If the 177 data is corrupted, it clears the variable data to ZERO. Otherwise, it outputs the 178 configuration data to IP4_CONFIG2_INSTANCE. 179 180 @param[in] VarName The pointer to the variable name 181 @param[in, out] Instance The pointer to the IP4 config2 instance data. 182 183 @retval EFI_NOT_FOUND The variable can not be found or already corrupted. 184 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation. 185 @retval EFI_SUCCESS The configuration data was retrieved successfully. 186 187 **/ 188 EFI_STATUS 189 Ip4Config2ReadConfigData ( 190 IN CHAR16 *VarName, 191 IN OUT IP4_CONFIG2_INSTANCE *Instance 192 ) 193 { 194 EFI_STATUS Status; 195 UINTN VarSize; 196 IP4_CONFIG2_VARIABLE *Variable; 197 IP4_CONFIG2_DATA_ITEM *DataItem; 198 UINTN Index; 199 IP4_CONFIG2_DATA_RECORD DataRecord; 200 CHAR8 *Data; 201 202 // 203 // Try to read the configuration variable. 204 // 205 VarSize = 0; 206 Status = gRT->GetVariable ( 207 VarName, 208 &gEfiIp4Config2ProtocolGuid, 209 NULL, 210 &VarSize, 211 NULL 212 ); 213 214 if (Status == EFI_BUFFER_TOO_SMALL) { 215 // 216 // Allocate buffer and read the config variable. 217 // 218 Variable = AllocatePool (VarSize); 219 if (Variable == NULL) { 220 return EFI_OUT_OF_RESOURCES; 221 } 222 223 Status = gRT->GetVariable ( 224 VarName, 225 &gEfiIp4Config2ProtocolGuid, 226 NULL, 227 &VarSize, 228 Variable 229 ); 230 if (EFI_ERROR (Status) || (UINT16) (~NetblockChecksum ((UINT8 *) Variable, (UINT32) VarSize)) != 0) { 231 // 232 // GetVariable still error or the variable is corrupted. 233 // Fall back to the default value. 234 // 235 FreePool (Variable); 236 237 // 238 // Remove the problematic variable and return EFI_NOT_FOUND, a new 239 // variable will be set again. 240 // 241 gRT->SetVariable ( 242 VarName, 243 &gEfiIp4Config2ProtocolGuid, 244 IP4_CONFIG2_VARIABLE_ATTRIBUTE, 245 0, 246 NULL 247 ); 248 249 return EFI_NOT_FOUND; 250 } 251 252 253 for (Index = 0; Index < Variable->DataRecordCount; Index++) { 254 255 CopyMem (&DataRecord, &Variable->DataRecord[Index], sizeof (DataRecord)); 256 257 DataItem = &Instance->DataItem[DataRecord.DataType]; 258 if (DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED) && 259 (DataItem->DataSize != DataRecord.DataSize) 260 ) { 261 // 262 // Perhaps a corrupted data record... 263 // 264 continue; 265 } 266 267 if (!DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED)) { 268 // 269 // This data item has variable length data. 270 // 271 DataItem->Data.Ptr = AllocatePool (DataRecord.DataSize); 272 if (DataItem->Data.Ptr == NULL) { 273 // 274 // no memory resource 275 // 276 continue; 277 } 278 } 279 280 Data = (CHAR8 *) Variable + DataRecord.Offset; 281 CopyMem (DataItem->Data.Ptr, Data, DataRecord.DataSize); 282 283 DataItem->DataSize = DataRecord.DataSize; 284 DataItem->Status = EFI_SUCCESS; 285 } 286 287 FreePool (Variable); 288 return EFI_SUCCESS; 289 } 290 291 return Status; 292 } 293 294 /** 295 Write the configuration data from IP4_CONFIG2_INSTANCE to variable storage. 296 297 @param[in] VarName The pointer to the variable name. 298 @param[in] Instance The pointer to the IP4 config2 instance data. 299 300 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation. 301 @retval EFI_SUCCESS The configuration data is written successfully. 302 303 **/ 304 EFI_STATUS 305 Ip4Config2WriteConfigData ( 306 IN CHAR16 *VarName, 307 IN IP4_CONFIG2_INSTANCE *Instance 308 ) 309 { 310 UINTN Index; 311 UINTN VarSize; 312 IP4_CONFIG2_DATA_ITEM *DataItem; 313 IP4_CONFIG2_VARIABLE *Variable; 314 IP4_CONFIG2_DATA_RECORD *DataRecord; 315 CHAR8 *Heap; 316 EFI_STATUS Status; 317 318 VarSize = sizeof (IP4_CONFIG2_VARIABLE) - sizeof (IP4_CONFIG2_DATA_RECORD); 319 320 for (Index = 0; Index < Ip4Config2DataTypeMaximum; Index++) { 321 322 DataItem = &Instance->DataItem[Index]; 323 if (!DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_VOLATILE) && !EFI_ERROR (DataItem->Status)) { 324 325 VarSize += sizeof (IP4_CONFIG2_DATA_RECORD) + DataItem->DataSize; 326 } 327 } 328 329 Variable = AllocatePool (VarSize); 330 if (Variable == NULL) { 331 return EFI_OUT_OF_RESOURCES; 332 } 333 334 Heap = (CHAR8 *) Variable + VarSize; 335 Variable->DataRecordCount = 0; 336 337 for (Index = 0; Index < Ip4Config2DataTypeMaximum; Index++) { 338 339 DataItem = &Instance->DataItem[Index]; 340 if (!DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_VOLATILE) && !EFI_ERROR (DataItem->Status)) { 341 342 Heap -= DataItem->DataSize; 343 CopyMem (Heap, DataItem->Data.Ptr, DataItem->DataSize); 344 345 DataRecord = &Variable->DataRecord[Variable->DataRecordCount]; 346 DataRecord->DataType = (EFI_IP4_CONFIG2_DATA_TYPE) Index; 347 DataRecord->DataSize = (UINT32) DataItem->DataSize; 348 DataRecord->Offset = (UINT16) (Heap - (CHAR8 *) Variable); 349 350 Variable->DataRecordCount++; 351 } 352 } 353 354 Variable->Checksum = 0; 355 Variable->Checksum = (UINT16) ~NetblockChecksum ((UINT8 *) Variable, (UINT32) VarSize); 356 357 Status = gRT->SetVariable ( 358 VarName, 359 &gEfiIp4Config2ProtocolGuid, 360 IP4_CONFIG2_VARIABLE_ATTRIBUTE, 361 VarSize, 362 Variable 363 ); 364 365 FreePool (Variable); 366 367 return Status; 368 } 369 370 371 /** 372 Build a EFI_IP4_ROUTE_TABLE to be returned to the caller of GetModeData. 373 The EFI_IP4_ROUTE_TABLE is clumsy to use in the internal operation of the 374 IP4 driver. 375 376 @param[in] IpSb The IP4 service binding instance. 377 @param[out] Table The built IP4 route table. 378 379 @retval EFI_SUCCESS The route table is successfully build 380 @retval EFI_NOT_FOUND Failed to allocate the memory for the route table. 381 382 **/ 383 EFI_STATUS 384 Ip4Config2BuildDefaultRouteTable ( 385 IN IP4_SERVICE *IpSb, 386 OUT EFI_IP4_ROUTE_TABLE *Table 387 ) 388 { 389 LIST_ENTRY *Entry; 390 IP4_ROUTE_ENTRY *RtEntry; 391 UINT32 Count; 392 INT32 Index; 393 394 if (IpSb->DefaultRouteTable == NULL) { 395 return EFI_NOT_FOUND; 396 } 397 398 Count = IpSb->DefaultRouteTable->TotalNum; 399 400 if (Count == 0) { 401 return EFI_NOT_FOUND; 402 } 403 404 // 405 // Copy the route entry to EFI route table. Keep the order of 406 // route entry copied from most specific to default route. That 407 // is, interlevel the route entry from the instance's route area 408 // and those from the default route table's route area. 409 // 410 Count = 0; 411 412 for (Index = IP4_MASK_MAX; Index >= 0; Index--) { 413 414 NET_LIST_FOR_EACH (Entry, &(IpSb->DefaultRouteTable->RouteArea[Index])) { 415 RtEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_ENTRY, Link); 416 417 EFI_IP4 (Table[Count].SubnetAddress) = HTONL (RtEntry->Dest & RtEntry->Netmask); 418 EFI_IP4 (Table[Count].SubnetMask) = HTONL (RtEntry->Netmask); 419 EFI_IP4 (Table[Count].GatewayAddress) = HTONL (RtEntry->NextHop); 420 421 Count++; 422 } 423 424 } 425 426 return EFI_SUCCESS; 427 } 428 429 /** 430 The event process routine when the DHCPv4 service binding protocol is installed 431 in the system. 432 433 @param[in] Event Not used. 434 @param[in] Context The pointer to the IP4 config2 instance data. 435 436 **/ 437 VOID 438 EFIAPI 439 Ip4Config2OnDhcp4SbInstalled ( 440 IN EFI_EVENT Event, 441 IN VOID *Context 442 ) 443 { 444 IP4_CONFIG2_INSTANCE *Instance; 445 446 Instance = (IP4_CONFIG2_INSTANCE *) Context; 447 448 if ((Instance->Dhcp4Handle != NULL) || (Instance->Policy != Ip4Config2PolicyDhcp)) { 449 // 450 // The DHCP4 child is already created or the policy is no longer DHCP. 451 // 452 return ; 453 } 454 455 Ip4StartAutoConfig (Instance); 456 } 457 458 /** 459 Set the station address and subnetmask for the default interface. 460 461 @param[in] IpSb The pointer to the IP4 service binding instance. 462 @param[in] StationAddress Ip address to be set. 463 @param[in] SubnetMask Subnet to be set. 464 465 @retval EFI_SUCCESS Set default address successful. 466 @retval Others Some errors occur in setting. 467 468 **/ 469 EFI_STATUS 470 Ip4Config2SetDefaultAddr ( 471 IN IP4_SERVICE *IpSb, 472 IN IP4_ADDR StationAddress, 473 IN IP4_ADDR SubnetMask 474 ) 475 { 476 EFI_STATUS Status; 477 IP4_INTERFACE *IpIf; 478 IP4_PROTOCOL *Ip4Instance; 479 EFI_ARP_PROTOCOL *Arp; 480 LIST_ENTRY *Entry; 481 IP4_ADDR Subnet; 482 IP4_ROUTE_TABLE *RouteTable; 483 484 IpIf = IpSb->DefaultInterface; 485 ASSERT (IpIf != NULL); 486 487 if ((IpIf->Ip == StationAddress) && (IpIf->SubnetMask == SubnetMask)) { 488 IpSb->State = IP4_SERVICE_CONFIGED; 489 return EFI_SUCCESS; 490 } 491 492 if (IpSb->Reconfig) { 493 // 494 // The default address is changed, free the previous interface first. 495 // 496 if (IpSb->DefaultRouteTable != NULL) { 497 Ip4FreeRouteTable (IpSb->DefaultRouteTable); 498 IpSb->DefaultRouteTable = NULL; 499 } 500 501 Ip4CancelReceive (IpSb->DefaultInterface); 502 Ip4FreeInterface (IpSb->DefaultInterface, NULL); 503 IpSb->DefaultInterface = NULL; 504 // 505 // Create new default interface and route table. 506 // 507 IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image); 508 if (IpIf == NULL) { 509 return EFI_OUT_OF_RESOURCES; 510 } 511 512 RouteTable = Ip4CreateRouteTable (); 513 if (RouteTable == NULL) { 514 Ip4FreeInterface (IpIf, NULL); 515 return EFI_OUT_OF_RESOURCES; 516 } 517 518 IpSb->DefaultInterface = IpIf; 519 InsertHeadList (&IpSb->Interfaces, &IpIf->Link); 520 IpSb->DefaultRouteTable = RouteTable; 521 Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb); 522 } 523 524 if (IpSb->State == IP4_SERVICE_CONFIGED) { 525 IpSb->State = IP4_SERVICE_UNSTARTED; 526 } 527 528 Status = Ip4SetAddress (IpIf, StationAddress, SubnetMask); 529 if (EFI_ERROR (Status)) { 530 return Status; 531 } 532 533 if (IpIf->Arp != NULL) { 534 // 535 // A non-NULL IpIf->Arp here means a new ARP child is created when setting default address, 536 // but some IP children may have referenced the default interface before it is configured, 537 // these IP instances also consume this ARP protocol so they need to open it BY_CHILD_CONTROLLER. 538 // 539 Arp = NULL; 540 NET_LIST_FOR_EACH (Entry, &IpIf->IpInstances) { 541 Ip4Instance = NET_LIST_USER_STRUCT_S (Entry, IP4_PROTOCOL, AddrLink, IP4_PROTOCOL_SIGNATURE); 542 Status = gBS->OpenProtocol ( 543 IpIf->ArpHandle, 544 &gEfiArpProtocolGuid, 545 (VOID **) &Arp, 546 gIp4DriverBinding.DriverBindingHandle, 547 Ip4Instance->Handle, 548 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 549 ); 550 if (EFI_ERROR (Status)) { 551 return Status; 552 } 553 } 554 } 555 556 // 557 // Add a route for the connected network. 558 // 559 Subnet = StationAddress & SubnetMask; 560 561 Ip4AddRoute ( 562 IpSb->DefaultRouteTable, 563 Subnet, 564 SubnetMask, 565 IP4_ALLZERO_ADDRESS 566 ); 567 568 IpSb->State = IP4_SERVICE_CONFIGED; 569 IpSb->Reconfig = FALSE; 570 571 return EFI_SUCCESS; 572 } 573 574 /** 575 Set the station address, subnetmask and gateway address for the default interface. 576 577 @param[in] Instance The pointer to the IP4 config2 instance data. 578 @param[in] StationAddress Ip address to be set. 579 @param[in] SubnetMask Subnet to be set. 580 @param[in] GatewayAddress Gateway to be set. 581 582 @retval EFI_SUCCESS Set default If successful. 583 @retval Others Errors occur as indicated. 584 585 **/ 586 EFI_STATUS 587 Ip4Config2SetDefaultIf ( 588 IN IP4_CONFIG2_INSTANCE *Instance, 589 IN IP4_ADDR StationAddress, 590 IN IP4_ADDR SubnetMask, 591 IN IP4_ADDR GatewayAddress 592 ) 593 { 594 EFI_STATUS Status; 595 IP4_SERVICE *IpSb; 596 597 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance); 598 599 // 600 // Check whether the StationAddress/SubnetMask pair is valid. 601 // 602 if (!Ip4StationAddressValid (StationAddress, SubnetMask)) { 603 return EFI_INVALID_PARAMETER; 604 } 605 606 Status = Ip4Config2SetDefaultAddr (IpSb, StationAddress, SubnetMask); 607 if (EFI_ERROR (Status)) { 608 return Status; 609 } 610 611 // 612 // Create a route if there is a default router. 613 // 614 if (GatewayAddress != IP4_ALLZERO_ADDRESS) { 615 Ip4AddRoute ( 616 IpSb->DefaultRouteTable, 617 IP4_ALLZERO_ADDRESS, 618 IP4_ALLZERO_ADDRESS, 619 GatewayAddress 620 ); 621 } 622 623 return EFI_SUCCESS; 624 } 625 626 627 /** 628 Release all the DHCP related resources. 629 630 @param Instance The IP4 config2 instance. 631 632 @return None 633 634 **/ 635 VOID 636 Ip4Config2CleanDhcp4 ( 637 IN IP4_CONFIG2_INSTANCE *Instance 638 ) 639 { 640 IP4_SERVICE *IpSb; 641 642 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance); 643 644 if (Instance->Dhcp4 != NULL) { 645 Instance->Dhcp4->Stop (Instance->Dhcp4); 646 647 gBS->CloseProtocol ( 648 Instance->Dhcp4Handle, 649 &gEfiDhcp4ProtocolGuid, 650 IpSb->Image, 651 IpSb->Controller 652 ); 653 654 Instance->Dhcp4 = NULL; 655 } 656 657 if (Instance->Dhcp4Handle != NULL) { 658 NetLibDestroyServiceChild ( 659 IpSb->Controller, 660 IpSb->Image, 661 &gEfiDhcp4ServiceBindingProtocolGuid, 662 Instance->Dhcp4Handle 663 ); 664 665 Instance->Dhcp4Handle = NULL; 666 } 667 668 if (Instance->Dhcp4Event != NULL) { 669 gBS->CloseEvent (Instance->Dhcp4Event); 670 Instance->Dhcp4Event = NULL; 671 } 672 } 673 674 /** 675 This worker function sets the DNS server list for the EFI IPv4 network 676 stack running on the communication device that this EFI_IP4_CONFIG2_PROTOCOL 677 manages. The DNS server addresses must be unicast IPv4 addresses. 678 679 @param[in] Instance The pointer to the IP4 config2 instance data. 680 @param[in] DataSize The size of the buffer pointed to by Data in bytes. 681 @param[in] Data The data buffer to set, points to an array of 682 EFI_IPv4_ADDRESS instances. 683 684 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type. 685 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid. 686 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation. 687 @retval EFI_ABORTED The DNS server addresses to be set equal the current 688 configuration. 689 @retval EFI_SUCCESS The specified configuration data for the EFI IPv4 690 network stack was set. 691 692 **/ 693 EFI_STATUS 694 Ip4Config2SetDnsServerWorker ( 695 IN IP4_CONFIG2_INSTANCE *Instance, 696 IN UINTN DataSize, 697 IN VOID *Data 698 ) 699 { 700 UINTN OldIndex; 701 UINTN NewIndex; 702 EFI_IPv4_ADDRESS *OldDns; 703 EFI_IPv4_ADDRESS *NewDns; 704 UINTN OldDnsCount; 705 UINTN NewDnsCount; 706 IP4_CONFIG2_DATA_ITEM *Item; 707 BOOLEAN OneAdded; 708 VOID *Tmp; 709 IP4_ADDR DnsAddress; 710 711 if ((DataSize % sizeof (EFI_IPv4_ADDRESS) != 0) || (DataSize == 0)) { 712 return EFI_BAD_BUFFER_SIZE; 713 } 714 715 Item = &Instance->DataItem[Ip4Config2DataTypeDnsServer]; 716 NewDns = (EFI_IPv4_ADDRESS *) Data; 717 OldDns = Item->Data.DnsServers; 718 NewDnsCount = DataSize / sizeof (EFI_IPv4_ADDRESS); 719 OldDnsCount = Item->DataSize / sizeof (EFI_IPv4_ADDRESS); 720 OneAdded = FALSE; 721 722 if (NewDnsCount != OldDnsCount) { 723 Tmp = AllocatePool (DataSize); 724 if (Tmp == NULL) { 725 return EFI_OUT_OF_RESOURCES; 726 } 727 } else { 728 Tmp = NULL; 729 } 730 731 for (NewIndex = 0; NewIndex < NewDnsCount; NewIndex++) { 732 CopyMem (&DnsAddress, NewDns + NewIndex, sizeof (IP4_ADDR)); 733 if (IP4_IS_UNSPECIFIED (NTOHL (DnsAddress)) || IP4_IS_LOCAL_BROADCAST (NTOHL (DnsAddress))) { 734 // 735 // The dns server address must be unicast. 736 // 737 if (Tmp != NULL) { 738 FreePool (Tmp); 739 } 740 return EFI_INVALID_PARAMETER; 741 } 742 743 if (OneAdded) { 744 // 745 // If any address in the new setting is not in the old settings, skip the 746 // comparision below. 747 // 748 continue; 749 } 750 751 for (OldIndex = 0; OldIndex < OldDnsCount; OldIndex++) { 752 if (EFI_IP4_EQUAL (NewDns + NewIndex, OldDns + OldIndex)) { 753 // 754 // If found break out. 755 // 756 break; 757 } 758 } 759 760 if (OldIndex == OldDnsCount) { 761 OneAdded = TRUE; 762 } 763 } 764 765 if (!OneAdded && (DataSize == Item->DataSize)) { 766 // 767 // No new item is added and the size is the same. 768 // 769 Item->Status = EFI_SUCCESS; 770 return EFI_ABORTED; 771 } else { 772 if (Tmp != NULL) { 773 if (Item->Data.Ptr != NULL) { 774 FreePool (Item->Data.Ptr); 775 } 776 Item->Data.Ptr = Tmp; 777 } 778 779 CopyMem (Item->Data.Ptr, Data, DataSize); 780 Item->DataSize = DataSize; 781 Item->Status = EFI_SUCCESS; 782 return EFI_SUCCESS; 783 } 784 } 785 786 787 788 /** 789 Callback function when DHCP process finished. It will save the 790 retrieved IP configure parameter from DHCP to the NVRam. 791 792 @param Event The callback event 793 @param Context Opaque context to the callback 794 795 @return None 796 797 **/ 798 VOID 799 EFIAPI 800 Ip4Config2OnDhcp4Complete ( 801 IN EFI_EVENT Event, 802 IN VOID *Context 803 ) 804 { 805 IP4_CONFIG2_INSTANCE *Instance; 806 EFI_DHCP4_MODE_DATA Dhcp4Mode; 807 EFI_STATUS Status; 808 IP4_ADDR StationAddress; 809 IP4_ADDR SubnetMask; 810 IP4_ADDR GatewayAddress; 811 UINT32 Index; 812 UINT32 OptionCount; 813 EFI_DHCP4_PACKET_OPTION **OptionList; 814 815 Instance = (IP4_CONFIG2_INSTANCE *) Context; 816 ASSERT (Instance->Dhcp4 != NULL); 817 818 // 819 // Get the DHCP retrieved parameters 820 // 821 Status = Instance->Dhcp4->GetModeData (Instance->Dhcp4, &Dhcp4Mode); 822 823 if (EFI_ERROR (Status)) { 824 goto Exit; 825 } 826 827 if (Dhcp4Mode.State == Dhcp4Bound) { 828 StationAddress = EFI_NTOHL (Dhcp4Mode.ClientAddress); 829 SubnetMask = EFI_NTOHL (Dhcp4Mode.SubnetMask); 830 GatewayAddress = EFI_NTOHL (Dhcp4Mode.RouterAddress); 831 832 Status = Ip4Config2SetDefaultIf (Instance, StationAddress, SubnetMask, GatewayAddress); 833 if (EFI_ERROR (Status)) { 834 goto Exit; 835 } 836 837 // 838 // Parse the ACK to get required DNS server information. 839 // 840 OptionCount = 0; 841 OptionList = NULL; 842 843 Status = Instance->Dhcp4->Parse (Instance->Dhcp4, Dhcp4Mode.ReplyPacket, &OptionCount, OptionList); 844 if (Status != EFI_BUFFER_TOO_SMALL) { 845 goto Exit; 846 } 847 848 OptionList = AllocateZeroPool (OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *)); 849 if (OptionList == NULL) { 850 goto Exit; 851 } 852 853 Status = Instance->Dhcp4->Parse (Instance->Dhcp4, Dhcp4Mode.ReplyPacket, &OptionCount, OptionList); 854 if (EFI_ERROR (Status)) { 855 FreePool (OptionList); 856 goto Exit; 857 } 858 859 for (Index = 0; Index < OptionCount; Index++) { 860 // 861 // Look for DNS Server opcode (6). 862 // 863 if (OptionList[Index]->OpCode == DHCP4_TAG_DNS_SERVER) { 864 if (((OptionList[Index]->Length & 0x3) != 0) || (OptionList[Index]->Length == 0)) { 865 break; 866 } 867 868 Ip4Config2SetDnsServerWorker (Instance, OptionList[Index]->Length, &OptionList[Index]->Data[0]); 869 break; 870 } 871 } 872 873 FreePool (OptionList); 874 875 Instance->DhcpSuccess = TRUE; 876 } 877 878 Exit: 879 Ip4Config2CleanDhcp4 (Instance); 880 DispatchDpc (); 881 } 882 883 884 /** 885 Start the DHCP configuration for this IP service instance. 886 It will locates the EFI_IP4_CONFIG2_PROTOCOL, then start the 887 DHCP configuration. 888 889 @param[in] Instance The IP4 config2 instance to configure 890 891 @retval EFI_SUCCESS The auto configuration is successfully started 892 @retval Others Failed to start auto configuration. 893 894 **/ 895 EFI_STATUS 896 Ip4StartAutoConfig ( 897 IN IP4_CONFIG2_INSTANCE *Instance 898 ) 899 { 900 IP4_SERVICE *IpSb; 901 EFI_DHCP4_PROTOCOL *Dhcp4; 902 EFI_DHCP4_MODE_DATA Dhcp4Mode; 903 EFI_DHCP4_PACKET_OPTION *OptionList[1]; 904 IP4_CONFIG2_DHCP4_OPTION ParaList; 905 EFI_STATUS Status; 906 907 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance); 908 909 if (IpSb->State > IP4_SERVICE_UNSTARTED) { 910 return EFI_SUCCESS; 911 } 912 913 // 914 // A host must not invoke DHCP configuration if it is already 915 // participating in the DHCP configuration process. 916 // 917 if (Instance->Dhcp4Handle != NULL) { 918 return EFI_SUCCESS; 919 } 920 921 Status = NetLibCreateServiceChild ( 922 IpSb->Controller, 923 IpSb->Image, 924 &gEfiDhcp4ServiceBindingProtocolGuid, 925 &Instance->Dhcp4Handle 926 ); 927 928 if (Status == EFI_UNSUPPORTED) { 929 // 930 // No DHCPv4 Service Binding protocol, register a notify. 931 // 932 if (Instance->Dhcp4SbNotifyEvent == NULL) { 933 Instance->Dhcp4SbNotifyEvent = EfiCreateProtocolNotifyEvent ( 934 &gEfiDhcp4ServiceBindingProtocolGuid, 935 TPL_CALLBACK, 936 Ip4Config2OnDhcp4SbInstalled, 937 (VOID *) Instance, 938 &Instance->Registration 939 ); 940 } 941 } 942 943 if (EFI_ERROR (Status)) { 944 return Status; 945 } 946 947 if (Instance->Dhcp4SbNotifyEvent != NULL) { 948 gBS->CloseEvent (Instance->Dhcp4SbNotifyEvent); 949 } 950 951 Status = gBS->OpenProtocol ( 952 Instance->Dhcp4Handle, 953 &gEfiDhcp4ProtocolGuid, 954 (VOID **) &Instance->Dhcp4, 955 IpSb->Image, 956 IpSb->Controller, 957 EFI_OPEN_PROTOCOL_BY_DRIVER 958 ); 959 if (EFI_ERROR (Status)) { 960 NetLibDestroyServiceChild ( 961 IpSb->Controller, 962 IpSb->Image, 963 &gEfiDhcp4ServiceBindingProtocolGuid, 964 Instance->Dhcp4Handle 965 ); 966 967 Instance->Dhcp4Handle = NULL; 968 969 return Status; 970 } 971 972 // 973 // Check the current DHCP status, if the DHCP process has 974 // already finished, return now. 975 // 976 Dhcp4 = Instance->Dhcp4; 977 Status = Dhcp4->GetModeData (Dhcp4, &Dhcp4Mode); 978 if (Dhcp4Mode.State == Dhcp4Bound) { 979 Ip4Config2OnDhcp4Complete (NULL, Instance); 980 981 return EFI_SUCCESS; 982 } 983 984 // 985 // Try to start the DHCP process. Use most of the current 986 // DHCP configuration to avoid problems if some DHCP client 987 // yields the control of this DHCP service to us. 988 // 989 ParaList.Head.OpCode = DHCP4_TAG_PARA_LIST; 990 ParaList.Head.Length = 3; 991 ParaList.Head.Data[0] = DHCP4_TAG_NETMASK; 992 ParaList.Route = DHCP4_TAG_ROUTER; 993 ParaList.Dns = DHCP4_TAG_DNS_SERVER; 994 OptionList[0] = &ParaList.Head; 995 Dhcp4Mode.ConfigData.OptionCount = 1; 996 Dhcp4Mode.ConfigData.OptionList = OptionList; 997 998 Status = Dhcp4->Configure (Dhcp4, &Dhcp4Mode.ConfigData); 999 if (EFI_ERROR (Status)) { 1000 gBS->CloseProtocol ( 1001 Instance->Dhcp4Handle, 1002 &gEfiDhcp4ProtocolGuid, 1003 IpSb->Image, 1004 IpSb->Controller 1005 ); 1006 1007 NetLibDestroyServiceChild ( 1008 IpSb->Controller, 1009 IpSb->Image, 1010 &gEfiDhcp4ServiceBindingProtocolGuid, 1011 Instance->Dhcp4Handle 1012 ); 1013 1014 Instance->Dhcp4 = NULL; 1015 1016 Instance->Dhcp4Handle = NULL; 1017 1018 return Status; 1019 } 1020 1021 // 1022 // Start the DHCP process 1023 // 1024 Status = gBS->CreateEvent ( 1025 EVT_NOTIFY_SIGNAL, 1026 TPL_CALLBACK, 1027 Ip4Config2OnDhcp4Complete, 1028 Instance, 1029 &Instance->Dhcp4Event 1030 ); 1031 if (EFI_ERROR (Status)) { 1032 Ip4Config2DestroyDhcp4 (Instance); 1033 return Status; 1034 } 1035 1036 Status = Dhcp4->Start (Dhcp4, Instance->Dhcp4Event); 1037 if (EFI_ERROR (Status)) { 1038 Ip4Config2DestroyDhcp4 (Instance); 1039 gBS->CloseEvent (Instance->Dhcp4Event); 1040 Instance->Dhcp4Event = NULL; 1041 1042 return Status; 1043 } 1044 1045 IpSb->State = IP4_SERVICE_STARTED; 1046 DispatchDpc (); 1047 1048 return EFI_SUCCESS; 1049 } 1050 1051 1052 1053 /** 1054 The work function is to get the interface information of the communication 1055 device this IP4_CONFIG2_INSTANCE manages. 1056 1057 @param[in] Instance Pointer to the IP4 config2 instance data. 1058 @param[in, out] DataSize On input, in bytes, the size of Data. On output, in 1059 bytes, the size of buffer required to store the specified 1060 configuration data. 1061 @param[in] Data The data buffer in which the configuration data is returned. 1062 Ignored if DataSize is ZERO. 1063 1064 @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified 1065 configuration data, and the required size is 1066 returned in DataSize. 1067 @retval EFI_SUCCESS The specified configuration data was obtained. 1068 1069 **/ 1070 EFI_STATUS 1071 Ip4Config2GetIfInfo ( 1072 IN IP4_CONFIG2_INSTANCE *Instance, 1073 IN OUT UINTN *DataSize, 1074 IN VOID *Data OPTIONAL 1075 ) 1076 { 1077 IP4_SERVICE *IpSb; 1078 UINTN Length; 1079 IP4_CONFIG2_DATA_ITEM *Item; 1080 EFI_IP4_CONFIG2_INTERFACE_INFO *IfInfo; 1081 IP4_ADDR Address; 1082 1083 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance); 1084 Length = sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO); 1085 1086 if (IpSb->DefaultRouteTable != NULL) { 1087 Length += IpSb->DefaultRouteTable->TotalNum * sizeof (EFI_IP4_ROUTE_TABLE); 1088 } 1089 1090 if (*DataSize < Length) { 1091 *DataSize = Length; 1092 return EFI_BUFFER_TOO_SMALL; 1093 } 1094 1095 // 1096 // Copy the fixed size part of the interface info. 1097 // 1098 Item = &Instance->DataItem[Ip4Config2DataTypeInterfaceInfo]; 1099 IfInfo = (EFI_IP4_CONFIG2_INTERFACE_INFO *) Data; 1100 CopyMem (IfInfo, Item->Data.Ptr, sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO)); 1101 1102 // 1103 // Update the address info. 1104 // 1105 if (IpSb->DefaultInterface != NULL) { 1106 Address = HTONL (IpSb->DefaultInterface->Ip); 1107 CopyMem (&IfInfo->StationAddress, &Address, sizeof (EFI_IPv4_ADDRESS)); 1108 Address = HTONL (IpSb->DefaultInterface->SubnetMask); 1109 CopyMem (&IfInfo->SubnetMask, &Address, sizeof (EFI_IPv4_ADDRESS)); 1110 } 1111 1112 if (IpSb->DefaultRouteTable != NULL) { 1113 IfInfo->RouteTableSize = IpSb->DefaultRouteTable->TotalNum; 1114 IfInfo->RouteTable = (EFI_IP4_ROUTE_TABLE *) ((UINT8 *) Data + sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO)); 1115 1116 Ip4Config2BuildDefaultRouteTable (IpSb, IfInfo->RouteTable); 1117 } 1118 1119 return EFI_SUCCESS; 1120 } 1121 1122 /** 1123 The work function is to set the general configuration policy for the EFI IPv4 network 1124 stack that is running on the communication device managed by this IP4_CONFIG2_INSTANCE. 1125 The policy will affect other configuration settings. 1126 1127 @param[in] Instance Pointer to the IP4 config2 instance data. 1128 @param[in] DataSize Size of the buffer pointed to by Data in bytes. 1129 @param[in] Data The data buffer to set. 1130 1131 @retval EFI_INVALID_PARAMETER The to be set policy is invalid. 1132 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type. 1133 @retval EFI_ABORTED The new policy equals the current policy. 1134 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6 1135 network stack was set. 1136 1137 **/ 1138 EFI_STATUS 1139 Ip4Config2SetPolicy ( 1140 IN IP4_CONFIG2_INSTANCE *Instance, 1141 IN UINTN DataSize, 1142 IN VOID *Data 1143 ) 1144 { 1145 EFI_IP4_CONFIG2_POLICY NewPolicy; 1146 IP4_CONFIG2_DATA_ITEM *DataItem; 1147 IP4_SERVICE *IpSb; 1148 1149 if (DataSize != sizeof (EFI_IP4_CONFIG2_POLICY)) { 1150 return EFI_BAD_BUFFER_SIZE; 1151 } 1152 1153 NewPolicy = *((EFI_IP4_CONFIG2_POLICY *) Data); 1154 1155 if (NewPolicy >= Ip4Config2PolicyMax) { 1156 return EFI_INVALID_PARAMETER; 1157 } 1158 1159 if (NewPolicy == Instance->Policy) { 1160 if (NewPolicy != Ip4Config2PolicyDhcp || Instance->DhcpSuccess) { 1161 return EFI_ABORTED; 1162 } 1163 } else { 1164 // 1165 // The policy is changed. Clean the ManualAddress, Gateway and DnsServers, 1166 // shrink the variable data size, and fire up all the related events. 1167 // 1168 DataItem = &Instance->DataItem[Ip4Config2DataTypeManualAddress]; 1169 if (DataItem->Data.Ptr != NULL) { 1170 FreePool (DataItem->Data.Ptr); 1171 } 1172 DataItem->Data.Ptr = NULL; 1173 DataItem->DataSize = 0; 1174 DataItem->Status = EFI_NOT_FOUND; 1175 NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL); 1176 1177 DataItem = &Instance->DataItem[Ip4Config2DataTypeGateway]; 1178 if (DataItem->Data.Ptr != NULL) { 1179 FreePool (DataItem->Data.Ptr); 1180 } 1181 DataItem->Data.Ptr = NULL; 1182 DataItem->DataSize = 0; 1183 DataItem->Status = EFI_NOT_FOUND; 1184 NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL); 1185 1186 DataItem = &Instance->DataItem[Ip4Config2DataTypeDnsServer]; 1187 if (DataItem->Data.Ptr != NULL) { 1188 FreePool (DataItem->Data.Ptr); 1189 } 1190 DataItem->Data.Ptr = NULL; 1191 DataItem->DataSize = 0; 1192 DataItem->Status = EFI_NOT_FOUND; 1193 NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL); 1194 1195 if (NewPolicy == Ip4Config2PolicyDhcp) { 1196 SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_VOLATILE); 1197 } else { 1198 // 1199 // The policy is changed from dhcp to static. Stop the DHCPv4 process 1200 // and destroy the DHCPv4 child. 1201 // 1202 if (Instance->Dhcp4Handle != NULL) { 1203 Ip4Config2DestroyDhcp4 (Instance); 1204 } 1205 1206 // 1207 // Close the event. 1208 // 1209 if (Instance->Dhcp4Event != NULL) { 1210 gBS->CloseEvent (Instance->Dhcp4Event); 1211 Instance->Dhcp4Event = NULL; 1212 } 1213 } 1214 } 1215 1216 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance); 1217 Ip4Config2OnPolicyChanged (IpSb, NewPolicy); 1218 1219 Instance->Policy = NewPolicy; 1220 1221 return EFI_SUCCESS; 1222 } 1223 1224 /** 1225 The work function is to set the station addresses manually for the EFI IPv4 1226 network stack. It is only configurable when the policy is Ip4Config2PolicyStatic. 1227 1228 @param[in] Instance Pointer to the IP4 config2 instance data. 1229 @param[in] DataSize Size of the buffer pointed to by Data in bytes. 1230 @param[in] Data The data buffer to set. 1231 1232 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type. 1233 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set 1234 under the current policy. 1235 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid. 1236 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation. 1237 @retval EFI_NOT_READY An asynchronous process is invoked to set the specified 1238 configuration data, and the process is not finished. 1239 @retval EFI_ABORTED The manual addresses to be set equal current 1240 configuration. 1241 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6 1242 network stack was set. 1243 1244 **/ 1245 EFI_STATUS 1246 Ip4Config2SetManualAddress ( 1247 IN IP4_CONFIG2_INSTANCE *Instance, 1248 IN UINTN DataSize, 1249 IN VOID *Data 1250 ) 1251 { 1252 EFI_IP4_CONFIG2_MANUAL_ADDRESS NewAddress; 1253 IP4_CONFIG2_DATA_ITEM *DataItem; 1254 EFI_STATUS Status; 1255 IP4_ADDR StationAddress; 1256 IP4_ADDR SubnetMask; 1257 VOID *Ptr; 1258 IP4_SERVICE *IpSb; 1259 IP4_INTERFACE *IpIf; 1260 IP4_ROUTE_TABLE *RouteTable; 1261 1262 DataItem = NULL; 1263 Status = EFI_SUCCESS; 1264 Ptr = NULL; 1265 IpIf = NULL; 1266 RouteTable = NULL; 1267 1268 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance); 1269 1270 ASSERT (Instance->DataItem[Ip4Config2DataTypeManualAddress].Status != EFI_NOT_READY); 1271 1272 if ((DataSize != 0) && ((DataSize % sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS)) != 0)) { 1273 return EFI_BAD_BUFFER_SIZE; 1274 } 1275 1276 if (Instance->Policy != Ip4Config2PolicyStatic) { 1277 return EFI_WRITE_PROTECTED; 1278 } 1279 1280 DataItem = &Instance->DataItem[Ip4Config2DataTypeManualAddress]; 1281 1282 if (Data != NULL && DataSize != 0) { 1283 NewAddress = *((EFI_IP4_CONFIG2_MANUAL_ADDRESS *) Data); 1284 1285 StationAddress = EFI_NTOHL (NewAddress.Address); 1286 SubnetMask = EFI_NTOHL (NewAddress.SubnetMask); 1287 1288 // 1289 // Check whether the StationAddress/SubnetMask pair is valid. 1290 // 1291 if (!Ip4StationAddressValid (StationAddress, SubnetMask)) { 1292 return EFI_INVALID_PARAMETER; 1293 } 1294 1295 // 1296 // Store the new data, and init the DataItem status to EFI_NOT_READY because 1297 // we may have an asynchronous configuration process. 1298 // 1299 Ptr = AllocateCopyPool (DataSize, Data); 1300 if (Ptr == NULL) { 1301 return EFI_OUT_OF_RESOURCES; 1302 } 1303 1304 if (DataItem->Data.Ptr != NULL) { 1305 FreePool (DataItem->Data.Ptr); 1306 } 1307 1308 DataItem->Data.Ptr = Ptr; 1309 DataItem->DataSize = DataSize; 1310 DataItem->Status = EFI_NOT_READY; 1311 1312 IpSb->Reconfig = TRUE; 1313 Status = Ip4Config2SetDefaultAddr (IpSb, StationAddress, SubnetMask); 1314 1315 DataItem->Status = Status; 1316 1317 if (EFI_ERROR (DataItem->Status) && DataItem->Status != EFI_NOT_READY) { 1318 if (Ptr != NULL) { 1319 FreePool (Ptr); 1320 } 1321 DataItem->Data.Ptr = NULL; 1322 } 1323 } else { 1324 // 1325 // DataSize is 0 and Data is NULL, clean up the manual address. 1326 // 1327 if (DataItem->Data.Ptr != NULL) { 1328 FreePool (DataItem->Data.Ptr); 1329 } 1330 DataItem->Data.Ptr = NULL; 1331 DataItem->DataSize = 0; 1332 DataItem->Status = EFI_NOT_FOUND; 1333 1334 // 1335 // Free the default router table and Interface, clean up the assemble table. 1336 // 1337 if (IpSb->DefaultInterface != NULL) { 1338 if (IpSb->DefaultRouteTable != NULL) { 1339 Ip4FreeRouteTable (IpSb->DefaultRouteTable); 1340 IpSb->DefaultRouteTable = NULL; 1341 } 1342 1343 Ip4CancelReceive (IpSb->DefaultInterface); 1344 1345 Ip4FreeInterface (IpSb->DefaultInterface, NULL); 1346 IpSb->DefaultInterface = NULL; 1347 } 1348 1349 Ip4CleanAssembleTable (&IpSb->Assemble); 1350 1351 // 1352 // Create new default interface and route table. 1353 // 1354 IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image); 1355 if (IpIf == NULL) { 1356 return EFI_OUT_OF_RESOURCES; 1357 } 1358 1359 RouteTable = Ip4CreateRouteTable (); 1360 if (RouteTable == NULL) { 1361 Ip4FreeInterface (IpIf, NULL); 1362 return EFI_OUT_OF_RESOURCES; 1363 } 1364 1365 IpSb->DefaultInterface = IpIf; 1366 InsertHeadList (&IpSb->Interfaces, &IpIf->Link); 1367 IpSb->DefaultRouteTable = RouteTable; 1368 Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb); 1369 1370 // 1371 // Reset the State to unstarted. 1372 // 1373 if (IpSb->State == IP4_SERVICE_CONFIGED || IpSb->State == IP4_SERVICE_STARTED) { 1374 IpSb->State = IP4_SERVICE_UNSTARTED; 1375 } 1376 } 1377 1378 return Status; 1379 } 1380 1381 /** 1382 The work function is to set the gateway addresses manually for the EFI IPv4 1383 network stack that is running on the communication device that this EFI IPv4 1384 Configuration Protocol manages. It is not configurable when the policy is 1385 Ip4Config2PolicyDhcp. The gateway addresses must be unicast IPv4 addresses. 1386 1387 @param[in] Instance The pointer to the IP4 config2 instance data. 1388 @param[in] DataSize The size of the buffer pointed to by Data in bytes. 1389 @param[in] Data The data buffer to set. This points to an array of 1390 EFI_IPv6_ADDRESS instances. 1391 1392 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type. 1393 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set 1394 under the current policy. 1395 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid. 1396 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to complete the operation. 1397 @retval EFI_ABORTED The manual gateway addresses to be set equal the 1398 current configuration. 1399 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6 1400 network stack was set. 1401 1402 **/ 1403 EFI_STATUS 1404 Ip4Config2SetGateway ( 1405 IN IP4_CONFIG2_INSTANCE *Instance, 1406 IN UINTN DataSize, 1407 IN VOID *Data 1408 ) 1409 { 1410 IP4_SERVICE *IpSb; 1411 IP4_CONFIG2_DATA_ITEM *DataItem; 1412 IP4_ADDR Gateway; 1413 1414 UINTN Index1; 1415 UINTN Index2; 1416 EFI_IPv4_ADDRESS *OldGateway; 1417 EFI_IPv4_ADDRESS *NewGateway; 1418 UINTN OldGatewayCount; 1419 UINTN NewGatewayCount; 1420 BOOLEAN OneRemoved; 1421 BOOLEAN OneAdded; 1422 VOID *Tmp; 1423 1424 OldGateway = NULL; 1425 NewGateway = NULL; 1426 OneRemoved = FALSE; 1427 OneAdded = FALSE; 1428 Tmp = NULL; 1429 1430 if ((DataSize != 0) && (DataSize % sizeof (EFI_IPv4_ADDRESS) != 0)) { 1431 return EFI_BAD_BUFFER_SIZE; 1432 } 1433 1434 if (Instance->Policy != Ip4Config2PolicyStatic) { 1435 return EFI_WRITE_PROTECTED; 1436 } 1437 1438 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance); 1439 1440 DataItem = &Instance->DataItem[Ip4Config2DataTypeGateway]; 1441 OldGateway = DataItem->Data.Gateway; 1442 OldGatewayCount = DataItem->DataSize / sizeof (EFI_IPv4_ADDRESS); 1443 1444 for (Index1 = 0; Index1 < OldGatewayCount; Index1++) { 1445 // 1446 // Remove the old route entry. 1447 // 1448 CopyMem (&Gateway, OldGateway + Index1, sizeof (IP4_ADDR)); 1449 Ip4DelRoute ( 1450 IpSb->DefaultRouteTable, 1451 IP4_ALLZERO_ADDRESS, 1452 IP4_ALLZERO_ADDRESS, 1453 NTOHL (Gateway) 1454 ); 1455 OneRemoved = TRUE; 1456 } 1457 1458 if (Data != NULL && DataSize != 0) { 1459 NewGateway = (EFI_IPv4_ADDRESS *) Data; 1460 NewGatewayCount = DataSize / sizeof (EFI_IPv4_ADDRESS); 1461 for (Index1 = 0; Index1 < NewGatewayCount; Index1++) { 1462 CopyMem (&Gateway, NewGateway + Index1, sizeof (IP4_ADDR)); 1463 1464 if ((IpSb->DefaultInterface->SubnetMask != 0) && 1465 !NetIp4IsUnicast (NTOHL (Gateway), IpSb->DefaultInterface->SubnetMask)) { 1466 return EFI_INVALID_PARAMETER; 1467 } 1468 1469 for (Index2 = Index1 + 1; Index2 < NewGatewayCount; Index2++) { 1470 if (EFI_IP4_EQUAL (NewGateway + Index1, NewGateway + Index2)) { 1471 return EFI_INVALID_PARAMETER; 1472 } 1473 } 1474 } 1475 1476 if (NewGatewayCount != OldGatewayCount) { 1477 Tmp = AllocatePool (DataSize); 1478 if (Tmp == NULL) { 1479 return EFI_OUT_OF_RESOURCES; 1480 } 1481 } else { 1482 Tmp = NULL; 1483 } 1484 1485 for (Index1 = 0; Index1 < NewGatewayCount; Index1++) { 1486 // 1487 // Add the new route entry. 1488 // 1489 CopyMem (&Gateway, NewGateway + Index1, sizeof (IP4_ADDR)); 1490 Ip4AddRoute ( 1491 IpSb->DefaultRouteTable, 1492 IP4_ALLZERO_ADDRESS, 1493 IP4_ALLZERO_ADDRESS, 1494 NTOHL (Gateway) 1495 ); 1496 1497 OneAdded = TRUE; 1498 } 1499 1500 if (!OneRemoved && !OneAdded) { 1501 DataItem->Status = EFI_SUCCESS; 1502 return EFI_ABORTED; 1503 } else { 1504 if (Tmp != NULL) { 1505 if (DataItem->Data.Ptr != NULL) { 1506 FreePool (DataItem->Data.Ptr); 1507 } 1508 DataItem->Data.Ptr = Tmp; 1509 } 1510 1511 CopyMem (DataItem->Data.Ptr, Data, DataSize); 1512 DataItem->DataSize = DataSize; 1513 DataItem->Status = EFI_SUCCESS; 1514 } 1515 } else { 1516 // 1517 // DataSize is 0 and Data is NULL, clean up the Gateway address. 1518 // 1519 if (DataItem->Data.Ptr != NULL) { 1520 FreePool (DataItem->Data.Ptr); 1521 } 1522 DataItem->Data.Ptr = NULL; 1523 DataItem->DataSize = 0; 1524 DataItem->Status = EFI_NOT_FOUND; 1525 } 1526 1527 return EFI_SUCCESS; 1528 } 1529 1530 /** 1531 The work function is to set the DNS server list for the EFI IPv4 network 1532 stack running on the communication device that this EFI_IP4_CONFIG2_PROTOCOL 1533 manages. It is not configurable when the policy is Ip4Config2PolicyDhcp. 1534 The DNS server addresses must be unicast IPv4 addresses. 1535 1536 @param[in] Instance The pointer to the IP4 config2 instance data. 1537 @param[in] DataSize The size of the buffer pointed to by Data in bytes. 1538 @param[in] Data The data buffer to set, points to an array of 1539 EFI_IPv4_ADDRESS instances. 1540 1541 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type. 1542 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set 1543 under the current policy. 1544 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid. 1545 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation. 1546 @retval EFI_ABORTED The DNS server addresses to be set equal the current 1547 configuration. 1548 @retval EFI_SUCCESS The specified configuration data for the EFI IPv4 1549 network stack was set. 1550 1551 **/ 1552 EFI_STATUS 1553 Ip4Config2SetDnsServer ( 1554 IN IP4_CONFIG2_INSTANCE *Instance, 1555 IN UINTN DataSize, 1556 IN VOID *Data 1557 ) 1558 { 1559 EFI_STATUS Status; 1560 IP4_CONFIG2_DATA_ITEM *Item; 1561 1562 Status = EFI_SUCCESS; 1563 Item = NULL; 1564 1565 if (Instance->Policy != Ip4Config2PolicyStatic) { 1566 return EFI_WRITE_PROTECTED; 1567 } 1568 1569 Item = &Instance->DataItem[Ip4Config2DataTypeDnsServer]; 1570 1571 if (DATA_ATTRIB_SET (Item->Attribute, DATA_ATTRIB_VOLATILE)) { 1572 REMOVE_DATA_ATTRIB (Item->Attribute, DATA_ATTRIB_VOLATILE); 1573 } 1574 1575 if (Data != NULL && DataSize != 0) { 1576 Status = Ip4Config2SetDnsServerWorker (Instance, DataSize, Data); 1577 } else { 1578 // 1579 // DataSize is 0 and Data is NULL, clean up the DnsServer address. 1580 // 1581 if (Item->Data.Ptr != NULL) { 1582 FreePool (Item->Data.Ptr); 1583 } 1584 Item->Data.Ptr = NULL; 1585 Item->DataSize = 0; 1586 Item->Status = EFI_NOT_FOUND; 1587 } 1588 1589 return Status; 1590 } 1591 1592 /** 1593 Generate the operational state of the interface this IP4 config2 instance manages 1594 and output in EFI_IP4_CONFIG2_INTERFACE_INFO. 1595 1596 @param[in] IpSb The pointer to the IP4 service binding instance. 1597 @param[out] IfInfo The pointer to the IP4 config2 interface information structure. 1598 1599 **/ 1600 VOID 1601 Ip4Config2InitIfInfo ( 1602 IN IP4_SERVICE *IpSb, 1603 OUT EFI_IP4_CONFIG2_INTERFACE_INFO *IfInfo 1604 ) 1605 { 1606 UnicodeSPrint ( 1607 IfInfo->Name, 1608 EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE, 1609 L"eth%d", 1610 IpSb->Ip4Config2Instance.IfIndex 1611 ); 1612 1613 IfInfo->IfType = IpSb->SnpMode.IfType; 1614 IfInfo->HwAddressSize = IpSb->SnpMode.HwAddressSize; 1615 CopyMem (&IfInfo->HwAddress, &IpSb->SnpMode.CurrentAddress, IfInfo->HwAddressSize); 1616 } 1617 1618 1619 1620 /** 1621 Set the configuration for the EFI IPv4 network stack running on the communication 1622 device this EFI_IP4_CONFIG2_PROTOCOL instance manages. 1623 1624 This function is used to set the configuration data of type DataType for the EFI 1625 IPv4 network stack that is running on the communication device that this EFI IPv4 1626 Configuration Protocol instance manages. 1627 1628 DataSize is used to calculate the count of structure instances in the Data for 1629 a DataType in which multiple structure instances are allowed. 1630 1631 This function is always non-blocking. When setting some type of configuration data, 1632 an asynchronous process is invoked to check the correctness of the data, such as 1633 performing Duplicate Address Detection on the manually set local IPv4 addresses. 1634 EFI_NOT_READY is returned immediately to indicate that such an asynchronous process 1635 is invoked, and the process is not finished yet. The caller wanting to get the result 1636 of the asynchronous process is required to call RegisterDataNotify() to register an 1637 event on the specified configuration data. Once the event is signaled, the caller 1638 can call GetData() to obtain the configuration data and know the result. 1639 For other types of configuration data that do not require an asynchronous configuration 1640 process, the result of the operation is immediately returned. 1641 1642 @param[in] This The pointer to the EFI_IP4_CONFIG2_PROTOCOL instance. 1643 @param[in] DataType The type of data to set. 1644 @param[in] DataSize Size of the buffer pointed to by Data in bytes. 1645 @param[in] Data The data buffer to set. The type of the data buffer is 1646 associated with the DataType. 1647 1648 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6 1649 network stack was set successfully. 1650 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: 1651 - This is NULL. 1652 - One or more fields in Data and DataSize do not match the 1653 requirement of the data type indicated by DataType. 1654 @retval EFI_WRITE_PROTECTED The specified configuration data is read-only or the specified 1655 configuration data cannot be set under the current policy. 1656 @retval EFI_ACCESS_DENIED Another set operation on the specified configuration 1657 data is already in process. 1658 @retval EFI_NOT_READY An asynchronous process was invoked to set the specified 1659 configuration data, and the process is not finished yet. 1660 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type 1661 indicated by DataType. 1662 @retval EFI_UNSUPPORTED This DataType is not supported. 1663 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. 1664 @retval EFI_DEVICE_ERROR An unexpected system error or network error occurred. 1665 1666 **/ 1667 EFI_STATUS 1668 EFIAPI 1669 EfiIp4Config2SetData ( 1670 IN EFI_IP4_CONFIG2_PROTOCOL *This, 1671 IN EFI_IP4_CONFIG2_DATA_TYPE DataType, 1672 IN UINTN DataSize, 1673 IN VOID *Data 1674 ) 1675 { 1676 EFI_TPL OldTpl; 1677 EFI_STATUS Status; 1678 IP4_CONFIG2_INSTANCE *Instance; 1679 IP4_SERVICE *IpSb; 1680 1681 if ((This == NULL) || (Data == NULL && DataSize != 0) || (Data != NULL && DataSize == 0)) { 1682 return EFI_INVALID_PARAMETER; 1683 } 1684 1685 if (DataType >= Ip4Config2DataTypeMaximum) { 1686 return EFI_UNSUPPORTED; 1687 } 1688 1689 Instance = IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This); 1690 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance); 1691 NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE); 1692 1693 1694 OldTpl = gBS->RaiseTPL (TPL_CALLBACK); 1695 1696 Status = Instance->DataItem[DataType].Status; 1697 if (Status != EFI_NOT_READY) { 1698 1699 if (Instance->DataItem[DataType].SetData == NULL) { 1700 // 1701 // This type of data is readonly. 1702 // 1703 Status = EFI_WRITE_PROTECTED; 1704 } else { 1705 1706 Status = Instance->DataItem[DataType].SetData (Instance, DataSize, Data); 1707 if (!EFI_ERROR (Status)) { 1708 // 1709 // Fire up the events registered with this type of data. 1710 // 1711 NetMapIterate (&Instance->DataItem[DataType].EventMap, Ip4Config2SignalEvent, NULL); 1712 Ip4Config2WriteConfigData (IpSb->MacString, Instance); 1713 } else if (Status == EFI_ABORTED) { 1714 // 1715 // The SetData is aborted because the data to set is the same with 1716 // the one maintained. 1717 // 1718 Status = EFI_SUCCESS; 1719 NetMapIterate (&Instance->DataItem[DataType].EventMap, Ip4Config2SignalEvent, NULL); 1720 } 1721 } 1722 } else { 1723 // 1724 // Another asynchronous process is on the way. 1725 // 1726 Status = EFI_ACCESS_DENIED; 1727 } 1728 1729 gBS->RestoreTPL (OldTpl); 1730 1731 return Status; 1732 } 1733 1734 /** 1735 Get the configuration data for the EFI IPv4 network stack running on the communication 1736 device that this EFI_IP4_CONFIG2_PROTOCOL instance manages. 1737 1738 This function returns the configuration data of type DataType for the EFI IPv4 network 1739 stack running on the communication device that this EFI IPv4 Configuration Protocol instance 1740 manages. 1741 1742 The caller is responsible for allocating the buffer used to return the specified 1743 configuration data. The required size will be returned to the caller if the size of 1744 the buffer is too small. 1745 1746 EFI_NOT_READY is returned if the specified configuration data is not ready due to an 1747 asynchronous configuration process already in progress. The caller can call RegisterDataNotify() 1748 to register an event on the specified configuration data. Once the asynchronous configuration 1749 process is finished, the event will be signaled, and a subsequent GetData() call will return 1750 the specified configuration data. 1751 1752 @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance. 1753 @param[in] DataType The type of data to get. 1754 @param[in, out] DataSize On input, in bytes, the size of Data. On output, in bytes, the 1755 size of buffer required to store the specified configuration data. 1756 @param[in] Data The data buffer in which the configuration data is returned. The 1757 type of the data buffer is associated with the DataType. 1758 This is an optional parameter that may be NULL. 1759 1760 @retval EFI_SUCCESS The specified configuration data was obtained successfully. 1761 @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE: 1762 - This is NULL. 1763 - DataSize is NULL. 1764 - Data is NULL if *DataSize is not zero. 1765 @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified configuration data, 1766 and the required size is returned in DataSize. 1767 @retval EFI_NOT_READY The specified configuration data is not ready due to an 1768 asynchronous configuration process already in progress. 1769 @retval EFI_NOT_FOUND The specified configuration data is not found. 1770 1771 **/ 1772 EFI_STATUS 1773 EFIAPI 1774 EfiIp4Config2GetData ( 1775 IN EFI_IP4_CONFIG2_PROTOCOL *This, 1776 IN EFI_IP4_CONFIG2_DATA_TYPE DataType, 1777 IN OUT UINTN *DataSize, 1778 IN VOID *Data OPTIONAL 1779 ) 1780 { 1781 EFI_TPL OldTpl; 1782 EFI_STATUS Status; 1783 IP4_CONFIG2_INSTANCE *Instance; 1784 IP4_CONFIG2_DATA_ITEM *DataItem; 1785 1786 if ((This == NULL) || (DataSize == NULL) || ((*DataSize != 0) && (Data == NULL))) { 1787 return EFI_INVALID_PARAMETER; 1788 } 1789 1790 if (DataType >= Ip4Config2DataTypeMaximum) { 1791 return EFI_NOT_FOUND; 1792 } 1793 1794 OldTpl = gBS->RaiseTPL (TPL_CALLBACK); 1795 1796 Instance = IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This); 1797 DataItem = &Instance->DataItem[DataType]; 1798 1799 Status = Instance->DataItem[DataType].Status; 1800 if (!EFI_ERROR (Status)) { 1801 1802 if (DataItem->GetData != NULL) { 1803 1804 Status = DataItem->GetData (Instance, DataSize, Data); 1805 } else if (*DataSize < Instance->DataItem[DataType].DataSize) { 1806 // 1807 // Update the buffer length. 1808 // 1809 *DataSize = Instance->DataItem[DataType].DataSize; 1810 Status = EFI_BUFFER_TOO_SMALL; 1811 } else { 1812 1813 *DataSize = Instance->DataItem[DataType].DataSize; 1814 CopyMem (Data, Instance->DataItem[DataType].Data.Ptr, *DataSize); 1815 } 1816 } 1817 1818 gBS->RestoreTPL (OldTpl); 1819 1820 return Status; 1821 } 1822 1823 /** 1824 Register an event that is signaled whenever a configuration process on the specified 1825 configuration data is done. 1826 1827 This function registers an event that is to be signaled whenever a configuration 1828 process on the specified configuration data is performed. An event can be registered 1829 for a different DataType simultaneously. The caller is responsible for determining 1830 which type of configuration data causes the signaling of the event in such an event. 1831 1832 @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance. 1833 @param[in] DataType The type of data to unregister the event for. 1834 @param[in] Event The event to register. 1835 1836 @retval EFI_SUCCESS The notification event for the specified configuration data is 1837 registered. 1838 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL. 1839 @retval EFI_UNSUPPORTED The configuration data type specified by DataType is not 1840 supported. 1841 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. 1842 @retval EFI_ACCESS_DENIED The Event is already registered for the DataType. 1843 1844 **/ 1845 EFI_STATUS 1846 EFIAPI 1847 EfiIp4Config2RegisterDataNotify ( 1848 IN EFI_IP4_CONFIG2_PROTOCOL *This, 1849 IN EFI_IP4_CONFIG2_DATA_TYPE DataType, 1850 IN EFI_EVENT Event 1851 ) 1852 { 1853 EFI_TPL OldTpl; 1854 EFI_STATUS Status; 1855 IP4_CONFIG2_INSTANCE *Instance; 1856 NET_MAP *EventMap; 1857 NET_MAP_ITEM *Item; 1858 1859 if ((This == NULL) || (Event == NULL)) { 1860 return EFI_INVALID_PARAMETER; 1861 } 1862 1863 if (DataType >= Ip4Config2DataTypeMaximum) { 1864 return EFI_UNSUPPORTED; 1865 } 1866 1867 OldTpl = gBS->RaiseTPL (TPL_CALLBACK); 1868 1869 Instance = IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This); 1870 EventMap = &Instance->DataItem[DataType].EventMap; 1871 1872 // 1873 // Check whether this event is already registered for this DataType. 1874 // 1875 Item = NetMapFindKey (EventMap, Event); 1876 if (Item == NULL) { 1877 1878 Status = NetMapInsertTail (EventMap, Event, NULL); 1879 1880 if (EFI_ERROR (Status)) { 1881 1882 Status = EFI_OUT_OF_RESOURCES; 1883 } 1884 1885 } else { 1886 1887 Status = EFI_ACCESS_DENIED; 1888 } 1889 1890 gBS->RestoreTPL (OldTpl); 1891 1892 return Status; 1893 } 1894 1895 /** 1896 Remove a previously registered event for the specified configuration data. 1897 1898 @param This The pointer to the EFI_IP4_CONFIG2_PROTOCOL instance. 1899 @param DataType The type of data to remove from the previously 1900 registered event. 1901 @param Event The event to be unregistered. 1902 1903 @retval EFI_SUCCESS The event registered for the specified 1904 configuration data was removed. 1905 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL. 1906 @retval EFI_NOT_FOUND The Event has not been registered for the 1907 specified DataType. 1908 1909 **/ 1910 EFI_STATUS 1911 EFIAPI 1912 EfiIp4Config2UnregisterDataNotify ( 1913 IN EFI_IP4_CONFIG2_PROTOCOL *This, 1914 IN EFI_IP4_CONFIG2_DATA_TYPE DataType, 1915 IN EFI_EVENT Event 1916 ) 1917 { 1918 EFI_TPL OldTpl; 1919 EFI_STATUS Status; 1920 IP4_CONFIG2_INSTANCE *Instance; 1921 NET_MAP_ITEM *Item; 1922 1923 if ((This == NULL) || (Event == NULL)) { 1924 return EFI_INVALID_PARAMETER; 1925 } 1926 1927 if (DataType >= Ip4Config2DataTypeMaximum) { 1928 return EFI_NOT_FOUND; 1929 } 1930 1931 OldTpl = gBS->RaiseTPL (TPL_CALLBACK); 1932 1933 Instance = IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This); 1934 1935 Item = NetMapFindKey (&Instance->DataItem[DataType].EventMap, Event); 1936 if (Item != NULL) { 1937 1938 NetMapRemoveItem (&Instance->DataItem[DataType].EventMap, Item, NULL); 1939 Status = EFI_SUCCESS; 1940 } else { 1941 1942 Status = EFI_NOT_FOUND; 1943 } 1944 1945 gBS->RestoreTPL (OldTpl); 1946 1947 return Status; 1948 } 1949 1950 /** 1951 Initialize an IP4_CONFIG2_INSTANCE. 1952 1953 @param[out] Instance The buffer of IP4_CONFIG2_INSTANCE to be initialized. 1954 1955 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation. 1956 @retval EFI_SUCCESS The IP4_CONFIG2_INSTANCE initialized successfully. 1957 1958 **/ 1959 EFI_STATUS 1960 Ip4Config2InitInstance ( 1961 OUT IP4_CONFIG2_INSTANCE *Instance 1962 ) 1963 { 1964 IP4_SERVICE *IpSb; 1965 IP4_CONFIG2_INSTANCE *TmpInstance; 1966 LIST_ENTRY *Entry; 1967 EFI_STATUS Status; 1968 UINTN Index; 1969 UINT16 IfIndex; 1970 IP4_CONFIG2_DATA_ITEM *DataItem; 1971 1972 1973 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance); 1974 1975 Instance->Signature = IP4_CONFIG2_INSTANCE_SIGNATURE; 1976 1977 1978 // 1979 // Determine the index of this interface. 1980 // 1981 IfIndex = 0; 1982 NET_LIST_FOR_EACH (Entry, &mIp4Config2InstanceList) { 1983 TmpInstance = NET_LIST_USER_STRUCT_S (Entry, IP4_CONFIG2_INSTANCE, Link, IP4_CONFIG2_INSTANCE_SIGNATURE); 1984 1985 if (TmpInstance->IfIndex > IfIndex) { 1986 // 1987 // There is a sequence hole because some interface is down. 1988 // 1989 break; 1990 } 1991 1992 IfIndex++; 1993 } 1994 1995 Instance->IfIndex = IfIndex; 1996 NetListInsertBefore (Entry, &Instance->Link); 1997 1998 for (Index = 0; Index < Ip4Config2DataTypeMaximum; Index++) { 1999 // 2000 // Initialize the event map for each data item. 2001 // 2002 NetMapInit (&Instance->DataItem[Index].EventMap); 2003 } 2004 2005 2006 // 2007 // Initialize each data type: associate storage and set data size for the 2008 // fixed size data types, hook the SetData function, set the data attribute. 2009 // 2010 DataItem = &Instance->DataItem[Ip4Config2DataTypeInterfaceInfo]; 2011 DataItem->GetData = Ip4Config2GetIfInfo; 2012 DataItem->Data.Ptr = &Instance->InterfaceInfo; 2013 DataItem->DataSize = sizeof (Instance->InterfaceInfo); 2014 SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED | DATA_ATTRIB_VOLATILE); 2015 Ip4Config2InitIfInfo (IpSb, &Instance->InterfaceInfo); 2016 2017 DataItem = &Instance->DataItem[Ip4Config2DataTypePolicy]; 2018 DataItem->SetData = Ip4Config2SetPolicy; 2019 DataItem->Data.Ptr = &Instance->Policy; 2020 DataItem->DataSize = sizeof (Instance->Policy); 2021 Instance->Policy = Ip4Config2PolicyStatic; 2022 SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED); 2023 2024 DataItem = &Instance->DataItem[Ip4Config2DataTypeManualAddress]; 2025 DataItem->SetData = Ip4Config2SetManualAddress; 2026 DataItem->Status = EFI_NOT_FOUND; 2027 2028 DataItem = &Instance->DataItem[Ip4Config2DataTypeGateway]; 2029 DataItem->SetData = Ip4Config2SetGateway; 2030 DataItem->Status = EFI_NOT_FOUND; 2031 2032 DataItem = &Instance->DataItem[Ip4Config2DataTypeDnsServer]; 2033 DataItem->SetData = Ip4Config2SetDnsServer; 2034 DataItem->Status = EFI_NOT_FOUND; 2035 2036 Instance->Configured = TRUE; 2037 2038 // 2039 // Try to read the config data from NV variable. 2040 // If not found, write initialized config data into NV variable 2041 // as a default config data. 2042 // 2043 Status = Ip4Config2ReadConfigData (IpSb->MacString, Instance); 2044 if (Status == EFI_NOT_FOUND) { 2045 Status = Ip4Config2WriteConfigData (IpSb->MacString, Instance); 2046 } 2047 2048 if (EFI_ERROR (Status)) { 2049 return Status; 2050 } 2051 2052 Instance->Ip4Config2.SetData = EfiIp4Config2SetData; 2053 Instance->Ip4Config2.GetData = EfiIp4Config2GetData; 2054 Instance->Ip4Config2.RegisterDataNotify = EfiIp4Config2RegisterDataNotify; 2055 Instance->Ip4Config2.UnregisterDataNotify = EfiIp4Config2UnregisterDataNotify; 2056 2057 // 2058 // Publish the IP4 configuration form 2059 // 2060 return Ip4Config2FormInit (Instance); 2061 } 2062 2063 2064 /** 2065 Release an IP4_CONFIG2_INSTANCE. 2066 2067 @param[in, out] Instance The buffer of IP4_CONFIG2_INSTANCE to be freed. 2068 2069 **/ 2070 VOID 2071 Ip4Config2CleanInstance ( 2072 IN OUT IP4_CONFIG2_INSTANCE *Instance 2073 ) 2074 { 2075 UINTN Index; 2076 IP4_CONFIG2_DATA_ITEM *DataItem; 2077 2078 if (Instance->DeclineAddress != NULL) { 2079 FreePool (Instance->DeclineAddress); 2080 } 2081 2082 if (!Instance->Configured) { 2083 return ; 2084 } 2085 2086 if (Instance->Dhcp4Handle != NULL) { 2087 2088 Ip4Config2DestroyDhcp4 (Instance); 2089 } 2090 2091 // 2092 // Close the event. 2093 // 2094 if (Instance->Dhcp4Event != NULL) { 2095 gBS->CloseEvent (Instance->Dhcp4Event); 2096 Instance->Dhcp4Event = NULL; 2097 } 2098 2099 for (Index = 0; Index < Ip4Config2DataTypeMaximum; Index++) { 2100 2101 DataItem = &Instance->DataItem[Index]; 2102 2103 if (!DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED)) { 2104 if (DataItem->Data.Ptr != NULL) { 2105 FreePool (DataItem->Data.Ptr); 2106 } 2107 DataItem->Data.Ptr = NULL; 2108 DataItem->DataSize = 0; 2109 } 2110 2111 NetMapClean (&Instance->DataItem[Index].EventMap); 2112 } 2113 2114 Ip4Config2FormUnload (Instance); 2115 2116 RemoveEntryList (&Instance->Link); 2117 } 2118 2119 /** 2120 The event handle for IP4 auto reconfiguration. The original default 2121 interface and route table will be removed as the default. 2122 2123 @param[in] Context The IP4 service binding instance. 2124 2125 **/ 2126 VOID 2127 EFIAPI 2128 Ip4AutoReconfigCallBackDpc ( 2129 IN VOID *Context 2130 ) 2131 { 2132 IP4_SERVICE *IpSb; 2133 2134 IpSb = (IP4_SERVICE *) Context; 2135 NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE); 2136 2137 if (IpSb->State > IP4_SERVICE_UNSTARTED) { 2138 IpSb->State = IP4_SERVICE_UNSTARTED; 2139 } 2140 2141 IpSb->Reconfig = TRUE; 2142 2143 Ip4StartAutoConfig (&IpSb->Ip4Config2Instance); 2144 2145 return ; 2146 } 2147 2148 2149 /** 2150 Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK. 2151 2152 @param Event The event that is signalled. 2153 @param Context The IP4 service binding instance. 2154 2155 **/ 2156 VOID 2157 EFIAPI 2158 Ip4AutoReconfigCallBack ( 2159 IN EFI_EVENT Event, 2160 IN VOID *Context 2161 ) 2162 { 2163 // 2164 // Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK 2165 // 2166 QueueDpc (TPL_CALLBACK, Ip4AutoReconfigCallBackDpc, Context); 2167 } 2168 2169