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