2 The implementation of EFI IPv4 Configuration II Protocol.
4 Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php.
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 LIST_ENTRY mIp4Config2InstanceList
= {&mIp4Config2InstanceList
, &mIp4Config2InstanceList
};
22 The event process routine when the DHCPv4 service binding protocol is installed
25 @param[in] Event Not used.
26 @param[in] Context Pointer to the IP4 config2 instance data.
31 Ip4Config2OnDhcp4SbInstalled (
37 Destroy the Dhcp4 child in IP4_CONFIG2_INSTANCE and release the resources.
39 @param[in, out] Instance The buffer of IP4 config2 instance to be freed.
41 @retval EFI_SUCCESS The child was successfully destroyed.
42 @retval Others Failed to destroy the child.
46 Ip4Config2DestroyDhcp4 (
47 IN OUT IP4_CONFIG2_INSTANCE
*Instance
52 EFI_DHCP4_PROTOCOL
*Dhcp4
;
54 Dhcp4
= Instance
->Dhcp4
;
55 ASSERT (Dhcp4
!= NULL
);
58 Dhcp4
->Configure (Dhcp4
, NULL
);
59 Instance
->Dhcp4
= NULL
;
61 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
64 // Close DHCPv4 protocol and destroy the child.
66 Status
= gBS
->CloseProtocol (
67 Instance
->Dhcp4Handle
,
68 &gEfiDhcp4ProtocolGuid
,
72 if (EFI_ERROR (Status
)) {
76 Status
= NetLibDestroyServiceChild (
79 &gEfiDhcp4ServiceBindingProtocolGuid
,
83 Instance
->Dhcp4Handle
= NULL
;
89 Update the current policy to NewPolicy. During the transition
90 period, the default router list
91 and address list in all interfaces will be released.
93 @param[in] IpSb The IP4 service binding instance.
94 @param[in] NewPolicy The new policy to be updated to.
98 Ip4Config2OnPolicyChanged (
100 IN EFI_IP4_CONFIG2_POLICY NewPolicy
104 IP4_ROUTE_TABLE
*RouteTable
;
107 // Currently there are only two policies: static and dhcp. Regardless of
108 // what transition is going on, i.e., static -> dhcp and dhcp ->
109 // static, we have to free default router table and all addresses.
112 if (IpSb
->DefaultInterface
!= NULL
) {
113 if (IpSb
->DefaultRouteTable
!= NULL
) {
114 Ip4FreeRouteTable (IpSb
->DefaultRouteTable
);
115 IpSb
->DefaultRouteTable
= NULL
;
118 Ip4CancelReceive (IpSb
->DefaultInterface
);
120 Ip4FreeInterface (IpSb
->DefaultInterface
, NULL
);
121 IpSb
->DefaultInterface
= NULL
;
124 Ip4CleanAssembleTable (&IpSb
->Assemble
);
127 // Create new default interface and route table.
129 IpIf
= Ip4CreateInterface (IpSb
->Mnp
, IpSb
->Controller
, IpSb
->Image
);
134 RouteTable
= Ip4CreateRouteTable ();
135 if (RouteTable
== NULL
) {
136 Ip4FreeInterface (IpIf
, NULL
);
140 IpSb
->DefaultInterface
= IpIf
;
141 InsertHeadList (&IpSb
->Interfaces
, &IpIf
->Link
);
142 IpSb
->DefaultRouteTable
= RouteTable
;
143 Ip4ReceiveFrame (IpIf
, NULL
, Ip4AccpetFrame
, IpSb
);
145 if (IpSb
->State
== IP4_SERVICE_CONFIGED
|| IpSb
->State
== IP4_SERVICE_STARTED
) {
146 IpSb
->State
= IP4_SERVICE_UNSTARTED
;
150 // Start the dhcp configuration.
152 if (NewPolicy
== Ip4Config2PolicyDhcp
) {
153 IpSb
->Reconfig
= TRUE
;
154 Ip4StartAutoConfig (&IpSb
->Ip4Config2Instance
);
160 Signal the registered event. It is the callback routine for NetMapIterate.
162 @param[in] Map Points to the list of registered event.
163 @param[in] Item The registered event.
164 @param[in] Arg Not used.
166 @retval EFI_SUCCESS The event was signaled successfully.
170 Ip4Config2SignalEvent (
172 IN NET_MAP_ITEM
*Item
,
176 gBS
->SignalEvent ((EFI_EVENT
) Item
->Key
);
182 Read the configuration data from variable storage according to the VarName and
183 gEfiIp4Config2ProtocolGuid. It checks the integrity of variable data. If the
184 data is corrupted, it clears the variable data to ZERO. Othewise, it outputs the
185 configuration data to IP4_CONFIG2_INSTANCE.
187 @param[in] VarName The pointer to the variable name
188 @param[in, out] Instance The pointer to the IP4 config2 instance data.
190 @retval EFI_NOT_FOUND The variable can not be found or already corrupted.
191 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
192 @retval EFI_SUCCESS The configuration data was retrieved successfully.
196 Ip4Config2ReadConfigData (
198 IN OUT IP4_CONFIG2_INSTANCE
*Instance
203 IP4_CONFIG2_VARIABLE
*Variable
;
204 IP4_CONFIG2_DATA_ITEM
*DataItem
;
206 IP4_CONFIG2_DATA_RECORD DataRecord
;
210 // Try to read the configuration variable.
213 Status
= gRT
->GetVariable (
215 &gEfiIp4Config2ProtocolGuid
,
221 if (Status
== EFI_BUFFER_TOO_SMALL
) {
223 // Allocate buffer and read the config variable.
225 Variable
= AllocatePool (VarSize
);
226 if (Variable
== NULL
) {
227 return EFI_OUT_OF_RESOURCES
;
230 Status
= gRT
->GetVariable (
232 &gEfiIp4Config2ProtocolGuid
,
237 if (EFI_ERROR (Status
) || (UINT16
) (~NetblockChecksum ((UINT8
*) Variable
, (UINT32
) VarSize
)) != 0) {
239 // GetVariable still error or the variable is corrupted.
240 // Fall back to the default value.
245 // Remove the problematic variable and return EFI_NOT_FOUND, a new
246 // variable will be set again.
250 &gEfiIp4Config2ProtocolGuid
,
251 IP4_CONFIG2_VARIABLE_ATTRIBUTE
,
256 return EFI_NOT_FOUND
;
260 for (Index
= 0; Index
< Variable
->DataRecordCount
; Index
++) {
262 CopyMem (&DataRecord
, &Variable
->DataRecord
[Index
], sizeof (DataRecord
));
264 DataItem
= &Instance
->DataItem
[DataRecord
.DataType
];
265 if (DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
) &&
266 (DataItem
->DataSize
!= DataRecord
.DataSize
)
269 // Perhaps a corrupted data record...
274 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
)) {
276 // This data item has variable length data.
278 DataItem
->Data
.Ptr
= AllocatePool (DataRecord
.DataSize
);
279 if (DataItem
->Data
.Ptr
== NULL
) {
281 // no memory resource
287 Data
= (CHAR8
*) Variable
+ DataRecord
.Offset
;
288 CopyMem (DataItem
->Data
.Ptr
, Data
, DataRecord
.DataSize
);
290 DataItem
->DataSize
= DataRecord
.DataSize
;
291 DataItem
->Status
= EFI_SUCCESS
;
302 Write the configuration data from IP4_CONFIG2_INSTANCE to variable storage.
304 @param[in] VarName The pointer to the variable name.
305 @param[in] Instance The pointer to the IP4 config2 instance data.
307 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
308 @retval EFI_SUCCESS The configuration data is written successfully.
312 Ip4Config2WriteConfigData (
314 IN IP4_CONFIG2_INSTANCE
*Instance
319 IP4_CONFIG2_DATA_ITEM
*DataItem
;
320 IP4_CONFIG2_VARIABLE
*Variable
;
321 IP4_CONFIG2_DATA_RECORD
*DataRecord
;
325 VarSize
= sizeof (IP4_CONFIG2_VARIABLE
) - sizeof (IP4_CONFIG2_DATA_RECORD
);
327 for (Index
= 0; Index
< Ip4Config2DataTypeMaximum
; Index
++) {
329 DataItem
= &Instance
->DataItem
[Index
];
330 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_VOLATILE
) && !EFI_ERROR (DataItem
->Status
)) {
332 VarSize
+= sizeof (IP4_CONFIG2_DATA_RECORD
) + DataItem
->DataSize
;
336 Variable
= AllocatePool (VarSize
);
337 if (Variable
== NULL
) {
338 return EFI_OUT_OF_RESOURCES
;
341 Heap
= (CHAR8
*) Variable
+ VarSize
;
342 Variable
->DataRecordCount
= 0;
344 for (Index
= 0; Index
< Ip4Config2DataTypeMaximum
; Index
++) {
346 DataItem
= &Instance
->DataItem
[Index
];
347 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_VOLATILE
) && !EFI_ERROR (DataItem
->Status
)) {
349 Heap
-= DataItem
->DataSize
;
350 CopyMem (Heap
, DataItem
->Data
.Ptr
, DataItem
->DataSize
);
352 DataRecord
= &Variable
->DataRecord
[Variable
->DataRecordCount
];
353 DataRecord
->DataType
= (EFI_IP4_CONFIG2_DATA_TYPE
) Index
;
354 DataRecord
->DataSize
= (UINT32
) DataItem
->DataSize
;
355 DataRecord
->Offset
= (UINT16
) (Heap
- (CHAR8
*) Variable
);
357 Variable
->DataRecordCount
++;
361 Variable
->Checksum
= 0;
362 Variable
->Checksum
= (UINT16
) ~NetblockChecksum ((UINT8
*) Variable
, (UINT32
) VarSize
);
364 Status
= gRT
->SetVariable (
366 &gEfiIp4Config2ProtocolGuid
,
367 IP4_CONFIG2_VARIABLE_ATTRIBUTE
,
379 Build a EFI_IP4_ROUTE_TABLE to be returned to the caller of GetModeData.
380 The EFI_IP4_ROUTE_TABLE is clumsy to use in the internal operation of the
383 @param[in] IpSb The IP4 service binding instance.
384 @param[out] Table The built IP4 route table.
386 @retval EFI_SUCCESS The route table is successfully build
387 @retval EFI_NOT_FOUND Failed to allocate the memory for the rotue table.
391 Ip4Config2BuildDefaultRouteTable (
392 IN IP4_SERVICE
*IpSb
,
393 OUT EFI_IP4_ROUTE_TABLE
*Table
397 IP4_ROUTE_ENTRY
*RtEntry
;
401 if (IpSb
->DefaultRouteTable
== NULL
) {
402 return EFI_NOT_FOUND
;
405 Count
= IpSb
->DefaultRouteTable
->TotalNum
;
408 return EFI_NOT_FOUND
;
412 // Copy the route entry to EFI route table. Keep the order of
413 // route entry copied from most specific to default route. That
414 // is, interlevel the route entry from the instance's route area
415 // and those from the default route table's route area.
419 for (Index
= IP4_MASK_MAX
; Index
>= 0; Index
--) {
421 NET_LIST_FOR_EACH (Entry
, &(IpSb
->DefaultRouteTable
->RouteArea
[Index
])) {
422 RtEntry
= NET_LIST_USER_STRUCT (Entry
, IP4_ROUTE_ENTRY
, Link
);
424 EFI_IP4 (Table
[Count
].SubnetAddress
) = HTONL (RtEntry
->Dest
& RtEntry
->Netmask
);
425 EFI_IP4 (Table
[Count
].SubnetMask
) = HTONL (RtEntry
->Netmask
);
426 EFI_IP4 (Table
[Count
].GatewayAddress
) = HTONL (RtEntry
->NextHop
);
437 The event process routine when the DHCPv4 service binding protocol is installed
440 @param[in] Event Not used.
441 @param[in] Context The pointer to the IP4 config2 instance data.
446 Ip4Config2OnDhcp4SbInstalled (
451 IP4_CONFIG2_INSTANCE
*Instance
;
453 Instance
= (IP4_CONFIG2_INSTANCE
*) Context
;
455 if ((Instance
->Dhcp4Handle
!= NULL
) || (Instance
->Policy
!= Ip4Config2PolicyDhcp
)) {
457 // The DHCP4 child is already created or the policy is no longer DHCP.
462 Ip4StartAutoConfig (Instance
);
466 Set the station address and subnetmask for the default interface.
468 @param[in] IpSb The pointer to the IP4 service binding instance.
469 @param[in] StationAddress Ip address to be set.
470 @param[in] SubnetMask Subnet to be set.
472 @retval EFI_SUCCESS Set default address successful.
473 @retval Others Some errors occur in setting.
477 Ip4Config2SetDefaultAddr (
478 IN IP4_SERVICE
*IpSb
,
479 IN IP4_ADDR StationAddress
,
480 IN IP4_ADDR SubnetMask
485 IP4_PROTOCOL
*Ip4Instance
;
486 EFI_ARP_PROTOCOL
*Arp
;
489 IP4_ROUTE_TABLE
*RouteTable
;
491 IpIf
= IpSb
->DefaultInterface
;
492 ASSERT (IpIf
!= NULL
);
494 if ((IpIf
->Ip
== StationAddress
) && (IpIf
->SubnetMask
== SubnetMask
)) {
495 IpSb
->State
= IP4_SERVICE_CONFIGED
;
499 if (IpSb
->Reconfig
) {
501 // The default address is changed, free the previous interface first.
503 if (IpSb
->DefaultRouteTable
!= NULL
) {
504 Ip4FreeRouteTable (IpSb
->DefaultRouteTable
);
505 IpSb
->DefaultRouteTable
= NULL
;
508 Ip4CancelReceive (IpSb
->DefaultInterface
);
509 Ip4FreeInterface (IpSb
->DefaultInterface
, NULL
);
510 IpSb
->DefaultInterface
= NULL
;
512 // Create new default interface and route table.
514 IpIf
= Ip4CreateInterface (IpSb
->Mnp
, IpSb
->Controller
, IpSb
->Image
);
516 return EFI_OUT_OF_RESOURCES
;
519 RouteTable
= Ip4CreateRouteTable ();
520 if (RouteTable
== NULL
) {
521 Ip4FreeInterface (IpIf
, NULL
);
522 return EFI_OUT_OF_RESOURCES
;
525 IpSb
->DefaultInterface
= IpIf
;
526 InsertHeadList (&IpSb
->Interfaces
, &IpIf
->Link
);
527 IpSb
->DefaultRouteTable
= RouteTable
;
528 Ip4ReceiveFrame (IpIf
, NULL
, Ip4AccpetFrame
, IpSb
);
531 if (IpSb
->State
== IP4_SERVICE_CONFIGED
) {
532 IpSb
->State
= IP4_SERVICE_UNSTARTED
;
535 Status
= Ip4SetAddress (IpIf
, StationAddress
, SubnetMask
);
536 if (EFI_ERROR (Status
)) {
540 if (IpIf
->Arp
!= NULL
) {
542 // A non-NULL IpIf->Arp here means a new ARP child is created when setting default address,
543 // but some IP children may have referenced the default interface before it is configured,
544 // these IP instances also consume this ARP protocol so they need to open it BY_CHILD_CONTROLLER.
547 NET_LIST_FOR_EACH (Entry
, &IpIf
->IpInstances
) {
548 Ip4Instance
= NET_LIST_USER_STRUCT_S (Entry
, IP4_PROTOCOL
, AddrLink
, IP4_PROTOCOL_SIGNATURE
);
549 Status
= gBS
->OpenProtocol (
551 &gEfiArpProtocolGuid
,
553 gIp4DriverBinding
.DriverBindingHandle
,
555 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
557 if (EFI_ERROR (Status
)) {
564 IpSb
->DefaultRouteTable
,
571 // Add a route for the connected network.
573 Subnet
= StationAddress
& SubnetMask
;
576 IpSb
->DefaultRouteTable
,
582 IpSb
->State
= IP4_SERVICE_CONFIGED
;
583 IpSb
->Reconfig
= FALSE
;
589 Set the station address, subnetmask and gateway address for the default interface.
591 @param[in] Instance The pointer to the IP4 config2 instance data.
592 @param[in] StationAddress Ip address to be set.
593 @param[in] SubnetMask Subnet to be set.
594 @param[in] GatewayAddress Gateway to be set.
596 @retval EFI_SUCCESS Set default If successful.
597 @retval Others Errors occur as indicated.
601 Ip4Config2SetDefaultIf (
602 IN IP4_CONFIG2_INSTANCE
*Instance
,
603 IN IP4_ADDR StationAddress
,
604 IN IP4_ADDR SubnetMask
,
605 IN IP4_ADDR GatewayAddress
611 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
613 Status
= Ip4Config2SetDefaultAddr (IpSb
, StationAddress
, SubnetMask
);
614 if (EFI_ERROR (Status
)) {
619 // Create a route if there is a default router.
621 if (GatewayAddress
!= IP4_ALLZERO_ADDRESS
) {
623 IpSb
->DefaultRouteTable
,
635 Release all the DHCP related resources.
637 @param Instance The IP4 config2 instance.
643 Ip4Config2CleanDhcp4 (
644 IN IP4_CONFIG2_INSTANCE
*Instance
649 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
651 if (Instance
->Dhcp4
!= NULL
) {
652 Instance
->Dhcp4
->Stop (Instance
->Dhcp4
);
655 Instance
->Dhcp4Handle
,
656 &gEfiDhcp4ProtocolGuid
,
661 Instance
->Dhcp4
= NULL
;
664 if (Instance
->Dhcp4Handle
!= NULL
) {
665 NetLibDestroyServiceChild (
668 &gEfiDhcp4ServiceBindingProtocolGuid
,
669 Instance
->Dhcp4Handle
672 Instance
->Dhcp4Handle
= NULL
;
675 if (Instance
->Dhcp4Event
!= NULL
) {
676 gBS
->CloseEvent (Instance
->Dhcp4Event
);
677 Instance
->Dhcp4Event
= NULL
;
682 This worker function sets the DNS server list for the EFI IPv4 network
683 stack running on the communication device that this EFI_IP4_CONFIG2_PROTOCOL
684 manages. The DNS server addresses must be unicast IPv4 addresses.
686 @param[in] Instance The pointer to the IP4 config2 instance data.
687 @param[in] DataSize The size of the buffer pointed to by Data in bytes.
688 @param[in] Data The data buffer to set, points to an array of
689 EFI_IPv4_ADDRESS instances.
691 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
692 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
693 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
694 @retval EFI_ABORTED The DNS server addresses to be set equal the current
696 @retval EFI_SUCCESS The specified configuration data for the EFI IPv4
697 network stack was set.
701 Ip4Config2SetDnsServerWorker (
702 IN IP4_CONFIG2_INSTANCE
*Instance
,
710 EFI_IPv4_ADDRESS
*OldDns
;
711 EFI_IPv4_ADDRESS
*NewDns
;
714 IP4_CONFIG2_DATA_ITEM
*Item
;
719 if ((DataSize
% sizeof (EFI_IPv4_ADDRESS
) != 0) || (DataSize
== 0)) {
720 return EFI_BAD_BUFFER_SIZE
;
723 Item
= &Instance
->DataItem
[Ip4Config2DataTypeDnsServer
];
724 NewDns
= (EFI_IPv4_ADDRESS
*) Data
;
725 OldDns
= Item
->Data
.DnsServers
;
726 NewDnsCount
= DataSize
/ sizeof (EFI_IPv4_ADDRESS
);
727 OldDnsCount
= Item
->DataSize
/ sizeof (EFI_IPv4_ADDRESS
);
730 if (NewDnsCount
!= OldDnsCount
) {
731 Tmp
= AllocatePool (DataSize
);
733 return EFI_OUT_OF_RESOURCES
;
739 for (NewIndex
= 0; NewIndex
< NewDnsCount
; NewIndex
++) {
740 CopyMem (&DnsAddress
, NewDns
+ NewIndex
, sizeof (IP4_ADDR
));
742 if (!NetIp4IsUnicast (NTOHL (DnsAddress
), 0)) {
744 // The dns server address must be unicast.
747 return EFI_INVALID_PARAMETER
;
750 for (Index1
= NewIndex
+ 1; Index1
< NewDnsCount
; Index1
++) {
751 if (EFI_IP4_EQUAL (NewDns
+ NewIndex
, NewDns
+ Index1
)) {
753 return EFI_INVALID_PARAMETER
;
759 // If any address in the new setting is not in the old settings, skip the
760 // comparision below.
765 for (OldIndex
= 0; OldIndex
< OldDnsCount
; OldIndex
++) {
766 if (EFI_IP4_EQUAL (NewDns
+ NewIndex
, OldDns
+ OldIndex
)) {
768 // If found break out.
774 if (OldIndex
== OldDnsCount
) {
779 if (!OneAdded
&& (DataSize
== Item
->DataSize
)) {
781 // No new item is added and the size is the same.
783 Item
->Status
= EFI_SUCCESS
;
787 if (Item
->Data
.Ptr
!= NULL
) {
788 FreePool (Item
->Data
.Ptr
);
790 Item
->Data
.Ptr
= Tmp
;
793 CopyMem (Item
->Data
.Ptr
, Data
, DataSize
);
794 Item
->DataSize
= DataSize
;
795 Item
->Status
= EFI_SUCCESS
;
803 Callback function when DHCP process finished. It will save the
804 retrieved IP configure parameter from DHCP to the NVRam.
806 @param Event The callback event
807 @param Context Opaque context to the callback
814 Ip4Config2OnDhcp4Complete (
819 IP4_CONFIG2_INSTANCE
*Instance
;
820 EFI_DHCP4_MODE_DATA Dhcp4Mode
;
822 IP4_ADDR StationAddress
;
824 IP4_ADDR GatewayAddress
;
827 EFI_DHCP4_PACKET_OPTION
**OptionList
;
829 Instance
= (IP4_CONFIG2_INSTANCE
*) Context
;
830 ASSERT (Instance
->Dhcp4
!= NULL
);
833 // Get the DHCP retrieved parameters
835 Status
= Instance
->Dhcp4
->GetModeData (Instance
->Dhcp4
, &Dhcp4Mode
);
837 if (EFI_ERROR (Status
)) {
841 if (Dhcp4Mode
.State
== Dhcp4Bound
) {
842 StationAddress
= EFI_NTOHL (Dhcp4Mode
.ClientAddress
);
843 SubnetMask
= EFI_NTOHL (Dhcp4Mode
.SubnetMask
);
844 GatewayAddress
= EFI_NTOHL (Dhcp4Mode
.RouterAddress
);
846 Status
= Ip4Config2SetDefaultIf (Instance
, StationAddress
, SubnetMask
, GatewayAddress
);
847 if (EFI_ERROR (Status
)) {
852 // Parse the ACK to get required DNS server information.
857 Status
= Instance
->Dhcp4
->Parse (Instance
->Dhcp4
, Dhcp4Mode
.ReplyPacket
, &OptionCount
, OptionList
);
858 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
862 OptionList
= AllocateZeroPool (OptionCount
* sizeof (EFI_DHCP4_PACKET_OPTION
*));
863 if (OptionList
== NULL
) {
867 Status
= Instance
->Dhcp4
->Parse (Instance
->Dhcp4
, Dhcp4Mode
.ReplyPacket
, &OptionCount
, OptionList
);
868 if (EFI_ERROR (Status
)) {
869 FreePool (OptionList
);
873 for (Index
= 0; Index
< OptionCount
; Index
++) {
875 // Look for DNS Server opcode (6).
877 if (OptionList
[Index
]->OpCode
== DHCP4_TAG_DNS_SERVER
) {
878 if (((OptionList
[Index
]->Length
& 0x3) != 0) || (OptionList
[Index
]->Length
== 0)) {
882 Ip4Config2SetDnsServerWorker (Instance
, OptionList
[Index
]->Length
, &OptionList
[Index
]->Data
[0]);
887 FreePool (OptionList
);
889 Instance
->DhcpSuccess
= TRUE
;
893 Ip4Config2CleanDhcp4 (Instance
);
899 Start the DHCP configuration for this IP service instance.
900 It will locates the EFI_IP4_CONFIG2_PROTOCOL, then start the
903 @param[in] Instance The IP4 config2 instance to configure
905 @retval EFI_SUCCESS The auto configuration is successfull started
906 @retval Others Failed to start auto configuration.
911 IN IP4_CONFIG2_INSTANCE
*Instance
915 EFI_DHCP4_PROTOCOL
*Dhcp4
;
916 EFI_DHCP4_MODE_DATA Dhcp4Mode
;
917 EFI_DHCP4_PACKET_OPTION
*OptionList
[1];
918 IP4_CONFIG2_DHCP4_OPTION ParaList
;
922 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
924 if (IpSb
->State
> IP4_SERVICE_UNSTARTED
) {
929 // A host must not invoke DHCP configuration if it is already
930 // participating in the DHCP configuraiton process.
932 if (Instance
->Dhcp4Handle
!= NULL
) {
936 Status
= NetLibCreateServiceChild (
939 &gEfiDhcp4ServiceBindingProtocolGuid
,
940 &Instance
->Dhcp4Handle
943 if (Status
== EFI_UNSUPPORTED
) {
945 // No DHCPv4 Service Binding protocol, register a notify.
947 if (Instance
->Dhcp4SbNotifyEvent
== NULL
) {
948 Instance
->Dhcp4SbNotifyEvent
= EfiCreateProtocolNotifyEvent (
949 &gEfiDhcp4ServiceBindingProtocolGuid
,
951 Ip4Config2OnDhcp4SbInstalled
,
953 &Instance
->Registration
958 if (EFI_ERROR (Status
)) {
962 if (Instance
->Dhcp4SbNotifyEvent
!= NULL
) {
963 gBS
->CloseEvent (Instance
->Dhcp4SbNotifyEvent
);
966 Status
= gBS
->OpenProtocol (
967 Instance
->Dhcp4Handle
,
968 &gEfiDhcp4ProtocolGuid
,
969 (VOID
**) &Instance
->Dhcp4
,
972 EFI_OPEN_PROTOCOL_BY_DRIVER
974 ASSERT_EFI_ERROR (Status
);
978 // Check the current DHCP status, if the DHCP process has
979 // already finished, return now.
981 Dhcp4
= Instance
->Dhcp4
;
982 Status
= Dhcp4
->GetModeData (Dhcp4
, &Dhcp4Mode
);
984 if (Dhcp4Mode
.State
== Dhcp4Bound
) {
985 Ip4Config2OnDhcp4Complete (NULL
, Instance
);
991 // Try to start the DHCP process. Use most of the current
992 // DHCP configuration to avoid problems if some DHCP client
993 // yields the control of this DHCP service to us.
995 ParaList
.Head
.OpCode
= DHCP4_TAG_PARA_LIST
;
996 ParaList
.Head
.Length
= 3;
997 ParaList
.Head
.Data
[0] = DHCP4_TAG_NETMASK
;
998 ParaList
.Route
= DHCP4_TAG_ROUTER
;
999 ParaList
.Dns
= DHCP4_TAG_DNS_SERVER
;
1000 OptionList
[0] = &ParaList
.Head
;
1001 Dhcp4Mode
.ConfigData
.OptionCount
= 1;
1002 Dhcp4Mode
.ConfigData
.OptionList
= OptionList
;
1004 Status
= Dhcp4
->Configure (Dhcp4
, &Dhcp4Mode
.ConfigData
);
1006 if (EFI_ERROR (Status
)) {
1011 // Start the DHCP process
1013 Status
= gBS
->CreateEvent (
1016 Ip4Config2OnDhcp4Complete
,
1018 &Instance
->Dhcp4Event
1021 if (EFI_ERROR (Status
)) {
1025 Status
= Dhcp4
->Start (Dhcp4
, Instance
->Dhcp4Event
);
1027 if (EFI_ERROR (Status
)) {
1031 IpSb
->State
= IP4_SERVICE_STARTED
;
1040 The work function is to get the interface information of the communication
1041 device this IP4_CONFIG2_INSTANCE manages.
1043 @param[in] Instance Pointer to the IP4 config2 instance data.
1044 @param[in, out] DataSize On input, in bytes, the size of Data. On output, in
1045 bytes, the size of buffer required to store the specified
1047 @param[in] Data The data buffer in which the configuration data is returned.
1048 Ignored if DataSize is ZERO.
1050 @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified
1051 configuration data, and the required size is
1052 returned in DataSize.
1053 @retval EFI_SUCCESS The specified configuration data was obtained.
1057 Ip4Config2GetIfInfo (
1058 IN IP4_CONFIG2_INSTANCE
*Instance
,
1059 IN OUT UINTN
*DataSize
,
1060 IN VOID
*Data OPTIONAL
1065 IP4_CONFIG2_DATA_ITEM
*Item
;
1066 EFI_IP4_CONFIG2_INTERFACE_INFO
*IfInfo
;
1069 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
1070 Length
= sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO
);
1072 if (IpSb
->DefaultRouteTable
!= NULL
) {
1073 Length
+= IpSb
->DefaultRouteTable
->TotalNum
* sizeof (EFI_IP4_ROUTE_TABLE
);
1076 if (*DataSize
< Length
) {
1078 return EFI_BUFFER_TOO_SMALL
;
1082 // Copy the fixed size part of the interface info.
1084 Item
= &Instance
->DataItem
[Ip4Config2DataTypeInterfaceInfo
];
1085 IfInfo
= (EFI_IP4_CONFIG2_INTERFACE_INFO
*) Data
;
1086 CopyMem (IfInfo
, Item
->Data
.Ptr
, sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO
));
1089 // Update the address info.
1091 if (IpSb
->DefaultInterface
!= NULL
) {
1092 Address
= HTONL (IpSb
->DefaultInterface
->Ip
);
1093 CopyMem (&IfInfo
->StationAddress
, &Address
, sizeof (EFI_IPv4_ADDRESS
));
1094 Address
= HTONL (IpSb
->DefaultInterface
->SubnetMask
);
1095 CopyMem (&IfInfo
->SubnetMask
, &Address
, sizeof (EFI_IPv4_ADDRESS
));
1098 if (IpSb
->DefaultRouteTable
!= NULL
) {
1099 IfInfo
->RouteTableSize
= IpSb
->DefaultRouteTable
->TotalNum
;
1100 IfInfo
->RouteTable
= (EFI_IP4_ROUTE_TABLE
*) ((UINT8
*) Data
+ sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO
));
1102 Ip4Config2BuildDefaultRouteTable (IpSb
, IfInfo
->RouteTable
);
1109 The work function is to set the general configuration policy for the EFI IPv4 network
1110 stack that is running on the communication device managed by this IP4_CONFIG2_INSTANCE.
1111 The policy will affect other configuration settings.
1113 @param[in] Instance Pointer to the IP4 config2 instance data.
1114 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
1115 @param[in] Data The data buffer to set.
1117 @retval EFI_INVALID_PARAMETER The to be set policy is invalid.
1118 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1119 @retval EFI_ABORTED The new policy equals the current policy.
1120 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1121 network stack was set.
1125 Ip4Config2SetPolicy (
1126 IN IP4_CONFIG2_INSTANCE
*Instance
,
1131 EFI_IP4_CONFIG2_POLICY NewPolicy
;
1132 IP4_CONFIG2_DATA_ITEM
*DataItem
;
1135 if (DataSize
!= sizeof (EFI_IP4_CONFIG2_POLICY
)) {
1136 return EFI_BAD_BUFFER_SIZE
;
1139 NewPolicy
= *((EFI_IP4_CONFIG2_POLICY
*) Data
);
1141 if (NewPolicy
>= Ip4Config2PolicyMax
) {
1142 return EFI_INVALID_PARAMETER
;
1145 if (NewPolicy
== Instance
->Policy
) {
1146 if (NewPolicy
!= Ip4Config2PolicyDhcp
|| Instance
->DhcpSuccess
) {
1150 if (NewPolicy
== Ip4Config2PolicyDhcp
) {
1152 // The policy is changed from static to dhcp:
1153 // Clean the ManualAddress, Gateway and DnsServers, shrink the variable
1154 // data size, and fire up all the related events.
1156 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeManualAddress
];
1157 if (DataItem
->Data
.Ptr
!= NULL
) {
1158 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
);
1169 DataItem
->Data
.Ptr
= NULL
;
1170 DataItem
->DataSize
= 0;
1171 DataItem
->Status
= EFI_NOT_FOUND
;
1172 NetMapIterate (&DataItem
->EventMap
, Ip4Config2SignalEvent
, NULL
);
1174 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeDnsServer
];
1175 if (DataItem
->Data
.Ptr
!= NULL
) {
1176 FreePool (DataItem
->Data
.Ptr
);
1178 DataItem
->Data
.Ptr
= NULL
;
1179 DataItem
->DataSize
= 0;
1180 DataItem
->Status
= EFI_NOT_FOUND
;
1181 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_VOLATILE
);
1182 NetMapIterate (&DataItem
->EventMap
, Ip4Config2SignalEvent
, NULL
);
1185 // The policy is changed from dhcp to static. Stop the DHCPv4 process
1186 // and destroy the DHCPv4 child.
1188 if (Instance
->Dhcp4Handle
!= NULL
) {
1189 Ip4Config2DestroyDhcp4 (Instance
);
1195 if (Instance
->Dhcp4Event
!= NULL
) {
1196 gBS
->CloseEvent (Instance
->Dhcp4Event
);
1197 Instance
->Dhcp4Event
= NULL
;
1202 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
1203 Ip4Config2OnPolicyChanged (IpSb
, NewPolicy
);
1205 Instance
->Policy
= NewPolicy
;
1211 The work function is to set the station addresses manually for the EFI IPv4
1212 network stack. It is only configurable when the policy is Ip4Config2PolicyStatic.
1214 @param[in] Instance Pointer to the IP4 config2 instance data.
1215 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
1216 @param[in] Data The data buffer to set.
1218 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1219 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
1220 under the current policy.
1221 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
1222 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
1223 @retval EFI_NOT_READY An asynchrous process is invoked to set the specified
1224 configuration data, and the process is not finished.
1225 @retval EFI_ABORTED The manual addresses to be set equal current
1227 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1228 network stack was set.
1232 Ip4Config2SetMaunualAddress (
1233 IN IP4_CONFIG2_INSTANCE
*Instance
,
1238 EFI_IP4_CONFIG2_MANUAL_ADDRESS NewAddress
;
1239 IP4_CONFIG2_DATA_ITEM
*DataItem
;
1241 IP4_ADDR StationAddress
;
1242 IP4_ADDR SubnetMask
;
1246 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
1248 ASSERT (Instance
->DataItem
[Ip4Config2DataTypeManualAddress
].Status
!= EFI_NOT_READY
);
1250 if (((DataSize
% sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS
)) != 0) || (DataSize
== 0)) {
1251 return EFI_BAD_BUFFER_SIZE
;
1254 if (Instance
->Policy
!= Ip4Config2PolicyStatic
) {
1255 return EFI_WRITE_PROTECTED
;
1258 NewAddress
= *((EFI_IP4_CONFIG2_MANUAL_ADDRESS
*) Data
);
1261 // Store the new data, and init the DataItem status to EFI_NOT_READY because
1262 // we may have an asynchronous configuration process.
1264 Ptr
= AllocateCopyPool (DataSize
, Data
);
1266 return EFI_OUT_OF_RESOURCES
;
1269 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeManualAddress
];
1270 if (DataItem
->Data
.Ptr
!= NULL
) {
1271 FreePool (DataItem
->Data
.Ptr
);
1274 DataItem
->Data
.Ptr
= Ptr
;
1275 DataItem
->DataSize
= DataSize
;
1276 DataItem
->Status
= EFI_NOT_READY
;
1278 StationAddress
= EFI_NTOHL (NewAddress
.Address
);
1279 SubnetMask
= EFI_NTOHL (NewAddress
.SubnetMask
);
1281 IpSb
->Reconfig
= TRUE
;
1282 Status
= Ip4Config2SetDefaultAddr (IpSb
, StationAddress
, SubnetMask
);
1283 if (EFI_ERROR (Status
)) {
1287 DataItem
->Status
= EFI_SUCCESS
;
1290 if (EFI_ERROR (DataItem
->Status
)) {
1294 DataItem
->Data
.Ptr
= NULL
;
1301 The work function is to set the gateway addresses manually for the EFI IPv4
1302 network stack that is running on the communication device that this EFI IPv4
1303 Configuration Protocol manages. It is not configurable when the policy is
1304 Ip4Config2PolicyDhcp. The gateway addresses must be unicast IPv4 addresses.
1306 @param[in] Instance The pointer to the IP4 config2 instance data.
1307 @param[in] DataSize The size of the buffer pointed to by Data in bytes.
1308 @param[in] Data The data buffer to set. This points to an array of
1309 EFI_IPv6_ADDRESS instances.
1311 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1312 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
1313 under the current policy.
1314 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
1315 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to complete the operation.
1316 @retval EFI_ABORTED The manual gateway addresses to be set equal the
1317 current configuration.
1318 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1319 network stack was set.
1323 Ip4Config2SetGateway (
1324 IN IP4_CONFIG2_INSTANCE
*Instance
,
1330 IP4_CONFIG2_DATA_ITEM
*DataItem
;
1335 EFI_IPv4_ADDRESS
*OldGateway
;
1336 EFI_IPv4_ADDRESS
*NewGateway
;
1337 UINTN OldGatewayCount
;
1338 UINTN NewGatewayCount
;
1343 if ((DataSize
% sizeof (EFI_IPv4_ADDRESS
) != 0) || (DataSize
== 0)) {
1344 return EFI_BAD_BUFFER_SIZE
;
1347 if (Instance
->Policy
!= Ip4Config2PolicyStatic
) {
1348 return EFI_WRITE_PROTECTED
;
1352 NewGateway
= (EFI_IPv4_ADDRESS
*) Data
;
1353 NewGatewayCount
= DataSize
/ sizeof (EFI_IPv4_ADDRESS
);
1354 for (Index1
= 0; Index1
< NewGatewayCount
; Index1
++) {
1355 CopyMem (&Gateway
, NewGateway
+ Index1
, sizeof (IP4_ADDR
));
1357 if (!NetIp4IsUnicast (NTOHL (Gateway
), 0)) {
1359 return EFI_INVALID_PARAMETER
;
1362 for (Index2
= Index1
+ 1; Index2
< NewGatewayCount
; Index2
++) {
1363 if (EFI_IP4_EQUAL (NewGateway
+ Index1
, NewGateway
+ Index2
)) {
1364 return EFI_INVALID_PARAMETER
;
1369 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
1370 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeGateway
];
1371 OldGateway
= DataItem
->Data
.Gateway
;
1372 OldGatewayCount
= DataItem
->DataSize
/ sizeof (EFI_IPv4_ADDRESS
);
1376 if (NewGatewayCount
!= OldGatewayCount
) {
1377 Tmp
= AllocatePool (DataSize
);
1379 return EFI_OUT_OF_RESOURCES
;
1385 for (Index1
= 0; Index1
< OldGatewayCount
; Index1
++) {
1387 // Remove this route entry.
1389 CopyMem (&Gateway
, OldGateway
+ Index1
, sizeof (IP4_ADDR
));
1391 IpSb
->DefaultRouteTable
,
1392 IP4_ALLZERO_ADDRESS
,
1393 IP4_ALLZERO_ADDRESS
,
1400 for (Index1
= 0; Index1
< NewGatewayCount
; Index1
++) {
1401 CopyMem (&Gateway
, NewGateway
+ Index1
, sizeof (IP4_ADDR
));
1403 IpSb
->DefaultRouteTable
,
1404 IP4_ALLZERO_ADDRESS
,
1405 IP4_ALLZERO_ADDRESS
,
1413 if (!OneRemoved
&& !OneAdded
) {
1414 DataItem
->Status
= EFI_SUCCESS
;
1419 if (DataItem
->Data
.Ptr
!= NULL
) {
1420 FreePool (DataItem
->Data
.Ptr
);
1422 DataItem
->Data
.Ptr
= Tmp
;
1425 CopyMem (DataItem
->Data
.Ptr
, Data
, DataSize
);
1426 DataItem
->DataSize
= DataSize
;
1427 DataItem
->Status
= EFI_SUCCESS
;
1434 The work function is to set the DNS server list for the EFI IPv4 network
1435 stack running on the communication device that this EFI_IP4_CONFIG2_PROTOCOL
1436 manages. It is not configurable when the policy is Ip4Config2PolicyDhcp.
1437 The DNS server addresses must be unicast IPv4 addresses.
1439 @param[in] Instance The pointer to the IP4 config2 instance data.
1440 @param[in] DataSize The size of the buffer pointed to by Data in bytes.
1441 @param[in] Data The data buffer to set, points to an array of
1442 EFI_IPv4_ADDRESS instances.
1444 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1445 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
1446 under the current policy.
1447 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
1448 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
1449 @retval EFI_ABORTED The DNS server addresses to be set equal the current
1451 @retval EFI_SUCCESS The specified configuration data for the EFI IPv4
1452 network stack was set.
1456 Ip4Config2SetDnsServer (
1457 IN IP4_CONFIG2_INSTANCE
*Instance
,
1462 IP4_CONFIG2_DATA_ITEM
*Item
;
1466 if (Instance
->Policy
!= Ip4Config2PolicyStatic
) {
1467 return EFI_WRITE_PROTECTED
;
1470 Item
= &Instance
->DataItem
[Ip4Config2DataTypeDnsServer
];
1472 if (DATA_ATTRIB_SET (Item
->Attribute
, DATA_ATTRIB_VOLATILE
)) {
1473 REMOVE_DATA_ATTRIB (Item
->Attribute
, DATA_ATTRIB_VOLATILE
);
1476 return Ip4Config2SetDnsServerWorker (Instance
, DataSize
, Data
);
1480 Generate the operational state of the interface this IP4 config2 instance manages
1481 and output in EFI_IP4_CONFIG2_INTERFACE_INFO.
1483 @param[in] IpSb The pointer to the IP4 service binding instance.
1484 @param[out] IfInfo The pointer to the IP4 config2 interface information structure.
1488 Ip4Config2InitIfInfo (
1489 IN IP4_SERVICE
*IpSb
,
1490 OUT EFI_IP4_CONFIG2_INTERFACE_INFO
*IfInfo
1493 IfInfo
->Name
[0] = L
'e';
1494 IfInfo
->Name
[1] = L
't';
1495 IfInfo
->Name
[2] = L
'h';
1496 IfInfo
->Name
[3] = (CHAR16
) (L
'0' + IpSb
->Ip4Config2Instance
.IfIndex
);
1497 IfInfo
->Name
[4] = 0;
1499 IfInfo
->IfType
= IpSb
->SnpMode
.IfType
;
1500 IfInfo
->HwAddressSize
= IpSb
->SnpMode
.HwAddressSize
;
1501 CopyMem (&IfInfo
->HwAddress
, &IpSb
->SnpMode
.CurrentAddress
, IfInfo
->HwAddressSize
);
1505 The event handle routine when DHCPv4 process is finished or is updated.
1507 @param[in] Event Not used.
1508 @param[in] Context The pointer to the IP4 configuration instance data.
1513 Ip4Config2OnDhcp4Event (
1523 Set the configuration for the EFI IPv4 network stack running on the communication
1524 device this EFI_IP4_CONFIG2_PROTOCOL instance manages.
1526 This function is used to set the configuration data of type DataType for the EFI
1527 IPv4 network stack that is running on the communication device that this EFI IPv4
1528 Configuration Protocol instance manages.
1530 DataSize is used to calculate the count of structure instances in the Data for
1531 a DataType in which multiple structure instances are allowed.
1533 This function is always non-blocking. When setting some type of configuration data,
1534 an asynchronous process is invoked to check the correctness of the data, such as
1535 performing Duplicate Address Detection on the manually set local IPv4 addresses.
1536 EFI_NOT_READY is returned immediately to indicate that such an asynchronous process
1537 is invoked, and the process is not finished yet. The caller wanting to get the result
1538 of the asynchronous process is required to call RegisterDataNotify() to register an
1539 event on the specified configuration data. Once the event is signaled, the caller
1540 can call GetData() to obtain the configuration data and know the result.
1541 For other types of configuration data that do not require an asynchronous configuration
1542 process, the result of the operation is immediately returned.
1544 @param[in] This The pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
1545 @param[in] DataType The type of data to set.
1546 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
1547 @param[in] Data The data buffer to set. The type of the data buffer is
1548 associated with the DataType.
1550 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1551 network stack was set successfully.
1552 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
1555 - One or more fields in Data do not match the requirement of the
1556 data type indicated by DataType.
1557 @retval EFI_WRITE_PROTECTED The specified configuration data is read-only or the specified
1558 configuration data cannot be set under the current policy.
1559 @retval EFI_ACCESS_DENIED Another set operation on the specified configuration
1560 data is already in process.
1561 @retval EFI_NOT_READY An asynchronous process was invoked to set the specified
1562 configuration data, and the process is not finished yet.
1563 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type
1564 indicated by DataType.
1565 @retval EFI_UNSUPPORTED This DataType is not supported.
1566 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
1567 @retval EFI_DEVICE_ERROR An unexpected system error or network error occurred.
1572 EfiIp4Config2SetData (
1573 IN EFI_IP4_CONFIG2_PROTOCOL
*This
,
1574 IN EFI_IP4_CONFIG2_DATA_TYPE DataType
,
1581 IP4_CONFIG2_INSTANCE
*Instance
;
1584 if ((This
== NULL
) || (Data
== NULL
)) {
1585 return EFI_INVALID_PARAMETER
;
1588 if (DataType
>= Ip4Config2DataTypeMaximum
) {
1589 return EFI_UNSUPPORTED
;
1592 Instance
= IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This
);
1593 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
1594 NET_CHECK_SIGNATURE (IpSb
, IP4_SERVICE_SIGNATURE
);
1597 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1599 Status
= Instance
->DataItem
[DataType
].Status
;
1600 if (Status
!= EFI_NOT_READY
) {
1602 if (Instance
->DataItem
[DataType
].SetData
== NULL
) {
1604 // This type of data is readonly.
1606 Status
= EFI_WRITE_PROTECTED
;
1609 Status
= Instance
->DataItem
[DataType
].SetData (Instance
, DataSize
, Data
);
1610 if (!EFI_ERROR (Status
)) {
1612 // Fire up the events registered with this type of data.
1614 NetMapIterate (&Instance
->DataItem
[DataType
].EventMap
, Ip4Config2SignalEvent
, NULL
);
1615 Ip4Config2WriteConfigData (IpSb
->MacString
, Instance
);
1616 } else if (Status
== EFI_ABORTED
) {
1618 // The SetData is aborted because the data to set is the same with
1619 // the one maintained.
1621 Status
= EFI_SUCCESS
;
1622 NetMapIterate (&Instance
->DataItem
[DataType
].EventMap
, Ip4Config2SignalEvent
, NULL
);
1627 // Another asynchornous process is on the way.
1629 Status
= EFI_ACCESS_DENIED
;
1632 gBS
->RestoreTPL (OldTpl
);
1638 Get the configuration data for the EFI IPv4 network stack running on the communication
1639 device that this EFI_IP4_CONFIG2_PROTOCOL instance manages.
1641 This function returns the configuration data of type DataType for the EFI IPv4 network
1642 stack running on the communication device that this EFI IPv4 Configuration Protocol instance
1645 The caller is responsible for allocating the buffer used to return the specified
1646 configuration data. The required size will be returned to the caller if the size of
1647 the buffer is too small.
1649 EFI_NOT_READY is returned if the specified configuration data is not ready due to an
1650 asynchronous configuration process already in progress. The caller can call RegisterDataNotify()
1651 to register an event on the specified configuration data. Once the asynchronous configuration
1652 process is finished, the event will be signaled, and a subsequent GetData() call will return
1653 the specified configuration data.
1655 @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
1656 @param[in] DataType The type of data to get.
1657 @param[in, out] DataSize On input, in bytes, the size of Data. On output, in bytes, the
1658 size of buffer required to store the specified configuration data.
1659 @param[in] Data The data buffer in which the configuration data is returned. The
1660 type of the data buffer is associated with the DataType.
1661 This is an optional parameter that may be NULL.
1663 @retval EFI_SUCCESS The specified configuration data was obtained successfully.
1664 @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
1667 - Data is NULL if *DataSize is not zero.
1668 @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified configuration data,
1669 and the required size is returned in DataSize.
1670 @retval EFI_NOT_READY The specified configuration data is not ready due to an
1671 asynchronous configuration process already in progress.
1672 @retval EFI_NOT_FOUND The specified configuration data is not found.
1677 EfiIp4Config2GetData (
1678 IN EFI_IP4_CONFIG2_PROTOCOL
*This
,
1679 IN EFI_IP4_CONFIG2_DATA_TYPE DataType
,
1680 IN OUT UINTN
*DataSize
,
1681 IN VOID
*Data OPTIONAL
1686 IP4_CONFIG2_INSTANCE
*Instance
;
1687 IP4_CONFIG2_DATA_ITEM
*DataItem
;
1689 if ((This
== NULL
) || (DataSize
== NULL
) || ((*DataSize
!= 0) && (Data
== NULL
))) {
1690 return EFI_INVALID_PARAMETER
;
1693 if (DataType
>= Ip4Config2DataTypeMaximum
) {
1694 return EFI_NOT_FOUND
;
1697 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1699 Instance
= IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This
);
1700 DataItem
= &Instance
->DataItem
[DataType
];
1702 Status
= Instance
->DataItem
[DataType
].Status
;
1703 if (!EFI_ERROR (Status
)) {
1705 if (DataItem
->GetData
!= NULL
) {
1707 Status
= DataItem
->GetData (Instance
, DataSize
, Data
);
1708 } else if (*DataSize
< Instance
->DataItem
[DataType
].DataSize
) {
1710 // Update the buffer length.
1712 *DataSize
= Instance
->DataItem
[DataType
].DataSize
;
1713 Status
= EFI_BUFFER_TOO_SMALL
;
1716 *DataSize
= Instance
->DataItem
[DataType
].DataSize
;
1717 CopyMem (Data
, Instance
->DataItem
[DataType
].Data
.Ptr
, *DataSize
);
1721 gBS
->RestoreTPL (OldTpl
);
1727 Register an event that is signaled whenever a configuration process on the specified
1728 configuration data is done.
1730 This function registers an event that is to be signaled whenever a configuration
1731 process on the specified configuration data is performed. An event can be registered
1732 for a different DataType simultaneously. The caller is responsible for determining
1733 which type of configuration data causes the signaling of the event in such an event.
1735 @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
1736 @param[in] DataType The type of data to unregister the event for.
1737 @param[in] Event The event to register.
1739 @retval EFI_SUCCESS The notification event for the specified configuration data is
1741 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
1742 @retval EFI_UNSUPPORTED The configuration data type specified by DataType is not
1744 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
1745 @retval EFI_ACCESS_DENIED The Event is already registered for the DataType.
1750 EfiIp4Config2RegisterDataNotify (
1751 IN EFI_IP4_CONFIG2_PROTOCOL
*This
,
1752 IN EFI_IP4_CONFIG2_DATA_TYPE DataType
,
1758 IP4_CONFIG2_INSTANCE
*Instance
;
1762 if ((This
== NULL
) || (Event
== NULL
)) {
1763 return EFI_INVALID_PARAMETER
;
1766 if (DataType
>= Ip4Config2DataTypeMaximum
) {
1767 return EFI_UNSUPPORTED
;
1770 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1772 Instance
= IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This
);
1773 EventMap
= &Instance
->DataItem
[DataType
].EventMap
;
1776 // Check whether this event is already registered for this DataType.
1778 Item
= NetMapFindKey (EventMap
, Event
);
1781 Status
= NetMapInsertTail (EventMap
, Event
, NULL
);
1783 if (EFI_ERROR (Status
)) {
1785 Status
= EFI_OUT_OF_RESOURCES
;
1790 Status
= EFI_ACCESS_DENIED
;
1793 gBS
->RestoreTPL (OldTpl
);
1799 Remove a previously registered event for the specified configuration data.
1801 @param This The pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
1802 @param DataType The type of data to remove from the previously
1804 @param Event The event to be unregistered.
1806 @retval EFI_SUCCESS The event registered for the specified
1807 configuration data was removed.
1808 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
1809 @retval EFI_NOT_FOUND The Event has not been registered for the
1815 EfiIp4Config2UnregisterDataNotify (
1816 IN EFI_IP4_CONFIG2_PROTOCOL
*This
,
1817 IN EFI_IP4_CONFIG2_DATA_TYPE DataType
,
1823 IP4_CONFIG2_INSTANCE
*Instance
;
1826 if ((This
== NULL
) || (Event
== NULL
)) {
1827 return EFI_INVALID_PARAMETER
;
1830 if (DataType
>= Ip4Config2DataTypeMaximum
) {
1831 return EFI_NOT_FOUND
;
1834 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1836 Instance
= IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This
);
1838 Item
= NetMapFindKey (&Instance
->DataItem
[DataType
].EventMap
, Event
);
1841 NetMapRemoveItem (&Instance
->DataItem
[DataType
].EventMap
, Item
, NULL
);
1842 Status
= EFI_SUCCESS
;
1845 Status
= EFI_NOT_FOUND
;
1848 gBS
->RestoreTPL (OldTpl
);
1854 Initialize an IP4_CONFIG2_INSTANCE.
1856 @param[out] Instance The buffer of IP4_CONFIG2_INSTANCE to be initialized.
1858 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
1859 @retval EFI_SUCCESS The IP4_CONFIG2_INSTANCE initialized successfully.
1863 Ip4Config2InitInstance (
1864 OUT IP4_CONFIG2_INSTANCE
*Instance
1868 IP4_CONFIG2_INSTANCE
*TmpInstance
;
1873 IP4_CONFIG2_DATA_ITEM
*DataItem
;
1876 IpSb
= IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance
);
1878 Instance
->Signature
= IP4_CONFIG2_INSTANCE_SIGNATURE
;
1882 // Determine the index of this interface.
1885 NET_LIST_FOR_EACH (Entry
, &mIp4Config2InstanceList
) {
1886 TmpInstance
= NET_LIST_USER_STRUCT_S (Entry
, IP4_CONFIG2_INSTANCE
, Link
, IP4_CONFIG2_INSTANCE_SIGNATURE
);
1888 if (TmpInstance
->IfIndex
> IfIndex
) {
1890 // There is a sequence hole because some interface is down.
1898 Instance
->IfIndex
= IfIndex
;
1899 NetListInsertBefore (Entry
, &Instance
->Link
);
1901 for (Index
= 0; Index
< Ip4Config2DataTypeMaximum
; Index
++) {
1903 // Initialize the event map for each data item.
1905 NetMapInit (&Instance
->DataItem
[Index
].EventMap
);
1910 // Initialize each data type: associate storage and set data size for the
1911 // fixed size data types, hook the SetData function, set the data attribute.
1913 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeInterfaceInfo
];
1914 DataItem
->GetData
= Ip4Config2GetIfInfo
;
1915 DataItem
->Data
.Ptr
= &Instance
->InterfaceInfo
;
1916 DataItem
->DataSize
= sizeof (Instance
->InterfaceInfo
);
1917 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
| DATA_ATTRIB_VOLATILE
);
1918 Ip4Config2InitIfInfo (IpSb
, &Instance
->InterfaceInfo
);
1920 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypePolicy
];
1921 DataItem
->SetData
= Ip4Config2SetPolicy
;
1922 DataItem
->Data
.Ptr
= &Instance
->Policy
;
1923 DataItem
->DataSize
= sizeof (Instance
->Policy
);
1924 Instance
->Policy
= Ip4Config2PolicyStatic
;
1925 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
);
1927 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeManualAddress
];
1928 DataItem
->SetData
= Ip4Config2SetMaunualAddress
;
1929 DataItem
->Status
= EFI_NOT_FOUND
;
1931 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeGateway
];
1932 DataItem
->SetData
= Ip4Config2SetGateway
;
1933 DataItem
->Status
= EFI_NOT_FOUND
;
1935 DataItem
= &Instance
->DataItem
[Ip4Config2DataTypeDnsServer
];
1936 DataItem
->SetData
= Ip4Config2SetDnsServer
;
1937 DataItem
->Status
= EFI_NOT_FOUND
;
1940 // Create the event used for DHCP.
1942 Status
= gBS
->CreateEvent (
1945 Ip4Config2OnDhcp4Event
,
1947 &Instance
->Dhcp4Event
1949 ASSERT_EFI_ERROR (Status
);
1951 Instance
->Configured
= TRUE
;
1954 // Try to read the config data from NV variable.
1955 // If not found, write initialized config data into NV variable
1956 // as a default config data.
1958 Status
= Ip4Config2ReadConfigData (IpSb
->MacString
, Instance
);
1959 if (Status
== EFI_NOT_FOUND
) {
1960 Status
= Ip4Config2WriteConfigData (IpSb
->MacString
, Instance
);
1963 if (EFI_ERROR (Status
)) {
1967 Instance
->Ip4Config2
.SetData
= EfiIp4Config2SetData
;
1968 Instance
->Ip4Config2
.GetData
= EfiIp4Config2GetData
;
1969 Instance
->Ip4Config2
.RegisterDataNotify
= EfiIp4Config2RegisterDataNotify
;
1970 Instance
->Ip4Config2
.UnregisterDataNotify
= EfiIp4Config2UnregisterDataNotify
;
1973 // Publish the IP4 configuration form
1975 return Ip4Config2FormInit (Instance
);
1980 Release an IP4_CONFIG2_INSTANCE.
1982 @param[in, out] Instance The buffer of IP4_CONFIG2_INSTANCE to be freed.
1986 Ip4Config2CleanInstance (
1987 IN OUT IP4_CONFIG2_INSTANCE
*Instance
1991 IP4_CONFIG2_DATA_ITEM
*DataItem
;
1993 if (Instance
->DeclineAddress
!= NULL
) {
1994 FreePool (Instance
->DeclineAddress
);
1997 if (!Instance
->Configured
) {
2001 if (Instance
->Dhcp4Handle
!= NULL
) {
2003 Ip4Config2DestroyDhcp4 (Instance
);
2009 if (Instance
->Dhcp4Event
!= NULL
) {
2010 gBS
->CloseEvent (Instance
->Dhcp4Event
);
2011 Instance
->Dhcp4Event
= NULL
;
2014 for (Index
= 0; Index
< Ip4Config2DataTypeMaximum
; Index
++) {
2016 DataItem
= &Instance
->DataItem
[Index
];
2018 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
)) {
2019 if (DataItem
->Data
.Ptr
!= NULL
) {
2020 FreePool (DataItem
->Data
.Ptr
);
2022 DataItem
->Data
.Ptr
= NULL
;
2023 DataItem
->DataSize
= 0;
2026 NetMapClean (&Instance
->DataItem
[Index
].EventMap
);
2029 Ip4Config2FormUnload (Instance
);
2031 RemoveEntryList (&Instance
->Link
);
2035 The event handle for IP4 auto reconfiguration. The original default
2036 interface and route table will be removed as the default.
2038 @param[in] Context The IP4 service binding instance.
2043 Ip4AutoReconfigCallBackDpc (
2049 IpSb
= (IP4_SERVICE
*) Context
;
2050 NET_CHECK_SIGNATURE (IpSb
, IP4_SERVICE_SIGNATURE
);
2052 if (IpSb
->State
> IP4_SERVICE_UNSTARTED
) {
2053 IpSb
->State
= IP4_SERVICE_UNSTARTED
;
2056 IpSb
->Reconfig
= TRUE
;
2058 Ip4StartAutoConfig (&IpSb
->Ip4Config2Instance
);
2065 Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK.
2067 @param Event The event that is signalled.
2068 @param Context The IP4 service binding instance.
2073 Ip4AutoReconfigCallBack (
2079 // Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK
2081 QueueDpc (TPL_CALLBACK
, Ip4AutoReconfigCallBackDpc
, Context
);