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