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