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