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