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