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