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