2 The implementation of EFI IPv4 Configuration II Protocol.
4 Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>
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.
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.
19 LIST_ENTRY mIp4Config2InstanceList
= {&mIp4Config2InstanceList
, &mIp4Config2InstanceList
};
22 The event process routine when the DHCPv4 service binding protocol is installed
25 @param[in] Event Not used.
26 @param[in] Context Pointer to the IP4 config2 instance data.
31 Ip4Config2OnDhcp4SbInstalled (
37 Destroy the Dhcp4 child in IP4_CONFIG2_INSTANCE and release the resources.
39 @param[in, out] Instance The buffer of IP4 config2 instance to be freed.
41 @retval EFI_SUCCESS The child was successfully destroyed.
42 @retval Others Failed to destroy the child.
46 Ip4Config2DestroyDhcp4 (
47 IN OUT IP4_CONFIG2_INSTANCE
*Instance
52 EFI_DHCP4_PROTOCOL
*Dhcp4
;
54 Dhcp4
= Instance
->Dhcp4
;
55 ASSERT (Dhcp4
!= NULL
);
58 Dhcp4
->Configure (Dhcp4
, NULL
);
59 Instance
->Dhcp4
= NULL
;
61 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
64 // Close DHCPv4 protocol and destroy the child.
66 Status
= gBS
->CloseProtocol (
67 Instance
->Dhcp4Handle
,
68 &gEfiDhcp4ProtocolGuid
,
72 if (EFI_ERROR (Status
)) {
76 Status
= NetLibDestroyServiceChild (
79 &gEfiDhcp4ServiceBindingProtocolGuid
,
83 Instance
->Dhcp4Handle
= NULL
;
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.
93 @param[in] IpSb The IP4 service binding instance.
94 @param[in] NewPolicy The new policy to be updated to.
98 Ip4Config2OnPolicyChanged (
100 IN EFI_IP4_CONFIG2_POLICY NewPolicy
104 IP4_ROUTE_TABLE
*RouteTable
;
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.
112 if (IpSb
->DefaultInterface
!= NULL
) {
113 if (IpSb
->DefaultRouteTable
!= NULL
) {
114 Ip4FreeRouteTable (IpSb
->DefaultRouteTable
);
115 IpSb
->DefaultRouteTable
= NULL
;
118 Ip4CancelReceive (IpSb
->DefaultInterface
);
120 Ip4FreeInterface (IpSb
->DefaultInterface
, NULL
);
121 IpSb
->DefaultInterface
= NULL
;
124 Ip4CleanAssembleTable (&IpSb
->Assemble
);
127 // Create new default interface and route table.
129 IpIf
= Ip4CreateInterface (IpSb
->Mnp
, IpSb
->Controller
, IpSb
->Image
);
134 RouteTable
= Ip4CreateRouteTable ();
135 if (RouteTable
== NULL
) {
136 Ip4FreeInterface (IpIf
, NULL
);
140 IpSb
->DefaultInterface
= IpIf
;
141 InsertHeadList (&IpSb
->Interfaces
, &IpIf
->Link
);
142 IpSb
->DefaultRouteTable
= RouteTable
;
143 Ip4ReceiveFrame (IpIf
, NULL
, Ip4AccpetFrame
, IpSb
);
145 if (IpSb
->State
== IP4_SERVICE_CONFIGED
|| IpSb
->State
== IP4_SERVICE_STARTED
) {
146 IpSb
->State
= IP4_SERVICE_UNSTARTED
;
150 // Start the dhcp configuration.
152 if (NewPolicy
== Ip4Config2PolicyDhcp
) {
153 Ip4StartAutoConfig (&IpSb
->Ip4Config2Instance
);
159 Signal the registered event. It is the callback routine for NetMapIterate.
161 @param[in] Map Points to the list of registered event.
162 @param[in] Item The registered event.
163 @param[in] Arg Not used.
165 @retval EFI_SUCCESS The event was signaled successfully.
169 Ip4Config2SignalEvent (
171 IN NET_MAP_ITEM
*Item
,
175 gBS
->SignalEvent ((EFI_EVENT
) Item
->Key
);
181 Read the configuration data from variable storage according to the VarName and
182 gEfiIp4Config2ProtocolGuid. It checks the integrity of variable data. If the
183 data is corrupted, it clears the variable data to ZERO. Othewise, it outputs the
184 configuration data to IP4_CONFIG2_INSTANCE.
186 @param[in] VarName The pointer to the variable name
187 @param[in, out] Instance The pointer to the IP4 config2 instance data.
189 @retval EFI_NOT_FOUND The variable can not be found or already corrupted.
190 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
191 @retval EFI_SUCCESS The configuration data was retrieved successfully.
195 Ip4Config2ReadConfigData (
197 IN OUT IP4_CONFIG2_INSTANCE
*Instance
202 IP4_CONFIG2_VARIABLE
*Variable
;
203 IP4_CONFIG2_DATA_ITEM
*DataItem
;
205 IP4_CONFIG2_DATA_RECORD DataRecord
;
209 // Try to read the configuration variable.
212 Status
= gRT
->GetVariable (
214 &gEfiIp4Config2ProtocolGuid
,
220 if (Status
== EFI_BUFFER_TOO_SMALL
) {
222 // Allocate buffer and read the config variable.
224 Variable
= AllocatePool (VarSize
);
225 if (Variable
== NULL
) {
226 return EFI_OUT_OF_RESOURCES
;
229 Status
= gRT
->GetVariable (
231 &gEfiIp4Config2ProtocolGuid
,
236 if (EFI_ERROR (Status
) || (UINT16
) (~NetblockChecksum ((UINT8
*) Variable
, (UINT32
) VarSize
)) != 0) {
238 // GetVariable still error or the variable is corrupted.
239 // Fall back to the default value.
244 // Remove the problematic variable and return EFI_NOT_FOUND, a new
245 // variable will be set again.
249 &gEfiIp4Config2ProtocolGuid
,
250 IP4_CONFIG2_VARIABLE_ATTRIBUTE
,
255 return EFI_NOT_FOUND
;
259 for (Index
= 0; Index
< Variable
->DataRecordCount
; Index
++) {
261 CopyMem (&DataRecord
, &Variable
->DataRecord
[Index
], sizeof (DataRecord
));
263 DataItem
= &Instance
->DataItem
[DataRecord
.DataType
];
264 if (DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
) &&
265 (DataItem
->DataSize
!= DataRecord
.DataSize
)
268 // Perhaps a corrupted data record...
273 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
)) {
275 // This data item has variable length data.
277 DataItem
->Data
.Ptr
= AllocatePool (DataRecord
.DataSize
);
278 if (DataItem
->Data
.Ptr
== NULL
) {
280 // no memory resource
286 Data
= (CHAR8
*) Variable
+ DataRecord
.Offset
;
287 CopyMem (DataItem
->Data
.Ptr
, Data
, DataRecord
.DataSize
);
289 DataItem
->DataSize
= DataRecord
.DataSize
;
290 DataItem
->Status
= EFI_SUCCESS
;
301 Write the configuration data from IP4_CONFIG2_INSTANCE to variable storage.
303 @param[in] VarName The pointer to the variable name.
304 @param[in] Instance The pointer to the IP4 config2 instance data.
306 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
307 @retval EFI_SUCCESS The configuration data is written successfully.
311 Ip4Config2WriteConfigData (
313 IN IP4_CONFIG2_INSTANCE
*Instance
318 IP4_CONFIG2_DATA_ITEM
*DataItem
;
319 IP4_CONFIG2_VARIABLE
*Variable
;
320 IP4_CONFIG2_DATA_RECORD
*DataRecord
;
324 VarSize
= sizeof (IP4_CONFIG2_VARIABLE
) - sizeof (IP4_CONFIG2_DATA_RECORD
);
326 for (Index
= 0; Index
< Ip4Config2DataTypeMaximum
; Index
++) {
328 DataItem
= &Instance
->DataItem
[Index
];
329 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_VOLATILE
) && !EFI_ERROR (DataItem
->Status
)) {
331 VarSize
+= sizeof (IP4_CONFIG2_DATA_RECORD
) + DataItem
->DataSize
;
335 Variable
= AllocatePool (VarSize
);
336 if (Variable
== NULL
) {
337 return EFI_OUT_OF_RESOURCES
;
340 Heap
= (CHAR8
*) Variable
+ VarSize
;
341 Variable
->DataRecordCount
= 0;
343 for (Index
= 0; Index
< Ip4Config2DataTypeMaximum
; Index
++) {
345 DataItem
= &Instance
->DataItem
[Index
];
346 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_VOLATILE
) && !EFI_ERROR (DataItem
->Status
)) {
348 Heap
-= DataItem
->DataSize
;
349 CopyMem (Heap
, DataItem
->Data
.Ptr
, DataItem
->DataSize
);
351 DataRecord
= &Variable
->DataRecord
[Variable
->DataRecordCount
];
352 DataRecord
->DataType
= (EFI_IP4_CONFIG2_DATA_TYPE
) Index
;
353 DataRecord
->DataSize
= (UINT32
) DataItem
->DataSize
;
354 DataRecord
->Offset
= (UINT16
) (Heap
- (CHAR8
*) Variable
);
356 Variable
->DataRecordCount
++;
360 Variable
->Checksum
= 0;
361 Variable
->Checksum
= (UINT16
) ~NetblockChecksum ((UINT8
*) Variable
, (UINT32
) VarSize
);
363 Status
= gRT
->SetVariable (
365 &gEfiIp4Config2ProtocolGuid
,
366 IP4_CONFIG2_VARIABLE_ATTRIBUTE
,
378 Build a EFI_IP4_ROUTE_TABLE to be returned to the caller of GetModeData.
379 The EFI_IP4_ROUTE_TABLE is clumsy to use in the internal operation of the
382 @param[in] IpSb The IP4 service binding instance.
383 @param[out] Table The built IP4 route table.
385 @retval EFI_SUCCESS The route table is successfully build
386 @retval EFI_NOT_FOUND Failed to allocate the memory for the rotue table.
390 Ip4Config2BuildDefaultRouteTable (
391 IN IP4_SERVICE
*IpSb
,
392 OUT EFI_IP4_ROUTE_TABLE
*Table
396 IP4_ROUTE_ENTRY
*RtEntry
;
400 if (IpSb
->DefaultRouteTable
== NULL
) {
401 return EFI_NOT_FOUND
;
404 Count
= IpSb
->DefaultRouteTable
->TotalNum
;
407 return EFI_NOT_FOUND
;
411 // Copy the route entry to EFI route table. Keep the order of
412 // route entry copied from most specific to default route. That
413 // is, interlevel the route entry from the instance's route area
414 // and those from the default route table's route area.
418 for (Index
= IP4_MASK_MAX
; Index
>= 0; Index
--) {
420 NET_LIST_FOR_EACH (Entry
, &(IpSb
->DefaultRouteTable
->RouteArea
[Index
])) {
421 RtEntry
= NET_LIST_USER_STRUCT (Entry
, IP4_ROUTE_ENTRY
, Link
);
423 EFI_IP4 (Table
[Count
].SubnetAddress
) = HTONL (RtEntry
->Dest
& RtEntry
->Netmask
);
424 EFI_IP4 (Table
[Count
].SubnetMask
) = HTONL (RtEntry
->Netmask
);
425 EFI_IP4 (Table
[Count
].GatewayAddress
) = HTONL (RtEntry
->NextHop
);
436 The event process routine when the DHCPv4 service binding protocol is installed
439 @param[in] Event Not used.
440 @param[in] Context The pointer to the IP4 config2 instance data.
445 Ip4Config2OnDhcp4SbInstalled (
450 IP4_CONFIG2_INSTANCE
*Instance
;
452 Instance
= (IP4_CONFIG2_INSTANCE
*) Context
;
454 if ((Instance
->Dhcp4Handle
!= NULL
) || (Instance
->Policy
!= Ip4Config2PolicyDhcp
)) {
456 // The DHCP4 child is already created or the policy is no longer DHCP.
461 Ip4StartAutoConfig (Instance
);
465 Set the station address and subnetmask for the default interface.
467 @param[in] IpSb The pointer to the IP4 service binding instance.
468 @param[in] StationAddress Ip address to be set.
469 @param[in] SubnetMask Subnet to be set.
471 @retval EFI_SUCCESS Set default address successful.
472 @retval Others Some errors occur in setting.
476 Ip4Config2SetDefaultAddr (
477 IN IP4_SERVICE
*IpSb
,
478 IN IP4_ADDR StationAddress
,
479 IN IP4_ADDR SubnetMask
484 IP4_PROTOCOL
*Ip4Instance
;
485 EFI_ARP_PROTOCOL
*Arp
;
488 IP4_ROUTE_TABLE
*RouteTable
;
490 IpIf
= IpSb
->DefaultInterface
;
491 ASSERT (IpIf
!= NULL
);
493 if ((IpIf
->Ip
== StationAddress
) && (IpIf
->SubnetMask
== SubnetMask
)) {
494 IpSb
->State
= IP4_SERVICE_CONFIGED
;
498 if (IpSb
->Reconfig
) {
500 // The default address is changed, free the previous interface first.
502 if (IpSb
->DefaultRouteTable
!= NULL
) {
503 Ip4FreeRouteTable (IpSb
->DefaultRouteTable
);
504 IpSb
->DefaultRouteTable
= NULL
;
507 Ip4CancelReceive (IpSb
->DefaultInterface
);
508 Ip4FreeInterface (IpSb
->DefaultInterface
, NULL
);
509 IpSb
->DefaultInterface
= NULL
;
511 // Create new default interface and route table.
513 IpIf
= Ip4CreateInterface (IpSb
->Mnp
, IpSb
->Controller
, IpSb
->Image
);
515 return EFI_OUT_OF_RESOURCES
;
518 RouteTable
= Ip4CreateRouteTable ();
519 if (RouteTable
== NULL
) {
520 Ip4FreeInterface (IpIf
, NULL
);
521 return EFI_OUT_OF_RESOURCES
;
524 IpSb
->DefaultInterface
= IpIf
;
525 InsertHeadList (&IpSb
->Interfaces
, &IpIf
->Link
);
526 IpSb
->DefaultRouteTable
= RouteTable
;
527 Ip4ReceiveFrame (IpIf
, NULL
, Ip4AccpetFrame
, IpSb
);
530 if (IpSb
->State
== IP4_SERVICE_CONFIGED
) {
531 IpSb
->State
= IP4_SERVICE_UNSTARTED
;
534 Status
= Ip4SetAddress (IpIf
, StationAddress
, SubnetMask
);
535 if (EFI_ERROR (Status
)) {
539 if (IpIf
->Arp
!= NULL
) {
541 // A non-NULL IpIf->Arp here means a new ARP child is created when setting default address,
542 // but some IP children may have referenced the default interface before it is configured,
543 // these IP instances also consume this ARP protocol so they need to open it BY_CHILD_CONTROLLER.
546 NET_LIST_FOR_EACH (Entry
, &IpIf
->IpInstances
) {
547 Ip4Instance
= NET_LIST_USER_STRUCT_S (Entry
, IP4_PROTOCOL
, AddrLink
, IP4_PROTOCOL_SIGNATURE
);
548 Status
= gBS
->OpenProtocol (
550 &gEfiArpProtocolGuid
,
552 gIp4DriverBinding
.DriverBindingHandle
,
554 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
556 if (EFI_ERROR (Status
)) {
563 IpSb
->DefaultRouteTable
,
570 // Add a route for the connected network.
572 Subnet
= StationAddress
& SubnetMask
;
575 IpSb
->DefaultRouteTable
,
581 IpSb
->State
= IP4_SERVICE_CONFIGED
;
582 IpSb
->Reconfig
= FALSE
;
588 Set the station address, subnetmask and gateway address for the default interface.
590 @param[in] Instance The pointer to the IP4 config2 instance data.
591 @param[in] StationAddress Ip address to be set.
592 @param[in] SubnetMask Subnet to be set.
593 @param[in] GatewayAddress Gateway to be set.
595 @retval EFI_SUCCESS Set default If successful.
596 @retval Others Errors occur as indicated.
600 Ip4Config2SetDefaultIf (
601 IN IP4_CONFIG2_INSTANCE
*Instance
,
602 IN IP4_ADDR StationAddress
,
603 IN IP4_ADDR SubnetMask
,
604 IN IP4_ADDR GatewayAddress
610 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
612 Status
= Ip4Config2SetDefaultAddr (IpSb
, StationAddress
, SubnetMask
);
613 if (EFI_ERROR (Status
)) {
618 // Create a route if there is a default router.
620 if (GatewayAddress
!= IP4_ALLZERO_ADDRESS
) {
622 IpSb
->DefaultRouteTable
,
634 Release all the DHCP related resources.
636 @param Instance The IP4 config2 instance.
642 Ip4Config2CleanDhcp4 (
643 IN IP4_CONFIG2_INSTANCE
*Instance
648 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
650 if (Instance
->Dhcp4
!= NULL
) {
651 Instance
->Dhcp4
->Stop (Instance
->Dhcp4
);
654 Instance
->Dhcp4Handle
,
655 &gEfiDhcp4ProtocolGuid
,
660 Instance
->Dhcp4
= NULL
;
663 if (Instance
->Dhcp4Handle
!= NULL
) {
664 NetLibDestroyServiceChild (
667 &gEfiDhcp4ServiceBindingProtocolGuid
,
668 Instance
->Dhcp4Handle
671 Instance
->Dhcp4Handle
= NULL
;
674 if (Instance
->Dhcp4Event
!= NULL
) {
675 gBS
->CloseEvent (Instance
->Dhcp4Event
);
676 Instance
->Dhcp4Event
= NULL
;
681 This worker function sets the DNS server list for the EFI IPv4 network
682 stack running on the communication device that this EFI_IP4_CONFIG2_PROTOCOL
683 manages. The DNS server addresses must be unicast IPv4 addresses.
685 @param[in] Instance The pointer to the IP4 config2 instance data.
686 @param[in] DataSize The size of the buffer pointed to by Data in bytes.
687 @param[in] Data The data buffer to set, points to an array of
688 EFI_IPv4_ADDRESS instances.
690 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
691 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
692 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
693 @retval EFI_ABORTED The DNS server addresses to be set equal the current
695 @retval EFI_SUCCESS The specified configuration data for the EFI IPv4
696 network stack was set.
700 Ip4Config2SetDnsServerWorker (
701 IN IP4_CONFIG2_INSTANCE
*Instance
,
709 EFI_IPv4_ADDRESS
*OldDns
;
710 EFI_IPv4_ADDRESS
*NewDns
;
713 IP4_CONFIG2_DATA_ITEM
*Item
;
718 if ((DataSize
% sizeof (EFI_IPv4_ADDRESS
) != 0) || (DataSize
== 0)) {
719 return EFI_BAD_BUFFER_SIZE
;
722 Item
= &Instance
->DataItem
[Ip4Config2DataTypeDnsServer
];
723 NewDns
= (EFI_IPv4_ADDRESS
*) Data
;
724 OldDns
= Item
->Data
.DnsServers
;
725 NewDnsCount
= DataSize
/ sizeof (EFI_IPv4_ADDRESS
);
726 OldDnsCount
= Item
->DataSize
/ sizeof (EFI_IPv4_ADDRESS
);
729 if (NewDnsCount
!= OldDnsCount
) {
730 Tmp
= AllocatePool (DataSize
);
732 return EFI_OUT_OF_RESOURCES
;
738 for (NewIndex
= 0; NewIndex
< NewDnsCount
; NewIndex
++) {
739 CopyMem (&DnsAddress
, NewDns
+ NewIndex
, sizeof (IP4_ADDR
));
740 if (IP4_IS_UNSPECIFIED (NTOHL (DnsAddress
)) || IP4_IS_LOCAL_BROADCAST (NTOHL (DnsAddress
))) {
742 // The dns server address must be unicast.
745 return EFI_INVALID_PARAMETER
;
748 for (Index1
= NewIndex
+ 1; Index1
< NewDnsCount
; Index1
++) {
749 if (EFI_IP4_EQUAL (NewDns
+ NewIndex
, NewDns
+ Index1
)) {
751 return EFI_INVALID_PARAMETER
;
757 // If any address in the new setting is not in the old settings, skip the
758 // comparision below.
763 for (OldIndex
= 0; OldIndex
< OldDnsCount
; OldIndex
++) {
764 if (EFI_IP4_EQUAL (NewDns
+ NewIndex
, OldDns
+ OldIndex
)) {
766 // If found break out.
772 if (OldIndex
== OldDnsCount
) {
777 if (!OneAdded
&& (DataSize
== Item
->DataSize
)) {
779 // No new item is added and the size is the same.
781 Item
->Status
= EFI_SUCCESS
;
785 if (Item
->Data
.Ptr
!= NULL
) {
786 FreePool (Item
->Data
.Ptr
);
788 Item
->Data
.Ptr
= Tmp
;
791 CopyMem (Item
->Data
.Ptr
, Data
, DataSize
);
792 Item
->DataSize
= DataSize
;
793 Item
->Status
= EFI_SUCCESS
;
801 Callback function when DHCP process finished. It will save the
802 retrieved IP configure parameter from DHCP to the NVRam.
804 @param Event The callback event
805 @param Context Opaque context to the callback
812 Ip4Config2OnDhcp4Complete (
817 IP4_CONFIG2_INSTANCE
*Instance
;
818 EFI_DHCP4_MODE_DATA Dhcp4Mode
;
820 IP4_ADDR StationAddress
;
822 IP4_ADDR GatewayAddress
;
825 EFI_DHCP4_PACKET_OPTION
**OptionList
;
827 Instance
= (IP4_CONFIG2_INSTANCE
*) Context
;
828 ASSERT (Instance
->Dhcp4
!= NULL
);
831 // Get the DHCP retrieved parameters
833 Status
= Instance
->Dhcp4
->GetModeData (Instance
->Dhcp4
, &Dhcp4Mode
);
835 if (EFI_ERROR (Status
)) {
839 if (Dhcp4Mode
.State
== Dhcp4Bound
) {
840 StationAddress
= EFI_NTOHL (Dhcp4Mode
.ClientAddress
);
841 SubnetMask
= EFI_NTOHL (Dhcp4Mode
.SubnetMask
);
842 GatewayAddress
= EFI_NTOHL (Dhcp4Mode
.RouterAddress
);
844 Status
= Ip4Config2SetDefaultIf (Instance
, StationAddress
, SubnetMask
, GatewayAddress
);
845 if (EFI_ERROR (Status
)) {
850 // Parse the ACK to get required DNS server information.
855 Status
= Instance
->Dhcp4
->Parse (Instance
->Dhcp4
, Dhcp4Mode
.ReplyPacket
, &OptionCount
, OptionList
);
856 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
860 OptionList
= AllocateZeroPool (OptionCount
* sizeof (EFI_DHCP4_PACKET_OPTION
*));
861 if (OptionList
== NULL
) {
865 Status
= Instance
->Dhcp4
->Parse (Instance
->Dhcp4
, Dhcp4Mode
.ReplyPacket
, &OptionCount
, OptionList
);
866 if (EFI_ERROR (Status
)) {
867 FreePool (OptionList
);
871 for (Index
= 0; Index
< OptionCount
; Index
++) {
873 // Look for DNS Server opcode (6).
875 if (OptionList
[Index
]->OpCode
== DHCP4_TAG_DNS_SERVER
) {
876 if (((OptionList
[Index
]->Length
& 0x3) != 0) || (OptionList
[Index
]->Length
== 0)) {
880 Ip4Config2SetDnsServerWorker (Instance
, OptionList
[Index
]->Length
, &OptionList
[Index
]->Data
[0]);
885 FreePool (OptionList
);
887 Instance
->DhcpSuccess
= TRUE
;
891 Ip4Config2CleanDhcp4 (Instance
);
897 Start the DHCP configuration for this IP service instance.
898 It will locates the EFI_IP4_CONFIG2_PROTOCOL, then start the
901 @param[in] Instance The IP4 config2 instance to configure
903 @retval EFI_SUCCESS The auto configuration is successfully started
904 @retval Others Failed to start auto configuration.
909 IN IP4_CONFIG2_INSTANCE
*Instance
913 EFI_DHCP4_PROTOCOL
*Dhcp4
;
914 EFI_DHCP4_MODE_DATA Dhcp4Mode
;
915 EFI_DHCP4_PACKET_OPTION
*OptionList
[1];
916 IP4_CONFIG2_DHCP4_OPTION ParaList
;
920 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
922 if (IpSb
->State
> IP4_SERVICE_UNSTARTED
) {
927 // A host must not invoke DHCP configuration if it is already
928 // participating in the DHCP configuraiton process.
930 if (Instance
->Dhcp4Handle
!= NULL
) {
934 Status
= NetLibCreateServiceChild (
937 &gEfiDhcp4ServiceBindingProtocolGuid
,
938 &Instance
->Dhcp4Handle
941 if (Status
== EFI_UNSUPPORTED
) {
943 // No DHCPv4 Service Binding protocol, register a notify.
945 if (Instance
->Dhcp4SbNotifyEvent
== NULL
) {
946 Instance
->Dhcp4SbNotifyEvent
= EfiCreateProtocolNotifyEvent (
947 &gEfiDhcp4ServiceBindingProtocolGuid
,
949 Ip4Config2OnDhcp4SbInstalled
,
951 &Instance
->Registration
956 if (EFI_ERROR (Status
)) {
960 if (Instance
->Dhcp4SbNotifyEvent
!= NULL
) {
961 gBS
->CloseEvent (Instance
->Dhcp4SbNotifyEvent
);
964 Status
= gBS
->OpenProtocol (
965 Instance
->Dhcp4Handle
,
966 &gEfiDhcp4ProtocolGuid
,
967 (VOID
**) &Instance
->Dhcp4
,
970 EFI_OPEN_PROTOCOL_BY_DRIVER
972 ASSERT_EFI_ERROR (Status
);
976 // Check the current DHCP status, if the DHCP process has
977 // already finished, return now.
979 Dhcp4
= Instance
->Dhcp4
;
980 Status
= Dhcp4
->GetModeData (Dhcp4
, &Dhcp4Mode
);
982 if (Dhcp4Mode
.State
== Dhcp4Bound
) {
983 Ip4Config2OnDhcp4Complete (NULL
, Instance
);
989 // Try to start the DHCP process. Use most of the current
990 // DHCP configuration to avoid problems if some DHCP client
991 // yields the control of this DHCP service to us.
993 ParaList
.Head
.OpCode
= DHCP4_TAG_PARA_LIST
;
994 ParaList
.Head
.Length
= 3;
995 ParaList
.Head
.Data
[0] = DHCP4_TAG_NETMASK
;
996 ParaList
.Route
= DHCP4_TAG_ROUTER
;
997 ParaList
.Dns
= DHCP4_TAG_DNS_SERVER
;
998 OptionList
[0] = &ParaList
.Head
;
999 Dhcp4Mode
.ConfigData
.OptionCount
= 1;
1000 Dhcp4Mode
.ConfigData
.OptionList
= OptionList
;
1002 Status
= Dhcp4
->Configure (Dhcp4
, &Dhcp4Mode
.ConfigData
);
1004 if (EFI_ERROR (Status
)) {
1009 // Start the DHCP process
1011 Status
= gBS
->CreateEvent (
1014 Ip4Config2OnDhcp4Complete
,
1016 &Instance
->Dhcp4Event
1019 if (EFI_ERROR (Status
)) {
1023 Status
= Dhcp4
->Start (Dhcp4
, Instance
->Dhcp4Event
);
1025 if (EFI_ERROR (Status
)) {
1029 IpSb
->State
= IP4_SERVICE_STARTED
;
1038 The work function is to get the interface information of the communication
1039 device this IP4_CONFIG2_INSTANCE manages.
1041 @param[in] Instance Pointer to the IP4 config2 instance data.
1042 @param[in, out] DataSize On input, in bytes, the size of Data. On output, in
1043 bytes, the size of buffer required to store the specified
1045 @param[in] Data The data buffer in which the configuration data is returned.
1046 Ignored if DataSize is ZERO.
1048 @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified
1049 configuration data, and the required size is
1050 returned in DataSize.
1051 @retval EFI_SUCCESS The specified configuration data was obtained.
1055 Ip4Config2GetIfInfo (
1056 IN IP4_CONFIG2_INSTANCE
*Instance
,
1057 IN OUT UINTN
*DataSize
,
1058 IN VOID
*Data OPTIONAL
1063 IP4_CONFIG2_DATA_ITEM
*Item
;
1064 EFI_IP4_CONFIG2_INTERFACE_INFO
*IfInfo
;
1067 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
1068 Length
= sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO
);
1070 if (IpSb
->DefaultRouteTable
!= NULL
) {
1071 Length
+= IpSb
->DefaultRouteTable
->TotalNum
* sizeof (EFI_IP4_ROUTE_TABLE
);
1074 if (*DataSize
< Length
) {
1076 return EFI_BUFFER_TOO_SMALL
;
1080 // Copy the fixed size part of the interface info.
1082 Item
= &Instance
->DataItem
[Ip4Config2DataTypeInterfaceInfo
];
1083 IfInfo
= (EFI_IP4_CONFIG2_INTERFACE_INFO
*) Data
;
1084 CopyMem (IfInfo
, Item
->Data
.Ptr
, sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO
));
1087 // Update the address info.
1089 if (IpSb
->DefaultInterface
!= NULL
) {
1090 Address
= HTONL (IpSb
->DefaultInterface
->Ip
);
1091 CopyMem (&IfInfo
->StationAddress
, &Address
, sizeof (EFI_IPv4_ADDRESS
));
1092 Address
= HTONL (IpSb
->DefaultInterface
->SubnetMask
);
1093 CopyMem (&IfInfo
->SubnetMask
, &Address
, sizeof (EFI_IPv4_ADDRESS
));
1096 if (IpSb
->DefaultRouteTable
!= NULL
) {
1097 IfInfo
->RouteTableSize
= IpSb
->DefaultRouteTable
->TotalNum
;
1098 IfInfo
->RouteTable
= (EFI_IP4_ROUTE_TABLE
*) ((UINT8
*) Data
+ sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO
));
1100 Ip4Config2BuildDefaultRouteTable (IpSb
, IfInfo
->RouteTable
);
1107 The work function is to set the general configuration policy for the EFI IPv4 network
1108 stack that is running on the communication device managed by this IP4_CONFIG2_INSTANCE.
1109 The policy will affect other configuration settings.
1111 @param[in] Instance Pointer to the IP4 config2 instance data.
1112 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
1113 @param[in] Data The data buffer to set.
1115 @retval EFI_INVALID_PARAMETER The to be set policy is invalid.
1116 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1117 @retval EFI_ABORTED The new policy equals the current policy.
1118 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1119 network stack was set.
1123 Ip4Config2SetPolicy (
1124 IN IP4_CONFIG2_INSTANCE
*Instance
,
1129 EFI_IP4_CONFIG2_POLICY NewPolicy
;
1130 IP4_CONFIG2_DATA_ITEM
*DataItem
;
1133 if (DataSize
!= sizeof (EFI_IP4_CONFIG2_POLICY
)) {
1134 return EFI_BAD_BUFFER_SIZE
;
1137 NewPolicy
= *((EFI_IP4_CONFIG2_POLICY
*) Data
);
1139 if (NewPolicy
>= Ip4Config2PolicyMax
) {
1140 return EFI_INVALID_PARAMETER
;
1143 if (NewPolicy
== Instance
->Policy
) {
1144 if (NewPolicy
!= Ip4Config2PolicyDhcp
|| Instance
->DhcpSuccess
) {
1149 // The policy is changed. Clean the ManualAddress, Gateway and DnsServers,
1150 // shrink the variable data size, and fire up all the related events.
1152 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeManualAddress
];
1153 if (DataItem
->Data
.Ptr
!= NULL
) {
1154 FreePool (DataItem
->Data
.Ptr
);
1156 DataItem
->Data
.Ptr
= NULL
;
1157 DataItem
->DataSize
= 0;
1158 DataItem
->Status
= EFI_NOT_FOUND
;
1159 NetMapIterate (&DataItem
->EventMap
, Ip4Config2SignalEvent
, NULL
);
1161 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeGateway
];
1162 if (DataItem
->Data
.Ptr
!= NULL
) {
1163 FreePool (DataItem
->Data
.Ptr
);
1165 DataItem
->Data
.Ptr
= NULL
;
1166 DataItem
->DataSize
= 0;
1167 DataItem
->Status
= EFI_NOT_FOUND
;
1168 NetMapIterate (&DataItem
->EventMap
, Ip4Config2SignalEvent
, NULL
);
1170 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeDnsServer
];
1171 if (DataItem
->Data
.Ptr
!= NULL
) {
1172 FreePool (DataItem
->Data
.Ptr
);
1174 DataItem
->Data
.Ptr
= NULL
;
1175 DataItem
->DataSize
= 0;
1176 DataItem
->Status
= EFI_NOT_FOUND
;
1177 NetMapIterate (&DataItem
->EventMap
, Ip4Config2SignalEvent
, NULL
);
1179 if (NewPolicy
== Ip4Config2PolicyDhcp
) {
1180 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_VOLATILE
);
1183 // The policy is changed from dhcp to static. Stop the DHCPv4 process
1184 // and destroy the DHCPv4 child.
1186 if (Instance
->Dhcp4Handle
!= NULL
) {
1187 Ip4Config2DestroyDhcp4 (Instance
);
1193 if (Instance
->Dhcp4Event
!= NULL
) {
1194 gBS
->CloseEvent (Instance
->Dhcp4Event
);
1195 Instance
->Dhcp4Event
= NULL
;
1200 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
1201 Ip4Config2OnPolicyChanged (IpSb
, NewPolicy
);
1203 Instance
->Policy
= NewPolicy
;
1209 The work function is to set the station addresses manually for the EFI IPv4
1210 network stack. It is only configurable when the policy is Ip4Config2PolicyStatic.
1212 @param[in] Instance Pointer to the IP4 config2 instance data.
1213 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
1214 @param[in] Data The data buffer to set.
1216 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1217 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
1218 under the current policy.
1219 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
1220 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
1221 @retval EFI_NOT_READY An asynchrous process is invoked to set the specified
1222 configuration data, and the process is not finished.
1223 @retval EFI_ABORTED The manual addresses to be set equal current
1225 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1226 network stack was set.
1230 Ip4Config2SetMaunualAddress (
1231 IN IP4_CONFIG2_INSTANCE
*Instance
,
1236 EFI_IP4_CONFIG2_MANUAL_ADDRESS NewAddress
;
1237 IP4_CONFIG2_DATA_ITEM
*DataItem
;
1239 IP4_ADDR StationAddress
;
1240 IP4_ADDR SubnetMask
;
1244 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
1246 ASSERT (Instance
->DataItem
[Ip4Config2DataTypeManualAddress
].Status
!= EFI_NOT_READY
);
1248 if (((DataSize
% sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS
)) != 0) || (DataSize
== 0)) {
1249 return EFI_BAD_BUFFER_SIZE
;
1252 if (Instance
->Policy
!= Ip4Config2PolicyStatic
) {
1253 return EFI_WRITE_PROTECTED
;
1256 NewAddress
= *((EFI_IP4_CONFIG2_MANUAL_ADDRESS
*) Data
);
1258 StationAddress
= EFI_NTOHL (NewAddress
.Address
);
1259 SubnetMask
= EFI_NTOHL (NewAddress
.SubnetMask
);
1261 if (NetGetMaskLength (SubnetMask
) == IP4_MASK_NUM
) {
1262 return EFI_INVALID_PARAMETER
;
1266 // Store the new data, and init the DataItem status to EFI_NOT_READY because
1267 // we may have an asynchronous configuration process.
1269 Ptr
= AllocateCopyPool (DataSize
, Data
);
1271 return EFI_OUT_OF_RESOURCES
;
1274 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeManualAddress
];
1275 if (DataItem
->Data
.Ptr
!= NULL
) {
1276 FreePool (DataItem
->Data
.Ptr
);
1279 DataItem
->Data
.Ptr
= Ptr
;
1280 DataItem
->DataSize
= DataSize
;
1281 DataItem
->Status
= EFI_NOT_READY
;
1283 IpSb
->Reconfig
= TRUE
;
1284 Status
= Ip4Config2SetDefaultAddr (IpSb
, StationAddress
, SubnetMask
);
1285 if (EFI_ERROR (Status
)) {
1289 DataItem
->Status
= EFI_SUCCESS
;
1292 if (EFI_ERROR (DataItem
->Status
)) {
1296 DataItem
->Data
.Ptr
= NULL
;
1303 The work function is to set the gateway addresses manually for the EFI IPv4
1304 network stack that is running on the communication device that this EFI IPv4
1305 Configuration Protocol manages. It is not configurable when the policy is
1306 Ip4Config2PolicyDhcp. The gateway addresses must be unicast IPv4 addresses.
1308 @param[in] Instance The pointer to the IP4 config2 instance data.
1309 @param[in] DataSize The size of the buffer pointed to by Data in bytes.
1310 @param[in] Data The data buffer to set. This points to an array of
1311 EFI_IPv6_ADDRESS instances.
1313 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1314 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
1315 under the current policy.
1316 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
1317 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to complete the operation.
1318 @retval EFI_ABORTED The manual gateway addresses to be set equal the
1319 current configuration.
1320 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1321 network stack was set.
1325 Ip4Config2SetGateway (
1326 IN IP4_CONFIG2_INSTANCE
*Instance
,
1332 IP4_CONFIG2_DATA_ITEM
*DataItem
;
1337 EFI_IPv4_ADDRESS
*OldGateway
;
1338 EFI_IPv4_ADDRESS
*NewGateway
;
1339 UINTN OldGatewayCount
;
1340 UINTN NewGatewayCount
;
1345 if ((DataSize
% sizeof (EFI_IPv4_ADDRESS
) != 0) || (DataSize
== 0)) {
1346 return EFI_BAD_BUFFER_SIZE
;
1349 if (Instance
->Policy
!= Ip4Config2PolicyStatic
) {
1350 return EFI_WRITE_PROTECTED
;
1353 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
1355 NewGateway
= (EFI_IPv4_ADDRESS
*) Data
;
1356 NewGatewayCount
= DataSize
/ sizeof (EFI_IPv4_ADDRESS
);
1357 for (Index1
= 0; Index1
< NewGatewayCount
; Index1
++) {
1358 CopyMem (&Gateway
, NewGateway
+ Index1
, sizeof (IP4_ADDR
));
1360 if ((IpSb
->DefaultInterface
->SubnetMask
!= 0) &&
1361 !NetIp4IsUnicast (NTOHL (Gateway
), IpSb
->DefaultInterface
->SubnetMask
)) {
1362 return EFI_INVALID_PARAMETER
;
1365 for (Index2
= Index1
+ 1; Index2
< NewGatewayCount
; Index2
++) {
1366 if (EFI_IP4_EQUAL (NewGateway
+ Index1
, NewGateway
+ Index2
)) {
1367 return EFI_INVALID_PARAMETER
;
1372 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeGateway
];
1373 OldGateway
= DataItem
->Data
.Gateway
;
1374 OldGatewayCount
= DataItem
->DataSize
/ sizeof (EFI_IPv4_ADDRESS
);
1378 if (NewGatewayCount
!= OldGatewayCount
) {
1379 Tmp
= AllocatePool (DataSize
);
1381 return EFI_OUT_OF_RESOURCES
;
1387 for (Index1
= 0; Index1
< OldGatewayCount
; Index1
++) {
1389 // Remove this route entry.
1391 CopyMem (&Gateway
, OldGateway
+ Index1
, sizeof (IP4_ADDR
));
1393 IpSb
->DefaultRouteTable
,
1394 IP4_ALLZERO_ADDRESS
,
1395 IP4_ALLZERO_ADDRESS
,
1402 for (Index1
= 0; Index1
< NewGatewayCount
; Index1
++) {
1403 CopyMem (&Gateway
, NewGateway
+ Index1
, sizeof (IP4_ADDR
));
1405 IpSb
->DefaultRouteTable
,
1406 IP4_ALLZERO_ADDRESS
,
1407 IP4_ALLZERO_ADDRESS
,
1415 if (!OneRemoved
&& !OneAdded
) {
1416 DataItem
->Status
= EFI_SUCCESS
;
1421 if (DataItem
->Data
.Ptr
!= NULL
) {
1422 FreePool (DataItem
->Data
.Ptr
);
1424 DataItem
->Data
.Ptr
= Tmp
;
1427 CopyMem (DataItem
->Data
.Ptr
, Data
, DataSize
);
1428 DataItem
->DataSize
= DataSize
;
1429 DataItem
->Status
= EFI_SUCCESS
;
1436 The work function is to set the DNS server list for the EFI IPv4 network
1437 stack running on the communication device that this EFI_IP4_CONFIG2_PROTOCOL
1438 manages. It is not configurable when the policy is Ip4Config2PolicyDhcp.
1439 The DNS server addresses must be unicast IPv4 addresses.
1441 @param[in] Instance The pointer to the IP4 config2 instance data.
1442 @param[in] DataSize The size of the buffer pointed to by Data in bytes.
1443 @param[in] Data The data buffer to set, points to an array of
1444 EFI_IPv4_ADDRESS instances.
1446 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1447 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
1448 under the current policy.
1449 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
1450 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
1451 @retval EFI_ABORTED The DNS server addresses to be set equal the current
1453 @retval EFI_SUCCESS The specified configuration data for the EFI IPv4
1454 network stack was set.
1458 Ip4Config2SetDnsServer (
1459 IN IP4_CONFIG2_INSTANCE
*Instance
,
1464 IP4_CONFIG2_DATA_ITEM
*Item
;
1468 if (Instance
->Policy
!= Ip4Config2PolicyStatic
) {
1469 return EFI_WRITE_PROTECTED
;
1472 Item
= &Instance
->DataItem
[Ip4Config2DataTypeDnsServer
];
1474 if (DATA_ATTRIB_SET (Item
->Attribute
, DATA_ATTRIB_VOLATILE
)) {
1475 REMOVE_DATA_ATTRIB (Item
->Attribute
, DATA_ATTRIB_VOLATILE
);
1478 return Ip4Config2SetDnsServerWorker (Instance
, DataSize
, Data
);
1482 Generate the operational state of the interface this IP4 config2 instance manages
1483 and output in EFI_IP4_CONFIG2_INTERFACE_INFO.
1485 @param[in] IpSb The pointer to the IP4 service binding instance.
1486 @param[out] IfInfo The pointer to the IP4 config2 interface information structure.
1490 Ip4Config2InitIfInfo (
1491 IN IP4_SERVICE
*IpSb
,
1492 OUT EFI_IP4_CONFIG2_INTERFACE_INFO
*IfInfo
1495 IfInfo
->Name
[0] = L
'e';
1496 IfInfo
->Name
[1] = L
't';
1497 IfInfo
->Name
[2] = L
'h';
1498 IfInfo
->Name
[3] = (CHAR16
) (L
'0' + IpSb
->Ip4Config2Instance
.IfIndex
);
1499 IfInfo
->Name
[4] = 0;
1501 IfInfo
->IfType
= IpSb
->SnpMode
.IfType
;
1502 IfInfo
->HwAddressSize
= IpSb
->SnpMode
.HwAddressSize
;
1503 CopyMem (&IfInfo
->HwAddress
, &IpSb
->SnpMode
.CurrentAddress
, IfInfo
->HwAddressSize
);
1507 The event handle routine when DHCPv4 process is finished or is updated.
1509 @param[in] Event Not used.
1510 @param[in] Context The pointer to the IP4 configuration instance data.
1515 Ip4Config2OnDhcp4Event (
1525 Set the configuration for the EFI IPv4 network stack running on the communication
1526 device this EFI_IP4_CONFIG2_PROTOCOL instance manages.
1528 This function is used to set the configuration data of type DataType for the EFI
1529 IPv4 network stack that is running on the communication device that this EFI IPv4
1530 Configuration Protocol instance manages.
1532 DataSize is used to calculate the count of structure instances in the Data for
1533 a DataType in which multiple structure instances are allowed.
1535 This function is always non-blocking. When setting some type of configuration data,
1536 an asynchronous process is invoked to check the correctness of the data, such as
1537 performing Duplicate Address Detection on the manually set local IPv4 addresses.
1538 EFI_NOT_READY is returned immediately to indicate that such an asynchronous process
1539 is invoked, and the process is not finished yet. The caller wanting to get the result
1540 of the asynchronous process is required to call RegisterDataNotify() to register an
1541 event on the specified configuration data. Once the event is signaled, the caller
1542 can call GetData() to obtain the configuration data and know the result.
1543 For other types of configuration data that do not require an asynchronous configuration
1544 process, the result of the operation is immediately returned.
1546 @param[in] This The pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
1547 @param[in] DataType The type of data to set.
1548 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
1549 @param[in] Data The data buffer to set. The type of the data buffer is
1550 associated with the DataType.
1552 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1553 network stack was set successfully.
1554 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
1557 - One or more fields in Data do not match the requirement of the
1558 data type indicated by DataType.
1559 @retval EFI_WRITE_PROTECTED The specified configuration data is read-only or the specified
1560 configuration data cannot be set under the current policy.
1561 @retval EFI_ACCESS_DENIED Another set operation on the specified configuration
1562 data is already in process.
1563 @retval EFI_NOT_READY An asynchronous process was invoked to set the specified
1564 configuration data, and the process is not finished yet.
1565 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type
1566 indicated by DataType.
1567 @retval EFI_UNSUPPORTED This DataType is not supported.
1568 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
1569 @retval EFI_DEVICE_ERROR An unexpected system error or network error occurred.
1574 EfiIp4Config2SetData (
1575 IN EFI_IP4_CONFIG2_PROTOCOL
*This
,
1576 IN EFI_IP4_CONFIG2_DATA_TYPE DataType
,
1583 IP4_CONFIG2_INSTANCE
*Instance
;
1586 if ((This
== NULL
) || (Data
== NULL
)) {
1587 return EFI_INVALID_PARAMETER
;
1590 if (DataType
>= Ip4Config2DataTypeMaximum
) {
1591 return EFI_UNSUPPORTED
;
1594 Instance
= IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This
);
1595 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
1596 NET_CHECK_SIGNATURE (IpSb
, IP4_SERVICE_SIGNATURE
);
1599 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1601 Status
= Instance
->DataItem
[DataType
].Status
;
1602 if (Status
!= EFI_NOT_READY
) {
1604 if (Instance
->DataItem
[DataType
].SetData
== NULL
) {
1606 // This type of data is readonly.
1608 Status
= EFI_WRITE_PROTECTED
;
1611 Status
= Instance
->DataItem
[DataType
].SetData (Instance
, DataSize
, Data
);
1612 if (!EFI_ERROR (Status
)) {
1614 // Fire up the events registered with this type of data.
1616 NetMapIterate (&Instance
->DataItem
[DataType
].EventMap
, Ip4Config2SignalEvent
, NULL
);
1617 Ip4Config2WriteConfigData (IpSb
->MacString
, Instance
);
1618 } else if (Status
== EFI_ABORTED
) {
1620 // The SetData is aborted because the data to set is the same with
1621 // the one maintained.
1623 Status
= EFI_SUCCESS
;
1624 NetMapIterate (&Instance
->DataItem
[DataType
].EventMap
, Ip4Config2SignalEvent
, NULL
);
1629 // Another asynchornous process is on the way.
1631 Status
= EFI_ACCESS_DENIED
;
1634 gBS
->RestoreTPL (OldTpl
);
1640 Get the configuration data for the EFI IPv4 network stack running on the communication
1641 device that this EFI_IP4_CONFIG2_PROTOCOL instance manages.
1643 This function returns the configuration data of type DataType for the EFI IPv4 network
1644 stack running on the communication device that this EFI IPv4 Configuration Protocol instance
1647 The caller is responsible for allocating the buffer used to return the specified
1648 configuration data. The required size will be returned to the caller if the size of
1649 the buffer is too small.
1651 EFI_NOT_READY is returned if the specified configuration data is not ready due to an
1652 asynchronous configuration process already in progress. The caller can call RegisterDataNotify()
1653 to register an event on the specified configuration data. Once the asynchronous configuration
1654 process is finished, the event will be signaled, and a subsequent GetData() call will return
1655 the specified configuration data.
1657 @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
1658 @param[in] DataType The type of data to get.
1659 @param[in, out] DataSize On input, in bytes, the size of Data. On output, in bytes, the
1660 size of buffer required to store the specified configuration data.
1661 @param[in] Data The data buffer in which the configuration data is returned. The
1662 type of the data buffer is associated with the DataType.
1663 This is an optional parameter that may be NULL.
1665 @retval EFI_SUCCESS The specified configuration data was obtained successfully.
1666 @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
1669 - Data is NULL if *DataSize is not zero.
1670 @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified configuration data,
1671 and the required size is returned in DataSize.
1672 @retval EFI_NOT_READY The specified configuration data is not ready due to an
1673 asynchronous configuration process already in progress.
1674 @retval EFI_NOT_FOUND The specified configuration data is not found.
1679 EfiIp4Config2GetData (
1680 IN EFI_IP4_CONFIG2_PROTOCOL
*This
,
1681 IN EFI_IP4_CONFIG2_DATA_TYPE DataType
,
1682 IN OUT UINTN
*DataSize
,
1683 IN VOID
*Data OPTIONAL
1688 IP4_CONFIG2_INSTANCE
*Instance
;
1689 IP4_CONFIG2_DATA_ITEM
*DataItem
;
1691 if ((This
== NULL
) || (DataSize
== NULL
) || ((*DataSize
!= 0) && (Data
== NULL
))) {
1692 return EFI_INVALID_PARAMETER
;
1695 if (DataType
>= Ip4Config2DataTypeMaximum
) {
1696 return EFI_NOT_FOUND
;
1699 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1701 Instance
= IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This
);
1702 DataItem
= &Instance
->DataItem
[DataType
];
1704 Status
= Instance
->DataItem
[DataType
].Status
;
1705 if (!EFI_ERROR (Status
)) {
1707 if (DataItem
->GetData
!= NULL
) {
1709 Status
= DataItem
->GetData (Instance
, DataSize
, Data
);
1710 } else if (*DataSize
< Instance
->DataItem
[DataType
].DataSize
) {
1712 // Update the buffer length.
1714 *DataSize
= Instance
->DataItem
[DataType
].DataSize
;
1715 Status
= EFI_BUFFER_TOO_SMALL
;
1718 *DataSize
= Instance
->DataItem
[DataType
].DataSize
;
1719 CopyMem (Data
, Instance
->DataItem
[DataType
].Data
.Ptr
, *DataSize
);
1723 gBS
->RestoreTPL (OldTpl
);
1729 Register an event that is signaled whenever a configuration process on the specified
1730 configuration data is done.
1732 This function registers an event that is to be signaled whenever a configuration
1733 process on the specified configuration data is performed. An event can be registered
1734 for a different DataType simultaneously. The caller is responsible for determining
1735 which type of configuration data causes the signaling of the event in such an event.
1737 @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
1738 @param[in] DataType The type of data to unregister the event for.
1739 @param[in] Event The event to register.
1741 @retval EFI_SUCCESS The notification event for the specified configuration data is
1743 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
1744 @retval EFI_UNSUPPORTED The configuration data type specified by DataType is not
1746 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
1747 @retval EFI_ACCESS_DENIED The Event is already registered for the DataType.
1752 EfiIp4Config2RegisterDataNotify (
1753 IN EFI_IP4_CONFIG2_PROTOCOL
*This
,
1754 IN EFI_IP4_CONFIG2_DATA_TYPE DataType
,
1760 IP4_CONFIG2_INSTANCE
*Instance
;
1764 if ((This
== NULL
) || (Event
== NULL
)) {
1765 return EFI_INVALID_PARAMETER
;
1768 if (DataType
>= Ip4Config2DataTypeMaximum
) {
1769 return EFI_UNSUPPORTED
;
1772 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1774 Instance
= IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This
);
1775 EventMap
= &Instance
->DataItem
[DataType
].EventMap
;
1778 // Check whether this event is already registered for this DataType.
1780 Item
= NetMapFindKey (EventMap
, Event
);
1783 Status
= NetMapInsertTail (EventMap
, Event
, NULL
);
1785 if (EFI_ERROR (Status
)) {
1787 Status
= EFI_OUT_OF_RESOURCES
;
1792 Status
= EFI_ACCESS_DENIED
;
1795 gBS
->RestoreTPL (OldTpl
);
1801 Remove a previously registered event for the specified configuration data.
1803 @param This The pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
1804 @param DataType The type of data to remove from the previously
1806 @param Event The event to be unregistered.
1808 @retval EFI_SUCCESS The event registered for the specified
1809 configuration data was removed.
1810 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
1811 @retval EFI_NOT_FOUND The Event has not been registered for the
1817 EfiIp4Config2UnregisterDataNotify (
1818 IN EFI_IP4_CONFIG2_PROTOCOL
*This
,
1819 IN EFI_IP4_CONFIG2_DATA_TYPE DataType
,
1825 IP4_CONFIG2_INSTANCE
*Instance
;
1828 if ((This
== NULL
) || (Event
== NULL
)) {
1829 return EFI_INVALID_PARAMETER
;
1832 if (DataType
>= Ip4Config2DataTypeMaximum
) {
1833 return EFI_NOT_FOUND
;
1836 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1838 Instance
= IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This
);
1840 Item
= NetMapFindKey (&Instance
->DataItem
[DataType
].EventMap
, Event
);
1843 NetMapRemoveItem (&Instance
->DataItem
[DataType
].EventMap
, Item
, NULL
);
1844 Status
= EFI_SUCCESS
;
1847 Status
= EFI_NOT_FOUND
;
1850 gBS
->RestoreTPL (OldTpl
);
1856 Initialize an IP4_CONFIG2_INSTANCE.
1858 @param[out] Instance The buffer of IP4_CONFIG2_INSTANCE to be initialized.
1860 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
1861 @retval EFI_SUCCESS The IP4_CONFIG2_INSTANCE initialized successfully.
1865 Ip4Config2InitInstance (
1866 OUT IP4_CONFIG2_INSTANCE
*Instance
1870 IP4_CONFIG2_INSTANCE
*TmpInstance
;
1875 IP4_CONFIG2_DATA_ITEM
*DataItem
;
1878 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
1880 Instance
->Signature
= IP4_CONFIG2_INSTANCE_SIGNATURE
;
1884 // Determine the index of this interface.
1887 NET_LIST_FOR_EACH (Entry
, &mIp4Config2InstanceList
) {
1888 TmpInstance
= NET_LIST_USER_STRUCT_S (Entry
, IP4_CONFIG2_INSTANCE
, Link
, IP4_CONFIG2_INSTANCE_SIGNATURE
);
1890 if (TmpInstance
->IfIndex
> IfIndex
) {
1892 // There is a sequence hole because some interface is down.
1900 Instance
->IfIndex
= IfIndex
;
1901 NetListInsertBefore (Entry
, &Instance
->Link
);
1903 for (Index
= 0; Index
< Ip4Config2DataTypeMaximum
; Index
++) {
1905 // Initialize the event map for each data item.
1907 NetMapInit (&Instance
->DataItem
[Index
].EventMap
);
1912 // Initialize each data type: associate storage and set data size for the
1913 // fixed size data types, hook the SetData function, set the data attribute.
1915 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeInterfaceInfo
];
1916 DataItem
->GetData
= Ip4Config2GetIfInfo
;
1917 DataItem
->Data
.Ptr
= &Instance
->InterfaceInfo
;
1918 DataItem
->DataSize
= sizeof (Instance
->InterfaceInfo
);
1919 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
| DATA_ATTRIB_VOLATILE
);
1920 Ip4Config2InitIfInfo (IpSb
, &Instance
->InterfaceInfo
);
1922 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypePolicy
];
1923 DataItem
->SetData
= Ip4Config2SetPolicy
;
1924 DataItem
->Data
.Ptr
= &Instance
->Policy
;
1925 DataItem
->DataSize
= sizeof (Instance
->Policy
);
1926 Instance
->Policy
= Ip4Config2PolicyStatic
;
1927 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
);
1929 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeManualAddress
];
1930 DataItem
->SetData
= Ip4Config2SetMaunualAddress
;
1931 DataItem
->Status
= EFI_NOT_FOUND
;
1933 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeGateway
];
1934 DataItem
->SetData
= Ip4Config2SetGateway
;
1935 DataItem
->Status
= EFI_NOT_FOUND
;
1937 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeDnsServer
];
1938 DataItem
->SetData
= Ip4Config2SetDnsServer
;
1939 DataItem
->Status
= EFI_NOT_FOUND
;
1942 // Create the event used for DHCP.
1944 Status
= gBS
->CreateEvent (
1947 Ip4Config2OnDhcp4Event
,
1949 &Instance
->Dhcp4Event
1951 ASSERT_EFI_ERROR (Status
);
1953 Instance
->Configured
= TRUE
;
1956 // Try to read the config data from NV variable.
1957 // If not found, write initialized config data into NV variable
1958 // as a default config data.
1960 Status
= Ip4Config2ReadConfigData (IpSb
->MacString
, Instance
);
1961 if (Status
== EFI_NOT_FOUND
) {
1962 Status
= Ip4Config2WriteConfigData (IpSb
->MacString
, Instance
);
1965 if (EFI_ERROR (Status
)) {
1969 Instance
->Ip4Config2
.SetData
= EfiIp4Config2SetData
;
1970 Instance
->Ip4Config2
.GetData
= EfiIp4Config2GetData
;
1971 Instance
->Ip4Config2
.RegisterDataNotify
= EfiIp4Config2RegisterDataNotify
;
1972 Instance
->Ip4Config2
.UnregisterDataNotify
= EfiIp4Config2UnregisterDataNotify
;
1975 // Publish the IP4 configuration form
1977 return Ip4Config2FormInit (Instance
);
1982 Release an IP4_CONFIG2_INSTANCE.
1984 @param[in, out] Instance The buffer of IP4_CONFIG2_INSTANCE to be freed.
1988 Ip4Config2CleanInstance (
1989 IN OUT IP4_CONFIG2_INSTANCE
*Instance
1993 IP4_CONFIG2_DATA_ITEM
*DataItem
;
1995 if (Instance
->DeclineAddress
!= NULL
) {
1996 FreePool (Instance
->DeclineAddress
);
1999 if (!Instance
->Configured
) {
2003 if (Instance
->Dhcp4Handle
!= NULL
) {
2005 Ip4Config2DestroyDhcp4 (Instance
);
2011 if (Instance
->Dhcp4Event
!= NULL
) {
2012 gBS
->CloseEvent (Instance
->Dhcp4Event
);
2013 Instance
->Dhcp4Event
= NULL
;
2016 for (Index
= 0; Index
< Ip4Config2DataTypeMaximum
; Index
++) {
2018 DataItem
= &Instance
->DataItem
[Index
];
2020 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
)) {
2021 if (DataItem
->Data
.Ptr
!= NULL
) {
2022 FreePool (DataItem
->Data
.Ptr
);
2024 DataItem
->Data
.Ptr
= NULL
;
2025 DataItem
->DataSize
= 0;
2028 NetMapClean (&Instance
->DataItem
[Index
].EventMap
);
2031 Ip4Config2FormUnload (Instance
);
2033 RemoveEntryList (&Instance
->Link
);
2037 The event handle for IP4 auto reconfiguration. The original default
2038 interface and route table will be removed as the default.
2040 @param[in] Context The IP4 service binding instance.
2045 Ip4AutoReconfigCallBackDpc (
2051 IpSb
= (IP4_SERVICE
*) Context
;
2052 NET_CHECK_SIGNATURE (IpSb
, IP4_SERVICE_SIGNATURE
);
2054 if (IpSb
->State
> IP4_SERVICE_UNSTARTED
) {
2055 IpSb
->State
= IP4_SERVICE_UNSTARTED
;
2058 IpSb
->Reconfig
= TRUE
;
2060 Ip4StartAutoConfig (&IpSb
->Ip4Config2Instance
);
2067 Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK.
2069 @param Event The event that is signalled.
2070 @param Context The IP4 service binding instance.
2075 Ip4AutoReconfigCallBack (
2081 // Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK
2083 QueueDpc (TPL_CALLBACK
, Ip4AutoReconfigCallBackDpc
, Context
);