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