2 The implementation of EFI IPv4 Configuration II Protocol.
4 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
13 LIST_ENTRY mIp4Config2InstanceList
= {&mIp4Config2InstanceList
, &mIp4Config2InstanceList
};
16 The event process routine when the DHCPv4 service binding protocol is installed
19 @param[in] Event Not used.
20 @param[in] Context Pointer to the IP4 config2 instance data.
25 Ip4Config2OnDhcp4SbInstalled (
31 Destroy the Dhcp4 child in IP4_CONFIG2_INSTANCE and release the resources.
33 @param[in, out] Instance The buffer of IP4 config2 instance to be freed.
35 @retval EFI_SUCCESS The child was successfully destroyed.
36 @retval Others Failed to destroy the child.
40 Ip4Config2DestroyDhcp4 (
41 IN OUT IP4_CONFIG2_INSTANCE
*Instance
46 EFI_DHCP4_PROTOCOL
*Dhcp4
;
48 Dhcp4
= Instance
->Dhcp4
;
49 ASSERT (Dhcp4
!= NULL
);
52 Dhcp4
->Configure (Dhcp4
, NULL
);
53 Instance
->Dhcp4
= NULL
;
55 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
58 // Close DHCPv4 protocol and destroy the child.
60 Status
= gBS
->CloseProtocol (
61 Instance
->Dhcp4Handle
,
62 &gEfiDhcp4ProtocolGuid
,
66 if (EFI_ERROR (Status
)) {
70 Status
= NetLibDestroyServiceChild (
73 &gEfiDhcp4ServiceBindingProtocolGuid
,
77 Instance
->Dhcp4Handle
= NULL
;
83 Update the current policy to NewPolicy. During the transition
84 period, the default router list
85 and address list in all interfaces will be released.
87 @param[in] IpSb The IP4 service binding instance.
88 @param[in] NewPolicy The new policy to be updated to.
92 Ip4Config2OnPolicyChanged (
94 IN EFI_IP4_CONFIG2_POLICY NewPolicy
98 IP4_ROUTE_TABLE
*RouteTable
;
101 // Currently there are only two policies: static and dhcp. Regardless of
102 // what transition is going on, i.e., static -> dhcp and dhcp ->
103 // static, we have to free default router table and all addresses.
106 if (IpSb
->DefaultInterface
!= NULL
) {
107 if (IpSb
->DefaultRouteTable
!= NULL
) {
108 Ip4FreeRouteTable (IpSb
->DefaultRouteTable
);
109 IpSb
->DefaultRouteTable
= NULL
;
112 Ip4CancelReceive (IpSb
->DefaultInterface
);
114 Ip4FreeInterface (IpSb
->DefaultInterface
, NULL
);
115 IpSb
->DefaultInterface
= NULL
;
118 Ip4CleanAssembleTable (&IpSb
->Assemble
);
121 // Create new default interface and route table.
123 IpIf
= Ip4CreateInterface (IpSb
->Mnp
, IpSb
->Controller
, IpSb
->Image
);
128 RouteTable
= Ip4CreateRouteTable ();
129 if (RouteTable
== NULL
) {
130 Ip4FreeInterface (IpIf
, NULL
);
134 IpSb
->DefaultInterface
= IpIf
;
135 InsertHeadList (&IpSb
->Interfaces
, &IpIf
->Link
);
136 IpSb
->DefaultRouteTable
= RouteTable
;
137 Ip4ReceiveFrame (IpIf
, NULL
, Ip4AccpetFrame
, IpSb
);
139 if (IpSb
->State
== IP4_SERVICE_CONFIGED
|| IpSb
->State
== IP4_SERVICE_STARTED
) {
140 IpSb
->State
= IP4_SERVICE_UNSTARTED
;
144 // Start the dhcp configuration.
146 if (NewPolicy
== Ip4Config2PolicyDhcp
) {
147 Ip4StartAutoConfig (&IpSb
->Ip4Config2Instance
);
153 Signal the registered event. It is the callback routine for NetMapIterate.
155 @param[in] Map Points to the list of registered event.
156 @param[in] Item The registered event.
157 @param[in] Arg Not used.
159 @retval EFI_SUCCESS The event was signaled successfully.
163 Ip4Config2SignalEvent (
165 IN NET_MAP_ITEM
*Item
,
169 gBS
->SignalEvent ((EFI_EVENT
) Item
->Key
);
175 Read the configuration data from variable storage according to the VarName and
176 gEfiIp4Config2ProtocolGuid. It checks the integrity of variable data. If the
177 data is corrupted, it clears the variable data to ZERO. Othewise, it outputs the
178 configuration data to IP4_CONFIG2_INSTANCE.
180 @param[in] VarName The pointer to the variable name
181 @param[in, out] Instance The pointer to the IP4 config2 instance data.
183 @retval EFI_NOT_FOUND The variable can not be found or already corrupted.
184 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
185 @retval EFI_SUCCESS The configuration data was retrieved successfully.
189 Ip4Config2ReadConfigData (
191 IN OUT IP4_CONFIG2_INSTANCE
*Instance
196 IP4_CONFIG2_VARIABLE
*Variable
;
197 IP4_CONFIG2_DATA_ITEM
*DataItem
;
199 IP4_CONFIG2_DATA_RECORD DataRecord
;
203 // Try to read the configuration variable.
206 Status
= gRT
->GetVariable (
208 &gEfiIp4Config2ProtocolGuid
,
214 if (Status
== EFI_BUFFER_TOO_SMALL
) {
216 // Allocate buffer and read the config variable.
218 Variable
= AllocatePool (VarSize
);
219 if (Variable
== NULL
) {
220 return EFI_OUT_OF_RESOURCES
;
223 Status
= gRT
->GetVariable (
225 &gEfiIp4Config2ProtocolGuid
,
230 if (EFI_ERROR (Status
) || (UINT16
) (~NetblockChecksum ((UINT8
*) Variable
, (UINT32
) VarSize
)) != 0) {
232 // GetVariable still error or the variable is corrupted.
233 // Fall back to the default value.
238 // Remove the problematic variable and return EFI_NOT_FOUND, a new
239 // variable will be set again.
243 &gEfiIp4Config2ProtocolGuid
,
244 IP4_CONFIG2_VARIABLE_ATTRIBUTE
,
249 return EFI_NOT_FOUND
;
253 for (Index
= 0; Index
< Variable
->DataRecordCount
; Index
++) {
255 CopyMem (&DataRecord
, &Variable
->DataRecord
[Index
], sizeof (DataRecord
));
257 DataItem
= &Instance
->DataItem
[DataRecord
.DataType
];
258 if (DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
) &&
259 (DataItem
->DataSize
!= DataRecord
.DataSize
)
262 // Perhaps a corrupted data record...
267 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
)) {
269 // This data item has variable length data.
271 DataItem
->Data
.Ptr
= AllocatePool (DataRecord
.DataSize
);
272 if (DataItem
->Data
.Ptr
== NULL
) {
274 // no memory resource
280 Data
= (CHAR8
*) Variable
+ DataRecord
.Offset
;
281 CopyMem (DataItem
->Data
.Ptr
, Data
, DataRecord
.DataSize
);
283 DataItem
->DataSize
= DataRecord
.DataSize
;
284 DataItem
->Status
= EFI_SUCCESS
;
295 Write the configuration data from IP4_CONFIG2_INSTANCE to variable storage.
297 @param[in] VarName The pointer to the variable name.
298 @param[in] Instance The pointer to the IP4 config2 instance data.
300 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
301 @retval EFI_SUCCESS The configuration data is written successfully.
305 Ip4Config2WriteConfigData (
307 IN IP4_CONFIG2_INSTANCE
*Instance
312 IP4_CONFIG2_DATA_ITEM
*DataItem
;
313 IP4_CONFIG2_VARIABLE
*Variable
;
314 IP4_CONFIG2_DATA_RECORD
*DataRecord
;
318 VarSize
= sizeof (IP4_CONFIG2_VARIABLE
) - sizeof (IP4_CONFIG2_DATA_RECORD
);
320 for (Index
= 0; Index
< Ip4Config2DataTypeMaximum
; Index
++) {
322 DataItem
= &Instance
->DataItem
[Index
];
323 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_VOLATILE
) && !EFI_ERROR (DataItem
->Status
)) {
325 VarSize
+= sizeof (IP4_CONFIG2_DATA_RECORD
) + DataItem
->DataSize
;
329 Variable
= AllocatePool (VarSize
);
330 if (Variable
== NULL
) {
331 return EFI_OUT_OF_RESOURCES
;
334 Heap
= (CHAR8
*) Variable
+ VarSize
;
335 Variable
->DataRecordCount
= 0;
337 for (Index
= 0; Index
< Ip4Config2DataTypeMaximum
; Index
++) {
339 DataItem
= &Instance
->DataItem
[Index
];
340 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_VOLATILE
) && !EFI_ERROR (DataItem
->Status
)) {
342 Heap
-= DataItem
->DataSize
;
343 CopyMem (Heap
, DataItem
->Data
.Ptr
, DataItem
->DataSize
);
345 DataRecord
= &Variable
->DataRecord
[Variable
->DataRecordCount
];
346 DataRecord
->DataType
= (EFI_IP4_CONFIG2_DATA_TYPE
) Index
;
347 DataRecord
->DataSize
= (UINT32
) DataItem
->DataSize
;
348 DataRecord
->Offset
= (UINT16
) (Heap
- (CHAR8
*) Variable
);
350 Variable
->DataRecordCount
++;
354 Variable
->Checksum
= 0;
355 Variable
->Checksum
= (UINT16
) ~NetblockChecksum ((UINT8
*) Variable
, (UINT32
) VarSize
);
357 Status
= gRT
->SetVariable (
359 &gEfiIp4Config2ProtocolGuid
,
360 IP4_CONFIG2_VARIABLE_ATTRIBUTE
,
372 Build a EFI_IP4_ROUTE_TABLE to be returned to the caller of GetModeData.
373 The EFI_IP4_ROUTE_TABLE is clumsy to use in the internal operation of the
376 @param[in] IpSb The IP4 service binding instance.
377 @param[out] Table The built IP4 route table.
379 @retval EFI_SUCCESS The route table is successfully build
380 @retval EFI_NOT_FOUND Failed to allocate the memory for the rotue table.
384 Ip4Config2BuildDefaultRouteTable (
385 IN IP4_SERVICE
*IpSb
,
386 OUT EFI_IP4_ROUTE_TABLE
*Table
390 IP4_ROUTE_ENTRY
*RtEntry
;
394 if (IpSb
->DefaultRouteTable
== NULL
) {
395 return EFI_NOT_FOUND
;
398 Count
= IpSb
->DefaultRouteTable
->TotalNum
;
401 return EFI_NOT_FOUND
;
405 // Copy the route entry to EFI route table. Keep the order of
406 // route entry copied from most specific to default route. That
407 // is, interlevel the route entry from the instance's route area
408 // and those from the default route table's route area.
412 for (Index
= IP4_MASK_MAX
; Index
>= 0; Index
--) {
414 NET_LIST_FOR_EACH (Entry
, &(IpSb
->DefaultRouteTable
->RouteArea
[Index
])) {
415 RtEntry
= NET_LIST_USER_STRUCT (Entry
, IP4_ROUTE_ENTRY
, Link
);
417 EFI_IP4 (Table
[Count
].SubnetAddress
) = HTONL (RtEntry
->Dest
& RtEntry
->Netmask
);
418 EFI_IP4 (Table
[Count
].SubnetMask
) = HTONL (RtEntry
->Netmask
);
419 EFI_IP4 (Table
[Count
].GatewayAddress
) = HTONL (RtEntry
->NextHop
);
430 The event process routine when the DHCPv4 service binding protocol is installed
433 @param[in] Event Not used.
434 @param[in] Context The pointer to the IP4 config2 instance data.
439 Ip4Config2OnDhcp4SbInstalled (
444 IP4_CONFIG2_INSTANCE
*Instance
;
446 Instance
= (IP4_CONFIG2_INSTANCE
*) Context
;
448 if ((Instance
->Dhcp4Handle
!= NULL
) || (Instance
->Policy
!= Ip4Config2PolicyDhcp
)) {
450 // The DHCP4 child is already created or the policy is no longer DHCP.
455 Ip4StartAutoConfig (Instance
);
459 Set the station address and subnetmask for the default interface.
461 @param[in] IpSb The pointer to the IP4 service binding instance.
462 @param[in] StationAddress Ip address to be set.
463 @param[in] SubnetMask Subnet to be set.
465 @retval EFI_SUCCESS Set default address successful.
466 @retval Others Some errors occur in setting.
470 Ip4Config2SetDefaultAddr (
471 IN IP4_SERVICE
*IpSb
,
472 IN IP4_ADDR StationAddress
,
473 IN IP4_ADDR SubnetMask
478 IP4_PROTOCOL
*Ip4Instance
;
479 EFI_ARP_PROTOCOL
*Arp
;
482 IP4_ROUTE_TABLE
*RouteTable
;
484 IpIf
= IpSb
->DefaultInterface
;
485 ASSERT (IpIf
!= NULL
);
487 if ((IpIf
->Ip
== StationAddress
) && (IpIf
->SubnetMask
== SubnetMask
)) {
488 IpSb
->State
= IP4_SERVICE_CONFIGED
;
492 if (IpSb
->Reconfig
) {
494 // The default address is changed, free the previous interface first.
496 if (IpSb
->DefaultRouteTable
!= NULL
) {
497 Ip4FreeRouteTable (IpSb
->DefaultRouteTable
);
498 IpSb
->DefaultRouteTable
= NULL
;
501 Ip4CancelReceive (IpSb
->DefaultInterface
);
502 Ip4FreeInterface (IpSb
->DefaultInterface
, NULL
);
503 IpSb
->DefaultInterface
= NULL
;
505 // Create new default interface and route table.
507 IpIf
= Ip4CreateInterface (IpSb
->Mnp
, IpSb
->Controller
, IpSb
->Image
);
509 return EFI_OUT_OF_RESOURCES
;
512 RouteTable
= Ip4CreateRouteTable ();
513 if (RouteTable
== NULL
) {
514 Ip4FreeInterface (IpIf
, NULL
);
515 return EFI_OUT_OF_RESOURCES
;
518 IpSb
->DefaultInterface
= IpIf
;
519 InsertHeadList (&IpSb
->Interfaces
, &IpIf
->Link
);
520 IpSb
->DefaultRouteTable
= RouteTable
;
521 Ip4ReceiveFrame (IpIf
, NULL
, Ip4AccpetFrame
, IpSb
);
524 if (IpSb
->State
== IP4_SERVICE_CONFIGED
) {
525 IpSb
->State
= IP4_SERVICE_UNSTARTED
;
528 Status
= Ip4SetAddress (IpIf
, StationAddress
, SubnetMask
);
529 if (EFI_ERROR (Status
)) {
533 if (IpIf
->Arp
!= NULL
) {
535 // A non-NULL IpIf->Arp here means a new ARP child is created when setting default address,
536 // but some IP children may have referenced the default interface before it is configured,
537 // these IP instances also consume this ARP protocol so they need to open it BY_CHILD_CONTROLLER.
540 NET_LIST_FOR_EACH (Entry
, &IpIf
->IpInstances
) {
541 Ip4Instance
= NET_LIST_USER_STRUCT_S (Entry
, IP4_PROTOCOL
, AddrLink
, IP4_PROTOCOL_SIGNATURE
);
542 Status
= gBS
->OpenProtocol (
544 &gEfiArpProtocolGuid
,
546 gIp4DriverBinding
.DriverBindingHandle
,
548 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
550 if (EFI_ERROR (Status
)) {
557 // Add a route for the connected network.
559 Subnet
= StationAddress
& SubnetMask
;
562 IpSb
->DefaultRouteTable
,
568 IpSb
->State
= IP4_SERVICE_CONFIGED
;
569 IpSb
->Reconfig
= FALSE
;
575 Set the station address, subnetmask and gateway address for the default interface.
577 @param[in] Instance The pointer to the IP4 config2 instance data.
578 @param[in] StationAddress Ip address to be set.
579 @param[in] SubnetMask Subnet to be set.
580 @param[in] GatewayAddress Gateway to be set.
582 @retval EFI_SUCCESS Set default If successful.
583 @retval Others Errors occur as indicated.
587 Ip4Config2SetDefaultIf (
588 IN IP4_CONFIG2_INSTANCE
*Instance
,
589 IN IP4_ADDR StationAddress
,
590 IN IP4_ADDR SubnetMask
,
591 IN IP4_ADDR GatewayAddress
597 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
600 // Check whether the StationAddress/SubnetMask pair is valid.
602 if (!Ip4StationAddressValid (StationAddress
, SubnetMask
)) {
603 return EFI_INVALID_PARAMETER
;
606 Status
= Ip4Config2SetDefaultAddr (IpSb
, StationAddress
, SubnetMask
);
607 if (EFI_ERROR (Status
)) {
612 // Create a route if there is a default router.
614 if (GatewayAddress
!= IP4_ALLZERO_ADDRESS
) {
616 IpSb
->DefaultRouteTable
,
628 Release all the DHCP related resources.
630 @param Instance The IP4 config2 instance.
636 Ip4Config2CleanDhcp4 (
637 IN IP4_CONFIG2_INSTANCE
*Instance
642 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
644 if (Instance
->Dhcp4
!= NULL
) {
645 Instance
->Dhcp4
->Stop (Instance
->Dhcp4
);
648 Instance
->Dhcp4Handle
,
649 &gEfiDhcp4ProtocolGuid
,
654 Instance
->Dhcp4
= NULL
;
657 if (Instance
->Dhcp4Handle
!= NULL
) {
658 NetLibDestroyServiceChild (
661 &gEfiDhcp4ServiceBindingProtocolGuid
,
662 Instance
->Dhcp4Handle
665 Instance
->Dhcp4Handle
= NULL
;
668 if (Instance
->Dhcp4Event
!= NULL
) {
669 gBS
->CloseEvent (Instance
->Dhcp4Event
);
670 Instance
->Dhcp4Event
= NULL
;
675 This worker function sets the DNS server list for the EFI IPv4 network
676 stack running on the communication device that this EFI_IP4_CONFIG2_PROTOCOL
677 manages. The DNS server addresses must be unicast IPv4 addresses.
679 @param[in] Instance The pointer to the IP4 config2 instance data.
680 @param[in] DataSize The size of the buffer pointed to by Data in bytes.
681 @param[in] Data The data buffer to set, points to an array of
682 EFI_IPv4_ADDRESS instances.
684 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
685 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
686 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
687 @retval EFI_ABORTED The DNS server addresses to be set equal the current
689 @retval EFI_SUCCESS The specified configuration data for the EFI IPv4
690 network stack was set.
694 Ip4Config2SetDnsServerWorker (
695 IN IP4_CONFIG2_INSTANCE
*Instance
,
702 EFI_IPv4_ADDRESS
*OldDns
;
703 EFI_IPv4_ADDRESS
*NewDns
;
706 IP4_CONFIG2_DATA_ITEM
*Item
;
711 if ((DataSize
% sizeof (EFI_IPv4_ADDRESS
) != 0) || (DataSize
== 0)) {
712 return EFI_BAD_BUFFER_SIZE
;
715 Item
= &Instance
->DataItem
[Ip4Config2DataTypeDnsServer
];
716 NewDns
= (EFI_IPv4_ADDRESS
*) Data
;
717 OldDns
= Item
->Data
.DnsServers
;
718 NewDnsCount
= DataSize
/ sizeof (EFI_IPv4_ADDRESS
);
719 OldDnsCount
= Item
->DataSize
/ sizeof (EFI_IPv4_ADDRESS
);
722 if (NewDnsCount
!= OldDnsCount
) {
723 Tmp
= AllocatePool (DataSize
);
725 return EFI_OUT_OF_RESOURCES
;
731 for (NewIndex
= 0; NewIndex
< NewDnsCount
; NewIndex
++) {
732 CopyMem (&DnsAddress
, NewDns
+ NewIndex
, sizeof (IP4_ADDR
));
733 if (IP4_IS_UNSPECIFIED (NTOHL (DnsAddress
)) || IP4_IS_LOCAL_BROADCAST (NTOHL (DnsAddress
))) {
735 // The dns server address must be unicast.
740 return EFI_INVALID_PARAMETER
;
745 // If any address in the new setting is not in the old settings, skip the
746 // comparision below.
751 for (OldIndex
= 0; OldIndex
< OldDnsCount
; OldIndex
++) {
752 if (EFI_IP4_EQUAL (NewDns
+ NewIndex
, OldDns
+ OldIndex
)) {
754 // If found break out.
760 if (OldIndex
== OldDnsCount
) {
765 if (!OneAdded
&& (DataSize
== Item
->DataSize
)) {
767 // No new item is added and the size is the same.
769 Item
->Status
= EFI_SUCCESS
;
773 if (Item
->Data
.Ptr
!= NULL
) {
774 FreePool (Item
->Data
.Ptr
);
776 Item
->Data
.Ptr
= Tmp
;
779 CopyMem (Item
->Data
.Ptr
, Data
, DataSize
);
780 Item
->DataSize
= DataSize
;
781 Item
->Status
= EFI_SUCCESS
;
789 Callback function when DHCP process finished. It will save the
790 retrieved IP configure parameter from DHCP to the NVRam.
792 @param Event The callback event
793 @param Context Opaque context to the callback
800 Ip4Config2OnDhcp4Complete (
805 IP4_CONFIG2_INSTANCE
*Instance
;
806 EFI_DHCP4_MODE_DATA Dhcp4Mode
;
808 IP4_ADDR StationAddress
;
810 IP4_ADDR GatewayAddress
;
813 EFI_DHCP4_PACKET_OPTION
**OptionList
;
815 Instance
= (IP4_CONFIG2_INSTANCE
*) Context
;
816 ASSERT (Instance
->Dhcp4
!= NULL
);
819 // Get the DHCP retrieved parameters
821 Status
= Instance
->Dhcp4
->GetModeData (Instance
->Dhcp4
, &Dhcp4Mode
);
823 if (EFI_ERROR (Status
)) {
827 if (Dhcp4Mode
.State
== Dhcp4Bound
) {
828 StationAddress
= EFI_NTOHL (Dhcp4Mode
.ClientAddress
);
829 SubnetMask
= EFI_NTOHL (Dhcp4Mode
.SubnetMask
);
830 GatewayAddress
= EFI_NTOHL (Dhcp4Mode
.RouterAddress
);
832 Status
= Ip4Config2SetDefaultIf (Instance
, StationAddress
, SubnetMask
, GatewayAddress
);
833 if (EFI_ERROR (Status
)) {
838 // Parse the ACK to get required DNS server information.
843 Status
= Instance
->Dhcp4
->Parse (Instance
->Dhcp4
, Dhcp4Mode
.ReplyPacket
, &OptionCount
, OptionList
);
844 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
848 OptionList
= AllocateZeroPool (OptionCount
* sizeof (EFI_DHCP4_PACKET_OPTION
*));
849 if (OptionList
== NULL
) {
853 Status
= Instance
->Dhcp4
->Parse (Instance
->Dhcp4
, Dhcp4Mode
.ReplyPacket
, &OptionCount
, OptionList
);
854 if (EFI_ERROR (Status
)) {
855 FreePool (OptionList
);
859 for (Index
= 0; Index
< OptionCount
; Index
++) {
861 // Look for DNS Server opcode (6).
863 if (OptionList
[Index
]->OpCode
== DHCP4_TAG_DNS_SERVER
) {
864 if (((OptionList
[Index
]->Length
& 0x3) != 0) || (OptionList
[Index
]->Length
== 0)) {
868 Ip4Config2SetDnsServerWorker (Instance
, OptionList
[Index
]->Length
, &OptionList
[Index
]->Data
[0]);
873 FreePool (OptionList
);
875 Instance
->DhcpSuccess
= TRUE
;
879 Ip4Config2CleanDhcp4 (Instance
);
885 Start the DHCP configuration for this IP service instance.
886 It will locates the EFI_IP4_CONFIG2_PROTOCOL, then start the
889 @param[in] Instance The IP4 config2 instance to configure
891 @retval EFI_SUCCESS The auto configuration is successfully started
892 @retval Others Failed to start auto configuration.
897 IN IP4_CONFIG2_INSTANCE
*Instance
901 EFI_DHCP4_PROTOCOL
*Dhcp4
;
902 EFI_DHCP4_MODE_DATA Dhcp4Mode
;
903 EFI_DHCP4_PACKET_OPTION
*OptionList
[1];
904 IP4_CONFIG2_DHCP4_OPTION ParaList
;
907 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
909 if (IpSb
->State
> IP4_SERVICE_UNSTARTED
) {
914 // A host must not invoke DHCP configuration if it is already
915 // participating in the DHCP configuraiton process.
917 if (Instance
->Dhcp4Handle
!= NULL
) {
921 Status
= NetLibCreateServiceChild (
924 &gEfiDhcp4ServiceBindingProtocolGuid
,
925 &Instance
->Dhcp4Handle
928 if (Status
== EFI_UNSUPPORTED
) {
930 // No DHCPv4 Service Binding protocol, register a notify.
932 if (Instance
->Dhcp4SbNotifyEvent
== NULL
) {
933 Instance
->Dhcp4SbNotifyEvent
= EfiCreateProtocolNotifyEvent (
934 &gEfiDhcp4ServiceBindingProtocolGuid
,
936 Ip4Config2OnDhcp4SbInstalled
,
938 &Instance
->Registration
943 if (EFI_ERROR (Status
)) {
947 if (Instance
->Dhcp4SbNotifyEvent
!= NULL
) {
948 gBS
->CloseEvent (Instance
->Dhcp4SbNotifyEvent
);
951 Status
= gBS
->OpenProtocol (
952 Instance
->Dhcp4Handle
,
953 &gEfiDhcp4ProtocolGuid
,
954 (VOID
**) &Instance
->Dhcp4
,
957 EFI_OPEN_PROTOCOL_BY_DRIVER
959 if (EFI_ERROR (Status
)) {
960 NetLibDestroyServiceChild (
963 &gEfiDhcp4ServiceBindingProtocolGuid
,
964 Instance
->Dhcp4Handle
967 Instance
->Dhcp4Handle
= NULL
;
973 // Check the current DHCP status, if the DHCP process has
974 // already finished, return now.
976 Dhcp4
= Instance
->Dhcp4
;
977 Status
= Dhcp4
->GetModeData (Dhcp4
, &Dhcp4Mode
);
978 if (Dhcp4Mode
.State
== Dhcp4Bound
) {
979 Ip4Config2OnDhcp4Complete (NULL
, Instance
);
985 // Try to start the DHCP process. Use most of the current
986 // DHCP configuration to avoid problems if some DHCP client
987 // yields the control of this DHCP service to us.
989 ParaList
.Head
.OpCode
= DHCP4_TAG_PARA_LIST
;
990 ParaList
.Head
.Length
= 3;
991 ParaList
.Head
.Data
[0] = DHCP4_TAG_NETMASK
;
992 ParaList
.Route
= DHCP4_TAG_ROUTER
;
993 ParaList
.Dns
= DHCP4_TAG_DNS_SERVER
;
994 OptionList
[0] = &ParaList
.Head
;
995 Dhcp4Mode
.ConfigData
.OptionCount
= 1;
996 Dhcp4Mode
.ConfigData
.OptionList
= OptionList
;
998 Status
= Dhcp4
->Configure (Dhcp4
, &Dhcp4Mode
.ConfigData
);
999 if (EFI_ERROR (Status
)) {
1000 gBS
->CloseProtocol (
1001 Instance
->Dhcp4Handle
,
1002 &gEfiDhcp4ProtocolGuid
,
1007 NetLibDestroyServiceChild (
1010 &gEfiDhcp4ServiceBindingProtocolGuid
,
1011 Instance
->Dhcp4Handle
1014 Instance
->Dhcp4
= NULL
;
1016 Instance
->Dhcp4Handle
= NULL
;
1022 // Start the DHCP process
1024 Status
= gBS
->CreateEvent (
1027 Ip4Config2OnDhcp4Complete
,
1029 &Instance
->Dhcp4Event
1031 if (EFI_ERROR (Status
)) {
1032 Ip4Config2DestroyDhcp4 (Instance
);
1036 Status
= Dhcp4
->Start (Dhcp4
, Instance
->Dhcp4Event
);
1037 if (EFI_ERROR (Status
)) {
1038 Ip4Config2DestroyDhcp4 (Instance
);
1039 gBS
->CloseEvent (Instance
->Dhcp4Event
);
1040 Instance
->Dhcp4Event
= NULL
;
1045 IpSb
->State
= IP4_SERVICE_STARTED
;
1054 The work function is to get the interface information of the communication
1055 device this IP4_CONFIG2_INSTANCE manages.
1057 @param[in] Instance Pointer to the IP4 config2 instance data.
1058 @param[in, out] DataSize On input, in bytes, the size of Data. On output, in
1059 bytes, the size of buffer required to store the specified
1061 @param[in] Data The data buffer in which the configuration data is returned.
1062 Ignored if DataSize is ZERO.
1064 @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified
1065 configuration data, and the required size is
1066 returned in DataSize.
1067 @retval EFI_SUCCESS The specified configuration data was obtained.
1071 Ip4Config2GetIfInfo (
1072 IN IP4_CONFIG2_INSTANCE
*Instance
,
1073 IN OUT UINTN
*DataSize
,
1074 IN VOID
*Data OPTIONAL
1079 IP4_CONFIG2_DATA_ITEM
*Item
;
1080 EFI_IP4_CONFIG2_INTERFACE_INFO
*IfInfo
;
1083 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
1084 Length
= sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO
);
1086 if (IpSb
->DefaultRouteTable
!= NULL
) {
1087 Length
+= IpSb
->DefaultRouteTable
->TotalNum
* sizeof (EFI_IP4_ROUTE_TABLE
);
1090 if (*DataSize
< Length
) {
1092 return EFI_BUFFER_TOO_SMALL
;
1096 // Copy the fixed size part of the interface info.
1098 Item
= &Instance
->DataItem
[Ip4Config2DataTypeInterfaceInfo
];
1099 IfInfo
= (EFI_IP4_CONFIG2_INTERFACE_INFO
*) Data
;
1100 CopyMem (IfInfo
, Item
->Data
.Ptr
, sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO
));
1103 // Update the address info.
1105 if (IpSb
->DefaultInterface
!= NULL
) {
1106 Address
= HTONL (IpSb
->DefaultInterface
->Ip
);
1107 CopyMem (&IfInfo
->StationAddress
, &Address
, sizeof (EFI_IPv4_ADDRESS
));
1108 Address
= HTONL (IpSb
->DefaultInterface
->SubnetMask
);
1109 CopyMem (&IfInfo
->SubnetMask
, &Address
, sizeof (EFI_IPv4_ADDRESS
));
1112 if (IpSb
->DefaultRouteTable
!= NULL
) {
1113 IfInfo
->RouteTableSize
= IpSb
->DefaultRouteTable
->TotalNum
;
1114 IfInfo
->RouteTable
= (EFI_IP4_ROUTE_TABLE
*) ((UINT8
*) Data
+ sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO
));
1116 Ip4Config2BuildDefaultRouteTable (IpSb
, IfInfo
->RouteTable
);
1123 The work function is to set the general configuration policy for the EFI IPv4 network
1124 stack that is running on the communication device managed by this IP4_CONFIG2_INSTANCE.
1125 The policy will affect other configuration settings.
1127 @param[in] Instance Pointer to the IP4 config2 instance data.
1128 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
1129 @param[in] Data The data buffer to set.
1131 @retval EFI_INVALID_PARAMETER The to be set policy is invalid.
1132 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1133 @retval EFI_ABORTED The new policy equals the current policy.
1134 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1135 network stack was set.
1139 Ip4Config2SetPolicy (
1140 IN IP4_CONFIG2_INSTANCE
*Instance
,
1145 EFI_IP4_CONFIG2_POLICY NewPolicy
;
1146 IP4_CONFIG2_DATA_ITEM
*DataItem
;
1149 if (DataSize
!= sizeof (EFI_IP4_CONFIG2_POLICY
)) {
1150 return EFI_BAD_BUFFER_SIZE
;
1153 NewPolicy
= *((EFI_IP4_CONFIG2_POLICY
*) Data
);
1155 if (NewPolicy
>= Ip4Config2PolicyMax
) {
1156 return EFI_INVALID_PARAMETER
;
1159 if (NewPolicy
== Instance
->Policy
) {
1160 if (NewPolicy
!= Ip4Config2PolicyDhcp
|| Instance
->DhcpSuccess
) {
1165 // The policy is changed. Clean the ManualAddress, Gateway and DnsServers,
1166 // shrink the variable data size, and fire up all the related events.
1168 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeManualAddress
];
1169 if (DataItem
->Data
.Ptr
!= NULL
) {
1170 FreePool (DataItem
->Data
.Ptr
);
1172 DataItem
->Data
.Ptr
= NULL
;
1173 DataItem
->DataSize
= 0;
1174 DataItem
->Status
= EFI_NOT_FOUND
;
1175 NetMapIterate (&DataItem
->EventMap
, Ip4Config2SignalEvent
, NULL
);
1177 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeGateway
];
1178 if (DataItem
->Data
.Ptr
!= NULL
) {
1179 FreePool (DataItem
->Data
.Ptr
);
1181 DataItem
->Data
.Ptr
= NULL
;
1182 DataItem
->DataSize
= 0;
1183 DataItem
->Status
= EFI_NOT_FOUND
;
1184 NetMapIterate (&DataItem
->EventMap
, Ip4Config2SignalEvent
, NULL
);
1186 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeDnsServer
];
1187 if (DataItem
->Data
.Ptr
!= NULL
) {
1188 FreePool (DataItem
->Data
.Ptr
);
1190 DataItem
->Data
.Ptr
= NULL
;
1191 DataItem
->DataSize
= 0;
1192 DataItem
->Status
= EFI_NOT_FOUND
;
1193 NetMapIterate (&DataItem
->EventMap
, Ip4Config2SignalEvent
, NULL
);
1195 if (NewPolicy
== Ip4Config2PolicyDhcp
) {
1196 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_VOLATILE
);
1199 // The policy is changed from dhcp to static. Stop the DHCPv4 process
1200 // and destroy the DHCPv4 child.
1202 if (Instance
->Dhcp4Handle
!= NULL
) {
1203 Ip4Config2DestroyDhcp4 (Instance
);
1209 if (Instance
->Dhcp4Event
!= NULL
) {
1210 gBS
->CloseEvent (Instance
->Dhcp4Event
);
1211 Instance
->Dhcp4Event
= NULL
;
1216 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
1217 Ip4Config2OnPolicyChanged (IpSb
, NewPolicy
);
1219 Instance
->Policy
= NewPolicy
;
1225 The work function is to set the station addresses manually for the EFI IPv4
1226 network stack. It is only configurable when the policy is Ip4Config2PolicyStatic.
1228 @param[in] Instance Pointer to the IP4 config2 instance data.
1229 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
1230 @param[in] Data The data buffer to set.
1232 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1233 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
1234 under the current policy.
1235 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
1236 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
1237 @retval EFI_NOT_READY An asynchrous process is invoked to set the specified
1238 configuration data, and the process is not finished.
1239 @retval EFI_ABORTED The manual addresses to be set equal current
1241 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1242 network stack was set.
1246 Ip4Config2SetManualAddress (
1247 IN IP4_CONFIG2_INSTANCE
*Instance
,
1252 EFI_IP4_CONFIG2_MANUAL_ADDRESS NewAddress
;
1253 IP4_CONFIG2_DATA_ITEM
*DataItem
;
1255 IP4_ADDR StationAddress
;
1256 IP4_ADDR SubnetMask
;
1259 IP4_INTERFACE
*IpIf
;
1260 IP4_ROUTE_TABLE
*RouteTable
;
1263 Status
= EFI_SUCCESS
;
1268 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
1270 ASSERT (Instance
->DataItem
[Ip4Config2DataTypeManualAddress
].Status
!= EFI_NOT_READY
);
1272 if ((DataSize
!= 0) && ((DataSize
% sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS
)) != 0)) {
1273 return EFI_BAD_BUFFER_SIZE
;
1276 if (Instance
->Policy
!= Ip4Config2PolicyStatic
) {
1277 return EFI_WRITE_PROTECTED
;
1280 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeManualAddress
];
1282 if (Data
!= NULL
&& DataSize
!= 0) {
1283 NewAddress
= *((EFI_IP4_CONFIG2_MANUAL_ADDRESS
*) Data
);
1285 StationAddress
= EFI_NTOHL (NewAddress
.Address
);
1286 SubnetMask
= EFI_NTOHL (NewAddress
.SubnetMask
);
1289 // Check whether the StationAddress/SubnetMask pair is valid.
1291 if (!Ip4StationAddressValid (StationAddress
, SubnetMask
)) {
1292 return EFI_INVALID_PARAMETER
;
1296 // Store the new data, and init the DataItem status to EFI_NOT_READY because
1297 // we may have an asynchronous configuration process.
1299 Ptr
= AllocateCopyPool (DataSize
, Data
);
1301 return EFI_OUT_OF_RESOURCES
;
1304 if (DataItem
->Data
.Ptr
!= NULL
) {
1305 FreePool (DataItem
->Data
.Ptr
);
1308 DataItem
->Data
.Ptr
= Ptr
;
1309 DataItem
->DataSize
= DataSize
;
1310 DataItem
->Status
= EFI_NOT_READY
;
1312 IpSb
->Reconfig
= TRUE
;
1313 Status
= Ip4Config2SetDefaultAddr (IpSb
, StationAddress
, SubnetMask
);
1315 DataItem
->Status
= Status
;
1317 if (EFI_ERROR (DataItem
->Status
) && DataItem
->Status
!= EFI_NOT_READY
) {
1321 DataItem
->Data
.Ptr
= NULL
;
1325 // DataSize is 0 and Data is NULL, clean up the manual address.
1327 if (DataItem
->Data
.Ptr
!= NULL
) {
1328 FreePool (DataItem
->Data
.Ptr
);
1330 DataItem
->Data
.Ptr
= NULL
;
1331 DataItem
->DataSize
= 0;
1332 DataItem
->Status
= EFI_NOT_FOUND
;
1335 // Free the default router table and Interface, clean up the assemble table.
1337 if (IpSb
->DefaultInterface
!= NULL
) {
1338 if (IpSb
->DefaultRouteTable
!= NULL
) {
1339 Ip4FreeRouteTable (IpSb
->DefaultRouteTable
);
1340 IpSb
->DefaultRouteTable
= NULL
;
1343 Ip4CancelReceive (IpSb
->DefaultInterface
);
1345 Ip4FreeInterface (IpSb
->DefaultInterface
, NULL
);
1346 IpSb
->DefaultInterface
= NULL
;
1349 Ip4CleanAssembleTable (&IpSb
->Assemble
);
1352 // Create new default interface and route table.
1354 IpIf
= Ip4CreateInterface (IpSb
->Mnp
, IpSb
->Controller
, IpSb
->Image
);
1356 return EFI_OUT_OF_RESOURCES
;
1359 RouteTable
= Ip4CreateRouteTable ();
1360 if (RouteTable
== NULL
) {
1361 Ip4FreeInterface (IpIf
, NULL
);
1362 return EFI_OUT_OF_RESOURCES
;
1365 IpSb
->DefaultInterface
= IpIf
;
1366 InsertHeadList (&IpSb
->Interfaces
, &IpIf
->Link
);
1367 IpSb
->DefaultRouteTable
= RouteTable
;
1368 Ip4ReceiveFrame (IpIf
, NULL
, Ip4AccpetFrame
, IpSb
);
1371 // Reset the State to unstarted.
1373 if (IpSb
->State
== IP4_SERVICE_CONFIGED
|| IpSb
->State
== IP4_SERVICE_STARTED
) {
1374 IpSb
->State
= IP4_SERVICE_UNSTARTED
;
1382 The work function is to set the gateway addresses manually for the EFI IPv4
1383 network stack that is running on the communication device that this EFI IPv4
1384 Configuration Protocol manages. It is not configurable when the policy is
1385 Ip4Config2PolicyDhcp. The gateway addresses must be unicast IPv4 addresses.
1387 @param[in] Instance The pointer to the IP4 config2 instance data.
1388 @param[in] DataSize The size of the buffer pointed to by Data in bytes.
1389 @param[in] Data The data buffer to set. This points to an array of
1390 EFI_IPv6_ADDRESS instances.
1392 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1393 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
1394 under the current policy.
1395 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
1396 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to complete the operation.
1397 @retval EFI_ABORTED The manual gateway addresses to be set equal the
1398 current configuration.
1399 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1400 network stack was set.
1404 Ip4Config2SetGateway (
1405 IN IP4_CONFIG2_INSTANCE
*Instance
,
1411 IP4_CONFIG2_DATA_ITEM
*DataItem
;
1416 EFI_IPv4_ADDRESS
*OldGateway
;
1417 EFI_IPv4_ADDRESS
*NewGateway
;
1418 UINTN OldGatewayCount
;
1419 UINTN NewGatewayCount
;
1430 if ((DataSize
!= 0) && (DataSize
% sizeof (EFI_IPv4_ADDRESS
) != 0)) {
1431 return EFI_BAD_BUFFER_SIZE
;
1434 if (Instance
->Policy
!= Ip4Config2PolicyStatic
) {
1435 return EFI_WRITE_PROTECTED
;
1438 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
1440 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeGateway
];
1441 OldGateway
= DataItem
->Data
.Gateway
;
1442 OldGatewayCount
= DataItem
->DataSize
/ sizeof (EFI_IPv4_ADDRESS
);
1444 for (Index1
= 0; Index1
< OldGatewayCount
; Index1
++) {
1446 // Remove the old route entry.
1448 CopyMem (&Gateway
, OldGateway
+ Index1
, sizeof (IP4_ADDR
));
1450 IpSb
->DefaultRouteTable
,
1451 IP4_ALLZERO_ADDRESS
,
1452 IP4_ALLZERO_ADDRESS
,
1458 if (Data
!= NULL
&& DataSize
!= 0) {
1459 NewGateway
= (EFI_IPv4_ADDRESS
*) Data
;
1460 NewGatewayCount
= DataSize
/ sizeof (EFI_IPv4_ADDRESS
);
1461 for (Index1
= 0; Index1
< NewGatewayCount
; Index1
++) {
1462 CopyMem (&Gateway
, NewGateway
+ Index1
, sizeof (IP4_ADDR
));
1464 if ((IpSb
->DefaultInterface
->SubnetMask
!= 0) &&
1465 !NetIp4IsUnicast (NTOHL (Gateway
), IpSb
->DefaultInterface
->SubnetMask
)) {
1466 return EFI_INVALID_PARAMETER
;
1469 for (Index2
= Index1
+ 1; Index2
< NewGatewayCount
; Index2
++) {
1470 if (EFI_IP4_EQUAL (NewGateway
+ Index1
, NewGateway
+ Index2
)) {
1471 return EFI_INVALID_PARAMETER
;
1476 if (NewGatewayCount
!= OldGatewayCount
) {
1477 Tmp
= AllocatePool (DataSize
);
1479 return EFI_OUT_OF_RESOURCES
;
1485 for (Index1
= 0; Index1
< NewGatewayCount
; Index1
++) {
1487 // Add the new route entry.
1489 CopyMem (&Gateway
, NewGateway
+ Index1
, sizeof (IP4_ADDR
));
1491 IpSb
->DefaultRouteTable
,
1492 IP4_ALLZERO_ADDRESS
,
1493 IP4_ALLZERO_ADDRESS
,
1500 if (!OneRemoved
&& !OneAdded
) {
1501 DataItem
->Status
= EFI_SUCCESS
;
1505 if (DataItem
->Data
.Ptr
!= NULL
) {
1506 FreePool (DataItem
->Data
.Ptr
);
1508 DataItem
->Data
.Ptr
= Tmp
;
1511 CopyMem (DataItem
->Data
.Ptr
, Data
, DataSize
);
1512 DataItem
->DataSize
= DataSize
;
1513 DataItem
->Status
= EFI_SUCCESS
;
1517 // DataSize is 0 and Data is NULL, clean up the Gateway address.
1519 if (DataItem
->Data
.Ptr
!= NULL
) {
1520 FreePool (DataItem
->Data
.Ptr
);
1522 DataItem
->Data
.Ptr
= NULL
;
1523 DataItem
->DataSize
= 0;
1524 DataItem
->Status
= EFI_NOT_FOUND
;
1531 The work function is to set the DNS server list for the EFI IPv4 network
1532 stack running on the communication device that this EFI_IP4_CONFIG2_PROTOCOL
1533 manages. It is not configurable when the policy is Ip4Config2PolicyDhcp.
1534 The DNS server addresses must be unicast IPv4 addresses.
1536 @param[in] Instance The pointer to the IP4 config2 instance data.
1537 @param[in] DataSize The size of the buffer pointed to by Data in bytes.
1538 @param[in] Data The data buffer to set, points to an array of
1539 EFI_IPv4_ADDRESS instances.
1541 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1542 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
1543 under the current policy.
1544 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
1545 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
1546 @retval EFI_ABORTED The DNS server addresses to be set equal the current
1548 @retval EFI_SUCCESS The specified configuration data for the EFI IPv4
1549 network stack was set.
1553 Ip4Config2SetDnsServer (
1554 IN IP4_CONFIG2_INSTANCE
*Instance
,
1560 IP4_CONFIG2_DATA_ITEM
*Item
;
1562 Status
= EFI_SUCCESS
;
1565 if (Instance
->Policy
!= Ip4Config2PolicyStatic
) {
1566 return EFI_WRITE_PROTECTED
;
1569 Item
= &Instance
->DataItem
[Ip4Config2DataTypeDnsServer
];
1571 if (DATA_ATTRIB_SET (Item
->Attribute
, DATA_ATTRIB_VOLATILE
)) {
1572 REMOVE_DATA_ATTRIB (Item
->Attribute
, DATA_ATTRIB_VOLATILE
);
1575 if (Data
!= NULL
&& DataSize
!= 0) {
1576 Status
= Ip4Config2SetDnsServerWorker (Instance
, DataSize
, Data
);
1579 // DataSize is 0 and Data is NULL, clean up the DnsServer address.
1581 if (Item
->Data
.Ptr
!= NULL
) {
1582 FreePool (Item
->Data
.Ptr
);
1584 Item
->Data
.Ptr
= NULL
;
1586 Item
->Status
= EFI_NOT_FOUND
;
1593 Generate the operational state of the interface this IP4 config2 instance manages
1594 and output in EFI_IP4_CONFIG2_INTERFACE_INFO.
1596 @param[in] IpSb The pointer to the IP4 service binding instance.
1597 @param[out] IfInfo The pointer to the IP4 config2 interface information structure.
1601 Ip4Config2InitIfInfo (
1602 IN IP4_SERVICE
*IpSb
,
1603 OUT EFI_IP4_CONFIG2_INTERFACE_INFO
*IfInfo
1608 EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE
,
1610 IpSb
->Ip4Config2Instance
.IfIndex
1613 IfInfo
->IfType
= IpSb
->SnpMode
.IfType
;
1614 IfInfo
->HwAddressSize
= IpSb
->SnpMode
.HwAddressSize
;
1615 CopyMem (&IfInfo
->HwAddress
, &IpSb
->SnpMode
.CurrentAddress
, IfInfo
->HwAddressSize
);
1621 Set the configuration for the EFI IPv4 network stack running on the communication
1622 device this EFI_IP4_CONFIG2_PROTOCOL instance manages.
1624 This function is used to set the configuration data of type DataType for the EFI
1625 IPv4 network stack that is running on the communication device that this EFI IPv4
1626 Configuration Protocol instance manages.
1628 DataSize is used to calculate the count of structure instances in the Data for
1629 a DataType in which multiple structure instances are allowed.
1631 This function is always non-blocking. When setting some type of configuration data,
1632 an asynchronous process is invoked to check the correctness of the data, such as
1633 performing Duplicate Address Detection on the manually set local IPv4 addresses.
1634 EFI_NOT_READY is returned immediately to indicate that such an asynchronous process
1635 is invoked, and the process is not finished yet. The caller wanting to get the result
1636 of the asynchronous process is required to call RegisterDataNotify() to register an
1637 event on the specified configuration data. Once the event is signaled, the caller
1638 can call GetData() to obtain the configuration data and know the result.
1639 For other types of configuration data that do not require an asynchronous configuration
1640 process, the result of the operation is immediately returned.
1642 @param[in] This The pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
1643 @param[in] DataType The type of data to set.
1644 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
1645 @param[in] Data The data buffer to set. The type of the data buffer is
1646 associated with the DataType.
1648 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1649 network stack was set successfully.
1650 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
1652 - One or more fields in Data and DataSize do not match the
1653 requirement of the data type indicated by DataType.
1654 @retval EFI_WRITE_PROTECTED The specified configuration data is read-only or the specified
1655 configuration data cannot be set under the current policy.
1656 @retval EFI_ACCESS_DENIED Another set operation on the specified configuration
1657 data is already in process.
1658 @retval EFI_NOT_READY An asynchronous process was invoked to set the specified
1659 configuration data, and the process is not finished yet.
1660 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type
1661 indicated by DataType.
1662 @retval EFI_UNSUPPORTED This DataType is not supported.
1663 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
1664 @retval EFI_DEVICE_ERROR An unexpected system error or network error occurred.
1669 EfiIp4Config2SetData (
1670 IN EFI_IP4_CONFIG2_PROTOCOL
*This
,
1671 IN EFI_IP4_CONFIG2_DATA_TYPE DataType
,
1678 IP4_CONFIG2_INSTANCE
*Instance
;
1681 if ((This
== NULL
) || (Data
== NULL
&& DataSize
!= 0) || (Data
!= NULL
&& DataSize
== 0)) {
1682 return EFI_INVALID_PARAMETER
;
1685 if (DataType
>= Ip4Config2DataTypeMaximum
) {
1686 return EFI_UNSUPPORTED
;
1689 Instance
= IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This
);
1690 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
1691 NET_CHECK_SIGNATURE (IpSb
, IP4_SERVICE_SIGNATURE
);
1694 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1696 Status
= Instance
->DataItem
[DataType
].Status
;
1697 if (Status
!= EFI_NOT_READY
) {
1699 if (Instance
->DataItem
[DataType
].SetData
== NULL
) {
1701 // This type of data is readonly.
1703 Status
= EFI_WRITE_PROTECTED
;
1706 Status
= Instance
->DataItem
[DataType
].SetData (Instance
, DataSize
, Data
);
1707 if (!EFI_ERROR (Status
)) {
1709 // Fire up the events registered with this type of data.
1711 NetMapIterate (&Instance
->DataItem
[DataType
].EventMap
, Ip4Config2SignalEvent
, NULL
);
1712 Ip4Config2WriteConfigData (IpSb
->MacString
, Instance
);
1713 } else if (Status
== EFI_ABORTED
) {
1715 // The SetData is aborted because the data to set is the same with
1716 // the one maintained.
1718 Status
= EFI_SUCCESS
;
1719 NetMapIterate (&Instance
->DataItem
[DataType
].EventMap
, Ip4Config2SignalEvent
, NULL
);
1724 // Another asynchornous process is on the way.
1726 Status
= EFI_ACCESS_DENIED
;
1729 gBS
->RestoreTPL (OldTpl
);
1735 Get the configuration data for the EFI IPv4 network stack running on the communication
1736 device that this EFI_IP4_CONFIG2_PROTOCOL instance manages.
1738 This function returns the configuration data of type DataType for the EFI IPv4 network
1739 stack running on the communication device that this EFI IPv4 Configuration Protocol instance
1742 The caller is responsible for allocating the buffer used to return the specified
1743 configuration data. The required size will be returned to the caller if the size of
1744 the buffer is too small.
1746 EFI_NOT_READY is returned if the specified configuration data is not ready due to an
1747 asynchronous configuration process already in progress. The caller can call RegisterDataNotify()
1748 to register an event on the specified configuration data. Once the asynchronous configuration
1749 process is finished, the event will be signaled, and a subsequent GetData() call will return
1750 the specified configuration data.
1752 @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
1753 @param[in] DataType The type of data to get.
1754 @param[in, out] DataSize On input, in bytes, the size of Data. On output, in bytes, the
1755 size of buffer required to store the specified configuration data.
1756 @param[in] Data The data buffer in which the configuration data is returned. The
1757 type of the data buffer is associated with the DataType.
1758 This is an optional parameter that may be NULL.
1760 @retval EFI_SUCCESS The specified configuration data was obtained successfully.
1761 @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
1764 - Data is NULL if *DataSize is not zero.
1765 @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified configuration data,
1766 and the required size is returned in DataSize.
1767 @retval EFI_NOT_READY The specified configuration data is not ready due to an
1768 asynchronous configuration process already in progress.
1769 @retval EFI_NOT_FOUND The specified configuration data is not found.
1774 EfiIp4Config2GetData (
1775 IN EFI_IP4_CONFIG2_PROTOCOL
*This
,
1776 IN EFI_IP4_CONFIG2_DATA_TYPE DataType
,
1777 IN OUT UINTN
*DataSize
,
1778 IN VOID
*Data OPTIONAL
1783 IP4_CONFIG2_INSTANCE
*Instance
;
1784 IP4_CONFIG2_DATA_ITEM
*DataItem
;
1786 if ((This
== NULL
) || (DataSize
== NULL
) || ((*DataSize
!= 0) && (Data
== NULL
))) {
1787 return EFI_INVALID_PARAMETER
;
1790 if (DataType
>= Ip4Config2DataTypeMaximum
) {
1791 return EFI_NOT_FOUND
;
1794 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1796 Instance
= IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This
);
1797 DataItem
= &Instance
->DataItem
[DataType
];
1799 Status
= Instance
->DataItem
[DataType
].Status
;
1800 if (!EFI_ERROR (Status
)) {
1802 if (DataItem
->GetData
!= NULL
) {
1804 Status
= DataItem
->GetData (Instance
, DataSize
, Data
);
1805 } else if (*DataSize
< Instance
->DataItem
[DataType
].DataSize
) {
1807 // Update the buffer length.
1809 *DataSize
= Instance
->DataItem
[DataType
].DataSize
;
1810 Status
= EFI_BUFFER_TOO_SMALL
;
1813 *DataSize
= Instance
->DataItem
[DataType
].DataSize
;
1814 CopyMem (Data
, Instance
->DataItem
[DataType
].Data
.Ptr
, *DataSize
);
1818 gBS
->RestoreTPL (OldTpl
);
1824 Register an event that is signaled whenever a configuration process on the specified
1825 configuration data is done.
1827 This function registers an event that is to be signaled whenever a configuration
1828 process on the specified configuration data is performed. An event can be registered
1829 for a different DataType simultaneously. The caller is responsible for determining
1830 which type of configuration data causes the signaling of the event in such an event.
1832 @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
1833 @param[in] DataType The type of data to unregister the event for.
1834 @param[in] Event The event to register.
1836 @retval EFI_SUCCESS The notification event for the specified configuration data is
1838 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
1839 @retval EFI_UNSUPPORTED The configuration data type specified by DataType is not
1841 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
1842 @retval EFI_ACCESS_DENIED The Event is already registered for the DataType.
1847 EfiIp4Config2RegisterDataNotify (
1848 IN EFI_IP4_CONFIG2_PROTOCOL
*This
,
1849 IN EFI_IP4_CONFIG2_DATA_TYPE DataType
,
1855 IP4_CONFIG2_INSTANCE
*Instance
;
1859 if ((This
== NULL
) || (Event
== NULL
)) {
1860 return EFI_INVALID_PARAMETER
;
1863 if (DataType
>= Ip4Config2DataTypeMaximum
) {
1864 return EFI_UNSUPPORTED
;
1867 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1869 Instance
= IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This
);
1870 EventMap
= &Instance
->DataItem
[DataType
].EventMap
;
1873 // Check whether this event is already registered for this DataType.
1875 Item
= NetMapFindKey (EventMap
, Event
);
1878 Status
= NetMapInsertTail (EventMap
, Event
, NULL
);
1880 if (EFI_ERROR (Status
)) {
1882 Status
= EFI_OUT_OF_RESOURCES
;
1887 Status
= EFI_ACCESS_DENIED
;
1890 gBS
->RestoreTPL (OldTpl
);
1896 Remove a previously registered event for the specified configuration data.
1898 @param This The pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
1899 @param DataType The type of data to remove from the previously
1901 @param Event The event to be unregistered.
1903 @retval EFI_SUCCESS The event registered for the specified
1904 configuration data was removed.
1905 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
1906 @retval EFI_NOT_FOUND The Event has not been registered for the
1912 EfiIp4Config2UnregisterDataNotify (
1913 IN EFI_IP4_CONFIG2_PROTOCOL
*This
,
1914 IN EFI_IP4_CONFIG2_DATA_TYPE DataType
,
1920 IP4_CONFIG2_INSTANCE
*Instance
;
1923 if ((This
== NULL
) || (Event
== NULL
)) {
1924 return EFI_INVALID_PARAMETER
;
1927 if (DataType
>= Ip4Config2DataTypeMaximum
) {
1928 return EFI_NOT_FOUND
;
1931 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1933 Instance
= IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This
);
1935 Item
= NetMapFindKey (&Instance
->DataItem
[DataType
].EventMap
, Event
);
1938 NetMapRemoveItem (&Instance
->DataItem
[DataType
].EventMap
, Item
, NULL
);
1939 Status
= EFI_SUCCESS
;
1942 Status
= EFI_NOT_FOUND
;
1945 gBS
->RestoreTPL (OldTpl
);
1951 Initialize an IP4_CONFIG2_INSTANCE.
1953 @param[out] Instance The buffer of IP4_CONFIG2_INSTANCE to be initialized.
1955 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
1956 @retval EFI_SUCCESS The IP4_CONFIG2_INSTANCE initialized successfully.
1960 Ip4Config2InitInstance (
1961 OUT IP4_CONFIG2_INSTANCE
*Instance
1965 IP4_CONFIG2_INSTANCE
*TmpInstance
;
1970 IP4_CONFIG2_DATA_ITEM
*DataItem
;
1973 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
1975 Instance
->Signature
= IP4_CONFIG2_INSTANCE_SIGNATURE
;
1979 // Determine the index of this interface.
1982 NET_LIST_FOR_EACH (Entry
, &mIp4Config2InstanceList
) {
1983 TmpInstance
= NET_LIST_USER_STRUCT_S (Entry
, IP4_CONFIG2_INSTANCE
, Link
, IP4_CONFIG2_INSTANCE_SIGNATURE
);
1985 if (TmpInstance
->IfIndex
> IfIndex
) {
1987 // There is a sequence hole because some interface is down.
1995 Instance
->IfIndex
= IfIndex
;
1996 NetListInsertBefore (Entry
, &Instance
->Link
);
1998 for (Index
= 0; Index
< Ip4Config2DataTypeMaximum
; Index
++) {
2000 // Initialize the event map for each data item.
2002 NetMapInit (&Instance
->DataItem
[Index
].EventMap
);
2007 // Initialize each data type: associate storage and set data size for the
2008 // fixed size data types, hook the SetData function, set the data attribute.
2010 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeInterfaceInfo
];
2011 DataItem
->GetData
= Ip4Config2GetIfInfo
;
2012 DataItem
->Data
.Ptr
= &Instance
->InterfaceInfo
;
2013 DataItem
->DataSize
= sizeof (Instance
->InterfaceInfo
);
2014 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
| DATA_ATTRIB_VOLATILE
);
2015 Ip4Config2InitIfInfo (IpSb
, &Instance
->InterfaceInfo
);
2017 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypePolicy
];
2018 DataItem
->SetData
= Ip4Config2SetPolicy
;
2019 DataItem
->Data
.Ptr
= &Instance
->Policy
;
2020 DataItem
->DataSize
= sizeof (Instance
->Policy
);
2021 Instance
->Policy
= Ip4Config2PolicyStatic
;
2022 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
);
2024 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeManualAddress
];
2025 DataItem
->SetData
= Ip4Config2SetManualAddress
;
2026 DataItem
->Status
= EFI_NOT_FOUND
;
2028 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeGateway
];
2029 DataItem
->SetData
= Ip4Config2SetGateway
;
2030 DataItem
->Status
= EFI_NOT_FOUND
;
2032 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeDnsServer
];
2033 DataItem
->SetData
= Ip4Config2SetDnsServer
;
2034 DataItem
->Status
= EFI_NOT_FOUND
;
2036 Instance
->Configured
= TRUE
;
2039 // Try to read the config data from NV variable.
2040 // If not found, write initialized config data into NV variable
2041 // as a default config data.
2043 Status
= Ip4Config2ReadConfigData (IpSb
->MacString
, Instance
);
2044 if (Status
== EFI_NOT_FOUND
) {
2045 Status
= Ip4Config2WriteConfigData (IpSb
->MacString
, Instance
);
2048 if (EFI_ERROR (Status
)) {
2052 Instance
->Ip4Config2
.SetData
= EfiIp4Config2SetData
;
2053 Instance
->Ip4Config2
.GetData
= EfiIp4Config2GetData
;
2054 Instance
->Ip4Config2
.RegisterDataNotify
= EfiIp4Config2RegisterDataNotify
;
2055 Instance
->Ip4Config2
.UnregisterDataNotify
= EfiIp4Config2UnregisterDataNotify
;
2058 // Publish the IP4 configuration form
2060 return Ip4Config2FormInit (Instance
);
2065 Release an IP4_CONFIG2_INSTANCE.
2067 @param[in, out] Instance The buffer of IP4_CONFIG2_INSTANCE to be freed.
2071 Ip4Config2CleanInstance (
2072 IN OUT IP4_CONFIG2_INSTANCE
*Instance
2076 IP4_CONFIG2_DATA_ITEM
*DataItem
;
2078 if (Instance
->DeclineAddress
!= NULL
) {
2079 FreePool (Instance
->DeclineAddress
);
2082 if (!Instance
->Configured
) {
2086 if (Instance
->Dhcp4Handle
!= NULL
) {
2088 Ip4Config2DestroyDhcp4 (Instance
);
2094 if (Instance
->Dhcp4Event
!= NULL
) {
2095 gBS
->CloseEvent (Instance
->Dhcp4Event
);
2096 Instance
->Dhcp4Event
= NULL
;
2099 for (Index
= 0; Index
< Ip4Config2DataTypeMaximum
; Index
++) {
2101 DataItem
= &Instance
->DataItem
[Index
];
2103 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
)) {
2104 if (DataItem
->Data
.Ptr
!= NULL
) {
2105 FreePool (DataItem
->Data
.Ptr
);
2107 DataItem
->Data
.Ptr
= NULL
;
2108 DataItem
->DataSize
= 0;
2111 NetMapClean (&Instance
->DataItem
[Index
].EventMap
);
2114 Ip4Config2FormUnload (Instance
);
2116 RemoveEntryList (&Instance
->Link
);
2120 The event handle for IP4 auto reconfiguration. The original default
2121 interface and route table will be removed as the default.
2123 @param[in] Context The IP4 service binding instance.
2128 Ip4AutoReconfigCallBackDpc (
2134 IpSb
= (IP4_SERVICE
*) Context
;
2135 NET_CHECK_SIGNATURE (IpSb
, IP4_SERVICE_SIGNATURE
);
2137 if (IpSb
->State
> IP4_SERVICE_UNSTARTED
) {
2138 IpSb
->State
= IP4_SERVICE_UNSTARTED
;
2141 IpSb
->Reconfig
= TRUE
;
2143 Ip4StartAutoConfig (&IpSb
->Ip4Config2Instance
);
2150 Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK.
2152 @param Event The event that is signalled.
2153 @param Context The IP4 service binding instance.
2158 Ip4AutoReconfigCallBack (
2164 // Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK
2166 QueueDpc (TPL_CALLBACK
, Ip4AutoReconfigCallBackDpc
, Context
);