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