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
);
152 Signal the registered event. It is the callback routine for NetMapIterate.
154 @param[in] Map Points to the list of registered event.
155 @param[in] Item The registered event.
156 @param[in] Arg Not used.
158 @retval EFI_SUCCESS The event was signaled successfully.
162 Ip4Config2SignalEvent (
164 IN NET_MAP_ITEM
*Item
,
168 gBS
->SignalEvent ((EFI_EVENT
)Item
->Key
);
174 Read the configuration data from variable storage according to the VarName and
175 gEfiIp4Config2ProtocolGuid. It checks the integrity of variable data. If the
176 data is corrupted, it clears the variable data to ZERO. Otherwise, it outputs the
177 configuration data to IP4_CONFIG2_INSTANCE.
179 @param[in] VarName The pointer to the variable name
180 @param[in, out] Instance The pointer to the IP4 config2 instance data.
182 @retval EFI_NOT_FOUND The variable can not be found or already corrupted.
183 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
184 @retval EFI_SUCCESS The configuration data was retrieved successfully.
188 Ip4Config2ReadConfigData (
190 IN OUT IP4_CONFIG2_INSTANCE
*Instance
195 IP4_CONFIG2_VARIABLE
*Variable
;
196 IP4_CONFIG2_DATA_ITEM
*DataItem
;
198 IP4_CONFIG2_DATA_RECORD DataRecord
;
202 // Try to read the configuration variable.
205 Status
= gRT
->GetVariable (
207 &gEfiIp4Config2ProtocolGuid
,
213 if (Status
== EFI_BUFFER_TOO_SMALL
) {
215 // Allocate buffer and read the config variable.
217 Variable
= AllocatePool (VarSize
);
218 if (Variable
== NULL
) {
219 return EFI_OUT_OF_RESOURCES
;
222 Status
= gRT
->GetVariable (
224 &gEfiIp4Config2ProtocolGuid
,
229 if (EFI_ERROR (Status
) || ((UINT16
)(~NetblockChecksum ((UINT8
*)Variable
, (UINT32
)VarSize
)) != 0)) {
231 // GetVariable still error or the variable is corrupted.
232 // Fall back to the default value.
237 // Remove the problematic variable and return EFI_NOT_FOUND, a new
238 // variable will be set again.
242 &gEfiIp4Config2ProtocolGuid
,
243 IP4_CONFIG2_VARIABLE_ATTRIBUTE
,
248 return EFI_NOT_FOUND
;
251 for (Index
= 0; Index
< Variable
->DataRecordCount
; Index
++) {
252 CopyMem (&DataRecord
, &Variable
->DataRecord
[Index
], sizeof (DataRecord
));
254 DataItem
= &Instance
->DataItem
[DataRecord
.DataType
];
255 if (DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
) &&
256 (DataItem
->DataSize
!= DataRecord
.DataSize
)
260 // Perhaps a corrupted data record...
265 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
)) {
267 // This data item has variable length data.
269 DataItem
->Data
.Ptr
= AllocatePool (DataRecord
.DataSize
);
270 if (DataItem
->Data
.Ptr
== NULL
) {
272 // no memory resource
278 Data
= (CHAR8
*)Variable
+ DataRecord
.Offset
;
279 CopyMem (DataItem
->Data
.Ptr
, Data
, DataRecord
.DataSize
);
281 DataItem
->DataSize
= DataRecord
.DataSize
;
282 DataItem
->Status
= EFI_SUCCESS
;
293 Write the configuration data from IP4_CONFIG2_INSTANCE to variable storage.
295 @param[in] VarName The pointer to the variable name.
296 @param[in] Instance The pointer to the IP4 config2 instance data.
298 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
299 @retval EFI_SUCCESS The configuration data is written successfully.
303 Ip4Config2WriteConfigData (
305 IN IP4_CONFIG2_INSTANCE
*Instance
310 IP4_CONFIG2_DATA_ITEM
*DataItem
;
311 IP4_CONFIG2_VARIABLE
*Variable
;
312 IP4_CONFIG2_DATA_RECORD
*DataRecord
;
316 VarSize
= sizeof (IP4_CONFIG2_VARIABLE
) - sizeof (IP4_CONFIG2_DATA_RECORD
);
318 for (Index
= 0; Index
< Ip4Config2DataTypeMaximum
; Index
++) {
319 DataItem
= &Instance
->DataItem
[Index
];
320 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_VOLATILE
) && !EFI_ERROR (DataItem
->Status
)) {
321 VarSize
+= sizeof (IP4_CONFIG2_DATA_RECORD
) + DataItem
->DataSize
;
325 Variable
= AllocatePool (VarSize
);
326 if (Variable
== NULL
) {
327 return EFI_OUT_OF_RESOURCES
;
330 Heap
= (CHAR8
*)Variable
+ VarSize
;
331 Variable
->DataRecordCount
= 0;
333 for (Index
= 0; Index
< Ip4Config2DataTypeMaximum
; Index
++) {
334 DataItem
= &Instance
->DataItem
[Index
];
335 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_VOLATILE
) && !EFI_ERROR (DataItem
->Status
)) {
336 Heap
-= DataItem
->DataSize
;
337 CopyMem (Heap
, DataItem
->Data
.Ptr
, DataItem
->DataSize
);
339 DataRecord
= &Variable
->DataRecord
[Variable
->DataRecordCount
];
340 DataRecord
->DataType
= (EFI_IP4_CONFIG2_DATA_TYPE
)Index
;
341 DataRecord
->DataSize
= (UINT32
)DataItem
->DataSize
;
342 DataRecord
->Offset
= (UINT16
)(Heap
- (CHAR8
*)Variable
);
344 Variable
->DataRecordCount
++;
348 Variable
->Checksum
= 0;
349 Variable
->Checksum
= (UINT16
) ~NetblockChecksum ((UINT8
*)Variable
, (UINT32
)VarSize
);
351 Status
= gRT
->SetVariable (
353 &gEfiIp4Config2ProtocolGuid
,
354 IP4_CONFIG2_VARIABLE_ATTRIBUTE
,
365 Build a EFI_IP4_ROUTE_TABLE to be returned to the caller of GetModeData.
366 The EFI_IP4_ROUTE_TABLE is clumsy to use in the internal operation of the
369 @param[in] IpSb The IP4 service binding instance.
370 @param[out] Table The built IP4 route table.
372 @retval EFI_SUCCESS The route table is successfully build
373 @retval EFI_NOT_FOUND Failed to allocate the memory for the route table.
377 Ip4Config2BuildDefaultRouteTable (
378 IN IP4_SERVICE
*IpSb
,
379 OUT EFI_IP4_ROUTE_TABLE
*Table
383 IP4_ROUTE_ENTRY
*RtEntry
;
387 if (IpSb
->DefaultRouteTable
== NULL
) {
388 return EFI_NOT_FOUND
;
391 Count
= IpSb
->DefaultRouteTable
->TotalNum
;
394 return EFI_NOT_FOUND
;
398 // Copy the route entry to EFI route table. Keep the order of
399 // route entry copied from most specific to default route. That
400 // is, interlevel the route entry from the instance's route area
401 // and those from the default route table's route area.
405 for (Index
= IP4_MASK_MAX
; Index
>= 0; Index
--) {
406 NET_LIST_FOR_EACH (Entry
, &(IpSb
->DefaultRouteTable
->RouteArea
[Index
])) {
407 RtEntry
= NET_LIST_USER_STRUCT (Entry
, IP4_ROUTE_ENTRY
, Link
);
409 EFI_IP4 (Table
[Count
].SubnetAddress
) = HTONL (RtEntry
->Dest
& RtEntry
->Netmask
);
410 EFI_IP4 (Table
[Count
].SubnetMask
) = HTONL (RtEntry
->Netmask
);
411 EFI_IP4 (Table
[Count
].GatewayAddress
) = HTONL (RtEntry
->NextHop
);
421 The event process routine when the DHCPv4 service binding protocol is installed
424 @param[in] Event Not used.
425 @param[in] Context The pointer to the IP4 config2 instance data.
430 Ip4Config2OnDhcp4SbInstalled (
435 IP4_CONFIG2_INSTANCE
*Instance
;
437 Instance
= (IP4_CONFIG2_INSTANCE
*)Context
;
439 if ((Instance
->Dhcp4Handle
!= NULL
) || (Instance
->Policy
!= Ip4Config2PolicyDhcp
)) {
441 // The DHCP4 child is already created or the policy is no longer DHCP.
446 Ip4StartAutoConfig (Instance
);
450 Set the station address and subnetmask for the default interface.
452 @param[in] IpSb The pointer to the IP4 service binding instance.
453 @param[in] StationAddress Ip address to be set.
454 @param[in] SubnetMask Subnet to be set.
456 @retval EFI_SUCCESS Set default address successful.
457 @retval Others Some errors occur in setting.
461 Ip4Config2SetDefaultAddr (
462 IN IP4_SERVICE
*IpSb
,
463 IN IP4_ADDR StationAddress
,
464 IN IP4_ADDR SubnetMask
469 IP4_PROTOCOL
*Ip4Instance
;
470 EFI_ARP_PROTOCOL
*Arp
;
473 IP4_ROUTE_TABLE
*RouteTable
;
475 IpIf
= IpSb
->DefaultInterface
;
476 ASSERT (IpIf
!= NULL
);
478 if ((IpIf
->Ip
== StationAddress
) && (IpIf
->SubnetMask
== SubnetMask
)) {
479 IpSb
->State
= IP4_SERVICE_CONFIGED
;
483 if (IpSb
->Reconfig
) {
485 // The default address is changed, free the previous interface first.
487 if (IpSb
->DefaultRouteTable
!= NULL
) {
488 Ip4FreeRouteTable (IpSb
->DefaultRouteTable
);
489 IpSb
->DefaultRouteTable
= NULL
;
492 Ip4CancelReceive (IpSb
->DefaultInterface
);
493 Ip4FreeInterface (IpSb
->DefaultInterface
, NULL
);
494 IpSb
->DefaultInterface
= NULL
;
496 // Create new default interface and route table.
498 IpIf
= Ip4CreateInterface (IpSb
->Mnp
, IpSb
->Controller
, IpSb
->Image
);
500 return EFI_OUT_OF_RESOURCES
;
503 RouteTable
= Ip4CreateRouteTable ();
504 if (RouteTable
== NULL
) {
505 Ip4FreeInterface (IpIf
, NULL
);
506 return EFI_OUT_OF_RESOURCES
;
509 IpSb
->DefaultInterface
= IpIf
;
510 InsertHeadList (&IpSb
->Interfaces
, &IpIf
->Link
);
511 IpSb
->DefaultRouteTable
= RouteTable
;
512 Ip4ReceiveFrame (IpIf
, NULL
, Ip4AccpetFrame
, IpSb
);
515 if (IpSb
->State
== IP4_SERVICE_CONFIGED
) {
516 IpSb
->State
= IP4_SERVICE_UNSTARTED
;
519 Status
= Ip4SetAddress (IpIf
, StationAddress
, SubnetMask
);
520 if (EFI_ERROR (Status
)) {
524 if (IpIf
->Arp
!= NULL
) {
526 // A non-NULL IpIf->Arp here means a new ARP child is created when setting default address,
527 // but some IP children may have referenced the default interface before it is configured,
528 // these IP instances also consume this ARP protocol so they need to open it BY_CHILD_CONTROLLER.
531 NET_LIST_FOR_EACH (Entry
, &IpIf
->IpInstances
) {
532 Ip4Instance
= NET_LIST_USER_STRUCT_S (Entry
, IP4_PROTOCOL
, AddrLink
, IP4_PROTOCOL_SIGNATURE
);
533 Status
= gBS
->OpenProtocol (
535 &gEfiArpProtocolGuid
,
537 gIp4DriverBinding
.DriverBindingHandle
,
539 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
541 if (EFI_ERROR (Status
)) {
548 // Add a route for the connected network.
550 Subnet
= StationAddress
& SubnetMask
;
553 IpSb
->DefaultRouteTable
,
559 IpSb
->State
= IP4_SERVICE_CONFIGED
;
560 IpSb
->Reconfig
= FALSE
;
566 Set the station address, subnetmask and gateway address for the default interface.
568 @param[in] Instance The pointer to the IP4 config2 instance data.
569 @param[in] StationAddress Ip address to be set.
570 @param[in] SubnetMask Subnet to be set.
571 @param[in] GatewayAddress Gateway to be set.
573 @retval EFI_SUCCESS Set default If successful.
574 @retval Others Errors occur as indicated.
578 Ip4Config2SetDefaultIf (
579 IN IP4_CONFIG2_INSTANCE
*Instance
,
580 IN IP4_ADDR StationAddress
,
581 IN IP4_ADDR SubnetMask
,
582 IN IP4_ADDR GatewayAddress
588 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
591 // Check whether the StationAddress/SubnetMask pair is valid.
593 if (!Ip4StationAddressValid (StationAddress
, SubnetMask
)) {
594 return EFI_INVALID_PARAMETER
;
597 Status
= Ip4Config2SetDefaultAddr (IpSb
, StationAddress
, SubnetMask
);
598 if (EFI_ERROR (Status
)) {
603 // Create a route if there is a default router.
605 if (GatewayAddress
!= IP4_ALLZERO_ADDRESS
) {
607 IpSb
->DefaultRouteTable
,
618 Release all the DHCP related resources.
620 @param Instance The IP4 config2 instance.
626 Ip4Config2CleanDhcp4 (
627 IN IP4_CONFIG2_INSTANCE
*Instance
632 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
634 if (Instance
->Dhcp4
!= NULL
) {
635 Instance
->Dhcp4
->Stop (Instance
->Dhcp4
);
638 Instance
->Dhcp4Handle
,
639 &gEfiDhcp4ProtocolGuid
,
644 Instance
->Dhcp4
= NULL
;
647 if (Instance
->Dhcp4Handle
!= NULL
) {
648 NetLibDestroyServiceChild (
651 &gEfiDhcp4ServiceBindingProtocolGuid
,
652 Instance
->Dhcp4Handle
655 Instance
->Dhcp4Handle
= NULL
;
658 if (Instance
->Dhcp4Event
!= NULL
) {
659 gBS
->CloseEvent (Instance
->Dhcp4Event
);
660 Instance
->Dhcp4Event
= NULL
;
665 This worker function sets the DNS server list for the EFI IPv4 network
666 stack running on the communication device that this EFI_IP4_CONFIG2_PROTOCOL
667 manages. The DNS server addresses must be unicast IPv4 addresses.
669 @param[in] Instance The pointer to the IP4 config2 instance data.
670 @param[in] DataSize The size of the buffer pointed to by Data in bytes.
671 @param[in] Data The data buffer to set, points to an array of
672 EFI_IPv4_ADDRESS instances.
674 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
675 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
676 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
677 @retval EFI_ABORTED The DNS server addresses to be set equal the current
679 @retval EFI_SUCCESS The specified configuration data for the EFI IPv4
680 network stack was set.
684 Ip4Config2SetDnsServerWorker (
685 IN IP4_CONFIG2_INSTANCE
*Instance
,
692 EFI_IPv4_ADDRESS
*OldDns
;
693 EFI_IPv4_ADDRESS
*NewDns
;
696 IP4_CONFIG2_DATA_ITEM
*Item
;
701 if ((DataSize
% sizeof (EFI_IPv4_ADDRESS
) != 0) || (DataSize
== 0)) {
702 return EFI_BAD_BUFFER_SIZE
;
705 Item
= &Instance
->DataItem
[Ip4Config2DataTypeDnsServer
];
706 NewDns
= (EFI_IPv4_ADDRESS
*)Data
;
707 OldDns
= Item
->Data
.DnsServers
;
708 NewDnsCount
= DataSize
/ sizeof (EFI_IPv4_ADDRESS
);
709 OldDnsCount
= Item
->DataSize
/ sizeof (EFI_IPv4_ADDRESS
);
712 if (NewDnsCount
!= OldDnsCount
) {
713 Tmp
= AllocatePool (DataSize
);
715 return EFI_OUT_OF_RESOURCES
;
721 for (NewIndex
= 0; NewIndex
< NewDnsCount
; NewIndex
++) {
722 CopyMem (&DnsAddress
, NewDns
+ NewIndex
, sizeof (IP4_ADDR
));
723 if (IP4_IS_UNSPECIFIED (NTOHL (DnsAddress
)) || IP4_IS_LOCAL_BROADCAST (NTOHL (DnsAddress
))) {
725 // The dns server address must be unicast.
731 return EFI_INVALID_PARAMETER
;
736 // If any address in the new setting is not in the old settings, skip the
737 // comparision below.
742 for (OldIndex
= 0; OldIndex
< OldDnsCount
; OldIndex
++) {
743 if (EFI_IP4_EQUAL (NewDns
+ NewIndex
, OldDns
+ OldIndex
)) {
745 // If found break out.
751 if (OldIndex
== OldDnsCount
) {
756 if (!OneAdded
&& (DataSize
== Item
->DataSize
)) {
758 // No new item is added and the size is the same.
760 Item
->Status
= EFI_SUCCESS
;
764 if (Item
->Data
.Ptr
!= NULL
) {
765 FreePool (Item
->Data
.Ptr
);
768 Item
->Data
.Ptr
= Tmp
;
771 CopyMem (Item
->Data
.Ptr
, Data
, DataSize
);
772 Item
->DataSize
= DataSize
;
773 Item
->Status
= EFI_SUCCESS
;
779 Callback function when DHCP process finished. It will save the
780 retrieved IP configure parameter from DHCP to the NVRam.
782 @param Event The callback event
783 @param Context Opaque context to the callback
790 Ip4Config2OnDhcp4Complete (
795 IP4_CONFIG2_INSTANCE
*Instance
;
796 EFI_DHCP4_MODE_DATA Dhcp4Mode
;
798 IP4_ADDR StationAddress
;
800 IP4_ADDR GatewayAddress
;
803 EFI_DHCP4_PACKET_OPTION
**OptionList
;
805 Instance
= (IP4_CONFIG2_INSTANCE
*)Context
;
806 ASSERT (Instance
->Dhcp4
!= NULL
);
809 // Get the DHCP retrieved parameters
811 Status
= Instance
->Dhcp4
->GetModeData (Instance
->Dhcp4
, &Dhcp4Mode
);
813 if (EFI_ERROR (Status
)) {
817 if (Dhcp4Mode
.State
== Dhcp4Bound
) {
818 StationAddress
= EFI_NTOHL (Dhcp4Mode
.ClientAddress
);
819 SubnetMask
= EFI_NTOHL (Dhcp4Mode
.SubnetMask
);
820 GatewayAddress
= EFI_NTOHL (Dhcp4Mode
.RouterAddress
);
822 Status
= Ip4Config2SetDefaultIf (Instance
, StationAddress
, SubnetMask
, GatewayAddress
);
823 if (EFI_ERROR (Status
)) {
828 // Parse the ACK to get required DNS server information.
833 Status
= Instance
->Dhcp4
->Parse (Instance
->Dhcp4
, Dhcp4Mode
.ReplyPacket
, &OptionCount
, OptionList
);
834 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
838 OptionList
= AllocateZeroPool (OptionCount
* sizeof (EFI_DHCP4_PACKET_OPTION
*));
839 if (OptionList
== NULL
) {
843 Status
= Instance
->Dhcp4
->Parse (Instance
->Dhcp4
, Dhcp4Mode
.ReplyPacket
, &OptionCount
, OptionList
);
844 if (EFI_ERROR (Status
)) {
845 FreePool (OptionList
);
849 for (Index
= 0; Index
< OptionCount
; Index
++) {
851 // Look for DNS Server opcode (6).
853 if (OptionList
[Index
]->OpCode
== DHCP4_TAG_DNS_SERVER
) {
854 if (((OptionList
[Index
]->Length
& 0x3) != 0) || (OptionList
[Index
]->Length
== 0)) {
858 Ip4Config2SetDnsServerWorker (Instance
, OptionList
[Index
]->Length
, &OptionList
[Index
]->Data
[0]);
863 FreePool (OptionList
);
865 Instance
->DhcpSuccess
= TRUE
;
869 Ip4Config2CleanDhcp4 (Instance
);
874 Start the DHCP configuration for this IP service instance.
875 It will locates the EFI_IP4_CONFIG2_PROTOCOL, then start the
878 @param[in] Instance The IP4 config2 instance to configure
880 @retval EFI_SUCCESS The auto configuration is successfully started
881 @retval Others Failed to start auto configuration.
886 IN IP4_CONFIG2_INSTANCE
*Instance
890 EFI_DHCP4_PROTOCOL
*Dhcp4
;
891 EFI_DHCP4_MODE_DATA Dhcp4Mode
;
892 EFI_DHCP4_PACKET_OPTION
*OptionList
[1];
893 IP4_CONFIG2_DHCP4_OPTION ParaList
;
896 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
898 if (IpSb
->State
> IP4_SERVICE_UNSTARTED
) {
903 // A host must not invoke DHCP configuration if it is already
904 // participating in the DHCP configuration process.
906 if (Instance
->Dhcp4Handle
!= NULL
) {
910 Status
= NetLibCreateServiceChild (
913 &gEfiDhcp4ServiceBindingProtocolGuid
,
914 &Instance
->Dhcp4Handle
917 if (Status
== EFI_UNSUPPORTED
) {
919 // No DHCPv4 Service Binding protocol, register a notify.
921 if (Instance
->Dhcp4SbNotifyEvent
== NULL
) {
922 Instance
->Dhcp4SbNotifyEvent
= EfiCreateProtocolNotifyEvent (
923 &gEfiDhcp4ServiceBindingProtocolGuid
,
925 Ip4Config2OnDhcp4SbInstalled
,
927 &Instance
->Registration
932 if (EFI_ERROR (Status
)) {
936 if (Instance
->Dhcp4SbNotifyEvent
!= NULL
) {
937 gBS
->CloseEvent (Instance
->Dhcp4SbNotifyEvent
);
940 Status
= gBS
->OpenProtocol (
941 Instance
->Dhcp4Handle
,
942 &gEfiDhcp4ProtocolGuid
,
943 (VOID
**)&Instance
->Dhcp4
,
946 EFI_OPEN_PROTOCOL_BY_DRIVER
948 if (EFI_ERROR (Status
)) {
949 NetLibDestroyServiceChild (
952 &gEfiDhcp4ServiceBindingProtocolGuid
,
953 Instance
->Dhcp4Handle
956 Instance
->Dhcp4Handle
= NULL
;
962 // Check the current DHCP status, if the DHCP process has
963 // already finished, return now.
965 Dhcp4
= Instance
->Dhcp4
;
966 Status
= Dhcp4
->GetModeData (Dhcp4
, &Dhcp4Mode
);
967 if (Dhcp4Mode
.State
== Dhcp4Bound
) {
968 Ip4Config2OnDhcp4Complete (NULL
, Instance
);
974 // Try to start the DHCP process. Use most of the current
975 // DHCP configuration to avoid problems if some DHCP client
976 // yields the control of this DHCP service to us.
978 ParaList
.Head
.OpCode
= DHCP4_TAG_PARA_LIST
;
979 ParaList
.Head
.Length
= 3;
980 ParaList
.Head
.Data
[0] = DHCP4_TAG_NETMASK
;
981 ParaList
.Route
= DHCP4_TAG_ROUTER
;
982 ParaList
.Dns
= DHCP4_TAG_DNS_SERVER
;
983 OptionList
[0] = &ParaList
.Head
;
984 Dhcp4Mode
.ConfigData
.OptionCount
= 1;
985 Dhcp4Mode
.ConfigData
.OptionList
= OptionList
;
987 Status
= Dhcp4
->Configure (Dhcp4
, &Dhcp4Mode
.ConfigData
);
988 if (EFI_ERROR (Status
)) {
990 Instance
->Dhcp4Handle
,
991 &gEfiDhcp4ProtocolGuid
,
996 NetLibDestroyServiceChild (
999 &gEfiDhcp4ServiceBindingProtocolGuid
,
1000 Instance
->Dhcp4Handle
1003 Instance
->Dhcp4
= NULL
;
1005 Instance
->Dhcp4Handle
= NULL
;
1011 // Start the DHCP process
1013 Status
= gBS
->CreateEvent (
1016 Ip4Config2OnDhcp4Complete
,
1018 &Instance
->Dhcp4Event
1020 if (EFI_ERROR (Status
)) {
1021 Ip4Config2DestroyDhcp4 (Instance
);
1025 Status
= Dhcp4
->Start (Dhcp4
, Instance
->Dhcp4Event
);
1026 if (EFI_ERROR (Status
)) {
1027 Ip4Config2DestroyDhcp4 (Instance
);
1028 gBS
->CloseEvent (Instance
->Dhcp4Event
);
1029 Instance
->Dhcp4Event
= NULL
;
1034 IpSb
->State
= IP4_SERVICE_STARTED
;
1041 The work function is to get the interface information of the communication
1042 device this IP4_CONFIG2_INSTANCE manages.
1044 @param[in] Instance Pointer to the IP4 config2 instance data.
1045 @param[in, out] DataSize On input, in bytes, the size of Data. On output, in
1046 bytes, the size of buffer required to store the specified
1048 @param[in] Data The data buffer in which the configuration data is returned.
1049 Ignored if DataSize is ZERO.
1051 @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified
1052 configuration data, and the required size is
1053 returned in DataSize.
1054 @retval EFI_SUCCESS The specified configuration data was obtained.
1058 Ip4Config2GetIfInfo (
1059 IN IP4_CONFIG2_INSTANCE
*Instance
,
1060 IN OUT UINTN
*DataSize
,
1061 IN VOID
*Data OPTIONAL
1066 IP4_CONFIG2_DATA_ITEM
*Item
;
1067 EFI_IP4_CONFIG2_INTERFACE_INFO
*IfInfo
;
1070 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
1071 Length
= sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO
);
1073 if (IpSb
->DefaultRouteTable
!= NULL
) {
1074 Length
+= IpSb
->DefaultRouteTable
->TotalNum
* sizeof (EFI_IP4_ROUTE_TABLE
);
1077 if (*DataSize
< Length
) {
1079 return EFI_BUFFER_TOO_SMALL
;
1083 // Copy the fixed size part of the interface info.
1085 Item
= &Instance
->DataItem
[Ip4Config2DataTypeInterfaceInfo
];
1086 IfInfo
= (EFI_IP4_CONFIG2_INTERFACE_INFO
*)Data
;
1087 CopyMem (IfInfo
, Item
->Data
.Ptr
, sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO
));
1090 // Update the address info.
1092 if (IpSb
->DefaultInterface
!= NULL
) {
1093 Address
= HTONL (IpSb
->DefaultInterface
->Ip
);
1094 CopyMem (&IfInfo
->StationAddress
, &Address
, sizeof (EFI_IPv4_ADDRESS
));
1095 Address
= HTONL (IpSb
->DefaultInterface
->SubnetMask
);
1096 CopyMem (&IfInfo
->SubnetMask
, &Address
, sizeof (EFI_IPv4_ADDRESS
));
1099 if (IpSb
->DefaultRouteTable
!= NULL
) {
1100 IfInfo
->RouteTableSize
= IpSb
->DefaultRouteTable
->TotalNum
;
1101 IfInfo
->RouteTable
= (EFI_IP4_ROUTE_TABLE
*)((UINT8
*)Data
+ sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO
));
1103 Ip4Config2BuildDefaultRouteTable (IpSb
, IfInfo
->RouteTable
);
1110 The work function is to set the general configuration policy for the EFI IPv4 network
1111 stack that is running on the communication device managed by this IP4_CONFIG2_INSTANCE.
1112 The policy will affect other configuration settings.
1114 @param[in] Instance Pointer to the IP4 config2 instance data.
1115 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
1116 @param[in] Data The data buffer to set.
1118 @retval EFI_INVALID_PARAMETER The to be set policy is invalid.
1119 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1120 @retval EFI_ABORTED The new policy equals the current policy.
1121 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1122 network stack was set.
1126 Ip4Config2SetPolicy (
1127 IN IP4_CONFIG2_INSTANCE
*Instance
,
1132 EFI_IP4_CONFIG2_POLICY NewPolicy
;
1133 IP4_CONFIG2_DATA_ITEM
*DataItem
;
1136 if (DataSize
!= sizeof (EFI_IP4_CONFIG2_POLICY
)) {
1137 return EFI_BAD_BUFFER_SIZE
;
1140 NewPolicy
= *((EFI_IP4_CONFIG2_POLICY
*)Data
);
1142 if (NewPolicy
>= Ip4Config2PolicyMax
) {
1143 return EFI_INVALID_PARAMETER
;
1146 if (NewPolicy
== Instance
->Policy
) {
1147 if ((NewPolicy
!= Ip4Config2PolicyDhcp
) || Instance
->DhcpSuccess
) {
1152 // The policy is changed. Clean the ManualAddress, Gateway and DnsServers,
1153 // shrink the variable data size, and fire up all the related events.
1155 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeManualAddress
];
1156 if (DataItem
->Data
.Ptr
!= NULL
) {
1157 FreePool (DataItem
->Data
.Ptr
);
1160 DataItem
->Data
.Ptr
= NULL
;
1161 DataItem
->DataSize
= 0;
1162 DataItem
->Status
= EFI_NOT_FOUND
;
1163 NetMapIterate (&DataItem
->EventMap
, Ip4Config2SignalEvent
, NULL
);
1165 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeGateway
];
1166 if (DataItem
->Data
.Ptr
!= NULL
) {
1167 FreePool (DataItem
->Data
.Ptr
);
1170 DataItem
->Data
.Ptr
= NULL
;
1171 DataItem
->DataSize
= 0;
1172 DataItem
->Status
= EFI_NOT_FOUND
;
1173 NetMapIterate (&DataItem
->EventMap
, Ip4Config2SignalEvent
, NULL
);
1175 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeDnsServer
];
1176 if (DataItem
->Data
.Ptr
!= NULL
) {
1177 FreePool (DataItem
->Data
.Ptr
);
1180 DataItem
->Data
.Ptr
= NULL
;
1181 DataItem
->DataSize
= 0;
1182 DataItem
->Status
= EFI_NOT_FOUND
;
1183 NetMapIterate (&DataItem
->EventMap
, Ip4Config2SignalEvent
, NULL
);
1185 if (NewPolicy
== Ip4Config2PolicyDhcp
) {
1186 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_VOLATILE
);
1189 // The policy is changed from dhcp to static. Stop the DHCPv4 process
1190 // and destroy the DHCPv4 child.
1192 if (Instance
->Dhcp4Handle
!= NULL
) {
1193 Ip4Config2DestroyDhcp4 (Instance
);
1199 if (Instance
->Dhcp4Event
!= NULL
) {
1200 gBS
->CloseEvent (Instance
->Dhcp4Event
);
1201 Instance
->Dhcp4Event
= NULL
;
1206 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
1207 Ip4Config2OnPolicyChanged (IpSb
, NewPolicy
);
1209 Instance
->Policy
= NewPolicy
;
1215 The work function is to set the station addresses manually for the EFI IPv4
1216 network stack. It is only configurable when the policy is Ip4Config2PolicyStatic.
1218 @param[in] Instance Pointer to the IP4 config2 instance data.
1219 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
1220 @param[in] Data The data buffer to set.
1222 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1223 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
1224 under the current policy.
1225 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
1226 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
1227 @retval EFI_NOT_READY An asynchronous process is invoked to set the specified
1228 configuration data, and the process is not finished.
1229 @retval EFI_ABORTED The manual addresses to be set equal current
1231 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1232 network stack was set.
1236 Ip4Config2SetManualAddress (
1237 IN IP4_CONFIG2_INSTANCE
*Instance
,
1242 EFI_IP4_CONFIG2_MANUAL_ADDRESS NewAddress
;
1243 IP4_CONFIG2_DATA_ITEM
*DataItem
;
1245 IP4_ADDR StationAddress
;
1246 IP4_ADDR SubnetMask
;
1249 IP4_INTERFACE
*IpIf
;
1250 IP4_ROUTE_TABLE
*RouteTable
;
1253 Status
= EFI_SUCCESS
;
1258 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
1260 ASSERT (Instance
->DataItem
[Ip4Config2DataTypeManualAddress
].Status
!= EFI_NOT_READY
);
1262 if ((DataSize
!= 0) && ((DataSize
% sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS
)) != 0)) {
1263 return EFI_BAD_BUFFER_SIZE
;
1266 if (Instance
->Policy
!= Ip4Config2PolicyStatic
) {
1267 return EFI_WRITE_PROTECTED
;
1270 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeManualAddress
];
1272 if ((Data
!= NULL
) && (DataSize
!= 0)) {
1273 NewAddress
= *((EFI_IP4_CONFIG2_MANUAL_ADDRESS
*)Data
);
1275 StationAddress
= EFI_NTOHL (NewAddress
.Address
);
1276 SubnetMask
= EFI_NTOHL (NewAddress
.SubnetMask
);
1279 // Check whether the StationAddress/SubnetMask pair is valid.
1281 if (!Ip4StationAddressValid (StationAddress
, SubnetMask
)) {
1282 return EFI_INVALID_PARAMETER
;
1286 // Store the new data, and init the DataItem status to EFI_NOT_READY because
1287 // we may have an asynchronous configuration process.
1289 Ptr
= AllocateCopyPool (DataSize
, Data
);
1291 return EFI_OUT_OF_RESOURCES
;
1294 if (DataItem
->Data
.Ptr
!= NULL
) {
1295 FreePool (DataItem
->Data
.Ptr
);
1298 DataItem
->Data
.Ptr
= Ptr
;
1299 DataItem
->DataSize
= DataSize
;
1300 DataItem
->Status
= EFI_NOT_READY
;
1302 IpSb
->Reconfig
= TRUE
;
1303 Status
= Ip4Config2SetDefaultAddr (IpSb
, StationAddress
, SubnetMask
);
1305 DataItem
->Status
= Status
;
1307 if (EFI_ERROR (DataItem
->Status
) && (DataItem
->Status
!= EFI_NOT_READY
)) {
1312 DataItem
->Data
.Ptr
= NULL
;
1316 // DataSize is 0 and Data is NULL, clean up the manual address.
1318 if (DataItem
->Data
.Ptr
!= NULL
) {
1319 FreePool (DataItem
->Data
.Ptr
);
1322 DataItem
->Data
.Ptr
= NULL
;
1323 DataItem
->DataSize
= 0;
1324 DataItem
->Status
= EFI_NOT_FOUND
;
1327 // Free the default router table and Interface, clean up the assemble table.
1329 if (IpSb
->DefaultInterface
!= NULL
) {
1330 if (IpSb
->DefaultRouteTable
!= NULL
) {
1331 Ip4FreeRouteTable (IpSb
->DefaultRouteTable
);
1332 IpSb
->DefaultRouteTable
= NULL
;
1335 Ip4CancelReceive (IpSb
->DefaultInterface
);
1337 Ip4FreeInterface (IpSb
->DefaultInterface
, NULL
);
1338 IpSb
->DefaultInterface
= NULL
;
1341 Ip4CleanAssembleTable (&IpSb
->Assemble
);
1344 // Create new default interface and route table.
1346 IpIf
= Ip4CreateInterface (IpSb
->Mnp
, IpSb
->Controller
, IpSb
->Image
);
1348 return EFI_OUT_OF_RESOURCES
;
1351 RouteTable
= Ip4CreateRouteTable ();
1352 if (RouteTable
== NULL
) {
1353 Ip4FreeInterface (IpIf
, NULL
);
1354 return EFI_OUT_OF_RESOURCES
;
1357 IpSb
->DefaultInterface
= IpIf
;
1358 InsertHeadList (&IpSb
->Interfaces
, &IpIf
->Link
);
1359 IpSb
->DefaultRouteTable
= RouteTable
;
1360 Ip4ReceiveFrame (IpIf
, NULL
, Ip4AccpetFrame
, IpSb
);
1363 // Reset the State to unstarted.
1365 if ((IpSb
->State
== IP4_SERVICE_CONFIGED
) || (IpSb
->State
== IP4_SERVICE_STARTED
)) {
1366 IpSb
->State
= IP4_SERVICE_UNSTARTED
;
1374 The work function is to set the gateway addresses manually for the EFI IPv4
1375 network stack that is running on the communication device that this EFI IPv4
1376 Configuration Protocol manages. It is not configurable when the policy is
1377 Ip4Config2PolicyDhcp. The gateway addresses must be unicast IPv4 addresses.
1379 @param[in] Instance The pointer to the IP4 config2 instance data.
1380 @param[in] DataSize The size of the buffer pointed to by Data in bytes.
1381 @param[in] Data The data buffer to set. This points to an array of
1382 EFI_IPv6_ADDRESS instances.
1384 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1385 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
1386 under the current policy.
1387 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
1388 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to complete the operation.
1389 @retval EFI_ABORTED The manual gateway addresses to be set equal the
1390 current configuration.
1391 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1392 network stack was set.
1396 Ip4Config2SetGateway (
1397 IN IP4_CONFIG2_INSTANCE
*Instance
,
1403 IP4_CONFIG2_DATA_ITEM
*DataItem
;
1408 EFI_IPv4_ADDRESS
*OldGateway
;
1409 EFI_IPv4_ADDRESS
*NewGateway
;
1410 UINTN OldGatewayCount
;
1411 UINTN NewGatewayCount
;
1422 if ((DataSize
!= 0) && (DataSize
% sizeof (EFI_IPv4_ADDRESS
) != 0)) {
1423 return EFI_BAD_BUFFER_SIZE
;
1426 if (Instance
->Policy
!= Ip4Config2PolicyStatic
) {
1427 return EFI_WRITE_PROTECTED
;
1430 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
1432 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeGateway
];
1433 OldGateway
= DataItem
->Data
.Gateway
;
1434 OldGatewayCount
= DataItem
->DataSize
/ sizeof (EFI_IPv4_ADDRESS
);
1436 for (Index1
= 0; Index1
< OldGatewayCount
; Index1
++) {
1438 // Remove the old route entry.
1440 CopyMem (&Gateway
, OldGateway
+ Index1
, sizeof (IP4_ADDR
));
1442 IpSb
->DefaultRouteTable
,
1443 IP4_ALLZERO_ADDRESS
,
1444 IP4_ALLZERO_ADDRESS
,
1450 if ((Data
!= NULL
) && (DataSize
!= 0)) {
1451 NewGateway
= (EFI_IPv4_ADDRESS
*)Data
;
1452 NewGatewayCount
= DataSize
/ sizeof (EFI_IPv4_ADDRESS
);
1453 for (Index1
= 0; Index1
< NewGatewayCount
; Index1
++) {
1454 CopyMem (&Gateway
, NewGateway
+ Index1
, sizeof (IP4_ADDR
));
1456 if ((IpSb
->DefaultInterface
->SubnetMask
!= 0) &&
1457 !NetIp4IsUnicast (NTOHL (Gateway
), IpSb
->DefaultInterface
->SubnetMask
))
1459 return EFI_INVALID_PARAMETER
;
1462 for (Index2
= Index1
+ 1; Index2
< NewGatewayCount
; Index2
++) {
1463 if (EFI_IP4_EQUAL (NewGateway
+ Index1
, NewGateway
+ Index2
)) {
1464 return EFI_INVALID_PARAMETER
;
1469 if (NewGatewayCount
!= OldGatewayCount
) {
1470 Tmp
= AllocatePool (DataSize
);
1472 return EFI_OUT_OF_RESOURCES
;
1478 for (Index1
= 0; Index1
< NewGatewayCount
; Index1
++) {
1480 // Add the new route entry.
1482 CopyMem (&Gateway
, NewGateway
+ Index1
, sizeof (IP4_ADDR
));
1484 IpSb
->DefaultRouteTable
,
1485 IP4_ALLZERO_ADDRESS
,
1486 IP4_ALLZERO_ADDRESS
,
1493 if (!OneRemoved
&& !OneAdded
) {
1494 DataItem
->Status
= EFI_SUCCESS
;
1498 if (DataItem
->Data
.Ptr
!= NULL
) {
1499 FreePool (DataItem
->Data
.Ptr
);
1502 DataItem
->Data
.Ptr
= Tmp
;
1505 CopyMem (DataItem
->Data
.Ptr
, Data
, DataSize
);
1506 DataItem
->DataSize
= DataSize
;
1507 DataItem
->Status
= EFI_SUCCESS
;
1511 // DataSize is 0 and Data is NULL, clean up the Gateway address.
1513 if (DataItem
->Data
.Ptr
!= NULL
) {
1514 FreePool (DataItem
->Data
.Ptr
);
1517 DataItem
->Data
.Ptr
= NULL
;
1518 DataItem
->DataSize
= 0;
1519 DataItem
->Status
= EFI_NOT_FOUND
;
1526 The work function is to set the DNS server list for the EFI IPv4 network
1527 stack running on the communication device that this EFI_IP4_CONFIG2_PROTOCOL
1528 manages. It is not configurable when the policy is Ip4Config2PolicyDhcp.
1529 The DNS server addresses must be unicast IPv4 addresses.
1531 @param[in] Instance The pointer to the IP4 config2 instance data.
1532 @param[in] DataSize The size of the buffer pointed to by Data in bytes.
1533 @param[in] Data The data buffer to set, points to an array of
1534 EFI_IPv4_ADDRESS instances.
1536 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1537 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
1538 under the current policy.
1539 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
1540 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
1541 @retval EFI_ABORTED The DNS server addresses to be set equal the current
1543 @retval EFI_SUCCESS The specified configuration data for the EFI IPv4
1544 network stack was set.
1548 Ip4Config2SetDnsServer (
1549 IN IP4_CONFIG2_INSTANCE
*Instance
,
1555 IP4_CONFIG2_DATA_ITEM
*Item
;
1557 Status
= EFI_SUCCESS
;
1560 if (Instance
->Policy
!= Ip4Config2PolicyStatic
) {
1561 return EFI_WRITE_PROTECTED
;
1564 Item
= &Instance
->DataItem
[Ip4Config2DataTypeDnsServer
];
1566 if (DATA_ATTRIB_SET (Item
->Attribute
, DATA_ATTRIB_VOLATILE
)) {
1567 REMOVE_DATA_ATTRIB (Item
->Attribute
, DATA_ATTRIB_VOLATILE
);
1570 if ((Data
!= NULL
) && (DataSize
!= 0)) {
1571 Status
= Ip4Config2SetDnsServerWorker (Instance
, DataSize
, Data
);
1574 // DataSize is 0 and Data is NULL, clean up the DnsServer address.
1576 if (Item
->Data
.Ptr
!= NULL
) {
1577 FreePool (Item
->Data
.Ptr
);
1580 Item
->Data
.Ptr
= NULL
;
1582 Item
->Status
= EFI_NOT_FOUND
;
1589 Generate the operational state of the interface this IP4 config2 instance manages
1590 and output in EFI_IP4_CONFIG2_INTERFACE_INFO.
1592 @param[in] IpSb The pointer to the IP4 service binding instance.
1593 @param[out] IfInfo The pointer to the IP4 config2 interface information structure.
1597 Ip4Config2InitIfInfo (
1598 IN IP4_SERVICE
*IpSb
,
1599 OUT EFI_IP4_CONFIG2_INTERFACE_INFO
*IfInfo
1604 EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE
,
1606 IpSb
->Ip4Config2Instance
.IfIndex
1609 IfInfo
->IfType
= IpSb
->SnpMode
.IfType
;
1610 IfInfo
->HwAddressSize
= IpSb
->SnpMode
.HwAddressSize
;
1611 CopyMem (&IfInfo
->HwAddress
, &IpSb
->SnpMode
.CurrentAddress
, IfInfo
->HwAddressSize
);
1615 Set the configuration for the EFI IPv4 network stack running on the communication
1616 device this EFI_IP4_CONFIG2_PROTOCOL instance manages.
1618 This function is used to set the configuration data of type DataType for the EFI
1619 IPv4 network stack that is running on the communication device that this EFI IPv4
1620 Configuration Protocol instance manages.
1622 DataSize is used to calculate the count of structure instances in the Data for
1623 a DataType in which multiple structure instances are allowed.
1625 This function is always non-blocking. When setting some type of configuration data,
1626 an asynchronous process is invoked to check the correctness of the data, such as
1627 performing Duplicate Address Detection on the manually set local IPv4 addresses.
1628 EFI_NOT_READY is returned immediately to indicate that such an asynchronous process
1629 is invoked, and the process is not finished yet. The caller wanting to get the result
1630 of the asynchronous process is required to call RegisterDataNotify() to register an
1631 event on the specified configuration data. Once the event is signaled, the caller
1632 can call GetData() to obtain the configuration data and know the result.
1633 For other types of configuration data that do not require an asynchronous configuration
1634 process, the result of the operation is immediately returned.
1636 @param[in] This The pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
1637 @param[in] DataType The type of data to set.
1638 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
1639 @param[in] Data The data buffer to set. The type of the data buffer is
1640 associated with the DataType.
1642 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1643 network stack was set successfully.
1644 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
1646 - One or more fields in Data and DataSize do not match the
1647 requirement of the data type indicated by DataType.
1648 @retval EFI_WRITE_PROTECTED The specified configuration data is read-only or the specified
1649 configuration data cannot be set under the current policy.
1650 @retval EFI_ACCESS_DENIED Another set operation on the specified configuration
1651 data is already in process.
1652 @retval EFI_NOT_READY An asynchronous process was invoked to set the specified
1653 configuration data, and the process is not finished yet.
1654 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type
1655 indicated by DataType.
1656 @retval EFI_UNSUPPORTED This DataType is not supported.
1657 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
1658 @retval EFI_DEVICE_ERROR An unexpected system error or network error occurred.
1663 EfiIp4Config2SetData (
1664 IN EFI_IP4_CONFIG2_PROTOCOL
*This
,
1665 IN EFI_IP4_CONFIG2_DATA_TYPE DataType
,
1672 IP4_CONFIG2_INSTANCE
*Instance
;
1675 if ((This
== NULL
) || ((Data
== NULL
) && (DataSize
!= 0)) || ((Data
!= NULL
) && (DataSize
== 0))) {
1676 return EFI_INVALID_PARAMETER
;
1679 if (DataType
>= Ip4Config2DataTypeMaximum
) {
1680 return EFI_UNSUPPORTED
;
1683 Instance
= IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This
);
1684 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
1685 NET_CHECK_SIGNATURE (IpSb
, IP4_SERVICE_SIGNATURE
);
1687 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1689 Status
= Instance
->DataItem
[DataType
].Status
;
1690 if (Status
!= EFI_NOT_READY
) {
1691 if (Instance
->DataItem
[DataType
].SetData
== NULL
) {
1693 // This type of data is readonly.
1695 Status
= EFI_WRITE_PROTECTED
;
1697 Status
= Instance
->DataItem
[DataType
].SetData (Instance
, DataSize
, Data
);
1698 if (!EFI_ERROR (Status
)) {
1700 // Fire up the events registered with this type of data.
1702 NetMapIterate (&Instance
->DataItem
[DataType
].EventMap
, Ip4Config2SignalEvent
, NULL
);
1703 Ip4Config2WriteConfigData (IpSb
->MacString
, Instance
);
1704 } else if (Status
== EFI_ABORTED
) {
1706 // The SetData is aborted because the data to set is the same with
1707 // the one maintained.
1709 Status
= EFI_SUCCESS
;
1710 NetMapIterate (&Instance
->DataItem
[DataType
].EventMap
, Ip4Config2SignalEvent
, NULL
);
1715 // Another asynchronous process is on the way.
1717 Status
= EFI_ACCESS_DENIED
;
1720 gBS
->RestoreTPL (OldTpl
);
1726 Get the configuration data for the EFI IPv4 network stack running on the communication
1727 device that this EFI_IP4_CONFIG2_PROTOCOL instance manages.
1729 This function returns the configuration data of type DataType for the EFI IPv4 network
1730 stack running on the communication device that this EFI IPv4 Configuration Protocol instance
1733 The caller is responsible for allocating the buffer used to return the specified
1734 configuration data. The required size will be returned to the caller if the size of
1735 the buffer is too small.
1737 EFI_NOT_READY is returned if the specified configuration data is not ready due to an
1738 asynchronous configuration process already in progress. The caller can call RegisterDataNotify()
1739 to register an event on the specified configuration data. Once the asynchronous configuration
1740 process is finished, the event will be signaled, and a subsequent GetData() call will return
1741 the specified configuration data.
1743 @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
1744 @param[in] DataType The type of data to get.
1745 @param[in, out] DataSize On input, in bytes, the size of Data. On output, in bytes, the
1746 size of buffer required to store the specified configuration data.
1747 @param[in] Data The data buffer in which the configuration data is returned. The
1748 type of the data buffer is associated with the DataType.
1749 This is an optional parameter that may be NULL.
1751 @retval EFI_SUCCESS The specified configuration data was obtained successfully.
1752 @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
1755 - Data is NULL if *DataSize is not zero.
1756 @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified configuration data,
1757 and the required size is returned in DataSize.
1758 @retval EFI_NOT_READY The specified configuration data is not ready due to an
1759 asynchronous configuration process already in progress.
1760 @retval EFI_NOT_FOUND The specified configuration data is not found.
1765 EfiIp4Config2GetData (
1766 IN EFI_IP4_CONFIG2_PROTOCOL
*This
,
1767 IN EFI_IP4_CONFIG2_DATA_TYPE DataType
,
1768 IN OUT UINTN
*DataSize
,
1769 IN VOID
*Data OPTIONAL
1774 IP4_CONFIG2_INSTANCE
*Instance
;
1775 IP4_CONFIG2_DATA_ITEM
*DataItem
;
1777 if ((This
== NULL
) || (DataSize
== NULL
) || ((*DataSize
!= 0) && (Data
== NULL
))) {
1778 return EFI_INVALID_PARAMETER
;
1781 if (DataType
>= Ip4Config2DataTypeMaximum
) {
1782 return EFI_NOT_FOUND
;
1785 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1787 Instance
= IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This
);
1788 DataItem
= &Instance
->DataItem
[DataType
];
1790 Status
= Instance
->DataItem
[DataType
].Status
;
1791 if (!EFI_ERROR (Status
)) {
1792 if (DataItem
->GetData
!= NULL
) {
1793 Status
= DataItem
->GetData (Instance
, DataSize
, Data
);
1794 } else if (*DataSize
< Instance
->DataItem
[DataType
].DataSize
) {
1796 // Update the buffer length.
1798 *DataSize
= Instance
->DataItem
[DataType
].DataSize
;
1799 Status
= EFI_BUFFER_TOO_SMALL
;
1801 *DataSize
= Instance
->DataItem
[DataType
].DataSize
;
1802 CopyMem (Data
, Instance
->DataItem
[DataType
].Data
.Ptr
, *DataSize
);
1806 gBS
->RestoreTPL (OldTpl
);
1812 Register an event that is signaled whenever a configuration process on the specified
1813 configuration data is done.
1815 This function registers an event that is to be signaled whenever a configuration
1816 process on the specified configuration data is performed. An event can be registered
1817 for a different DataType simultaneously. The caller is responsible for determining
1818 which type of configuration data causes the signaling of the event in such an event.
1820 @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
1821 @param[in] DataType The type of data to unregister the event for.
1822 @param[in] Event The event to register.
1824 @retval EFI_SUCCESS The notification event for the specified configuration data is
1826 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
1827 @retval EFI_UNSUPPORTED The configuration data type specified by DataType is not
1829 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
1830 @retval EFI_ACCESS_DENIED The Event is already registered for the DataType.
1835 EfiIp4Config2RegisterDataNotify (
1836 IN EFI_IP4_CONFIG2_PROTOCOL
*This
,
1837 IN EFI_IP4_CONFIG2_DATA_TYPE DataType
,
1843 IP4_CONFIG2_INSTANCE
*Instance
;
1847 if ((This
== NULL
) || (Event
== NULL
)) {
1848 return EFI_INVALID_PARAMETER
;
1851 if (DataType
>= Ip4Config2DataTypeMaximum
) {
1852 return EFI_UNSUPPORTED
;
1855 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1857 Instance
= IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This
);
1858 EventMap
= &Instance
->DataItem
[DataType
].EventMap
;
1861 // Check whether this event is already registered for this DataType.
1863 Item
= NetMapFindKey (EventMap
, Event
);
1865 Status
= NetMapInsertTail (EventMap
, Event
, NULL
);
1867 if (EFI_ERROR (Status
)) {
1868 Status
= EFI_OUT_OF_RESOURCES
;
1871 Status
= EFI_ACCESS_DENIED
;
1874 gBS
->RestoreTPL (OldTpl
);
1880 Remove a previously registered event for the specified configuration data.
1882 @param This The pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
1883 @param DataType The type of data to remove from the previously
1885 @param Event The event to be unregistered.
1887 @retval EFI_SUCCESS The event registered for the specified
1888 configuration data was removed.
1889 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
1890 @retval EFI_NOT_FOUND The Event has not been registered for the
1896 EfiIp4Config2UnregisterDataNotify (
1897 IN EFI_IP4_CONFIG2_PROTOCOL
*This
,
1898 IN EFI_IP4_CONFIG2_DATA_TYPE DataType
,
1904 IP4_CONFIG2_INSTANCE
*Instance
;
1907 if ((This
== NULL
) || (Event
== NULL
)) {
1908 return EFI_INVALID_PARAMETER
;
1911 if (DataType
>= Ip4Config2DataTypeMaximum
) {
1912 return EFI_NOT_FOUND
;
1915 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1917 Instance
= IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This
);
1919 Item
= NetMapFindKey (&Instance
->DataItem
[DataType
].EventMap
, Event
);
1921 NetMapRemoveItem (&Instance
->DataItem
[DataType
].EventMap
, Item
, NULL
);
1922 Status
= EFI_SUCCESS
;
1924 Status
= EFI_NOT_FOUND
;
1927 gBS
->RestoreTPL (OldTpl
);
1933 Initialize an IP4_CONFIG2_INSTANCE.
1935 @param[out] Instance The buffer of IP4_CONFIG2_INSTANCE to be initialized.
1937 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
1938 @retval EFI_SUCCESS The IP4_CONFIG2_INSTANCE initialized successfully.
1942 Ip4Config2InitInstance (
1943 OUT IP4_CONFIG2_INSTANCE
*Instance
1947 IP4_CONFIG2_INSTANCE
*TmpInstance
;
1952 IP4_CONFIG2_DATA_ITEM
*DataItem
;
1954 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
1956 Instance
->Signature
= IP4_CONFIG2_INSTANCE_SIGNATURE
;
1959 // Determine the index of this interface.
1962 NET_LIST_FOR_EACH (Entry
, &mIp4Config2InstanceList
) {
1963 TmpInstance
= NET_LIST_USER_STRUCT_S (Entry
, IP4_CONFIG2_INSTANCE
, Link
, IP4_CONFIG2_INSTANCE_SIGNATURE
);
1965 if (TmpInstance
->IfIndex
> IfIndex
) {
1967 // There is a sequence hole because some interface is down.
1975 Instance
->IfIndex
= IfIndex
;
1976 NetListInsertBefore (Entry
, &Instance
->Link
);
1978 for (Index
= 0; Index
< Ip4Config2DataTypeMaximum
; Index
++) {
1980 // Initialize the event map for each data item.
1982 NetMapInit (&Instance
->DataItem
[Index
].EventMap
);
1986 // Initialize each data type: associate storage and set data size for the
1987 // fixed size data types, hook the SetData function, set the data attribute.
1989 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeInterfaceInfo
];
1990 DataItem
->GetData
= Ip4Config2GetIfInfo
;
1991 DataItem
->Data
.Ptr
= &Instance
->InterfaceInfo
;
1992 DataItem
->DataSize
= sizeof (Instance
->InterfaceInfo
);
1993 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
| DATA_ATTRIB_VOLATILE
);
1994 Ip4Config2InitIfInfo (IpSb
, &Instance
->InterfaceInfo
);
1996 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypePolicy
];
1997 DataItem
->SetData
= Ip4Config2SetPolicy
;
1998 DataItem
->Data
.Ptr
= &Instance
->Policy
;
1999 DataItem
->DataSize
= sizeof (Instance
->Policy
);
2000 Instance
->Policy
= Ip4Config2PolicyStatic
;
2001 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
);
2003 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeManualAddress
];
2004 DataItem
->SetData
= Ip4Config2SetManualAddress
;
2005 DataItem
->Status
= EFI_NOT_FOUND
;
2007 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeGateway
];
2008 DataItem
->SetData
= Ip4Config2SetGateway
;
2009 DataItem
->Status
= EFI_NOT_FOUND
;
2011 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeDnsServer
];
2012 DataItem
->SetData
= Ip4Config2SetDnsServer
;
2013 DataItem
->Status
= EFI_NOT_FOUND
;
2015 Instance
->Configured
= TRUE
;
2018 // Try to read the config data from NV variable.
2019 // If not found, write initialized config data into NV variable
2020 // as a default config data.
2022 Status
= Ip4Config2ReadConfigData (IpSb
->MacString
, Instance
);
2023 if (Status
== EFI_NOT_FOUND
) {
2024 Status
= Ip4Config2WriteConfigData (IpSb
->MacString
, Instance
);
2027 if (EFI_ERROR (Status
)) {
2031 Instance
->Ip4Config2
.SetData
= EfiIp4Config2SetData
;
2032 Instance
->Ip4Config2
.GetData
= EfiIp4Config2GetData
;
2033 Instance
->Ip4Config2
.RegisterDataNotify
= EfiIp4Config2RegisterDataNotify
;
2034 Instance
->Ip4Config2
.UnregisterDataNotify
= EfiIp4Config2UnregisterDataNotify
;
2037 // Publish the IP4 configuration form
2039 return Ip4Config2FormInit (Instance
);
2043 Release an IP4_CONFIG2_INSTANCE.
2045 @param[in, out] Instance The buffer of IP4_CONFIG2_INSTANCE to be freed.
2049 Ip4Config2CleanInstance (
2050 IN OUT IP4_CONFIG2_INSTANCE
*Instance
2054 IP4_CONFIG2_DATA_ITEM
*DataItem
;
2056 if (Instance
->DeclineAddress
!= NULL
) {
2057 FreePool (Instance
->DeclineAddress
);
2060 if (!Instance
->Configured
) {
2064 if (Instance
->Dhcp4Handle
!= NULL
) {
2065 Ip4Config2DestroyDhcp4 (Instance
);
2071 if (Instance
->Dhcp4Event
!= NULL
) {
2072 gBS
->CloseEvent (Instance
->Dhcp4Event
);
2073 Instance
->Dhcp4Event
= NULL
;
2076 for (Index
= 0; Index
< Ip4Config2DataTypeMaximum
; Index
++) {
2077 DataItem
= &Instance
->DataItem
[Index
];
2079 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
)) {
2080 if (DataItem
->Data
.Ptr
!= NULL
) {
2081 FreePool (DataItem
->Data
.Ptr
);
2084 DataItem
->Data
.Ptr
= NULL
;
2085 DataItem
->DataSize
= 0;
2088 NetMapClean (&Instance
->DataItem
[Index
].EventMap
);
2091 Ip4Config2FormUnload (Instance
);
2093 RemoveEntryList (&Instance
->Link
);
2097 The event handle for IP4 auto reconfiguration. The original default
2098 interface and route table will be removed as the default.
2100 @param[in] Context The IP4 service binding instance.
2105 Ip4AutoReconfigCallBackDpc (
2111 IpSb
= (IP4_SERVICE
*)Context
;
2112 NET_CHECK_SIGNATURE (IpSb
, IP4_SERVICE_SIGNATURE
);
2114 if (IpSb
->State
> IP4_SERVICE_UNSTARTED
) {
2115 IpSb
->State
= IP4_SERVICE_UNSTARTED
;
2118 IpSb
->Reconfig
= TRUE
;
2120 Ip4StartAutoConfig (&IpSb
->Ip4Config2Instance
);
2126 Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK.
2128 @param Event The event that is signalled.
2129 @param Context The IP4 service binding instance.
2134 Ip4AutoReconfigCallBack (
2140 // Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK
2142 QueueDpc (TPL_CALLBACK
, Ip4AutoReconfigCallBackDpc
, Context
);