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