]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigNv.c
Per UEFI spec, on CallBack action EFI_BROWSER_ACTION_CHANGING, the return value of...
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4ConfigDxe / Ip4ConfigNv.c
... / ...
CommitLineData
1/** @file\r
2 Helper functions for configuring or getting the parameters relating to Ip4.\r
3\r
4Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "Ip4ConfigNv.h"\r
16#include "NicIp4Variable.h"\r
17\r
18/**\r
19 Calculate the prefix length of the IPv4 subnet mask.\r
20\r
21 @param[in] SubnetMask The IPv4 subnet mask.\r
22\r
23 @return The prefix length of the subnet mask.\r
24 @retval 0 Other errors as indicated.\r
25**/\r
26UINT8\r
27GetSubnetMaskPrefixLength (\r
28 IN EFI_IPv4_ADDRESS *SubnetMask\r
29 )\r
30{\r
31 UINT8 Len;\r
32 UINT32 ReverseMask;\r
33\r
34 //\r
35 // The SubnetMask is in network byte order.\r
36 //\r
37 ReverseMask = SwapBytes32 (*(UINT32 *)&SubnetMask[0]);\r
38\r
39 //\r
40 // Reverse it.\r
41 //\r
42 ReverseMask = ~ReverseMask;\r
43\r
44 if ((ReverseMask & (ReverseMask + 1)) != 0) {\r
45 return 0;\r
46 }\r
47\r
48 Len = 0;\r
49\r
50 while (ReverseMask != 0) {\r
51 ReverseMask = ReverseMask >> 1;\r
52 Len++;\r
53 }\r
54\r
55 return (UINT8) (32 - Len);\r
56}\r
57\r
58/**\r
59 Convert the decimal dotted IPv4 address into the binary IPv4 address.\r
60\r
61 @param[in] Str The UNICODE string.\r
62 @param[out] Ip The storage to return the IPv4 address.\r
63\r
64 @retval EFI_SUCCESS The binary IP address is returned in Ip.\r
65 @retval EFI_INVALID_PARAMETER The IP string is malformatted.\r
66**/\r
67EFI_STATUS\r
68Ip4StrToIp (\r
69 IN CHAR16 *Str,\r
70 OUT EFI_IPv4_ADDRESS *Ip\r
71 )\r
72{\r
73 UINTN Index;\r
74 UINTN Number;\r
75\r
76 Index = 0;\r
77\r
78 while (*Str != L'\0') {\r
79\r
80 if (Index > 3) {\r
81 return EFI_INVALID_PARAMETER;\r
82 }\r
83\r
84 Number = 0;\r
85 while ((*Str >= L'0') && (*Str <= L'9')) {\r
86 Number = Number * 10 + (*Str - L'0');\r
87 Str++;\r
88 }\r
89\r
90 if (Number > 0xFF) {\r
91 return EFI_INVALID_PARAMETER;\r
92 }\r
93\r
94 Ip->Addr[Index] = (UINT8) Number;\r
95\r
96 if ((*Str != L'\0') && (*Str != L'.')) {\r
97 //\r
98 // The current character should be either the NULL terminator or\r
99 // the dot delimiter.\r
100 //\r
101 return EFI_INVALID_PARAMETER;\r
102 }\r
103\r
104 if (*Str == L'.') {\r
105 //\r
106 // Skip the delimiter.\r
107 //\r
108 Str++;\r
109 }\r
110\r
111 Index++;\r
112 }\r
113\r
114 if (Index != 4) {\r
115 return EFI_INVALID_PARAMETER;\r
116 }\r
117\r
118 return EFI_SUCCESS;\r
119}\r
120\r
121/**\r
122 Convert the IPv4 address into a dotted string.\r
123\r
124 @param[in] Ip The IPv4 address.\r
125 @param[out] Str The dotted IP string.\r
126**/\r
127VOID\r
128Ip4ConfigIpToStr (\r
129 IN EFI_IPv4_ADDRESS *Ip,\r
130 OUT CHAR16 *Str\r
131 )\r
132{\r
133 UnicodeSPrint (Str, 2 * IP4_STR_MAX_SIZE, L"%d.%d.%d.%d", Ip->Addr[0], Ip->Addr[1], Ip->Addr[2], Ip->Addr[3]);\r
134}\r
135\r
136\r
137/**\r
138 Convert the network configuration data into the IFR data.\r
139\r
140 @param[in] Ip4ConfigInstance The IP4Config instance\r
141 @param[out] IfrFormNvData The IFR nv data.\r
142**/\r
143VOID\r
144Ip4ConfigConvertDeviceConfigDataToIfrNvData (\r
145 IN IP4_CONFIG_INSTANCE *Ip4ConfigInstance,\r
146 OUT IP4_CONFIG_IFR_NVDATA *IfrFormNvData\r
147 )\r
148{\r
149 NIC_IP4_CONFIG_INFO *NicConfig;\r
150\r
151 NicConfig = EfiNicIp4ConfigGetInfo (Ip4ConfigInstance);\r
152 if (NicConfig != NULL) {\r
153 IfrFormNvData->Configure = 1;\r
154 Ip4ConfigInstance->Ip4ConfigCallbackInfo.Configured = TRUE;\r
155 if (NicConfig->Source == IP4_CONFIG_SOURCE_DHCP) {\r
156 IfrFormNvData->DhcpEnable = 1;\r
157 Ip4ConfigInstance->Ip4ConfigCallbackInfo.DhcpEnabled = TRUE;\r
158 } else {\r
159 IfrFormNvData->DhcpEnable = 0;\r
160 Ip4ConfigIpToStr (&NicConfig->Ip4Info.StationAddress, IfrFormNvData->StationAddress);\r
161 Ip4ConfigIpToStr (&NicConfig->Ip4Info.SubnetMask, IfrFormNvData->SubnetMask);\r
162 Ip4ConfigIpToStr (&NicConfig->Ip4Info.RouteTable[1].GatewayAddress, IfrFormNvData->GatewayAddress);\r
163\r
164 Ip4ConfigInstance->Ip4ConfigCallbackInfo.DhcpEnabled = FALSE;\r
165 CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.LocalIp, &NicConfig->Ip4Info.StationAddress, sizeof (EFI_IPv4_ADDRESS));\r
166 CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.SubnetMask, &NicConfig->Ip4Info.SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
167 CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.Gateway, &NicConfig->Ip4Info.RouteTable[1].GatewayAddress, sizeof (EFI_IPv4_ADDRESS));\r
168 }\r
169\r
170 FreePool (NicConfig);\r
171 } else {\r
172 IfrFormNvData->Configure = 0;\r
173 Ip4ConfigInstance->Ip4ConfigCallbackInfo.Configured = FALSE;\r
174 }\r
175}\r
176\r
177/**\r
178 Convert the IFR data into the network configuration data and set the IP\r
179 configure parameters for the NIC.\r
180\r
181 @param[in] IfrFormNvData The IFR NV data.\r
182 @param[in, out] Ip4ConfigInstance The IP4Config instance.\r
183\r
184 @retval EFI_SUCCESS The configure parameter for this NIC was\r
185 set successfully.\r
186 @retval EFI_ALREADY_STARTED There is a pending auto configuration.\r
187 @retval EFI_NOT_FOUND No auto configure parameter is found.\r
188\r
189**/\r
190EFI_STATUS\r
191Ip4ConfigConvertIfrNvDataToDeviceConfigData (\r
192 IN IP4_CONFIG_IFR_NVDATA *IfrFormNvData,\r
193 IN OUT IP4_CONFIG_INSTANCE *Ip4ConfigInstance\r
194 )\r
195{\r
196 EFI_STATUS Status;\r
197 EFI_IP_ADDRESS HostIp;\r
198 EFI_IP_ADDRESS SubnetMask;\r
199 EFI_IP_ADDRESS Gateway;\r
200 EFI_INPUT_KEY Key;\r
201 NIC_IP4_CONFIG_INFO *NicInfo;\r
202 EFI_IP_ADDRESS Ip;\r
203\r
204 ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo, sizeof (IP4_SETTING_INFO));\r
205\r
206 Ip4ConfigInstance->Ip4ConfigCallbackInfo.Configured = IfrFormNvData->Configure;\r
207 Ip4ConfigInstance->Ip4ConfigCallbackInfo.DhcpEnabled = IfrFormNvData->DhcpEnable;\r
208 Ip4StrToIp (IfrFormNvData->StationAddress, &Ip4ConfigInstance->Ip4ConfigCallbackInfo.LocalIp);\r
209 Ip4StrToIp (IfrFormNvData->SubnetMask, &Ip4ConfigInstance->Ip4ConfigCallbackInfo.SubnetMask);\r
210 Ip4StrToIp (IfrFormNvData->GatewayAddress, &Ip4ConfigInstance->Ip4ConfigCallbackInfo.Gateway);\r
211\r
212 if (!Ip4ConfigInstance->Ip4ConfigCallbackInfo.Configured) {\r
213 //\r
214 // Clear the variable\r
215 //\r
216 ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo, sizeof (IP4_SETTING_INFO));\r
217\r
218 Status = EfiNicIp4ConfigSetInfo (Ip4ConfigInstance, NULL, TRUE);\r
219 if (Status == EFI_NOT_FOUND) {\r
220 return EFI_SUCCESS;\r
221 }\r
222\r
223 return Status;\r
224 }\r
225\r
226 NicInfo = AllocateZeroPool (sizeof (NIC_IP4_CONFIG_INFO) + 2 * sizeof (EFI_IP4_ROUTE_TABLE));\r
227 ASSERT (NicInfo != NULL);\r
228\r
229 NicInfo->Ip4Info.RouteTable = (EFI_IP4_ROUTE_TABLE *) (NicInfo + 1);\r
230\r
231 if (!Ip4ConfigInstance->Ip4ConfigCallbackInfo.DhcpEnabled) {\r
232 CopyMem (&HostIp.v4, &Ip4ConfigInstance->Ip4ConfigCallbackInfo.LocalIp, sizeof (HostIp.v4));\r
233 CopyMem (&SubnetMask.v4, &Ip4ConfigInstance->Ip4ConfigCallbackInfo.SubnetMask, sizeof (SubnetMask.v4));\r
234 CopyMem (&Gateway.v4, &Ip4ConfigInstance->Ip4ConfigCallbackInfo.Gateway, sizeof (Gateway.v4));\r
235\r
236 if (!NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {\r
237 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);\r
238 return EFI_INVALID_PARAMETER;\r
239 }\r
240 if (EFI_IP4_EQUAL (&SubnetMask, &mZeroIp4Addr)) {\r
241 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL);\r
242 return EFI_INVALID_PARAMETER;\r
243 }\r
244\r
245 if ((Gateway.Addr[0] != 0)) {\r
246 if (SubnetMask.Addr[0] == 0) {\r
247 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Gateway address is set but subnet mask is zero.", NULL);\r
248 return EFI_INVALID_PARAMETER;\r
249\r
250 } else if (!IP4_NET_EQUAL (HostIp.Addr[0], Gateway.Addr[0], SubnetMask.Addr[0])) {\r
251 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Local IP and Gateway are not in the same subnet.", NULL);\r
252 return EFI_INVALID_PARAMETER; }\r
253 }\r
254\r
255 NicInfo->Source = IP4_CONFIG_SOURCE_STATIC;\r
256 NicInfo->Ip4Info.RouteTableSize = 2;\r
257\r
258 CopyMem (&NicInfo->Ip4Info.StationAddress, &HostIp.v4, sizeof (EFI_IPv4_ADDRESS));\r
259 CopyMem (&NicInfo->Ip4Info.SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS));\r
260\r
261 Ip.Addr[0] = HostIp.Addr[0] & SubnetMask.Addr[0];\r
262\r
263 CopyMem (&NicInfo->Ip4Info.RouteTable[0].SubnetAddress, &Ip.v4, sizeof (EFI_IPv4_ADDRESS));\r
264 CopyMem (&NicInfo->Ip4Info.RouteTable[0].SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS));\r
265 CopyMem (&NicInfo->Ip4Info.RouteTable[1].GatewayAddress, &Gateway.v4, sizeof (EFI_IPv4_ADDRESS));\r
266\r
267 } else {\r
268 NicInfo->Source = IP4_CONFIG_SOURCE_DHCP;\r
269 ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.LocalIp, sizeof (EFI_IPv4_ADDRESS));\r
270 ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
271 ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.Gateway, sizeof (EFI_IPv4_ADDRESS));\r
272 }\r
273\r
274 NicInfo->Perment = TRUE;\r
275 CopyMem (&NicInfo->NicAddr, &Ip4ConfigInstance->NicAddr, sizeof (NIC_ADDR));\r
276\r
277 return EfiNicIp4ConfigSetInfo (Ip4ConfigInstance, NicInfo, TRUE);\r
278}\r
279\r
280/**\r
281 This function allows the caller to request the current\r
282 configuration for one or more named elements. The resulting\r
283 string is in <ConfigAltResp> format. Any and all alternative\r
284 configuration strings shall also be appended to the end of the\r
285 current configuration string. If they are, they must appear\r
286 after the current configuration. They must contain the same\r
287 routing (GUID, NAME, PATH) as the current configuration string.\r
288 They must have an additional description indicating the type of\r
289 alternative configuration the string represents,\r
290 "ALTCFG=<StringToken>". That <StringToken> (when\r
291 converted from Hex UNICODE to binary) is a reference to a\r
292 string in the associated string pack.\r
293\r
294 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
295 @param[in] Request A null-terminated Unicode string in\r
296 <ConfigRequest> format. Note that this\r
297 includes the routing information as well as\r
298 the configurable name / value pairs. It is\r
299 invalid for this string to be in\r
300 <MultiConfigRequest> format.\r
301 @param[out] Progress On return, points to a character in the\r
302 Request string. Points to the string's null\r
303 terminator if request was successful. Points\r
304 to the most recent "&" before the first\r
305 failing name / value pair (or the beginning\r
306 of the string if the failure is in the first\r
307 name / value pair) if the request was not\r
308 successful.\r
309 @param[out] Results A null-terminated Unicode string in\r
310 <ConfigAltResp> format which has all values\r
311 filled in for the names in the Request string.\r
312 String to be allocated by the called function.\r
313\r
314 @retval EFI_SUCCESS The Results string is filled with the\r
315 values corresponding to all requested\r
316 names.\r
317 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the\r
318 parts of the results that must be\r
319 stored awaiting possible future\r
320 protocols.\r
321 @retval EFI_NOT_FOUND Routing data doesn't match any\r
322 known driver. Progress set to the\r
323 first character in the routing header.\r
324 Note: There is no requirement that the\r
325 driver validate the routing data. It\r
326 must skip the <ConfigHdr> in order to\r
327 process the names.\r
328 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set\r
329 to most recent & before the\r
330 error or the beginning of the\r
331 string.\r
332 @retval EFI_INVALID_PARAMETER Unknown name. Progress points\r
333 to the & before the name in\r
334 question.Currently not implemented.\r
335**/\r
336EFI_STATUS\r
337EFIAPI\r
338Ip4DeviceExtractConfig (\r
339 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
340 IN CONST EFI_STRING Request,\r
341 OUT EFI_STRING *Progress,\r
342 OUT EFI_STRING *Results\r
343 )\r
344{\r
345 EFI_STATUS Status;\r
346 NIC_IP4_CONFIG_INFO *IfrDeviceNvData;\r
347 NIC_IP4_CONFIG_INFO *NicConfig;\r
348 IP4_CONFIG_INSTANCE *Ip4ConfigInstance;\r
349 IP4_CONFIG_IFR_NVDATA *IfrFormNvData;\r
350 EFI_STRING ConfigRequestHdr;\r
351 EFI_STRING ConfigRequest;\r
352 EFI_STRING DeviceResult;\r
353 EFI_STRING FormResult;\r
354 CHAR16 *StrPointer;\r
355 BOOLEAN AllocatedRequest;\r
356 UINTN Size;\r
357 UINTN BufferSize;\r
358\r
359 if (Progress == NULL || Results == NULL) {\r
360 return EFI_INVALID_PARAMETER;\r
361 }\r
362\r
363 *Progress = Request;\r
364 Size = 0;\r
365 DeviceResult = NULL;\r
366 FormResult = NULL;\r
367 ConfigRequest = NULL;\r
368 Status = EFI_SUCCESS;\r
369 AllocatedRequest = FALSE;\r
370 Ip4ConfigInstance = IP4_CONFIG_INSTANCE_FROM_CONFIG_ACCESS (This);\r
371\r
372 //\r
373 // Check Request data in <ConfigHdr>.\r
374 //\r
375 if ((Request == NULL) || HiiIsConfigHdrMatch (Request, &gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {\r
376 IfrDeviceNvData = AllocateZeroPool (NIC_ITEM_CONFIG_SIZE);\r
377 if (IfrDeviceNvData == NULL) {\r
378 return EFI_OUT_OF_RESOURCES;\r
379 }\r
380\r
381 NicConfig = EfiNicIp4ConfigGetInfo (Ip4ConfigInstance);\r
382 if (NicConfig == NULL) {\r
383 return EFI_NOT_FOUND;\r
384 }\r
385 CopyMem (IfrDeviceNvData, NicConfig, SIZEOF_NIC_IP4_CONFIG_INFO (NicConfig));\r
386 FreePool (NicConfig);\r
387\r
388 ConfigRequest = Request;\r
389 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
390 //\r
391 // Request has no request element, construct full request string.\r
392 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
393 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
394 //\r
395 ConfigRequestHdr = HiiConstructConfigHdr (&gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE, Ip4ConfigInstance->ChildHandle);\r
396 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
397 ConfigRequest = AllocateZeroPool (Size);\r
398 ASSERT (ConfigRequest != NULL);\r
399 AllocatedRequest = TRUE;\r
400 BufferSize = NIC_ITEM_CONFIG_SIZE;\r
401 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
402 FreePool (ConfigRequestHdr);\r
403 }\r
404\r
405 //\r
406 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
407 //\r
408 Status = gHiiConfigRouting->BlockToConfig (\r
409 gHiiConfigRouting,\r
410 ConfigRequest,\r
411 (UINT8 *) IfrDeviceNvData,\r
412 NIC_ITEM_CONFIG_SIZE,\r
413 &DeviceResult,\r
414 Progress\r
415 );\r
416\r
417 FreePool (IfrDeviceNvData);\r
418 //\r
419 // Free the allocated config request string.\r
420 //\r
421 if (AllocatedRequest) {\r
422 FreePool (ConfigRequest);\r
423 ConfigRequest = NULL;\r
424 }\r
425\r
426 if (EFI_ERROR (Status)) {\r
427 goto Failure;\r
428 }\r
429 }\r
430\r
431 if ((Request == NULL) || HiiIsConfigHdrMatch (Request, &gNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {\r
432\r
433 IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG_IFR_NVDATA));\r
434 if (IfrFormNvData == NULL) {\r
435 return EFI_OUT_OF_RESOURCES;\r
436 }\r
437\r
438 Ip4ConfigConvertDeviceConfigDataToIfrNvData (Ip4ConfigInstance, IfrFormNvData);\r
439\r
440 ConfigRequest = Request;\r
441 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
442 //\r
443 // Request has no request element, construct full request string.\r
444 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
445 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
446 //\r
447 ConfigRequestHdr = HiiConstructConfigHdr (&gNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE, Ip4ConfigInstance->ChildHandle);\r
448 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
449 ConfigRequest = AllocateZeroPool (Size);\r
450 ASSERT (ConfigRequest != NULL);\r
451 AllocatedRequest = TRUE;\r
452 BufferSize = sizeof (IP4_CONFIG_IFR_NVDATA);\r
453 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
454 FreePool (ConfigRequestHdr);\r
455 }\r
456\r
457 //\r
458 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
459 //\r
460 Status = gHiiConfigRouting->BlockToConfig (\r
461 gHiiConfigRouting,\r
462 ConfigRequest,\r
463 (UINT8 *) IfrFormNvData,\r
464 sizeof (IP4_CONFIG_IFR_NVDATA),\r
465 &FormResult,\r
466 Progress\r
467 );\r
468\r
469 FreePool (IfrFormNvData);\r
470 //\r
471 // Free the allocated config request string.\r
472 //\r
473 if (AllocatedRequest) {\r
474 FreePool (ConfigRequest);\r
475 ConfigRequest = NULL;\r
476 }\r
477\r
478 if (EFI_ERROR (Status)) {\r
479 goto Failure;\r
480 }\r
481 }\r
482\r
483 if (Request == NULL) {\r
484 Size = StrLen (DeviceResult);\r
485 Size = Size + 1;\r
486 Size = Size + StrLen (FormResult) + 1;\r
487 *Results = AllocateZeroPool (Size * sizeof (CHAR16));\r
488 ASSERT (*Results != NULL);\r
489 StrPointer = *Results;\r
490 StrCpy (StrPointer, DeviceResult);\r
491 StrPointer = StrPointer + StrLen (StrPointer);\r
492 *StrPointer = L'&';\r
493 StrCpy (StrPointer + 1, FormResult);\r
494 FreePool (DeviceResult);\r
495 FreePool (FormResult);\r
496 } else if (HiiIsConfigHdrMatch (Request, &gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {\r
497 *Results = DeviceResult;\r
498 } else if (HiiIsConfigHdrMatch (Request, &gNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {\r
499 *Results = FormResult;\r
500 } else {\r
501 return EFI_NOT_FOUND;\r
502 }\r
503\r
504Failure:\r
505 //\r
506 // Set Progress string to the original request string.\r
507 //\r
508 if (Request == NULL) {\r
509 *Progress = NULL;\r
510 } else if (StrStr (Request, L"OFFSET") == NULL) {\r
511 *Progress = Request + StrLen (Request);\r
512 }\r
513\r
514 return Status;\r
515}\r
516\r
517/**\r
518 This function applies changes in a driver's configuration.\r
519 Input is a Configuration, which has the routing data for this\r
520 driver followed by name / value configuration pairs. The driver\r
521 must apply those pairs to its configurable storage. If the\r
522 driver's configuration is stored in a linear block of data\r
523 and the driver's name / value pairs are in <BlockConfig>\r
524 format, it may use the ConfigToBlock helper function (above) to\r
525 simplify the job. Currently not implemented.\r
526\r
527 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
528 @param[in] Configuration A null-terminated Unicode string in\r
529 <ConfigString> format.\r
530 @param[out] Progress A pointer to a string filled in with the\r
531 offset of the most recent '&' before the\r
532 first failing name / value pair (or the\r
533 beginn ing of the string if the failure\r
534 is in the first name / value pair) or\r
535 the terminating NULL if all was\r
536 successful.\r
537\r
538 @retval EFI_SUCCESS The results have been distributed or are\r
539 awaiting distribution.\r
540 @retval EFI_OUT_OF_MEMORY Not enough memory to store the\r
541 parts of the results that must be\r
542 stored awaiting possible future\r
543 protocols.\r
544 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the\r
545 Results parameter would result\r
546 in this type of error.\r
547 @retval EFI_NOT_FOUND Target for the specified routing data\r
548 was not found.\r
549**/\r
550EFI_STATUS\r
551EFIAPI\r
552Ip4DeviceRouteConfig (\r
553 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
554 IN CONST EFI_STRING Configuration,\r
555 OUT EFI_STRING *Progress\r
556 )\r
557{\r
558 EFI_STATUS Status;\r
559 UINTN BufferSize;\r
560 NIC_IP4_CONFIG_INFO *IfrDeviceNvData;\r
561 IP4_CONFIG_IFR_NVDATA *IfrFormNvData;\r
562 NIC_IP4_CONFIG_INFO *NicInfo;\r
563 IP4_CONFIG_INSTANCE *Ip4ConfigInstance;\r
564 EFI_MAC_ADDRESS ZeroMac;\r
565\r
566 if (Configuration == NULL || Progress == NULL) {\r
567 return EFI_INVALID_PARAMETER;\r
568 }\r
569\r
570 //\r
571 // Reclaim Ip4Config variable\r
572 //\r
573 Ip4ConfigReclaimVariable ();\r
574\r
575 *Progress = Configuration;\r
576\r
577 Ip4ConfigInstance = IP4_CONFIG_INSTANCE_FROM_CONFIG_ACCESS (This);\r
578\r
579 //\r
580 // Check Routing data in <ConfigHdr>.\r
581 //\r
582 if (HiiIsConfigHdrMatch (Configuration, &gNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {\r
583 //\r
584 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
585 //\r
586 IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG_IFR_NVDATA));\r
587 if (IfrFormNvData == NULL) {\r
588 return EFI_OUT_OF_RESOURCES;\r
589 }\r
590\r
591 BufferSize = NIC_ITEM_CONFIG_SIZE;\r
592 Status = gHiiConfigRouting->ConfigToBlock (\r
593 gHiiConfigRouting,\r
594 Configuration,\r
595 (UINT8 *) IfrFormNvData,\r
596 &BufferSize,\r
597 Progress\r
598 );\r
599 if (!EFI_ERROR (Status)) {\r
600 Status = Ip4ConfigConvertIfrNvDataToDeviceConfigData (IfrFormNvData, Ip4ConfigInstance);\r
601 }\r
602\r
603 FreePool (IfrFormNvData);\r
604\r
605 } else if (HiiIsConfigHdrMatch (Configuration, &gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {\r
606\r
607 IfrDeviceNvData = AllocateZeroPool (NIC_ITEM_CONFIG_SIZE);\r
608 if (IfrDeviceNvData == NULL) {\r
609 return EFI_OUT_OF_RESOURCES;\r
610 }\r
611\r
612 BufferSize = NIC_ITEM_CONFIG_SIZE;\r
613 Status = gHiiConfigRouting->ConfigToBlock (\r
614 gHiiConfigRouting,\r
615 Configuration,\r
616 (UINT8 *) IfrDeviceNvData,\r
617 &BufferSize,\r
618 Progress\r
619 );\r
620 if (!EFI_ERROR (Status)) {\r
621 ZeroMem (&ZeroMac, sizeof (EFI_MAC_ADDRESS));\r
622 if (CompareMem (&IfrDeviceNvData->NicAddr.MacAddr, &ZeroMac, IfrDeviceNvData->NicAddr.Len) != 0) {\r
623 BufferSize = SIZEOF_NIC_IP4_CONFIG_INFO (IfrDeviceNvData);\r
624 NicInfo = AllocateCopyPool (BufferSize, IfrDeviceNvData);\r
625 if (NicInfo == NULL) {\r
626 return EFI_OUT_OF_RESOURCES;\r
627 }\r
628 Status = EfiNicIp4ConfigSetInfo (Ip4ConfigInstance, NicInfo, TRUE);\r
629 FreePool (NicInfo);\r
630 } else {\r
631 ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo, sizeof (IP4_SETTING_INFO));\r
632 Status = EfiNicIp4ConfigSetInfo (Ip4ConfigInstance, NULL, TRUE);\r
633 }\r
634 }\r
635\r
636 FreePool (IfrDeviceNvData);\r
637\r
638 } else {\r
639\r
640 return EFI_NOT_FOUND;\r
641 }\r
642\r
643 return Status;\r
644\r
645}\r
646\r
647/**\r
648 This function is called to provide results data to the driver.\r
649 This data consists of a unique key that is used to identify\r
650 which data is either being passed back or being asked for.\r
651\r
652 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
653 @param[in] Action Specifies the type of action taken by the browser.\r
654 @param[in] QuestionId A unique value which is sent to the original\r
655 exporting driver so that it can identify the type\r
656 of data to expect. The format of the data tends to\r
657 vary based on the opcode that enerated the callback.\r
658 @param[in] Type The type of value for the question.\r
659 @param[in] Value A pointer to the data being sent to the original\r
660 exporting driver.\r
661 @param[out] ActionRequest On return, points to the action requested by the\r
662 callback function.\r
663\r
664 @retval EFI_SUCCESS The callback successfully handled the action.\r
665 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the\r
666 variable and its data.\r
667 @retval EFI_DEVICE_ERROR The variable could not be saved.\r
668 @retval EFI_UNSUPPORTED The specified Action is not supported by the\r
669 callback.Currently not implemented.\r
670 @retval EFI_INVALID_PARAMETERS Passing in wrong parameter.\r
671 @retval Others Other errors as indicated.\r
672**/\r
673EFI_STATUS\r
674EFIAPI\r
675Ip4FormCallback (\r
676 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
677 IN EFI_BROWSER_ACTION Action,\r
678 IN EFI_QUESTION_ID QuestionId,\r
679 IN UINT8 Type,\r
680 IN EFI_IFR_TYPE_VALUE *Value,\r
681 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
682 )\r
683{\r
684 IP4_CONFIG_INSTANCE *Ip4ConfigInstance;\r
685 IP4_CONFIG_IFR_NVDATA *IfrFormNvData;\r
686 EFI_IP_ADDRESS HostIp;\r
687 EFI_IP_ADDRESS SubnetMask;\r
688 EFI_IP_ADDRESS Gateway;\r
689 EFI_STATUS Status;\r
690 EFI_INPUT_KEY Key;\r
691\r
692 if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
693 Ip4ConfigInstance = IP4_CONFIG_INSTANCE_FROM_CONFIG_ACCESS (This);\r
694\r
695 IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG_IFR_NVDATA));\r
696 if (IfrFormNvData == NULL) {\r
697 return EFI_OUT_OF_RESOURCES;\r
698 }\r
699\r
700 //\r
701 // Retrive uncommitted data from Browser\r
702 //\r
703 if (!HiiGetBrowserData (&gNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE, sizeof (IP4_CONFIG_IFR_NVDATA), (UINT8 *) IfrFormNvData)) {\r
704 FreePool (IfrFormNvData);\r
705 return EFI_NOT_FOUND;\r
706 }\r
707\r
708 Status = EFI_SUCCESS;\r
709\r
710 switch (QuestionId) {\r
711 case KEY_LOCAL_IP:\r
712 Status = Ip4StrToIp (IfrFormNvData->StationAddress, &HostIp.v4);\r
713 if (EFI_ERROR (Status) || !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {\r
714 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);\r
715 Status = EFI_INVALID_PARAMETER;\r
716 } else {\r
717 CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.LocalIp, &HostIp.v4, sizeof (HostIp.v4));\r
718 }\r
719\r
720 break;\r
721\r
722 case KEY_SUBNET_MASK:\r
723 Status = Ip4StrToIp (IfrFormNvData->SubnetMask, &SubnetMask.v4);\r
724 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (GetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {\r
725 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL);\r
726 Status = EFI_INVALID_PARAMETER;\r
727 } else {\r
728 CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));\r
729 }\r
730\r
731 break;\r
732\r
733 case KEY_GATE_WAY:\r
734 Status = Ip4StrToIp (IfrFormNvData->GatewayAddress, &Gateway.v4);\r
735 if (EFI_ERROR (Status) || ((Gateway.Addr[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), 0))) {\r
736 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL);\r
737 Status = EFI_INVALID_PARAMETER;\r
738 } else {\r
739 CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.Gateway, &Gateway.v4, sizeof (Gateway.v4));\r
740 }\r
741\r
742 break;\r
743\r
744 case KEY_SAVE_CHANGES:\r
745 Status = Ip4ConfigConvertIfrNvDataToDeviceConfigData (IfrFormNvData, Ip4ConfigInstance);\r
746 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
747 break;\r
748\r
749 default:\r
750 break;\r
751 }\r
752\r
753 FreePool (IfrFormNvData);\r
754\r
755 return Status;\r
756 }\r
757\r
758 //\r
759 // All other action return unsupported.\r
760 //\r
761 return EFI_UNSUPPORTED;\r
762}\r
763\r
764/**\r
765 Install HII Config Access protocol for network device and allocate resource.\r
766\r
767 @param[in] Instance The IP4 Config instance.\r
768\r
769 @retval EFI_SUCCESS The HII Config Access protocol is installed.\r
770 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
771 @retval Others Other errors as indicated.\r
772**/\r
773EFI_STATUS\r
774Ip4ConfigDeviceInit (\r
775 IN IP4_CONFIG_INSTANCE *Instance\r
776 )\r
777{\r
778 EFI_STATUS Status;\r
779 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
780 VENDOR_DEVICE_PATH VendorDeviceNode;\r
781 EFI_SERVICE_BINDING_PROTOCOL *MnpSb;\r
782 CHAR16 *MacString;\r
783 CHAR16 MenuString[128];\r
784 CHAR16 PortString[128];\r
785 CHAR16 *OldMenuString;\r
786\r
787 ConfigAccess = &Instance->HiiConfigAccessProtocol;\r
788 ConfigAccess->ExtractConfig = Ip4DeviceExtractConfig;\r
789 ConfigAccess->RouteConfig = Ip4DeviceRouteConfig;\r
790 ConfigAccess->Callback = Ip4FormCallback;\r
791\r
792 //\r
793 // Construct device path node for EFI HII Config Access protocol,\r
794 // which consists of controller physical device path and one hardware\r
795 // vendor guid node.\r
796 //\r
797 ZeroMem (&VendorDeviceNode, sizeof (VENDOR_DEVICE_PATH));\r
798 VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH;\r
799 VendorDeviceNode.Header.SubType = HW_VENDOR_DP;\r
800\r
801 CopyGuid (&VendorDeviceNode.Guid, &gEfiNicIp4ConfigVariableGuid);\r
802\r
803 SetDevicePathNodeLength (&VendorDeviceNode.Header, sizeof (VENDOR_DEVICE_PATH));\r
804 Instance->HiiVendorDevicePath = AppendDevicePathNode (\r
805 Instance->ParentDevicePath,\r
806 (EFI_DEVICE_PATH_PROTOCOL *) &VendorDeviceNode\r
807 );\r
808\r
809 Instance->ChildHandle = NULL;\r
810 //\r
811 // Install Device Path Protocol and Config Access protocol on new handle\r
812 //\r
813 Status = gBS->InstallMultipleProtocolInterfaces (\r
814 &Instance->ChildHandle,\r
815 &gEfiDevicePathProtocolGuid,\r
816 Instance->HiiVendorDevicePath,\r
817 &gEfiHiiConfigAccessProtocolGuid,\r
818 ConfigAccess,\r
819 NULL\r
820 );\r
821 if (!EFI_ERROR (Status)) {\r
822 //\r
823 // Open the Parent Handle for the child\r
824 //\r
825 Status = gBS->OpenProtocol (\r
826 Instance->Controller,\r
827 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
828 (VOID **) &MnpSb,\r
829 Instance->Image,\r
830 Instance->ChildHandle,\r
831 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
832 );\r
833 }\r
834\r
835 ASSERT_EFI_ERROR (Status);\r
836\r
837 //\r
838 // Publish our HII data\r
839 //\r
840 Instance->RegisteredHandle = HiiAddPackages (\r
841 &gNicIp4ConfigNvDataGuid,\r
842 Instance->ChildHandle,\r
843 Ip4ConfigDxeStrings,\r
844 Ip4ConfigDxeBin,\r
845 NULL\r
846 );\r
847 if (Instance->RegisteredHandle == NULL) {\r
848 return EFI_OUT_OF_RESOURCES;\r
849 }\r
850\r
851 //\r
852 // Append MAC string in the menu help string and tile help string\r
853 //\r
854 Status = NetLibGetMacString (Instance->Controller, Instance->Image, &MacString);\r
855 if (!EFI_ERROR (Status)) {\r
856 OldMenuString = HiiGetString (Instance->RegisteredHandle, STRING_TOKEN (STR_IP4_CONFIG_FORM_HELP), NULL);\r
857 UnicodeSPrint (MenuString, 128, L"%s (MAC:%s)", OldMenuString, MacString);\r
858 HiiSetString (Instance->RegisteredHandle, STRING_TOKEN (STR_IP4_CONFIG_FORM_HELP), MenuString, NULL);\r
859\r
860 UnicodeSPrint (PortString, 128, L"MAC:%s", MacString);\r
861 HiiSetString (Instance->RegisteredHandle, STRING_TOKEN (STR_IP4_DEVICE_FORM_HELP), PortString, NULL);\r
862 FreePool (MacString);\r
863 }\r
864\r
865 return Status;\r
866}\r
867\r
868/**\r
869 Uninstall HII Config Access protocol for network device and free resource.\r
870\r
871 @param[in] Instance The IP4 Config instance.\r
872\r
873 @retval EFI_SUCCESS The HII Config Access protocol is uninstalled.\r
874 @retval Others Other errors as indicated.\r
875**/\r
876EFI_STATUS\r
877Ip4ConfigDeviceUnload (\r
878 IN IP4_CONFIG_INSTANCE *Instance\r
879 )\r
880{\r
881 //\r
882 // Remove HII package list\r
883 //\r
884 HiiRemovePackages (Instance->RegisteredHandle);\r
885\r
886 //\r
887 // Close the child handle\r
888 //\r
889 gBS->CloseProtocol (\r
890 Instance->Controller,\r
891 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
892 Instance->Image,\r
893 Instance->ChildHandle\r
894 );\r
895\r
896 //\r
897 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL\r
898 //\r
899 gBS->UninstallMultipleProtocolInterfaces (\r
900 Instance->ChildHandle,\r
901 &gEfiDevicePathProtocolGuid,\r
902 Instance->HiiVendorDevicePath,\r
903 &gEfiHiiConfigAccessProtocolGuid,\r
904 &Instance->HiiConfigAccessProtocol,\r
905 NULL\r
906 );\r
907\r
908 return EFI_SUCCESS;\r
909}\r