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