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