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 |
18 | LIST_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 |
28 | VOID\r |
29 | EFIAPI\r |
30 | Ip4Config2OnDhcp4SbInstalled (\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 |
44 | EFI_STATUS\r |
45 | Ip4Config2DestroyDhcp4 (\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 |
98 | EFI_STATUS\r |
99 | Ip4StartAutoConfig (\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 |
112 | VOID\r |
113 | Ip4Config2OnPolicyChanged (\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 |
182 | EFI_STATUS\r |
183 | EFIAPI\r |
184 | Ip4Config2SignalEvent (\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 |
209 | EFI_STATUS\r |
210 | Ip4Config2ReadConfigData (\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 |
325 | EFI_STATUS\r |
326 | Ip4Config2WriteConfigData (\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 |
404 | EFI_STATUS\r |
405 | Ip4Config2BuildDefaultRouteTable (\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 |
458 | VOID\r |
459 | EFIAPI\r |
460 | Ip4Config2OnDhcp4SbInstalled (\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 |
490 | EFI_STATUS\r |
491 | Ip4Config2SetDefaultAddr (\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 |
611 | EFI_STATUS\r |
612 | Ip4Config2SetDefaultIf (\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 |
652 | VOID\r |
653 | Ip4Config2CleanDhcp4 (\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 |
702 | VOID\r |
703 | EFIAPI\r |
704 | Ip4Config2OnDhcp4Complete (\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 |
741 | Exit:\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 |
758 | EFI_STATUS\r |
759 | Ip4StartAutoConfig (\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 |
904 | EFI_STATUS\r |
905 | Ip4Config2GetIfInfo (\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 |
973 | EFI_STATUS\r |
974 | Ip4Config2SetPolicy (\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 |
1079 | EFI_STATUS\r |
1080 | Ip4Config2SetMaunualAddress (\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 |
1133 | ON_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 |
1166 | EFI_STATUS\r |
1167 | Ip4Config2SetGateway (\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 |
1299 | EFI_STATUS\r |
1300 | Ip4Config2SetDnsServer (\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 |
1412 | VOID\r |
1413 | Ip4Config2InitIfInfo (\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 |
1436 | VOID\r |
1437 | EFIAPI\r |
1438 | Ip4Config2OnDhcp4Event (\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 |
1495 | EFI_STATUS\r |
1496 | EFIAPI\r |
1497 | EfiIp4Config2SetData (\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 |
1600 | EFI_STATUS\r |
1601 | EFIAPI\r |
1602 | EfiIp4Config2GetData (\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 |
1673 | EFI_STATUS\r |
1674 | EFIAPI\r |
1675 | EfiIp4Config2RegisterDataNotify (\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 |
1738 | EFI_STATUS\r |
1739 | EFIAPI\r |
1740 | EfiIp4Config2UnregisterDataNotify (\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 |
1787 | EFI_STATUS\r |
1788 | Ip4Config2InitInstance (\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 |
1922 | VOID\r |
1923 | Ip4Config2CleanInstance (\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 |