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