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