]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Impl.c
caf84fb7a5fdb097ee5b457dacc32db621970140
[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 IpSb->State = IP4_SERVICE_CONFIGED;
496 return EFI_SUCCESS;
497 }
498
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 if (IpSb->State == IP4_SERVICE_CONFIGED) {
530 IpSb->State = IP4_SERVICE_UNSTARTED;
531 }
532
533 Status = Ip4SetAddress (IpIf, StationAddress, SubnetMask);
534 if (EFI_ERROR (Status)) {
535 return Status;
536 }
537
538 if (IpIf->Arp != NULL) {
539 //
540 // A non-NULL IpIf->Arp here means a new ARP child is created when setting default address,
541 // but some IP children may have referenced the default interface before it is configured,
542 // these IP instances also consume this ARP protocol so they need to open it BY_CHILD_CONTROLLER.
543 //
544 Arp = NULL;
545 NET_LIST_FOR_EACH (Entry, &IpIf->IpInstances) {
546 Ip4Instance = NET_LIST_USER_STRUCT_S (Entry, IP4_PROTOCOL, AddrLink, IP4_PROTOCOL_SIGNATURE);
547 Status = gBS->OpenProtocol (
548 IpIf->ArpHandle,
549 &gEfiArpProtocolGuid,
550 (VOID **) &Arp,
551 gIp4DriverBinding.DriverBindingHandle,
552 Ip4Instance->Handle,
553 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
554 );
555 if (EFI_ERROR (Status)) {
556 return Status;
557 }
558 }
559 }
560
561 Ip4AddRoute (
562 IpSb->DefaultRouteTable,
563 StationAddress,
564 SubnetMask,
565 IP4_ALLZERO_ADDRESS
566 );
567
568 //
569 // Add a route for the connected network.
570 //
571 Subnet = StationAddress & SubnetMask;
572
573 Ip4AddRoute (
574 IpSb->DefaultRouteTable,
575 Subnet,
576 SubnetMask,
577 IP4_ALLZERO_ADDRESS
578 );
579
580 IpSb->State = IP4_SERVICE_CONFIGED;
581 return EFI_SUCCESS;
582 }
583
584 /**
585 Set the station address, subnetmask and gateway address for the default interface.
586
587 @param[in] Instance The pointer to the IP4 config2 instance data.
588 @param[in] StationAddress Ip address to be set.
589 @param[in] SubnetMask Subnet to be set.
590 @param[in] GatewayAddress Gateway to be set.
591
592 @retval EFI_SUCCESS Set default If successful.
593 @retval Others Errors occur as indicated.
594
595 **/
596 EFI_STATUS
597 Ip4Config2SetDefaultIf (
598 IN IP4_CONFIG2_INSTANCE *Instance,
599 IN IP4_ADDR StationAddress,
600 IN IP4_ADDR SubnetMask,
601 IN IP4_ADDR GatewayAddress
602 )
603 {
604 EFI_STATUS Status;
605 IP4_SERVICE *IpSb;
606
607 Status = Ip4Config2SetDefaultAddr (Instance, StationAddress, SubnetMask);
608 if (EFI_ERROR (Status)) {
609 return Status;
610 }
611
612 //
613 // Create a route if there is a default router.
614 //
615 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
616 if (GatewayAddress != IP4_ALLZERO_ADDRESS) {
617 Ip4AddRoute (
618 IpSb->DefaultRouteTable,
619 IP4_ALLZERO_ADDRESS,
620 IP4_ALLZERO_ADDRESS,
621 GatewayAddress
622 );
623 }
624
625 return EFI_SUCCESS;
626 }
627
628
629 /**
630 Release all the DHCP related resources.
631
632 @param Instance The IP4 config2 instance.
633
634 @return None
635
636 **/
637 VOID
638 Ip4Config2CleanDhcp4 (
639 IN IP4_CONFIG2_INSTANCE *Instance
640 )
641 {
642 IP4_SERVICE *IpSb;
643
644 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
645
646 if (Instance->Dhcp4 != NULL) {
647 Instance->Dhcp4->Stop (Instance->Dhcp4);
648
649 gBS->CloseProtocol (
650 Instance->Dhcp4Handle,
651 &gEfiDhcp4ProtocolGuid,
652 IpSb->Image,
653 IpSb->Controller
654 );
655
656 Instance->Dhcp4 = NULL;
657 }
658
659 if (Instance->Dhcp4Handle != NULL) {
660 NetLibDestroyServiceChild (
661 IpSb->Controller,
662 IpSb->Image,
663 &gEfiDhcp4ServiceBindingProtocolGuid,
664 Instance->Dhcp4Handle
665 );
666
667 Instance->Dhcp4Handle = NULL;
668 }
669
670 if (Instance->Dhcp4Event != NULL) {
671 gBS->CloseEvent (Instance->Dhcp4Event);
672 Instance->Dhcp4Event = NULL;
673 }
674 }
675
676
677 /**
678 Callback function when DHCP process finished. It will save the
679 retrieved IP configure parameter from DHCP to the NVRam.
680
681 @param Event The callback event
682 @param Context Opaque context to the callback
683
684 @return None
685
686 **/
687 VOID
688 EFIAPI
689 Ip4Config2OnDhcp4Complete (
690 IN EFI_EVENT Event,
691 IN VOID *Context
692 )
693 {
694 IP4_CONFIG2_INSTANCE *Instance;
695 EFI_DHCP4_MODE_DATA Dhcp4Mode;
696 EFI_STATUS Status;
697 IP4_ADDR StationAddress;
698 IP4_ADDR SubnetMask;
699 IP4_ADDR GatewayAddress;
700
701 Instance = (IP4_CONFIG2_INSTANCE *) Context;
702 ASSERT (Instance->Dhcp4 != NULL);
703
704 //
705 // Get the DHCP retrieved parameters
706 //
707 Status = Instance->Dhcp4->GetModeData (Instance->Dhcp4, &Dhcp4Mode);
708
709 if (EFI_ERROR (Status)) {
710 goto Exit;
711 }
712
713 if (Dhcp4Mode.State == Dhcp4Bound) {
714 StationAddress = EFI_NTOHL (Dhcp4Mode.ClientAddress);
715 SubnetMask = EFI_NTOHL (Dhcp4Mode.SubnetMask);
716 GatewayAddress = EFI_NTOHL (Dhcp4Mode.RouterAddress);
717
718 Status = Ip4Config2SetDefaultIf (Instance, StationAddress, SubnetMask, GatewayAddress);
719 if (EFI_ERROR (Status)) {
720 goto Exit;
721 }
722
723 Instance->DhcpSuccess = TRUE;
724 }
725
726 Exit:
727 Ip4Config2CleanDhcp4 (Instance);
728 DispatchDpc ();
729 }
730
731
732 /**
733 Start the DHCP configuration for this IP service instance.
734 It will locates the EFI_IP4_CONFIG2_PROTOCOL, then start the
735 DHCP configuration.
736
737 @param[in] Instance The IP4 config2 instance to configure
738
739 @retval EFI_SUCCESS The auto configuration is successfull started
740 @retval Others Failed to start auto configuration.
741
742 **/
743 EFI_STATUS
744 Ip4StartAutoConfig (
745 IN IP4_CONFIG2_INSTANCE *Instance
746 )
747 {
748 IP4_SERVICE *IpSb;
749 EFI_DHCP4_PROTOCOL *Dhcp4;
750 EFI_DHCP4_MODE_DATA Dhcp4Mode;
751 EFI_DHCP4_PACKET_OPTION *OptionList[1];
752 IP4_CONFIG2_DHCP4_OPTION ParaList;
753 EFI_STATUS Status;
754
755
756 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
757
758 if (IpSb->State > IP4_SERVICE_UNSTARTED) {
759 return EFI_SUCCESS;
760 }
761
762 //
763 // A host must not invoke DHCP configuration if it is already
764 // participating in the DHCP configuraiton process.
765 //
766 if (Instance->Dhcp4Handle != NULL) {
767 return EFI_SUCCESS;
768 }
769
770 Status = NetLibCreateServiceChild (
771 IpSb->Controller,
772 IpSb->Image,
773 &gEfiDhcp4ServiceBindingProtocolGuid,
774 &Instance->Dhcp4Handle
775 );
776
777 if (Status == EFI_UNSUPPORTED) {
778 //
779 // No DHCPv4 Service Binding protocol, register a notify.
780 //
781 if (Instance->Dhcp4SbNotifyEvent == NULL) {
782 Instance->Dhcp4SbNotifyEvent = EfiCreateProtocolNotifyEvent (
783 &gEfiDhcp4ServiceBindingProtocolGuid,
784 TPL_CALLBACK,
785 Ip4Config2OnDhcp4SbInstalled,
786 (VOID *) Instance,
787 &Instance->Registration
788 );
789 }
790 }
791
792 if (EFI_ERROR (Status)) {
793 return Status;
794 }
795
796 if (Instance->Dhcp4SbNotifyEvent != NULL) {
797 gBS->CloseEvent (Instance->Dhcp4SbNotifyEvent);
798 }
799
800 Status = gBS->OpenProtocol (
801 Instance->Dhcp4Handle,
802 &gEfiDhcp4ProtocolGuid,
803 (VOID **) &Instance->Dhcp4,
804 IpSb->Image,
805 IpSb->Controller,
806 EFI_OPEN_PROTOCOL_BY_DRIVER
807 );
808 ASSERT_EFI_ERROR (Status);
809
810
811 //
812 // Check the current DHCP status, if the DHCP process has
813 // already finished, return now.
814 //
815 Dhcp4 = Instance->Dhcp4;
816 Status = Dhcp4->GetModeData (Dhcp4, &Dhcp4Mode);
817
818 if (Dhcp4Mode.State == Dhcp4Bound) {
819 Ip4Config2OnDhcp4Complete (NULL, Instance);
820 return EFI_SUCCESS;
821
822 }
823
824 //
825 // Try to start the DHCP process. Use most of the current
826 // DHCP configuration to avoid problems if some DHCP client
827 // yields the control of this DHCP service to us.
828 //
829 ParaList.Head.OpCode = DHCP_TAG_PARA_LIST;
830 ParaList.Head.Length = 2;
831 ParaList.Head.Data[0] = DHCP_TAG_NETMASK;
832 ParaList.Route = DHCP_TAG_ROUTER;
833 OptionList[0] = &ParaList.Head;
834 Dhcp4Mode.ConfigData.OptionCount = 1;
835 Dhcp4Mode.ConfigData.OptionList = OptionList;
836
837 Status = Dhcp4->Configure (Dhcp4, &Dhcp4Mode.ConfigData);
838
839 if (EFI_ERROR (Status)) {
840 return Status;
841 }
842
843 //
844 // Start the DHCP process
845 //
846 Status = gBS->CreateEvent (
847 EVT_NOTIFY_SIGNAL,
848 TPL_CALLBACK,
849 Ip4Config2OnDhcp4Complete,
850 Instance,
851 &Instance->Dhcp4Event
852 );
853
854 if (EFI_ERROR (Status)) {
855 return Status;
856 }
857
858 Status = Dhcp4->Start (Dhcp4, Instance->Dhcp4Event);
859
860 if (EFI_ERROR (Status)) {
861 return Status;
862 }
863
864 IpSb->State = IP4_SERVICE_STARTED;
865 DispatchDpc ();
866 return EFI_SUCCESS;
867
868 }
869
870
871
872 /**
873 The work function is to get the interface information of the communication
874 device this IP4_CONFIG2_INSTANCE manages.
875
876 @param[in] Instance Pointer to the IP4 config2 instance data.
877 @param[in, out] DataSize On input, in bytes, the size of Data. On output, in
878 bytes, the size of buffer required to store the specified
879 configuration data.
880 @param[in] Data The data buffer in which the configuration data is returned.
881 Ignored if DataSize is ZERO.
882
883 @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified
884 configuration data, and the required size is
885 returned in DataSize.
886 @retval EFI_SUCCESS The specified configuration data was obtained.
887
888 **/
889 EFI_STATUS
890 Ip4Config2GetIfInfo (
891 IN IP4_CONFIG2_INSTANCE *Instance,
892 IN OUT UINTN *DataSize,
893 IN VOID *Data OPTIONAL
894 )
895 {
896
897 IP4_SERVICE *IpSb;
898 UINTN Length;
899 IP4_CONFIG2_DATA_ITEM *Item;
900 EFI_IP4_CONFIG2_INTERFACE_INFO *IfInfo;
901 IP4_ADDR Address;
902
903 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
904 Length = sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO);
905
906 if (IpSb->DefaultRouteTable != NULL) {
907 Length += IpSb->DefaultRouteTable->TotalNum * sizeof (EFI_IP4_ROUTE_TABLE);
908 }
909
910 if (*DataSize < Length) {
911 *DataSize = Length;
912 return EFI_BUFFER_TOO_SMALL;
913 }
914
915 //
916 // Copy the fixed size part of the interface info.
917 //
918 Item = &Instance->DataItem[Ip4Config2DataTypeInterfaceInfo];
919 IfInfo = (EFI_IP4_CONFIG2_INTERFACE_INFO *) Data;
920 CopyMem (IfInfo, Item->Data.Ptr, sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO));
921
922 //
923 // Update the address info.
924 //
925 if (IpSb->DefaultInterface != NULL) {
926 Address = HTONL (IpSb->DefaultInterface->Ip);
927 CopyMem (&IfInfo->StationAddress, &Address, sizeof (EFI_IPv4_ADDRESS));
928 Address = HTONL (IpSb->DefaultInterface->SubnetMask);
929 CopyMem (&IfInfo->SubnetMask, &Address, sizeof (EFI_IPv4_ADDRESS));
930 }
931
932 if (IpSb->DefaultRouteTable != NULL) {
933 IfInfo->RouteTableSize = IpSb->DefaultRouteTable->TotalNum;
934 IfInfo->RouteTable = (EFI_IP4_ROUTE_TABLE *) ((UINT8 *) Data + sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO));
935
936 Ip4Config2BuildDefaultRouteTable (IpSb, IfInfo->RouteTable);
937 }
938
939 return EFI_SUCCESS;
940 }
941
942 /**
943 The work function is to set the general configuration policy for the EFI IPv4 network
944 stack that is running on the communication device managed by this IP4_CONFIG2_INSTANCE.
945 The policy will affect other configuration settings.
946
947 @param[in] Instance Pointer to the IP4 config2 instance data.
948 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
949 @param[in] Data The data buffer to set.
950
951 @retval EFI_INVALID_PARAMETER The to be set policy is invalid.
952 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
953 @retval EFI_ABORTED The new policy equals the current policy.
954 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
955 network stack was set.
956
957 **/
958 EFI_STATUS
959 Ip4Config2SetPolicy (
960 IN IP4_CONFIG2_INSTANCE *Instance,
961 IN UINTN DataSize,
962 IN VOID *Data
963 )
964 {
965 EFI_IP4_CONFIG2_POLICY NewPolicy;
966 IP4_CONFIG2_DATA_ITEM *DataItem;
967 IP4_SERVICE *IpSb;
968
969 if (DataSize != sizeof (EFI_IP4_CONFIG2_POLICY)) {
970 return EFI_BAD_BUFFER_SIZE;
971 }
972
973 NewPolicy = *((EFI_IP4_CONFIG2_POLICY *) Data);
974
975 if (NewPolicy >= Ip4Config2PolicyMax) {
976 return EFI_INVALID_PARAMETER;
977 }
978
979 if (NewPolicy == Instance->Policy) {
980 return EFI_ABORTED;
981 } else {
982 if (NewPolicy == Ip4Config2PolicyDhcp) {
983 //
984 // The policy is changed from static to dhcp:
985 // Clean the ManualAddress, Gateway and DnsServers, shrink the variable
986 // data size, and fire up all the related events.
987 //
988 DataItem = &Instance->DataItem[Ip4Config2DataTypeManualAddress];
989 if (DataItem->Data.Ptr != NULL) {
990 FreePool (DataItem->Data.Ptr);
991 }
992 DataItem->Data.Ptr = NULL;
993 DataItem->DataSize = 0;
994 DataItem->Status = EFI_NOT_FOUND;
995 NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL);
996
997 DataItem = &Instance->DataItem[Ip4Config2DataTypeGateway];
998 if (DataItem->Data.Ptr != NULL) {
999 FreePool (DataItem->Data.Ptr);
1000 }
1001 DataItem->Data.Ptr = NULL;
1002 DataItem->DataSize = 0;
1003 DataItem->Status = EFI_NOT_FOUND;
1004 NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL);
1005
1006 DataItem = &Instance->DataItem[Ip4Config2DataTypeDnsServer];
1007 if (DataItem->Data.Ptr != NULL) {
1008 FreePool (DataItem->Data.Ptr);
1009 }
1010 DataItem->Data.Ptr = NULL;
1011 DataItem->DataSize = 0;
1012 DataItem->Status = EFI_NOT_FOUND;
1013 NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL);
1014 } else {
1015 //
1016 // The policy is changed from dhcp to static. Stop the DHCPv4 process
1017 // and destroy the DHCPv4 child.
1018 //
1019 if (Instance->Dhcp4Handle != NULL) {
1020 Ip4Config2DestroyDhcp4 (Instance);
1021 }
1022
1023 //
1024 // Close the event.
1025 //
1026 if (Instance->Dhcp4Event != NULL) {
1027 gBS->CloseEvent (Instance->Dhcp4Event);
1028 }
1029 }
1030 }
1031
1032 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
1033 Ip4Config2OnPolicyChanged (IpSb, NewPolicy);
1034
1035 Instance->Policy = NewPolicy;
1036
1037 return EFI_SUCCESS;
1038 }
1039
1040 /**
1041 The work function is to set the station addresses manually for the EFI IPv4
1042 network stack. It is only configurable when the policy is Ip4Config2PolicyStatic.
1043
1044 @param[in] Instance Pointer to the IP4 config2 instance data.
1045 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
1046 @param[in] Data The data buffer to set.
1047
1048 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1049 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
1050 under the current policy.
1051 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
1052 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
1053 @retval EFI_NOT_READY An asynchrous process is invoked to set the specified
1054 configuration data, and the process is not finished.
1055 @retval EFI_ABORTED The manual addresses to be set equal current
1056 configuration.
1057 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1058 network stack was set.
1059
1060 **/
1061 EFI_STATUS
1062 Ip4Config2SetMaunualAddress (
1063 IN IP4_CONFIG2_INSTANCE *Instance,
1064 IN UINTN DataSize,
1065 IN VOID *Data
1066 )
1067 {
1068 EFI_IP4_CONFIG2_MANUAL_ADDRESS NewAddress;
1069 IP4_CONFIG2_DATA_ITEM *DataItem;
1070 EFI_STATUS Status;
1071 IP4_ADDR StationAddress;
1072 IP4_ADDR SubnetMask;
1073 VOID *Ptr;
1074
1075 ASSERT (Instance->DataItem[Ip4Config2DataTypeManualAddress].Status != EFI_NOT_READY);
1076
1077 if (((DataSize % sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS)) != 0) || (DataSize == 0)) {
1078 return EFI_BAD_BUFFER_SIZE;
1079 }
1080
1081 if (Instance->Policy != Ip4Config2PolicyStatic) {
1082 return EFI_WRITE_PROTECTED;
1083 }
1084
1085 NewAddress = *((EFI_IP4_CONFIG2_MANUAL_ADDRESS *) Data);
1086
1087 //
1088 // Store the new data, and init the DataItem status to EFI_NOT_READY because
1089 // we may have an asynchronous configuration process.
1090 //
1091 Ptr = AllocateCopyPool (DataSize, Data);
1092 if (Ptr == NULL) {
1093 return EFI_OUT_OF_RESOURCES;
1094 }
1095
1096 DataItem = &Instance->DataItem[Ip4Config2DataTypeManualAddress];
1097 if (DataItem->Data.Ptr != NULL) {
1098 FreePool (DataItem->Data.Ptr);
1099 }
1100
1101 DataItem->Data.Ptr = Ptr;
1102 DataItem->DataSize = DataSize;
1103 DataItem->Status = EFI_NOT_READY;
1104
1105 StationAddress = EFI_NTOHL (NewAddress.Address);
1106 SubnetMask = EFI_NTOHL (NewAddress.SubnetMask);
1107
1108 Status = Ip4Config2SetDefaultAddr (Instance, StationAddress, SubnetMask);
1109 if (EFI_ERROR (Status)) {
1110 goto ON_EXIT;
1111 }
1112
1113 DataItem->Status = EFI_SUCCESS;
1114
1115 ON_EXIT:
1116 if (EFI_ERROR (DataItem->Status)) {
1117 if (Ptr != NULL) {
1118 FreePool (Ptr);
1119 }
1120 DataItem->Data.Ptr = NULL;
1121 }
1122
1123 return EFI_SUCCESS;
1124 }
1125
1126 /**
1127 The work function is to set the gateway addresses manually for the EFI IPv4
1128 network stack that is running on the communication device that this EFI IPv4
1129 Configuration Protocol manages. It is not configurable when the policy is
1130 Ip4Config2PolicyDhcp. The gateway addresses must be unicast IPv4 addresses.
1131
1132 @param[in] Instance The pointer to the IP4 config2 instance data.
1133 @param[in] DataSize The size of the buffer pointed to by Data in bytes.
1134 @param[in] Data The data buffer to set. This points to an array of
1135 EFI_IPv6_ADDRESS instances.
1136
1137 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1138 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
1139 under the current policy.
1140 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
1141 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to complete the operation.
1142 @retval EFI_ABORTED The manual gateway addresses to be set equal the
1143 current configuration.
1144 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1145 network stack was set.
1146
1147 **/
1148 EFI_STATUS
1149 Ip4Config2SetGateway (
1150 IN IP4_CONFIG2_INSTANCE *Instance,
1151 IN UINTN DataSize,
1152 IN VOID *Data
1153 )
1154 {
1155 IP4_SERVICE *IpSb;
1156 IP4_CONFIG2_DATA_ITEM *DataItem;
1157 IP4_ADDR Gateway;
1158
1159 UINTN Index1;
1160 UINTN Index2;
1161 EFI_IPv4_ADDRESS *OldGateway;
1162 EFI_IPv4_ADDRESS *NewGateway;
1163 UINTN OldGatewayCount;
1164 UINTN NewGatewayCount;
1165 BOOLEAN OneRemoved;
1166 BOOLEAN OneAdded;
1167 VOID *Tmp;
1168
1169 if ((DataSize % sizeof (EFI_IPv4_ADDRESS) != 0) || (DataSize == 0)) {
1170 return EFI_BAD_BUFFER_SIZE;
1171 }
1172
1173 if (Instance->Policy != Ip4Config2PolicyStatic) {
1174 return EFI_WRITE_PROTECTED;
1175 }
1176
1177
1178 NewGateway = (EFI_IPv4_ADDRESS *) Data;
1179 NewGatewayCount = DataSize / sizeof (EFI_IPv4_ADDRESS);
1180 for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {
1181 CopyMem (&Gateway, NewGateway + Index1, sizeof (IP4_ADDR));
1182
1183 if (!NetIp4IsUnicast (NTOHL (Gateway), 0)) {
1184
1185 return EFI_INVALID_PARAMETER;
1186 }
1187
1188 for (Index2 = Index1 + 1; Index2 < NewGatewayCount; Index2++) {
1189 if (EFI_IP4_EQUAL (NewGateway + Index1, NewGateway + Index2)) {
1190 return EFI_INVALID_PARAMETER;
1191 }
1192 }
1193 }
1194
1195 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
1196 DataItem = &Instance->DataItem[Ip4Config2DataTypeGateway];
1197 OldGateway = DataItem->Data.Gateway;
1198 OldGatewayCount = DataItem->DataSize / sizeof (EFI_IPv4_ADDRESS);
1199 OneRemoved = FALSE;
1200 OneAdded = FALSE;
1201
1202 if (NewGatewayCount != OldGatewayCount) {
1203 Tmp = AllocatePool (DataSize);
1204 if (Tmp == NULL) {
1205 return EFI_OUT_OF_RESOURCES;
1206 }
1207 } else {
1208 Tmp = NULL;
1209 }
1210
1211 for (Index1 = 0; Index1 < OldGatewayCount; Index1++) {
1212 //
1213 // Remove this route entry.
1214 //
1215 CopyMem (&Gateway, OldGateway + Index1, sizeof (IP4_ADDR));
1216 Ip4DelRoute (
1217 IpSb->DefaultRouteTable,
1218 IP4_ALLZERO_ADDRESS,
1219 IP4_ALLZERO_ADDRESS,
1220 NTOHL (Gateway)
1221 );
1222 OneRemoved = TRUE;
1223
1224 }
1225
1226 for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {
1227 CopyMem (&Gateway, NewGateway + Index1, sizeof (IP4_ADDR));
1228 Ip4AddRoute (
1229 IpSb->DefaultRouteTable,
1230 IP4_ALLZERO_ADDRESS,
1231 IP4_ALLZERO_ADDRESS,
1232 NTOHL (Gateway)
1233 );
1234
1235 OneAdded = TRUE;
1236 }
1237
1238
1239 if (!OneRemoved && !OneAdded) {
1240 DataItem->Status = EFI_SUCCESS;
1241 return EFI_ABORTED;
1242 } else {
1243
1244 if (Tmp != NULL) {
1245 if (DataItem->Data.Ptr != NULL) {
1246 FreePool (DataItem->Data.Ptr);
1247 }
1248 DataItem->Data.Ptr = Tmp;
1249 }
1250
1251 CopyMem (DataItem->Data.Ptr, Data, DataSize);
1252 DataItem->DataSize = DataSize;
1253 DataItem->Status = EFI_SUCCESS;
1254 return EFI_SUCCESS;
1255 }
1256
1257 }
1258
1259 /**
1260 The work function is to set the DNS server list for the EFI IPv4 network
1261 stack running on the communication device that this EFI_IP4_CONFIG2_PROTOCOL
1262 manages. It is not configurable when the policy is Ip4Config2PolicyDhcp.
1263 The DNS server addresses must be unicast IPv4 addresses.
1264
1265 @param[in] Instance The pointer to the IP4 config2 instance data.
1266 @param[in] DataSize The size of the buffer pointed to by Data in bytes.
1267 @param[in] Data The data buffer to set, points to an array of
1268 EFI_IPv4_ADDRESS instances.
1269
1270 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1271 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
1272 under the current policy.
1273 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
1274 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
1275 @retval EFI_ABORTED The DNS server addresses to be set equal the current
1276 configuration.
1277 @retval EFI_SUCCESS The specified configuration data for the EFI IPv4
1278 network stack was set.
1279
1280 **/
1281 EFI_STATUS
1282 Ip4Config2SetDnsServer (
1283 IN IP4_CONFIG2_INSTANCE *Instance,
1284 IN UINTN DataSize,
1285 IN VOID *Data
1286 )
1287 {
1288 UINTN OldIndex;
1289 UINTN NewIndex;
1290 UINTN Index1;
1291 EFI_IPv4_ADDRESS *OldDns;
1292 EFI_IPv4_ADDRESS *NewDns;
1293 UINTN OldDnsCount;
1294 UINTN NewDnsCount;
1295 IP4_CONFIG2_DATA_ITEM *Item;
1296 BOOLEAN OneAdded;
1297 VOID *Tmp;
1298 IP4_ADDR DnsAddress;
1299
1300 if ((DataSize % sizeof (EFI_IPv4_ADDRESS) != 0) || (DataSize == 0)) {
1301 return EFI_BAD_BUFFER_SIZE;
1302 }
1303
1304 if (Instance->Policy != Ip4Config2PolicyStatic) {
1305 return EFI_WRITE_PROTECTED;
1306 }
1307
1308 Item = &Instance->DataItem[Ip4Config2DataTypeDnsServer];
1309 NewDns = (EFI_IPv4_ADDRESS *) Data;
1310 OldDns = Item->Data.DnsServers;
1311 NewDnsCount = DataSize / sizeof (EFI_IPv4_ADDRESS);
1312 OldDnsCount = Item->DataSize / sizeof (EFI_IPv4_ADDRESS);
1313 OneAdded = FALSE;
1314
1315 if (NewDnsCount != OldDnsCount) {
1316 Tmp = AllocatePool (DataSize);
1317 if (Tmp == NULL) {
1318 return EFI_OUT_OF_RESOURCES;
1319 }
1320 } else {
1321 Tmp = NULL;
1322 }
1323
1324 for (NewIndex = 0; NewIndex < NewDnsCount; NewIndex++) {
1325 CopyMem (&DnsAddress, NewDns + NewIndex, sizeof (IP4_ADDR));
1326
1327 if (!NetIp4IsUnicast (NTOHL (DnsAddress), 0)) {
1328 //
1329 // The dns server address must be unicast.
1330 //
1331 FreePool (Tmp);
1332 return EFI_INVALID_PARAMETER;
1333 }
1334
1335 for (Index1 = NewIndex + 1; Index1 < NewDnsCount; Index1++) {
1336 if (EFI_IP4_EQUAL (NewDns + NewIndex, NewDns + Index1)) {
1337 FreePool (Tmp);
1338 return EFI_INVALID_PARAMETER;
1339 }
1340 }
1341
1342 if (OneAdded) {
1343 //
1344 // If any address in the new setting is not in the old settings, skip the
1345 // comparision below.
1346 //
1347 continue;
1348 }
1349
1350 for (OldIndex = 0; OldIndex < OldDnsCount; OldIndex++) {
1351 if (EFI_IP4_EQUAL (NewDns + NewIndex, OldDns + OldIndex)) {
1352 //
1353 // If found break out.
1354 //
1355 break;
1356 }
1357 }
1358
1359 if (OldIndex == OldDnsCount) {
1360 OneAdded = TRUE;
1361 }
1362 }
1363
1364 if (!OneAdded && (DataSize == Item->DataSize)) {
1365 //
1366 // No new item is added and the size is the same.
1367 //
1368 Item->Status = EFI_SUCCESS;
1369 return EFI_ABORTED;
1370 } else {
1371 if (Tmp != NULL) {
1372 if (Item->Data.Ptr != NULL) {
1373 FreePool (Item->Data.Ptr);
1374 }
1375 Item->Data.Ptr = Tmp;
1376 }
1377
1378 CopyMem (Item->Data.Ptr, Data, DataSize);
1379 Item->DataSize = DataSize;
1380 Item->Status = EFI_SUCCESS;
1381 return EFI_SUCCESS;
1382 }
1383
1384 }
1385
1386 /**
1387 Generate the operational state of the interface this IP4 config2 instance manages
1388 and output in EFI_IP4_CONFIG2_INTERFACE_INFO.
1389
1390 @param[in] IpSb The pointer to the IP4 service binding instance.
1391 @param[out] IfInfo The pointer to the IP4 config2 interface information structure.
1392
1393 **/
1394 VOID
1395 Ip4Config2InitIfInfo (
1396 IN IP4_SERVICE *IpSb,
1397 OUT EFI_IP4_CONFIG2_INTERFACE_INFO *IfInfo
1398 )
1399 {
1400 IfInfo->Name[0] = L'e';
1401 IfInfo->Name[1] = L't';
1402 IfInfo->Name[2] = L'h';
1403 IfInfo->Name[3] = (CHAR16) (L'0' + IpSb->Ip4Config2Instance.IfIndex);
1404 IfInfo->Name[4] = 0;
1405
1406 IfInfo->IfType = IpSb->SnpMode.IfType;
1407 IfInfo->HwAddressSize = IpSb->SnpMode.HwAddressSize;
1408 CopyMem (&IfInfo->HwAddress, &IpSb->SnpMode.CurrentAddress, IfInfo->HwAddressSize);
1409 }
1410
1411 /**
1412 The event handle routine when DHCPv4 process is finished or is updated.
1413
1414 @param[in] Event Not used.
1415 @param[in] Context The pointer to the IP4 configuration instance data.
1416
1417 **/
1418 VOID
1419 EFIAPI
1420 Ip4Config2OnDhcp4Event (
1421 IN EFI_EVENT Event,
1422 IN VOID *Context
1423 )
1424 {
1425 return ;
1426 }
1427
1428
1429 /**
1430 Set the configuration for the EFI IPv4 network stack running on the communication
1431 device this EFI_IP4_CONFIG2_PROTOCOL instance manages.
1432
1433 This function is used to set the configuration data of type DataType for the EFI
1434 IPv4 network stack that is running on the communication device that this EFI IPv4
1435 Configuration Protocol instance manages.
1436
1437 DataSize is used to calculate the count of structure instances in the Data for
1438 a DataType in which multiple structure instances are allowed.
1439
1440 This function is always non-blocking. When setting some type of configuration data,
1441 an asynchronous process is invoked to check the correctness of the data, such as
1442 performing Duplicate Address Detection on the manually set local IPv4 addresses.
1443 EFI_NOT_READY is returned immediately to indicate that such an asynchronous process
1444 is invoked, and the process is not finished yet. The caller wanting to get the result
1445 of the asynchronous process is required to call RegisterDataNotify() to register an
1446 event on the specified configuration data. Once the event is signaled, the caller
1447 can call GetData() to obtain the configuration data and know the result.
1448 For other types of configuration data that do not require an asynchronous configuration
1449 process, the result of the operation is immediately returned.
1450
1451 @param[in] This The pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
1452 @param[in] DataType The type of data to set.
1453 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
1454 @param[in] Data The data buffer to set. The type of the data buffer is
1455 associated with the DataType.
1456
1457 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1458 network stack was set successfully.
1459 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
1460 - This is NULL.
1461 - Data is NULL.
1462 - One or more fields in Data do not match the requirement of the
1463 data type indicated by DataType.
1464 @retval EFI_WRITE_PROTECTED The specified configuration data is read-only or the specified
1465 configuration data cannot be set under the current policy.
1466 @retval EFI_ACCESS_DENIED Another set operation on the specified configuration
1467 data is already in process.
1468 @retval EFI_NOT_READY An asynchronous process was invoked to set the specified
1469 configuration data, and the process is not finished yet.
1470 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type
1471 indicated by DataType.
1472 @retval EFI_UNSUPPORTED This DataType is not supported.
1473 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
1474 @retval EFI_DEVICE_ERROR An unexpected system error or network error occurred.
1475
1476 **/
1477 EFI_STATUS
1478 EFIAPI
1479 EfiIp4Config2SetData (
1480 IN EFI_IP4_CONFIG2_PROTOCOL *This,
1481 IN EFI_IP4_CONFIG2_DATA_TYPE DataType,
1482 IN UINTN DataSize,
1483 IN VOID *Data
1484 )
1485 {
1486 EFI_TPL OldTpl;
1487 EFI_STATUS Status;
1488 IP4_CONFIG2_INSTANCE *Instance;
1489 IP4_SERVICE *IpSb;
1490
1491 if ((This == NULL) || (Data == NULL)) {
1492 return EFI_INVALID_PARAMETER;
1493 }
1494
1495 if (DataType >= Ip4Config2DataTypeMaximum) {
1496 return EFI_UNSUPPORTED;
1497 }
1498
1499 Instance = IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This);
1500 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
1501 NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE);
1502
1503
1504 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1505
1506 Status = Instance->DataItem[DataType].Status;
1507 if (Status != EFI_NOT_READY) {
1508
1509 if (Instance->DataItem[DataType].SetData == NULL) {
1510 //
1511 // This type of data is readonly.
1512 //
1513 Status = EFI_WRITE_PROTECTED;
1514 } else {
1515
1516 Status = Instance->DataItem[DataType].SetData (Instance, DataSize, Data);
1517 if (!EFI_ERROR (Status)) {
1518 //
1519 // Fire up the events registered with this type of data.
1520 //
1521 NetMapIterate (&Instance->DataItem[DataType].EventMap, Ip4Config2SignalEvent, NULL);
1522 Ip4Config2WriteConfigData (IpSb->MacString, Instance);
1523 } else if (Status == EFI_ABORTED) {
1524 //
1525 // The SetData is aborted because the data to set is the same with
1526 // the one maintained.
1527 //
1528 Status = EFI_SUCCESS;
1529 NetMapIterate (&Instance->DataItem[DataType].EventMap, Ip4Config2SignalEvent, NULL);
1530 }
1531 }
1532 } else {
1533 //
1534 // Another asynchornous process is on the way.
1535 //
1536 Status = EFI_ACCESS_DENIED;
1537 }
1538
1539 gBS->RestoreTPL (OldTpl);
1540
1541 return Status;
1542 }
1543
1544 /**
1545 Get the configuration data for the EFI IPv4 network stack running on the communication
1546 device that this EFI_IP4_CONFIG2_PROTOCOL instance manages.
1547
1548 This function returns the configuration data of type DataType for the EFI IPv4 network
1549 stack running on the communication device that this EFI IPv4 Configuration Protocol instance
1550 manages.
1551
1552 The caller is responsible for allocating the buffer used to return the specified
1553 configuration data. The required size will be returned to the caller if the size of
1554 the buffer is too small.
1555
1556 EFI_NOT_READY is returned if the specified configuration data is not ready due to an
1557 asynchronous configuration process already in progress. The caller can call RegisterDataNotify()
1558 to register an event on the specified configuration data. Once the asynchronous configuration
1559 process is finished, the event will be signaled, and a subsequent GetData() call will return
1560 the specified configuration data.
1561
1562 @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
1563 @param[in] DataType The type of data to get.
1564 @param[in, out] DataSize On input, in bytes, the size of Data. On output, in bytes, the
1565 size of buffer required to store the specified configuration data.
1566 @param[in] Data The data buffer in which the configuration data is returned. The
1567 type of the data buffer is associated with the DataType.
1568 This is an optional parameter that may be NULL.
1569
1570 @retval EFI_SUCCESS The specified configuration data was obtained successfully.
1571 @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
1572 - This is NULL.
1573 - DataSize is NULL.
1574 - Data is NULL if *DataSize is not zero.
1575 @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified configuration data,
1576 and the required size is returned in DataSize.
1577 @retval EFI_NOT_READY The specified configuration data is not ready due to an
1578 asynchronous configuration process already in progress.
1579 @retval EFI_NOT_FOUND The specified configuration data is not found.
1580
1581 **/
1582 EFI_STATUS
1583 EFIAPI
1584 EfiIp4Config2GetData (
1585 IN EFI_IP4_CONFIG2_PROTOCOL *This,
1586 IN EFI_IP4_CONFIG2_DATA_TYPE DataType,
1587 IN OUT UINTN *DataSize,
1588 IN VOID *Data OPTIONAL
1589 )
1590 {
1591 EFI_TPL OldTpl;
1592 EFI_STATUS Status;
1593 IP4_CONFIG2_INSTANCE *Instance;
1594 IP4_CONFIG2_DATA_ITEM *DataItem;
1595
1596 if ((This == NULL) || (DataSize == NULL) || ((*DataSize != 0) && (Data == NULL))) {
1597 return EFI_INVALID_PARAMETER;
1598 }
1599
1600 if (DataType >= Ip4Config2DataTypeMaximum) {
1601 return EFI_NOT_FOUND;
1602 }
1603
1604 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1605
1606 Instance = IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This);
1607 DataItem = &Instance->DataItem[DataType];
1608
1609 Status = Instance->DataItem[DataType].Status;
1610 if (!EFI_ERROR (Status)) {
1611
1612 if (DataItem->GetData != NULL) {
1613
1614 Status = DataItem->GetData (Instance, DataSize, Data);
1615 } else if (*DataSize < Instance->DataItem[DataType].DataSize) {
1616 //
1617 // Update the buffer length.
1618 //
1619 *DataSize = Instance->DataItem[DataType].DataSize;
1620 Status = EFI_BUFFER_TOO_SMALL;
1621 } else {
1622
1623 *DataSize = Instance->DataItem[DataType].DataSize;
1624 CopyMem (Data, Instance->DataItem[DataType].Data.Ptr, *DataSize);
1625 }
1626 }
1627
1628 gBS->RestoreTPL (OldTpl);
1629
1630 return Status;
1631 }
1632
1633 /**
1634 Register an event that is signaled whenever a configuration process on the specified
1635 configuration data is done.
1636
1637 This function registers an event that is to be signaled whenever a configuration
1638 process on the specified configuration data is performed. An event can be registered
1639 for a different DataType simultaneously. The caller is responsible for determining
1640 which type of configuration data causes the signaling of the event in such an event.
1641
1642 @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
1643 @param[in] DataType The type of data to unregister the event for.
1644 @param[in] Event The event to register.
1645
1646 @retval EFI_SUCCESS The notification event for the specified configuration data is
1647 registered.
1648 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
1649 @retval EFI_UNSUPPORTED The configuration data type specified by DataType is not
1650 supported.
1651 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
1652 @retval EFI_ACCESS_DENIED The Event is already registered for the DataType.
1653
1654 **/
1655 EFI_STATUS
1656 EFIAPI
1657 EfiIp4Config2RegisterDataNotify (
1658 IN EFI_IP4_CONFIG2_PROTOCOL *This,
1659 IN EFI_IP4_CONFIG2_DATA_TYPE DataType,
1660 IN EFI_EVENT Event
1661 )
1662 {
1663 EFI_TPL OldTpl;
1664 EFI_STATUS Status;
1665 IP4_CONFIG2_INSTANCE *Instance;
1666 NET_MAP *EventMap;
1667 NET_MAP_ITEM *Item;
1668
1669 if ((This == NULL) || (Event == NULL)) {
1670 return EFI_INVALID_PARAMETER;
1671 }
1672
1673 if (DataType >= Ip4Config2DataTypeMaximum) {
1674 return EFI_UNSUPPORTED;
1675 }
1676
1677 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1678
1679 Instance = IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This);
1680 EventMap = &Instance->DataItem[DataType].EventMap;
1681
1682 //
1683 // Check whether this event is already registered for this DataType.
1684 //
1685 Item = NetMapFindKey (EventMap, Event);
1686 if (Item == NULL) {
1687
1688 Status = NetMapInsertTail (EventMap, Event, NULL);
1689
1690 if (EFI_ERROR (Status)) {
1691
1692 Status = EFI_OUT_OF_RESOURCES;
1693 }
1694
1695 } else {
1696
1697 Status = EFI_ACCESS_DENIED;
1698 }
1699
1700 gBS->RestoreTPL (OldTpl);
1701
1702 return Status;
1703 }
1704
1705 /**
1706 Remove a previously registered event for the specified configuration data.
1707
1708 @param This The pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
1709 @param DataType The type of data to remove from the previously
1710 registered event.
1711 @param Event The event to be unregistered.
1712
1713 @retval EFI_SUCCESS The event registered for the specified
1714 configuration data was removed.
1715 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
1716 @retval EFI_NOT_FOUND The Event has not been registered for the
1717 specified DataType.
1718
1719 **/
1720 EFI_STATUS
1721 EFIAPI
1722 EfiIp4Config2UnregisterDataNotify (
1723 IN EFI_IP4_CONFIG2_PROTOCOL *This,
1724 IN EFI_IP4_CONFIG2_DATA_TYPE DataType,
1725 IN EFI_EVENT Event
1726 )
1727 {
1728 EFI_TPL OldTpl;
1729 EFI_STATUS Status;
1730 IP4_CONFIG2_INSTANCE *Instance;
1731 NET_MAP_ITEM *Item;
1732
1733 if ((This == NULL) || (Event == NULL)) {
1734 return EFI_INVALID_PARAMETER;
1735 }
1736
1737 if (DataType >= Ip4Config2DataTypeMaximum) {
1738 return EFI_NOT_FOUND;
1739 }
1740
1741 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1742
1743 Instance = IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This);
1744
1745 Item = NetMapFindKey (&Instance->DataItem[DataType].EventMap, Event);
1746 if (Item != NULL) {
1747
1748 NetMapRemoveItem (&Instance->DataItem[DataType].EventMap, Item, NULL);
1749 Status = EFI_SUCCESS;
1750 } else {
1751
1752 Status = EFI_NOT_FOUND;
1753 }
1754
1755 gBS->RestoreTPL (OldTpl);
1756
1757 return Status;
1758 }
1759
1760 /**
1761 Initialize an IP4_CONFIG2_INSTANCE.
1762
1763 @param[out] Instance The buffer of IP4_CONFIG2_INSTANCE to be initialized.
1764
1765 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
1766 @retval EFI_SUCCESS The IP4_CONFIG2_INSTANCE initialized successfully.
1767
1768 **/
1769 EFI_STATUS
1770 Ip4Config2InitInstance (
1771 OUT IP4_CONFIG2_INSTANCE *Instance
1772 )
1773 {
1774 IP4_SERVICE *IpSb;
1775 IP4_CONFIG2_INSTANCE *TmpInstance;
1776 LIST_ENTRY *Entry;
1777 EFI_STATUS Status;
1778 UINTN Index;
1779 UINT16 IfIndex;
1780 IP4_CONFIG2_DATA_ITEM *DataItem;
1781
1782
1783 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
1784
1785 Instance->Signature = IP4_CONFIG2_INSTANCE_SIGNATURE;
1786
1787
1788 //
1789 // Determine the index of this interface.
1790 //
1791 IfIndex = 0;
1792 NET_LIST_FOR_EACH (Entry, &mIp4Config2InstanceList) {
1793 TmpInstance = NET_LIST_USER_STRUCT_S (Entry, IP4_CONFIG2_INSTANCE, Link, IP4_CONFIG2_INSTANCE_SIGNATURE);
1794
1795 if (TmpInstance->IfIndex > IfIndex) {
1796 //
1797 // There is a sequence hole because some interface is down.
1798 //
1799 break;
1800 }
1801
1802 IfIndex++;
1803 }
1804
1805 Instance->IfIndex = IfIndex;
1806 NetListInsertBefore (Entry, &Instance->Link);
1807
1808 for (Index = 0; Index < Ip4Config2DataTypeMaximum; Index++) {
1809 //
1810 // Initialize the event map for each data item.
1811 //
1812 NetMapInit (&Instance->DataItem[Index].EventMap);
1813 }
1814
1815
1816 //
1817 // Initialize each data type: associate storage and set data size for the
1818 // fixed size data types, hook the SetData function, set the data attribute.
1819 //
1820 DataItem = &Instance->DataItem[Ip4Config2DataTypeInterfaceInfo];
1821 DataItem->GetData = Ip4Config2GetIfInfo;
1822 DataItem->Data.Ptr = &Instance->InterfaceInfo;
1823 DataItem->DataSize = sizeof (Instance->InterfaceInfo);
1824 SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED | DATA_ATTRIB_VOLATILE);
1825 Ip4Config2InitIfInfo (IpSb, &Instance->InterfaceInfo);
1826
1827 DataItem = &Instance->DataItem[Ip4Config2DataTypePolicy];
1828 DataItem->SetData = Ip4Config2SetPolicy;
1829 DataItem->Data.Ptr = &Instance->Policy;
1830 DataItem->DataSize = sizeof (Instance->Policy);
1831 Instance->Policy = Ip4Config2PolicyDhcp;
1832 SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED);
1833
1834 DataItem = &Instance->DataItem[Ip4Config2DataTypeManualAddress];
1835 DataItem->SetData = Ip4Config2SetMaunualAddress;
1836 DataItem->Status = EFI_NOT_FOUND;
1837
1838 DataItem = &Instance->DataItem[Ip4Config2DataTypeGateway];
1839 DataItem->SetData = Ip4Config2SetGateway;
1840 DataItem->Status = EFI_NOT_FOUND;
1841
1842 DataItem = &Instance->DataItem[Ip4Config2DataTypeDnsServer];
1843 DataItem->SetData = Ip4Config2SetDnsServer;
1844 DataItem->Status = EFI_NOT_FOUND;
1845
1846 //
1847 // Create the event used for DHCP.
1848 //
1849 Status = gBS->CreateEvent (
1850 EVT_NOTIFY_SIGNAL,
1851 TPL_CALLBACK,
1852 Ip4Config2OnDhcp4Event,
1853 Instance,
1854 &Instance->Dhcp4Event
1855 );
1856 ASSERT_EFI_ERROR (Status);
1857
1858 Instance->Configured = TRUE;
1859
1860 //
1861 // Try to read the config data from NV variable.
1862 //
1863 Status = Ip4Config2ReadConfigData (IpSb->MacString, Instance);
1864 if (Status == EFI_NOT_FOUND) {
1865 Status = Ip4Config2WriteConfigData (IpSb->MacString, Instance);
1866 }
1867
1868 if (EFI_ERROR (Status)) {
1869 return Status;
1870 }
1871
1872 //
1873 // Try to set the configured parameter.
1874 //
1875 for (Index = Ip4Config2DataTypePolicy; Index < Ip4Config2DataTypeMaximum; Index++) {
1876 DataItem = &IpSb->Ip4Config2Instance.DataItem[Index];
1877 if (DataItem->Data.Ptr != NULL) {
1878 DataItem->SetData (
1879 &IpSb->Ip4Config2Instance,
1880 DataItem->DataSize,
1881 DataItem->Data.Ptr
1882 );
1883 }
1884 }
1885
1886 Instance->Ip4Config2.SetData = EfiIp4Config2SetData;
1887 Instance->Ip4Config2.GetData = EfiIp4Config2GetData;
1888 Instance->Ip4Config2.RegisterDataNotify = EfiIp4Config2RegisterDataNotify;
1889 Instance->Ip4Config2.UnregisterDataNotify = EfiIp4Config2UnregisterDataNotify;
1890
1891 //
1892 // Publish the IP4 configuration form
1893 //
1894 return Ip4Config2FormInit (Instance);
1895 }
1896
1897
1898 /**
1899 Release an IP4_CONFIG2_INSTANCE.
1900
1901 @param[in, out] Instance The buffer of IP4_CONFIG2_INSTANCE to be freed.
1902
1903 **/
1904 VOID
1905 Ip4Config2CleanInstance (
1906 IN OUT IP4_CONFIG2_INSTANCE *Instance
1907 )
1908 {
1909 UINTN Index;
1910 IP4_CONFIG2_DATA_ITEM *DataItem;
1911
1912 if (Instance->DeclineAddress != NULL) {
1913 FreePool (Instance->DeclineAddress);
1914 }
1915
1916 if (!Instance->Configured) {
1917 return ;
1918 }
1919
1920 if (Instance->Dhcp4Handle != NULL) {
1921
1922 Ip4Config2DestroyDhcp4 (Instance);
1923 }
1924
1925 //
1926 // Close the event.
1927 //
1928 if (Instance->Dhcp4Event != NULL) {
1929 gBS->CloseEvent (Instance->Dhcp4Event);
1930 }
1931
1932 for (Index = 0; Index < Ip4Config2DataTypeMaximum; Index++) {
1933
1934 DataItem = &Instance->DataItem[Index];
1935
1936 if (!DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED)) {
1937 if (DataItem->Data.Ptr != NULL) {
1938 FreePool (DataItem->Data.Ptr);
1939 }
1940 DataItem->Data.Ptr = NULL;
1941 DataItem->DataSize = 0;
1942 }
1943
1944 NetMapClean (&Instance->DataItem[Index].EventMap);
1945 }
1946
1947 Ip4Config2FormUnload (Instance);
1948
1949 RemoveEntryList (&Instance->Link);
1950 }
1951