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