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