]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigNv.c
Correct one comment to match the function name.
[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
083f7c69 4Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 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
63886849 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
72ed3d75 37 ReverseMask = SwapBytes32 (*(UINT32 *)&SubnetMask[0]);\r
63886849 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
74df5026 62 @param[out] Ip The storage to return the IPv4 address.\r
63886849 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
74df5026 68Ip4StrToIp (\r
69 IN CHAR16 *Str,\r
63886849 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
74df5026 78 while (*Str != L'\0') {\r
63886849 79\r
80 if (Index > 3) {\r
81 return EFI_INVALID_PARAMETER;\r
82 }\r
83\r
84 Number = 0;\r
74df5026 85 while ((*Str >= L'0') && (*Str <= L'9')) {\r
86 Number = Number * 10 + (*Str - L'0');\r
63886849 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
74df5026 96 if ((*Str != L'\0') && (*Str != L'.')) {\r
63886849 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
74df5026 104 if (*Str == L'.') {\r
63886849 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
f6b7393c 140 @param[in] Ip4ConfigInstance The IP4Config instance\r
141 @param[out] IfrFormNvData The IFR nv data.\r
63886849 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
74df5026 149 NIC_IP4_CONFIG_INFO *NicConfig;\r
150\r
151 NicConfig = EfiNicIp4ConfigGetInfo (Ip4ConfigInstance);\r
152 if (NicConfig != NULL) {\r
c22b6cdf 153 IfrFormNvData->Configure = 1;\r
4ad858e0 154 Ip4ConfigInstance->Ip4ConfigCallbackInfo.Configured = TRUE;\r
63886849 155 if (NicConfig->Source == IP4_CONFIG_SOURCE_DHCP) {\r
156 IfrFormNvData->DhcpEnable = 1;\r
4ad858e0 157 Ip4ConfigInstance->Ip4ConfigCallbackInfo.DhcpEnabled = TRUE;\r
63886849 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
4ad858e0 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
63886849 168 }\r
74df5026 169\r
170 FreePool (NicConfig);\r
c22b6cdf 171 } else {\r
172 IfrFormNvData->Configure = 0;\r
4ad858e0 173 Ip4ConfigInstance->Ip4ConfigCallbackInfo.Configured = FALSE;\r
63886849 174 }\r
63886849 175}\r
176\r
177/**\r
d80ea739 178 Convert the IFR data into the network configuration data and set the IP\r
179 configure parameters for the NIC.\r
180\r
74df5026 181 @param[in] IfrFormNvData The IFR NV data.\r
d80ea739 182 @param[in, out] Ip4ConfigInstance The IP4Config instance.\r
c22b6cdf 183\r
184 @retval EFI_SUCCESS The configure parameter for this NIC was\r
d80ea739 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
c22b6cdf 188\r
63886849 189**/\r
d80ea739 190EFI_STATUS\r
191Ip4ConfigConvertIfrNvDataToDeviceConfigData (\r
74df5026 192 IN IP4_CONFIG_IFR_NVDATA *IfrFormNvData,\r
d80ea739 193 IN OUT IP4_CONFIG_INSTANCE *Ip4ConfigInstance\r
63886849 194 )\r
195{\r
c22b6cdf 196 EFI_STATUS Status;\r
d80ea739 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
63886849 203\r
74df5026 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
c22b6cdf 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
d80ea739 226 NicInfo = AllocateZeroPool (sizeof (NIC_IP4_CONFIG_INFO) + 2 * sizeof (EFI_IP4_ROUTE_TABLE));\r
227 ASSERT (NicInfo != NULL);\r
63886849 228\r
d80ea739 229 NicInfo->Ip4Info.RouteTable = (EFI_IP4_ROUTE_TABLE *) (NicInfo + 1);\r
230\r
c22b6cdf 231 if (!Ip4ConfigInstance->Ip4ConfigCallbackInfo.DhcpEnabled) {\r
d80ea739 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
c22b6cdf 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
d80ea739 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
63886849 253 }\r
254\r
d80ea739 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
c22b6cdf 266\r
d80ea739 267 } else {\r
268 NicInfo->Source = IP4_CONFIG_SOURCE_DHCP;\r
c22b6cdf 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
63886849 272 }\r
273\r
d80ea739 274 NicInfo->Perment = TRUE;\r
275 CopyMem (&NicInfo->NicAddr, &Ip4ConfigInstance->NicAddr, sizeof (NIC_ADDR));\r
276\r
277 return EfiNicIp4ConfigSetInfo (Ip4ConfigInstance, NicInfo, TRUE);\r
63886849 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
63886849 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
63886849 346 NIC_IP4_CONFIG_INFO *IfrDeviceNvData;\r
74df5026 347 NIC_IP4_CONFIG_INFO *NicConfig;\r
63886849 348 IP4_CONFIG_INSTANCE *Ip4ConfigInstance;\r
d80ea739 349 IP4_CONFIG_IFR_NVDATA *IfrFormNvData;\r
59aefb7e
LG
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
63886849 360 return EFI_INVALID_PARAMETER;\r
361 }\r
362\r
59aefb7e
LG
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
d80ea739 370 Ip4ConfigInstance = IP4_CONFIG_INSTANCE_FROM_CONFIG_ACCESS (This);\r
371\r
391a0724 372 //\r
373 // Check Request data in <ConfigHdr>.\r
374 //\r
59aefb7e 375 if ((Request == NULL) || HiiIsConfigHdrMatch (Request, &gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {\r
d80ea739 376 IfrDeviceNvData = AllocateZeroPool (NIC_ITEM_CONFIG_SIZE);\r
377 if (IfrDeviceNvData == NULL) {\r
378 return EFI_OUT_OF_RESOURCES;\r
379 }\r
391a0724 380\r
74df5026 381 NicConfig = EfiNicIp4ConfigGetInfo (Ip4ConfigInstance);\r
382 if (NicConfig == NULL) {\r
d80ea739 383 return EFI_NOT_FOUND;\r
384 }\r
74df5026 385 CopyMem (IfrDeviceNvData, NicConfig, SIZEOF_NIC_IP4_CONFIG_INFO (NicConfig));\r
386 FreePool (NicConfig);\r
c22b6cdf 387\r
59aefb7e
LG
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
d80ea739 405 //\r
406 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
407 //\r
408 Status = gHiiConfigRouting->BlockToConfig (\r
409 gHiiConfigRouting,\r
59aefb7e 410 ConfigRequest,\r
d80ea739 411 (UINT8 *) IfrDeviceNvData,\r
412 NIC_ITEM_CONFIG_SIZE,\r
59aefb7e 413 &DeviceResult,\r
d80ea739 414 Progress\r
415 );\r
c22b6cdf 416\r
d80ea739 417 FreePool (IfrDeviceNvData);\r
59aefb7e
LG
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
63886849 425\r
59aefb7e
LG
426 if (EFI_ERROR (Status)) {\r
427 goto Failure;\r
428 }\r
74df5026 429 }\r
430\r
c8ad2d7a 431 if ((Request == NULL) || HiiIsConfigHdrMatch (Request, &gNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {\r
63886849 432\r
74df5026 433 IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG_IFR_NVDATA));\r
d80ea739 434 if (IfrFormNvData == NULL) {\r
435 return EFI_OUT_OF_RESOURCES;\r
436 }\r
c22b6cdf 437\r
d80ea739 438 Ip4ConfigConvertDeviceConfigDataToIfrNvData (Ip4ConfigInstance, IfrFormNvData);\r
c22b6cdf 439\r
59aefb7e
LG
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
c8ad2d7a 447 ConfigRequestHdr = HiiConstructConfigHdr (&gNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE, Ip4ConfigInstance->ChildHandle);\r
59aefb7e
LG
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
74df5026 456\r
d80ea739 457 //\r
458 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
459 //\r
460 Status = gHiiConfigRouting->BlockToConfig (\r
461 gHiiConfigRouting,\r
59aefb7e 462 ConfigRequest,\r
d80ea739 463 (UINT8 *) IfrFormNvData,\r
464 sizeof (IP4_CONFIG_IFR_NVDATA),\r
59aefb7e 465 &FormResult,\r
d80ea739 466 Progress\r
467 );\r
c22b6cdf 468\r
d80ea739 469 FreePool (IfrFormNvData);\r
59aefb7e
LG
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
d80ea739 482\r
59aefb7e
LG
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
b26fc8d8 496 } else if (HiiIsConfigHdrMatch (Request, &gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {\r
59aefb7e 497 *Results = DeviceResult;\r
c8ad2d7a 498 } else if (HiiIsConfigHdrMatch (Request, &gNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {\r
59aefb7e 499 *Results = FormResult;\r
d80ea739 500 } else {\r
63886849 501 return EFI_NOT_FOUND;\r
502 }\r
503\r
59aefb7e
LG
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
74df5026 513\r
63886849 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
c22b6cdf 561 IP4_CONFIG_IFR_NVDATA *IfrFormNvData;\r
391a0724 562 NIC_IP4_CONFIG_INFO *NicInfo;\r
63886849 563 IP4_CONFIG_INSTANCE *Ip4ConfigInstance;\r
564 EFI_MAC_ADDRESS ZeroMac;\r
565\r
d80ea739 566 if (Configuration == NULL || Progress == NULL) {\r
63886849 567 return EFI_INVALID_PARAMETER;\r
568 }\r
569\r
74df5026 570 //\r
571 // Reclaim Ip4Config variable\r
572 //\r
573 Ip4ConfigReclaimVariable ();\r
574\r
63886849 575 *Progress = Configuration;\r
576\r
d80ea739 577 Ip4ConfigInstance = IP4_CONFIG_INSTANCE_FROM_CONFIG_ACCESS (This);\r
63886849 578\r
579 //\r
d80ea739 580 // Check Routing data in <ConfigHdr>.\r
63886849 581 //\r
c8ad2d7a 582 if (HiiIsConfigHdrMatch (Configuration, &gNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {\r
d80ea739 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
63886849 589 }\r
63886849 590\r
d80ea739 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
74df5026 600 Status = Ip4ConfigConvertIfrNvDataToDeviceConfigData (IfrFormNvData, Ip4ConfigInstance);\r
d80ea739 601 }\r
c22b6cdf 602\r
d80ea739 603 FreePool (IfrFormNvData);\r
63886849 604\r
d80ea739 605 } else if (HiiIsConfigHdrMatch (Configuration, &gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {\r
63886849 606\r
d80ea739 607 IfrDeviceNvData = AllocateZeroPool (NIC_ITEM_CONFIG_SIZE);\r
608 if (IfrDeviceNvData == NULL) {\r
609 return EFI_OUT_OF_RESOURCES;\r
610 }\r
63886849 611\r
d80ea739 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
74df5026 623 BufferSize = SIZEOF_NIC_IP4_CONFIG_INFO (IfrDeviceNvData);\r
c22b6cdf 624 NicInfo = AllocateCopyPool (BufferSize, IfrDeviceNvData);\r
74df5026 625 if (NicInfo == NULL) {\r
626 return EFI_OUT_OF_RESOURCES;\r
627 }\r
d80ea739 628 Status = EfiNicIp4ConfigSetInfo (Ip4ConfigInstance, NicInfo, TRUE);\r
74df5026 629 FreePool (NicInfo);\r
d80ea739 630 } else {\r
c22b6cdf 631 ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo, sizeof (IP4_SETTING_INFO));\r
d80ea739 632 Status = EfiNicIp4ConfigSetInfo (Ip4ConfigInstance, NULL, TRUE);\r
633 }\r
634 }\r
63886849 635\r
d80ea739 636 FreePool (IfrDeviceNvData);\r
63886849 637\r
d80ea739 638 } else {\r
ae79d2f9 639\r
ae79d2f9
LG
640 return EFI_NOT_FOUND;\r
641 }\r
c22b6cdf 642\r
d80ea739 643 return Status;\r
ae79d2f9 644\r
63886849 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
63886849 685 IP4_CONFIG_IFR_NVDATA *IfrFormNvData;\r
63886849 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
63886849 691\r
083f7c69
ED
692 if (Action == EFI_BROWSER_ACTION_CHANGING) {\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
5adb8db7 700 //\r
083f7c69 701 // Retrive uncommitted data from Browser\r
5adb8db7 702 //\r
c8ad2d7a 703 if (!HiiGetBrowserData (&gNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE, sizeof (IP4_CONFIG_IFR_NVDATA), (UINT8 *) IfrFormNvData)) {\r
083f7c69
ED
704 FreePool (IfrFormNvData);\r
705 return EFI_NOT_FOUND;\r
706 }\r
5adb8db7 707\r
083f7c69 708 Status = EFI_SUCCESS;\r
63886849 709\r
083f7c69
ED
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
63886849 719\r
083f7c69 720 break;\r
63886849 721\r
083f7c69
ED
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
63886849 730\r
083f7c69 731 break;\r
63886849 732\r
083f7c69
ED
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
63886849 741\r
083f7c69 742 break;\r
63886849 743\r
083f7c69
ED
744 case KEY_SAVE_CHANGES:\r
745 Status = Ip4ConfigConvertIfrNvDataToDeviceConfigData (IfrFormNvData, Ip4ConfigInstance);\r
746 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
747 break;\r
63886849 748\r
083f7c69
ED
749 default:\r
750 break;\r
63886849 751 }\r
752\r
083f7c69 753 FreePool (IfrFormNvData);\r
63886849 754\r
083f7c69 755 return Status;\r
63886849 756 }\r
757\r
083f7c69
ED
758 //\r
759 // All other action return unsupported.\r
760 //\r
761 return EFI_UNSUPPORTED;\r
63886849 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
d80ea739 775 IN IP4_CONFIG_INSTANCE *Instance\r
63886849 776 )\r
777{\r
d80ea739 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
63886849 786\r
d80ea739 787 ConfigAccess = &Instance->HiiConfigAccessProtocol;\r
788 ConfigAccess->ExtractConfig = Ip4DeviceExtractConfig;\r
789 ConfigAccess->RouteConfig = Ip4DeviceRouteConfig;\r
790 ConfigAccess->Callback = Ip4FormCallback;\r
63886849 791\r
d80ea739 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
63886849 800\r
d80ea739 801 CopyGuid (&VendorDeviceNode.Guid, &gEfiNicIp4ConfigVariableGuid);\r
63886849 802\r
d80ea739 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
63886849 808\r
d80ea739 809 Instance->ChildHandle = NULL;\r
63886849 810 //\r
d80ea739 811 // Install Device Path Protocol and Config Access protocol on new handle\r
63886849 812 //\r
813 Status = gBS->InstallMultipleProtocolInterfaces (\r
d80ea739 814 &Instance->ChildHandle,\r
815 &gEfiDevicePathProtocolGuid,\r
c22b6cdf 816 Instance->HiiVendorDevicePath,\r
63886849 817 &gEfiHiiConfigAccessProtocolGuid,\r
d80ea739 818 ConfigAccess,\r
63886849 819 NULL\r
820 );\r
d80ea739 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
c22b6cdf 830 Instance->ChildHandle,\r
d80ea739 831 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
832 );\r
833 }\r
834\r
63886849 835 ASSERT_EFI_ERROR (Status);\r
c22b6cdf 836\r
d80ea739 837 //\r
838 // Publish our HII data\r
839 //\r
840 Instance->RegisteredHandle = HiiAddPackages (\r
c8ad2d7a 841 &gNicIp4ConfigNvDataGuid,\r
d80ea739 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
3ddc4cf2 852 // Append MAC string in the menu help string and tile help string\r
d80ea739 853 //\r
854 Status = NetLibGetMacString (Instance->Controller, Instance->Image, &MacString);\r
855 if (!EFI_ERROR (Status)) {\r
c7f204db 856 OldMenuString = HiiGetString (Instance->RegisteredHandle, STRING_TOKEN (STR_IP4_CONFIG_FORM_HELP), NULL);\r
d80ea739 857 UnicodeSPrint (MenuString, 128, L"%s (MAC:%s)", OldMenuString, MacString);\r
c7f204db 858 HiiSetString (Instance->RegisteredHandle, STRING_TOKEN (STR_IP4_CONFIG_FORM_HELP), MenuString, NULL);\r
c22b6cdf 859\r
d80ea739 860 UnicodeSPrint (PortString, 128, L"MAC:%s", MacString);\r
c7f204db 861 HiiSetString (Instance->RegisteredHandle, STRING_TOKEN (STR_IP4_DEVICE_FORM_HELP), PortString, NULL);\r
d80ea739 862 FreePool (MacString);\r
863 }\r
63886849 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
63886849 881 //\r
d80ea739 882 // Remove HII package list\r
63886849 883 //\r
d80ea739 884 HiiRemovePackages (Instance->RegisteredHandle);\r
63886849 885\r
886 //\r
d80ea739 887 // Close the child handle\r
63886849 888 //\r
d80ea739 889 gBS->CloseProtocol (\r
890 Instance->Controller,\r
891 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
892 Instance->Image,\r
893 Instance->ChildHandle\r
894 );\r
63886849 895\r
896 //\r
897 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL\r
898 //\r
899 gBS->UninstallMultipleProtocolInterfaces (\r
d80ea739 900 Instance->ChildHandle,\r
63886849 901 &gEfiDevicePathProtocolGuid,\r
c22b6cdf 902 Instance->HiiVendorDevicePath,\r
63886849 903 &gEfiHiiConfigAccessProtocolGuid,\r
d80ea739 904 &Instance->HiiConfigAccessProtocol,\r
63886849 905 NULL\r
906 );\r
907\r
63886849 908 return EFI_SUCCESS;\r
909}\r