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