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