]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Nv.c
MdeModulePkg/Network: Fix potential ASSERT if NetIp4IsUnicast is called
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4Dxe / Ip4Config2Nv.c
CommitLineData
1f6729ff 1/** @file\r
2 Helper functions for configuring or getting the parameters relating to Ip4.\r
3\r
d0e76ac5 4Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>\r
1f6729ff 5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "Ip4Impl.h"\r
16\r
17CHAR16 mIp4Config2StorageName[] = L"IP4_CONFIG2_IFR_NVDATA";\r
18\r
19/**\r
20 Calculate the prefix length of the IPv4 subnet mask.\r
21\r
22 @param[in] SubnetMask The IPv4 subnet mask.\r
23\r
24 @return The prefix length of the subnet mask.\r
25 @retval 0 Other errors as indicated.\r
26 \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 = SwapBytes32 (*(UINT32 *)&SubnetMask[0]);\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 IPv4 address.\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
69**/\r
70EFI_STATUS\r
71Ip4Config2StrToIp (\r
72 IN CHAR16 *Str,\r
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
81 while (*Str != L'\0') {\r
82\r
83 if (Index > 3) {\r
84 return EFI_INVALID_PARAMETER;\r
85 }\r
86\r
87 Number = 0;\r
88 while ((*Str >= L'0') && (*Str <= L'9')) {\r
89 Number = Number * 10 + (*Str - L'0');\r
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
99 if ((*Str != L'\0') && (*Str != L'.')) {\r
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
107 if (*Str == L'.') {\r
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 decimal dotted IPv4 addresses separated by space into the binary IPv4 address list.\r
126\r
127 @param[in] Str The UNICODE string contains IPv4 addresses.\r
128 @param[out] PtrIpList The storage to return the IPv4 address list.\r
129 @param[out] IpCount The size of the IPv4 address list.\r
130\r
131 @retval EFI_SUCCESS The binary IP address list is returned in PtrIpList.\r
132 @retval EFI_OUT_OF_RESOURCES Error occurs in allocating memory.\r
133 @retval EFI_INVALID_PARAMETER The IP string is malformatted.\r
134 \r
135**/\r
136EFI_STATUS\r
137Ip4Config2StrToIpList (\r
138 IN CHAR16 *Str,\r
139 OUT EFI_IPv4_ADDRESS **PtrIpList,\r
140 OUT UINTN *IpCount\r
141 )\r
142{\r
143 UINTN BeginIndex;\r
144 UINTN EndIndex; \r
145 UINTN Index;\r
146 UINTN IpIndex;\r
147 CHAR16 *StrTemp;\r
148 BOOLEAN SpaceTag;\r
149 \r
150 BeginIndex = 0;\r
151 EndIndex = BeginIndex;\r
152 Index = 0;\r
153 IpIndex = 0;\r
154 StrTemp = NULL;\r
155 SpaceTag = TRUE;\r
156 \r
157 *PtrIpList = NULL;\r
158 *IpCount = 0;\r
159\r
160 if (Str == NULL) {\r
161 return EFI_SUCCESS;\r
162 }\r
163\r
164 //\r
165 // Get the number of Ip.\r
166 //\r
167 while (*(Str + Index) != L'\0') {\r
168 if (*(Str + Index) == L' ') {\r
169 SpaceTag = TRUE;\r
170 } else {\r
171 if (SpaceTag) {\r
172 (*IpCount)++;\r
173 SpaceTag = FALSE;\r
174 }\r
175 }\r
176 \r
177 Index++;\r
178 }\r
179\r
180 if (*IpCount == 0) {\r
181 return EFI_SUCCESS;\r
182 }\r
183 \r
184 //\r
185 // Allocate buffer for IpList.\r
186 //\r
187 *PtrIpList = AllocateZeroPool(*IpCount * sizeof(EFI_IPv4_ADDRESS));\r
188 if (*PtrIpList == NULL) {\r
189 return EFI_OUT_OF_RESOURCES;\r
190 }\r
191\r
192 //\r
193 // Get IpList from Str.\r
194 //\r
195 Index = 0;\r
196 while (*(Str + Index) != L'\0') {\r
197 if (*(Str + Index) == L' ') {\r
198 if(!SpaceTag) {\r
199 StrTemp = AllocateZeroPool((EndIndex - BeginIndex + 1) * sizeof(CHAR16));\r
200 if (StrTemp == NULL) {\r
201 FreePool(*PtrIpList);\r
202 *PtrIpList = NULL;\r
203 *IpCount = 0;\r
204 return EFI_OUT_OF_RESOURCES;\r
205 }\r
206 \r
207 CopyMem (StrTemp, Str + BeginIndex, (EndIndex - BeginIndex) * sizeof(CHAR16));\r
208 *(StrTemp + (EndIndex - BeginIndex)) = L'\0';\r
209 \r
210 if (Ip4Config2StrToIp (StrTemp, &((*PtrIpList)[IpIndex])) != EFI_SUCCESS) {\r
211 FreePool(StrTemp);\r
212 FreePool(*PtrIpList);\r
213 *PtrIpList = NULL;\r
214 *IpCount = 0;\r
215 return EFI_INVALID_PARAMETER;\r
216 }\r
217 \r
218 BeginIndex = EndIndex;\r
219 IpIndex++;\r
220\r
221 FreePool(StrTemp);\r
222 }\r
223\r
224 BeginIndex++;\r
225 EndIndex++;\r
226 SpaceTag = TRUE;\r
227 } else {\r
228 EndIndex++;\r
229 SpaceTag = FALSE;\r
230 }\r
231 \r
232 Index++;\r
233 \r
234 if (*(Str + Index) == L'\0') {\r
235 if (!SpaceTag) {\r
236 StrTemp = AllocateZeroPool((EndIndex - BeginIndex + 1) * sizeof(CHAR16));\r
237 if (StrTemp == NULL) {\r
238 FreePool(*PtrIpList);\r
239 *PtrIpList = NULL;\r
240 *IpCount = 0;\r
241 return EFI_OUT_OF_RESOURCES;\r
242 }\r
243 \r
244 CopyMem (StrTemp, Str + BeginIndex, (EndIndex - BeginIndex) * sizeof(CHAR16));\r
245 *(StrTemp + (EndIndex - BeginIndex)) = L'\0';\r
246 \r
247 if (Ip4Config2StrToIp (StrTemp, &((*PtrIpList)[IpIndex])) != EFI_SUCCESS) {\r
248 FreePool(StrTemp);\r
249 FreePool(*PtrIpList);\r
250 *PtrIpList = NULL;\r
251 *IpCount = 0;\r
252 return EFI_INVALID_PARAMETER;\r
253 }\r
254\r
255 FreePool(StrTemp);\r
256 }\r
257 }\r
258 } \r
259\r
260 return EFI_SUCCESS;\r
261}\r
262\r
263/**\r
264 Convert the IPv4 address into a dotted string.\r
265\r
266 @param[in] Ip The IPv4 address.\r
267 @param[out] Str The dotted IP string.\r
268 \r
269**/\r
270VOID\r
271Ip4Config2IpToStr (\r
272 IN EFI_IPv4_ADDRESS *Ip,\r
273 OUT CHAR16 *Str\r
274 )\r
275{\r
276 UnicodeSPrint (\r
277 Str,\r
278 2 * IP4_STR_MAX_SIZE, \r
279 L"%d.%d.%d.%d", \r
280 Ip->Addr[0],\r
281 Ip->Addr[1],\r
282 Ip->Addr[2],\r
283 Ip->Addr[3]\r
284 );\r
285}\r
286\r
287\r
288/**\r
289 Convert the IPv4 address list into string consists of several decimal \r
290 dotted IPv4 addresses separated by space.\r
291\r
292 @param[in] Ip The IPv4 address list.\r
293 @param[in] IpCount The size of IPv4 address list.\r
294 @param[out] Str The string contains several decimal dotted\r
295 IPv4 addresses separated by space. \r
296**/\r
297VOID\r
298Ip4Config2IpListToStr (\r
299 IN EFI_IPv4_ADDRESS *Ip,\r
300 IN UINTN IpCount,\r
301 OUT CHAR16 *Str\r
302 )\r
303{\r
304 UINTN Index;\r
305 UINTN TemIndex;\r
306 UINTN StrIndex;\r
307 CHAR16 *TempStr;\r
308 EFI_IPv4_ADDRESS *TempIp;\r
309 \r
310 Index = 0;\r
311 TemIndex = 0;\r
312 StrIndex = 0;\r
313 TempStr = NULL;\r
314 TempIp = NULL;\r
315\r
316 for (Index = 0; Index < IpCount; Index ++) {\r
317 TempIp = Ip + Index;\r
318 if (TempStr == NULL) {\r
319 TempStr = AllocateZeroPool(2 * IP4_STR_MAX_SIZE);\r
320 ASSERT(TempStr != NULL);\r
321 }\r
322\r
323 UnicodeSPrint (\r
324 TempStr, \r
325 2 * IP4_STR_MAX_SIZE, \r
326 L"%d.%d.%d.%d", \r
327 TempIp->Addr[0],\r
328 TempIp->Addr[1],\r
329 TempIp->Addr[2],\r
330 TempIp->Addr[3]\r
331 );\r
332\r
333 for (TemIndex = 0; TemIndex < IP4_STR_MAX_SIZE; TemIndex ++) {\r
334 if (*(TempStr + TemIndex) == L'\0') {\r
335 if (Index == IpCount - 1) {\r
336 Str[StrIndex++] = L'\0';\r
337 } else {\r
338 Str[StrIndex++] = L' ';\r
339 } \r
340 break;\r
341 } else {\r
342 Str[StrIndex++] = *(TempStr + TemIndex);\r
343 }\r
344 }\r
345 }\r
346\r
347 if (TempStr != NULL) {\r
348 FreePool(TempStr);\r
349 }\r
350}\r
351\r
352/**\r
353 The notify function of create event when performing a manual configuration.\r
354\r
355 @param[in] Event The pointer of Event.\r
356 @param[in] Context The pointer of Context.\r
357 \r
358**/\r
359VOID\r
360EFIAPI\r
361Ip4Config2ManualAddressNotify (\r
362 IN EFI_EVENT Event,\r
363 IN VOID *Context\r
364 )\r
365{\r
366 *((BOOLEAN *) Context) = TRUE;\r
367}\r
368\r
369/**\r
370 Convert the network configuration data into the IFR data.\r
371\r
372 @param[in] Instance The IP4 config2 instance.\r
373 @param[in, out] IfrNvData The IFR nv data.\r
374\r
375 @retval EFI_SUCCESS The configure parameter to IFR data was\r
376 set successfully.\r
377 @retval EFI_INVALID_PARAMETER Source instance or target IFR data is not available.\r
378 @retval Others Other errors as indicated.\r
379 \r
380**/\r
381EFI_STATUS\r
382Ip4Config2ConvertConfigNvDataToIfrNvData (\r
383 IN IP4_CONFIG2_INSTANCE *Instance,\r
384 IN OUT IP4_CONFIG2_IFR_NVDATA *IfrNvData\r
385 )\r
386{\r
387 IP4_SERVICE *IpSb;\r
388 EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2;\r
389 EFI_IP4_CONFIG2_INTERFACE_INFO *Ip4Info;\r
390 EFI_IP4_CONFIG2_POLICY Policy;\r
391 UINTN DataSize;\r
392 UINTN GatewaySize;\r
393 EFI_IPv4_ADDRESS GatewayAddress;\r
394 EFI_STATUS Status;\r
395 UINTN DnsSize;\r
396 UINTN DnsCount;\r
397 EFI_IPv4_ADDRESS *DnsAddress;\r
398\r
399 Status = EFI_SUCCESS;\r
400 Ip4Config2 = &Instance->Ip4Config2;\r
401 Ip4Info = NULL;\r
402 DnsAddress = NULL;\r
403 GatewaySize = sizeof (EFI_IPv4_ADDRESS);\r
404 \r
405 if ((IfrNvData == NULL) || (Instance == NULL)) {\r
406 return EFI_INVALID_PARAMETER;\r
407 }\r
408 \r
409 NET_CHECK_SIGNATURE (Instance, IP4_CONFIG2_INSTANCE_SIGNATURE);\r
410\r
411 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
412\r
413 if (IpSb->DefaultInterface->Configured) {\r
414 IfrNvData->Configure = 1;\r
415 } else {\r
416 IfrNvData->Configure = 0;\r
417 goto Exit;\r
418 }\r
419\r
420 //\r
421 // Get the Policy info.\r
422 // \r
423 DataSize = sizeof (EFI_IP4_CONFIG2_POLICY);\r
424 Status = Ip4Config2->GetData (\r
425 Ip4Config2,\r
426 Ip4Config2DataTypePolicy,\r
427 &DataSize,\r
428 &Policy\r
429 );\r
430 if (EFI_ERROR (Status)) {\r
431 goto Exit;\r
432 }\r
433 \r
434 if (Policy == Ip4Config2PolicyStatic) {\r
435 IfrNvData->DhcpEnable = FALSE;\r
436 } else if (Policy == Ip4Config2PolicyDhcp) {\r
437 IfrNvData->DhcpEnable = TRUE;\r
438 goto Exit;\r
439 }\r
440 \r
441 //\r
442 // Get the interface info.\r
443 //\r
444 DataSize = 0;\r
445 Status = Ip4Config2->GetData (\r
446 Ip4Config2,\r
447 Ip4Config2DataTypeInterfaceInfo,\r
448 &DataSize,\r
449 NULL\r
450 );\r
451 if (Status != EFI_BUFFER_TOO_SMALL) {\r
452 return Status;\r
453 }\r
454 \r
455 Ip4Info = AllocateZeroPool (DataSize);\r
456 if (Ip4Info == NULL) {\r
457 Status = EFI_OUT_OF_RESOURCES;\r
458 return Status;\r
459 }\r
460\r
461 Status = Ip4Config2->GetData (\r
462 Ip4Config2,\r
463 Ip4Config2DataTypeInterfaceInfo,\r
464 &DataSize,\r
465 Ip4Info\r
466 );\r
467 if (EFI_ERROR (Status)) {\r
468 goto Exit;\r
469 }\r
470 \r
471 //\r
472 // Get the Gateway info.\r
473 //\r
474 Status = Ip4Config2->GetData (\r
475 Ip4Config2,\r
476 Ip4Config2DataTypeGateway,\r
477 &GatewaySize,\r
478 &GatewayAddress\r
479 );\r
480 if (EFI_ERROR (Status)) {\r
481 goto Exit;\r
482 }\r
483\r
484 //\r
485 // Get the Dns info.\r
486 //\r
487 DnsSize = 0;\r
488 Status = Ip4Config2->GetData (\r
489 Ip4Config2,\r
490 Ip4Config2DataTypeDnsServer,\r
491 &DnsSize,\r
492 NULL\r
493 );\r
494 if ((Status != EFI_BUFFER_TOO_SMALL) && (Status != EFI_NOT_FOUND)) {\r
495 goto Exit;\r
496 }\r
497 \r
498 DnsCount = (UINT32) (DnsSize / sizeof (EFI_IPv4_ADDRESS));\r
499\r
500 if (DnsSize > 0) {\r
501 DnsAddress = AllocateZeroPool(DnsSize);\r
502 if (DnsAddress == NULL) {\r
503 Status = EFI_OUT_OF_RESOURCES;\r
504 goto Exit;\r
505 }\r
506 \r
507 Status = Ip4Config2->GetData (\r
508 Ip4Config2,\r
509 Ip4Config2DataTypeDnsServer,\r
510 &DnsSize,\r
511 DnsAddress\r
512 );\r
513 if (EFI_ERROR (Status)) {\r
514 goto Exit;\r
515 }\r
516 }\r
517\r
518 Ip4Config2IpToStr (&Ip4Info->StationAddress, IfrNvData->StationAddress);\r
519 Ip4Config2IpToStr (&Ip4Info->SubnetMask, IfrNvData->SubnetMask);\r
520 Ip4Config2IpToStr (&GatewayAddress, IfrNvData->GatewayAddress);\r
521 Ip4Config2IpListToStr (DnsAddress, DnsCount, IfrNvData->DnsAddress);\r
522\r
523Exit:\r
524\r
525 if (DnsAddress != NULL) {\r
526 FreePool(DnsAddress);\r
527 }\r
528\r
529 if (Ip4Info != NULL) {\r
530 FreePool(Ip4Info);\r
531 }\r
532 \r
533 return Status;\r
534}\r
535\r
536/**\r
537 Convert the IFR data into the network configuration data and set the IP\r
538 configure parameters for the NIC.\r
539\r
540 @param[in] IfrFormNvData The IFR NV data.\r
541 @param[in, out] Instance The IP4 config2 instance.\r
542\r
543 @retval EFI_SUCCESS The configure parameter for this NIC was\r
544 set successfully.\r
545 @retval EFI_INVALID_PARAMETER The address information for setting is invalid.\r
546 @retval Others Other errors as indicated.\r
547 \r
548**/\r
549EFI_STATUS\r
550Ip4Config2ConvertIfrNvDataToConfigNvData (\r
551 IN IP4_CONFIG2_IFR_NVDATA *IfrFormNvData,\r
552 IN OUT IP4_CONFIG2_INSTANCE *Instance\r
553 )\r
554{\r
555 EFI_STATUS Status; \r
556 EFI_IP4_CONFIG2_PROTOCOL *Ip4Cfg2;\r
557 IP4_CONFIG2_NVDATA *Ip4NvData; \r
558\r
559 EFI_IP_ADDRESS StationAddress;\r
560 EFI_IP_ADDRESS SubnetMask;\r
561 EFI_IP_ADDRESS Gateway;\r
562 IP4_ADDR Ip;\r
563 EFI_IPv4_ADDRESS *DnsAddress;\r
564 UINTN DnsCount;\r
565 UINTN Index;\r
566\r
567 EFI_EVENT TimeoutEvent;\r
568 EFI_EVENT SetAddressEvent;\r
569 BOOLEAN IsAddressOk;\r
570 UINTN DataSize;\r
571 EFI_INPUT_KEY Key;\r
572\r
573 Status = EFI_SUCCESS;\r
574 Ip4Cfg2 = &Instance->Ip4Config2;\r
575 Ip4NvData = &Instance->Ip4NvData;\r
576 \r
577 DnsCount = 0;\r
578 DnsAddress = NULL; \r
579 \r
580 TimeoutEvent = NULL;\r
581 SetAddressEvent = NULL;\r
582\r
583\r
584 \r
585 if (Instance == NULL || IfrFormNvData == NULL) {\r
586 return EFI_INVALID_PARAMETER;\r
587 }\r
588\r
589 if (IfrFormNvData->Configure != TRUE) {\r
590 return EFI_SUCCESS;\r
591 }\r
592 \r
593 if (IfrFormNvData->DhcpEnable == TRUE) {\r
594 Ip4NvData->Policy = Ip4Config2PolicyDhcp;\r
595 \r
596 Status = Ip4Cfg2->SetData (\r
597 Ip4Cfg2,\r
598 Ip4Config2DataTypePolicy,\r
599 sizeof (EFI_IP4_CONFIG2_POLICY),\r
600 &Ip4NvData->Policy\r
601 );\r
602 if (EFI_ERROR(Status)) {\r
603 return Status;\r
604 }\r
605 } else {\r
606 //\r
607 // Get Ip4NvData from IfrFormNvData if it is valid.\r
608 //\r
609 Ip4NvData->Policy = Ip4Config2PolicyStatic;\r
610\r
1f6729ff 611 Status = Ip4Config2StrToIp (IfrFormNvData->SubnetMask, &SubnetMask.v4);\r
612 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (GetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {\r
613 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL);\r
614 return EFI_INVALID_PARAMETER;\r
615 }\r
01b5ac88
FS
616\r
617 Status = Ip4Config2StrToIp (IfrFormNvData->StationAddress, &StationAddress.v4);\r
d0e76ac5
JW
618 if (EFI_ERROR (Status) || \r
619 (SubnetMask.Addr[0] != 0 && !NetIp4IsUnicast (NTOHL (StationAddress.Addr[0]), NTOHL (SubnetMask.Addr[0]))) || \r
620 !Ip4StationAddressValid (NTOHL (StationAddress.Addr[0]), NTOHL (SubnetMask.Addr[0]))) {\r
01b5ac88
FS
621 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);\r
622 return EFI_INVALID_PARAMETER;\r
623 }\r
1f6729ff 624 \r
625 Status = Ip4Config2StrToIp (IfrFormNvData->GatewayAddress, &Gateway.v4);\r
d0e76ac5
JW
626 if (EFI_ERROR (Status) || \r
627 (Gateway.Addr[0] != 0 && SubnetMask.Addr[0] != 0 && !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), NTOHL (SubnetMask.Addr[0])))) {\r
1f6729ff 628 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL);\r
629 return EFI_INVALID_PARAMETER;\r
630 }\r
631\r
632 Status = Ip4Config2StrToIpList (IfrFormNvData->DnsAddress, &DnsAddress, &DnsCount);\r
633 if (!EFI_ERROR (Status) && DnsCount > 0) {\r
634 for (Index = 0; Index < DnsCount; Index ++) {\r
635 CopyMem (&Ip, &DnsAddress[Index], sizeof (IP4_ADDR));\r
01b5ac88 636 if (IP4_IS_UNSPECIFIED (NTOHL (Ip)) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip))) {\r
1f6729ff 637 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL);\r
638 FreePool(DnsAddress);\r
639 return EFI_INVALID_PARAMETER;\r
640 } \r
641 } \r
642 } else {\r
643 if (EFI_ERROR (Status)) {\r
644 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL);\r
645 }\r
646 }\r
647 \r
648 if (Ip4NvData->ManualAddress != NULL) {\r
649 FreePool(Ip4NvData->ManualAddress); \r
650 }\r
651 Ip4NvData->ManualAddressCount = 1;\r
652 Ip4NvData->ManualAddress = AllocateZeroPool(sizeof(EFI_IP4_CONFIG2_MANUAL_ADDRESS));\r
653 if (Ip4NvData->ManualAddress == NULL) {\r
654 if (DnsAddress != NULL) {\r
655 FreePool(DnsAddress);\r
656 }\r
657 \r
658 return EFI_OUT_OF_RESOURCES;\r
659 }\r
660 CopyMem(&Ip4NvData->ManualAddress->Address, &StationAddress.v4, sizeof(EFI_IPv4_ADDRESS));\r
661 CopyMem(&Ip4NvData->ManualAddress->SubnetMask, &SubnetMask.v4, sizeof(EFI_IPv4_ADDRESS));\r
662 \r
663 if (Ip4NvData->GatewayAddress != NULL) {\r
664 FreePool(Ip4NvData->GatewayAddress); \r
665 }\r
666 Ip4NvData->GatewayAddressCount = 1;\r
667 Ip4NvData->GatewayAddress = AllocateZeroPool(sizeof(EFI_IPv4_ADDRESS));\r
668 if (Ip4NvData->GatewayAddress == NULL) {\r
669 if (DnsAddress != NULL) {\r
670 FreePool(DnsAddress);\r
671 }\r
672 return EFI_OUT_OF_RESOURCES;\r
673 }\r
674 CopyMem(Ip4NvData->GatewayAddress, &Gateway.v4, sizeof(EFI_IPv4_ADDRESS));\r
675 \r
676 if (Ip4NvData->DnsAddress != NULL) {\r
677 FreePool(Ip4NvData->DnsAddress); \r
678 }\r
679 Ip4NvData->DnsAddressCount = (UINT32) DnsCount;\r
680 Ip4NvData->DnsAddress = DnsAddress;\r
681\r
682 //\r
683 // Setting Ip4NvData.\r
684 //\r
685 Status = Ip4Cfg2->SetData (\r
686 Ip4Cfg2,\r
687 Ip4Config2DataTypePolicy,\r
688 sizeof (EFI_IP4_CONFIG2_POLICY),\r
689 &Ip4NvData->Policy\r
690 );\r
691 if (EFI_ERROR(Status)) {\r
692 return Status;\r
693 }\r
694\r
695 //\r
696 // Create events & timers for asynchronous settings.\r
697 //\r
698 Status = gBS->CreateEvent (\r
699 EVT_TIMER,\r
700 TPL_CALLBACK,\r
701 NULL,\r
702 NULL,\r
703 &TimeoutEvent\r
704 );\r
705 if (EFI_ERROR (Status)) {\r
706 return EFI_OUT_OF_RESOURCES;\r
707 }\r
708\r
709 Status = gBS->CreateEvent (\r
710 EVT_NOTIFY_SIGNAL,\r
711 TPL_NOTIFY,\r
712 Ip4Config2ManualAddressNotify,\r
713 &IsAddressOk,\r
714 &SetAddressEvent\r
715 );\r
716 if (EFI_ERROR (Status)) {\r
717 goto Exit;\r
718 }\r
719\r
720 IsAddressOk = FALSE;\r
721 \r
722 Status = Ip4Cfg2->RegisterDataNotify (\r
723 Ip4Cfg2,\r
724 Ip4Config2DataTypeManualAddress,\r
725 SetAddressEvent\r
726 );\r
727 if (EFI_ERROR (Status)) {\r
728 goto Exit;\r
729 }\r
730\r
731 //\r
732 // Set ManualAddress.\r
733 //\r
734 DataSize = Ip4NvData->ManualAddressCount * sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS);\r
735 Status = Ip4Cfg2->SetData (\r
736 Ip4Cfg2,\r
737 Ip4Config2DataTypeManualAddress,\r
738 DataSize,\r
739 (VOID *) Ip4NvData->ManualAddress\r
740 );\r
741\r
742 if (Status == EFI_NOT_READY) {\r
743 gBS->SetTimer (TimeoutEvent, TimerRelative, 50000000);\r
744 while (EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {\r
745 if (IsAddressOk) {\r
746 Status = EFI_SUCCESS;\r
747 break;\r
748 }\r
749 }\r
750 }\r
751\r
752 Ip4Cfg2->UnregisterDataNotify (\r
753 Ip4Cfg2,\r
754 Ip4Config2DataTypeManualAddress,\r
755 SetAddressEvent\r
756 );\r
757 if (EFI_ERROR (Status)) {\r
758 goto Exit;\r
759 }\r
760\r
761 //\r
762 // Set gateway.\r
763 //\r
764 DataSize = Ip4NvData->GatewayAddressCount * sizeof (EFI_IPv4_ADDRESS);\r
765 Status = Ip4Cfg2->SetData (\r
766 Ip4Cfg2,\r
767 Ip4Config2DataTypeGateway,\r
768 DataSize,\r
769 Ip4NvData->GatewayAddress\r
770 );\r
771 if (EFI_ERROR (Status)) {\r
772 goto Exit;\r
773 }\r
774\r
775 //\r
776 // Set DNS addresses.\r
777 //\r
778 if (Ip4NvData->DnsAddressCount > 0 && Ip4NvData->DnsAddress != NULL) {\r
779 DataSize = Ip4NvData->DnsAddressCount * sizeof (EFI_IPv4_ADDRESS);\r
780 Status = Ip4Cfg2->SetData (\r
781 Ip4Cfg2,\r
782 Ip4Config2DataTypeDnsServer,\r
783 DataSize,\r
784 Ip4NvData->DnsAddress\r
785 );\r
786 \r
787 if (EFI_ERROR (Status)) {\r
788 goto Exit;\r
789 } \r
790 } \r
791 } \r
792\r
793Exit:\r
794 if (SetAddressEvent != NULL) {\r
795 gBS->CloseEvent (SetAddressEvent);\r
796 }\r
797\r
798 if (TimeoutEvent != NULL) {\r
799 gBS->CloseEvent (TimeoutEvent);\r
800 }\r
801\r
802 return Status;\r
803}\r
804\r
805/**\r
806 This function allows the caller to request the current\r
807 configuration for one or more named elements. The resulting\r
808 string is in <ConfigAltResp> format. Any and all alternative\r
809 configuration strings shall also be appended to the end of the\r
810 current configuration string. If they are, they must appear\r
811 after the current configuration. They must contain the same\r
812 routing (GUID, NAME, PATH) as the current configuration string.\r
813 They must have an additional description indicating the type of\r
814 alternative configuration the string represents,\r
815 "ALTCFG=<StringToken>". That <StringToken> (when\r
816 converted from Hex UNICODE to binary) is a reference to a\r
817 string in the associated string pack.\r
818\r
819 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
820 @param[in] Request A null-terminated Unicode string in\r
821 <ConfigRequest> format. Note that this\r
822 includes the routing information as well as\r
823 the configurable name / value pairs. It is\r
824 invalid for this string to be in\r
825 <MultiConfigRequest> format.\r
826 @param[out] Progress On return, points to a character in the\r
827 Request string. Points to the string's null\r
828 terminator if request was successful. Points\r
829 to the most recent "&" before the first\r
830 failing name / value pair (or the beginning\r
831 of the string if the failure is in the first\r
832 name / value pair) if the request was not\r
833 successful.\r
834 @param[out] Results A null-terminated Unicode string in\r
835 <ConfigAltResp> format which has all values\r
836 filled in for the names in the Request string.\r
837 String to be allocated by the called function.\r
838\r
839 @retval EFI_SUCCESS The Results string is filled with the\r
840 values corresponding to all requested\r
841 names.\r
842 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the\r
843 parts of the results that must be\r
844 stored awaiting possible future\r
845 protocols.\r
846 @retval EFI_NOT_FOUND Routing data doesn't match any\r
847 known driver. Progress set to the\r
848 first character in the routing header.\r
849 Note: There is no requirement that the\r
850 driver validate the routing data. It\r
851 must skip the <ConfigHdr> in order to\r
852 process the names.\r
853 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set\r
854 to most recent & before the\r
855 error or the beginning of the\r
856 string.\r
857 @retval EFI_INVALID_PARAMETER Unknown name. Progress points\r
858 to the & before the name in\r
859 question.Currently not implemented.\r
860**/\r
861EFI_STATUS\r
862EFIAPI\r
863Ip4FormExtractConfig (\r
864 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
865 IN CONST EFI_STRING Request,\r
866 OUT EFI_STRING *Progress,\r
867 OUT EFI_STRING *Results\r
868 )\r
869{\r
870 EFI_STATUS Status; \r
871 IP4_CONFIG2_INSTANCE *Ip4Config2Instance;\r
872 IP4_FORM_CALLBACK_INFO *Private; \r
873 IP4_CONFIG2_IFR_NVDATA *IfrFormNvData;\r
874 EFI_STRING ConfigRequestHdr;\r
875 EFI_STRING ConfigRequest; \r
876 BOOLEAN AllocatedRequest;\r
877 EFI_STRING FormResult;\r
878 UINTN Size;\r
879 UINTN BufferSize;\r
b1d4218a 880\r
881 if (Progress == NULL || Results == NULL) {\r
882 return EFI_INVALID_PARAMETER;\r
883 }\r
1f6729ff 884 \r
885 Status = EFI_SUCCESS; \r
886 IfrFormNvData = NULL;\r
887 ConfigRequest = NULL;\r
888 FormResult = NULL; \r
889 Size = 0;\r
890 AllocatedRequest = FALSE; \r
891 ConfigRequest = Request; \r
892 Private = IP4_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS(This);\r
893 Ip4Config2Instance = IP4_CONFIG2_INSTANCE_FROM_FORM_CALLBACK(Private);\r
894 BufferSize = sizeof (IP4_CONFIG2_IFR_NVDATA);\r
895 *Progress = Request;\r
896 \r
1f6729ff 897 //\r
898 // Check Request data in <ConfigHdr>.\r
899 //\r
900 if ((Request == NULL) || HiiIsConfigHdrMatch (Request, &gIp4Config2NvDataGuid, mIp4Config2StorageName)) {\r
901 IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG2_IFR_NVDATA));\r
902 if (IfrFormNvData == NULL) {\r
903 return EFI_OUT_OF_RESOURCES;\r
904 }\r
905 \r
906 Ip4Config2ConvertConfigNvDataToIfrNvData (Ip4Config2Instance, IfrFormNvData);\r
907 \r
908 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
909 //\r
910 // Request has no request element, construct full request string.\r
911 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
912 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
913 //\r
914 ConfigRequestHdr = HiiConstructConfigHdr (&gIp4Config2NvDataGuid, mIp4Config2StorageName, Private->ChildHandle);\r
915 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
916 ConfigRequest = AllocateZeroPool (Size);\r
917 ASSERT (ConfigRequest != NULL);\r
918 AllocatedRequest = TRUE;\r
919 \r
920 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
921 FreePool (ConfigRequestHdr);\r
922 }\r
923\r
924 //\r
925 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
926 //\r
927 Status = gHiiConfigRouting->BlockToConfig (\r
928 gHiiConfigRouting,\r
929 ConfigRequest,\r
930 (UINT8 *) IfrFormNvData,\r
931 BufferSize,\r
932 &FormResult,\r
933 Progress\r
934 );\r
935\r
936 FreePool (IfrFormNvData);\r
937 \r
938 //\r
939 // Free the allocated config request string.\r
940 //\r
941 if (AllocatedRequest) {\r
942 FreePool (ConfigRequest);\r
943 ConfigRequest = NULL;\r
944 }\r
945\r
946 if (EFI_ERROR (Status)) {\r
947 goto Failure;\r
948 }\r
949 }\r
950 \r
951 if (Request == NULL || HiiIsConfigHdrMatch (Request, &gIp4Config2NvDataGuid, mIp4Config2StorageName)) {\r
952 *Results = FormResult;\r
953 } else {\r
954 return EFI_NOT_FOUND;\r
955 }\r
956\r
957Failure:\r
958 //\r
959 // Set Progress string to the original request string.\r
960 //\r
961 if (Request == NULL) {\r
962 *Progress = NULL;\r
963 } else if (StrStr (Request, L"OFFSET") == NULL) {\r
964 *Progress = Request + StrLen (Request);\r
965 }\r
966\r
967 return Status;\r
968}\r
969\r
970/**\r
971 This function applies changes in a driver's configuration.\r
972 Input is a Configuration, which has the routing data for this\r
973 driver followed by name / value configuration pairs. The driver\r
974 must apply those pairs to its configurable storage. If the\r
975 driver's configuration is stored in a linear block of data\r
976 and the driver's name / value pairs are in <BlockConfig>\r
977 format, it may use the ConfigToBlock helper function (above) to\r
978 simplify the job. Currently not implemented.\r
979\r
980 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
981 @param[in] Configuration A null-terminated Unicode string in\r
982 <ConfigString> format.\r
983 @param[out] Progress A pointer to a string filled in with the\r
984 offset of the most recent '&' before the\r
985 first failing name / value pair (or the\r
986 beginn ing of the string if the failure\r
987 is in the first name / value pair) or\r
988 the terminating NULL if all was\r
989 successful.\r
990\r
991 @retval EFI_SUCCESS The results have been distributed or are\r
992 awaiting distribution.\r
993 @retval EFI_OUT_OF_MEMORY Not enough memory to store the\r
994 parts of the results that must be\r
995 stored awaiting possible future\r
996 protocols.\r
997 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the\r
998 Results parameter would result\r
999 in this type of error.\r
1000 @retval EFI_NOT_FOUND Target for the specified routing data\r
1001 was not found.\r
1002**/\r
1003EFI_STATUS\r
1004EFIAPI\r
1005Ip4FormRouteConfig (\r
1006 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
1007 IN CONST EFI_STRING Configuration,\r
1008 OUT EFI_STRING *Progress\r
1009 )\r
1010{\r
1011 EFI_STATUS Status;\r
1012 UINTN BufferSize;\r
1013 IP4_CONFIG2_IFR_NVDATA *IfrFormNvData;\r
1014 IP4_CONFIG2_INSTANCE *Ip4Config2Instance;\r
1015 IP4_FORM_CALLBACK_INFO *Private;\r
1016\r
1017 Status = EFI_SUCCESS;\r
1018 IfrFormNvData = NULL;\r
1019\r
1020 if (Configuration == NULL || Progress == NULL) {\r
1021 return EFI_INVALID_PARAMETER;\r
1022 }\r
1023\r
1024 *Progress = Configuration;\r
1025\r
1026 Private = IP4_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS(This);\r
1027 Ip4Config2Instance = IP4_CONFIG2_INSTANCE_FROM_FORM_CALLBACK(Private);\r
1028\r
1029 //\r
1030 // Check Routing data in <ConfigHdr>.\r
1031 //\r
1032 if (HiiIsConfigHdrMatch (Configuration, &gIp4Config2NvDataGuid, mIp4Config2StorageName)) {\r
1033 //\r
1034 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
1035 //\r
1036 IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG2_IFR_NVDATA));\r
1037 if (IfrFormNvData == NULL) {\r
1038 return EFI_OUT_OF_RESOURCES;\r
1039 }\r
1040\r
1041 BufferSize = 0;\r
1042\r
1043 Status = gHiiConfigRouting->ConfigToBlock (\r
1044 gHiiConfigRouting,\r
1045 Configuration,\r
1046 (UINT8 *) IfrFormNvData,\r
1047 &BufferSize,\r
1048 Progress\r
1049 );\r
1050 if (Status != EFI_BUFFER_TOO_SMALL) {\r
1051 return Status;\r
1052 }\r
1053\r
1054 Status = gHiiConfigRouting->ConfigToBlock (\r
1055 gHiiConfigRouting,\r
1056 Configuration,\r
1057 (UINT8 *) IfrFormNvData,\r
1058 &BufferSize,\r
1059 Progress\r
1060 );\r
1061 if (!EFI_ERROR (Status)) {\r
1062 Status = Ip4Config2ConvertIfrNvDataToConfigNvData (IfrFormNvData, Ip4Config2Instance);\r
1063 }\r
1064\r
1065 FreePool (IfrFormNvData);\r
1066 } else {\r
1067 return EFI_NOT_FOUND;\r
1068 }\r
1069\r
1070 return Status;\r
1071\r
1072}\r
1073\r
1074/**\r
1075 This function is called to provide results data to the driver.\r
1076 This data consists of a unique key that is used to identify\r
1077 which data is either being passed back or being asked for.\r
1078\r
1079 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
1080 @param[in] Action Specifies the type of action taken by the browser.\r
1081 @param[in] QuestionId A unique value which is sent to the original\r
1082 exporting driver so that it can identify the type\r
1083 of data to expect. The format of the data tends to\r
1084 vary based on the opcode that enerated the callback.\r
1085 @param[in] Type The type of value for the question.\r
1086 @param[in] Value A pointer to the data being sent to the original\r
1087 exporting driver.\r
1088 @param[out] ActionRequest On return, points to the action requested by the\r
1089 callback function.\r
1090\r
1091 @retval EFI_SUCCESS The callback successfully handled the action.\r
1092 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the\r
1093 variable and its data.\r
1094 @retval EFI_DEVICE_ERROR The variable could not be saved.\r
1095 @retval EFI_UNSUPPORTED The specified Action is not supported by the\r
1096 callback.Currently not implemented.\r
1097 @retval EFI_INVALID_PARAMETERS Passing in wrong parameter.\r
1098 @retval Others Other errors as indicated.\r
1099 \r
1100**/\r
1101EFI_STATUS\r
1102EFIAPI\r
1103Ip4FormCallback (\r
1104 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
1105 IN EFI_BROWSER_ACTION Action,\r
1106 IN EFI_QUESTION_ID QuestionId,\r
1107 IN UINT8 Type,\r
1108 IN EFI_IFR_TYPE_VALUE *Value,\r
1109 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
1110 )\r
1111{\r
1112 EFI_STATUS Status;\r
1113 IP4_CONFIG2_INSTANCE *Instance;\r
1114 IP4_CONFIG2_IFR_NVDATA *IfrFormNvData;\r
1115 IP4_FORM_CALLBACK_INFO *Private;\r
1116 \r
1117 EFI_IP_ADDRESS StationAddress;\r
1118 EFI_IP_ADDRESS SubnetMask;\r
1119 EFI_IP_ADDRESS Gateway;\r
1120 IP4_ADDR Ip;\r
1121 EFI_IPv4_ADDRESS *DnsAddress;\r
1122 UINTN DnsCount;\r
1123 UINTN Index;\r
1124 EFI_INPUT_KEY Key;\r
1125 \r
1126 IfrFormNvData = NULL;\r
1127 DnsCount = 0;\r
1128 DnsAddress = NULL; \r
1129\r
1130 if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
1131 Private = IP4_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS(This);\r
1132 Instance = IP4_CONFIG2_INSTANCE_FROM_FORM_CALLBACK(Private);\r
1133 \r
1134 IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG2_IFR_NVDATA));\r
1135 if (IfrFormNvData == NULL) {\r
1136 return EFI_OUT_OF_RESOURCES;\r
1137 }\r
1138\r
1139 //\r
0a18956d 1140 // Retrieve uncommitted data from Browser\r
1f6729ff 1141 //\r
1142 if (!HiiGetBrowserData (&gIp4Config2NvDataGuid, mIp4Config2StorageName, sizeof (IP4_CONFIG2_IFR_NVDATA), (UINT8 *) IfrFormNvData)) {\r
1143 FreePool (IfrFormNvData);\r
1144 return EFI_NOT_FOUND;\r
1145 }\r
1146\r
1147 Status = EFI_SUCCESS;\r
1148\r
1149 switch (QuestionId) {\r
1150 case KEY_LOCAL_IP:\r
1151 Status = Ip4Config2StrToIp (IfrFormNvData->StationAddress, &StationAddress.v4);\r
01b5ac88 1152 if (EFI_ERROR (Status) || IP4_IS_UNSPECIFIED (NTOHL (StationAddress.Addr[0])) || IP4_IS_LOCAL_BROADCAST (NTOHL (StationAddress.Addr[0]))) {\r
1f6729ff 1153 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);\r
1154 Status = EFI_INVALID_PARAMETER;\r
1155 }\r
1156 break;\r
1157\r
1158 case KEY_SUBNET_MASK:\r
1159 Status = Ip4Config2StrToIp (IfrFormNvData->SubnetMask, &SubnetMask.v4);\r
1160 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (GetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {\r
1161 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL);\r
1162 Status = EFI_INVALID_PARAMETER;\r
1163 }\r
1164 break;\r
1165\r
1166 case KEY_GATE_WAY:\r
1167 Status = Ip4Config2StrToIp (IfrFormNvData->GatewayAddress, &Gateway.v4);\r
01b5ac88 1168 if (EFI_ERROR (Status) || IP4_IS_LOCAL_BROADCAST(NTOHL(Gateway.Addr[0]))) {\r
1f6729ff 1169 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL);\r
1170 Status = EFI_INVALID_PARAMETER;\r
1171 }\r
1172 break;\r
1173 \r
1174 case KEY_DNS:\r
1175 Status = Ip4Config2StrToIpList (IfrFormNvData->DnsAddress, &DnsAddress, &DnsCount);\r
1176 if (!EFI_ERROR (Status) && DnsCount > 0) {\r
1177 for (Index = 0; Index < DnsCount; Index ++) {\r
1178 CopyMem (&Ip, &DnsAddress[Index], sizeof (IP4_ADDR));\r
01b5ac88 1179 if (IP4_IS_UNSPECIFIED (NTOHL (Ip)) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip))) {\r
1f6729ff 1180 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL);\r
1181 Status = EFI_INVALID_PARAMETER;\r
1182 break;\r
1183 } \r
1184 }\r
1185 } else {\r
1186 if (EFI_ERROR (Status)) {\r
1187 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL);\r
1188 }\r
1189 }\r
1190 \r
1191 if(DnsAddress != NULL) { \r
1192 FreePool(DnsAddress);\r
1193 }\r
1194 break;\r
1195 \r
1196 case KEY_SAVE_CHANGES:\r
1197 Status = Ip4Config2ConvertIfrNvDataToConfigNvData (IfrFormNvData, Instance);\r
1198 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
1199 break;\r
1200\r
1201 default:\r
1202 break;\r
1203 }\r
1204\r
1205 FreePool (IfrFormNvData);\r
1206\r
1207 return Status;\r
1208 }\r
1209\r
1210 //\r
1211 // All other action return unsupported.\r
1212 //\r
1213 return EFI_UNSUPPORTED;\r
1214}\r
1215\r
1216/**\r
1217 Install HII Config Access protocol for network device and allocate resource.\r
1218\r
1219 @param[in, out] Instance The IP4 config2 Instance.\r
1220\r
1221 @retval EFI_SUCCESS The HII Config Access protocol is installed.\r
1222 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
1223 @retval Others Other errors as indicated.\r
1224 \r
1225**/\r
1226EFI_STATUS\r
1227Ip4Config2FormInit (\r
1228 IN OUT IP4_CONFIG2_INSTANCE *Instance\r
1229 )\r
1230{\r
1231 EFI_STATUS Status;\r
1232 IP4_SERVICE *IpSb;\r
1233 IP4_FORM_CALLBACK_INFO *CallbackInfo;\r
1234 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
1235 VENDOR_DEVICE_PATH VendorDeviceNode;\r
1236 EFI_SERVICE_BINDING_PROTOCOL *MnpSb;\r
1237 CHAR16 *MacString;\r
1238 CHAR16 MenuString[128];\r
1239 CHAR16 PortString[128];\r
1240 CHAR16 *OldMenuString;\r
1241 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
1242\r
1243 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
1244 ASSERT (IpSb != NULL);\r
1245 \r
1246 CallbackInfo = &Instance->CallbackInfo;\r
1247 \r
1248 CallbackInfo->Signature = IP4_FORM_CALLBACK_INFO_SIGNATURE;\r
1249\r
1250 Status = gBS->HandleProtocol (\r
1251 IpSb->Controller,\r
1252 &gEfiDevicePathProtocolGuid,\r
1253 (VOID **) &ParentDevicePath\r
1254 );\r
1255 if (EFI_ERROR (Status)) {\r
1256 return Status;\r
1257 }\r
1258\r
1259 //\r
1260 // Construct device path node for EFI HII Config Access protocol,\r
1261 // which consists of controller physical device path and one hardware\r
1262 // vendor guid node.\r
1263 //\r
1264 ZeroMem (&VendorDeviceNode, sizeof (VENDOR_DEVICE_PATH));\r
1265 VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH;\r
1266 VendorDeviceNode.Header.SubType = HW_VENDOR_DP;\r
1267\r
1268 CopyGuid (&VendorDeviceNode.Guid, &gEfiCallerIdGuid);\r
1269\r
1270 SetDevicePathNodeLength (&VendorDeviceNode.Header, sizeof (VENDOR_DEVICE_PATH));\r
1271 CallbackInfo->HiiVendorDevicePath = AppendDevicePathNode (\r
1272 ParentDevicePath,\r
1273 (EFI_DEVICE_PATH_PROTOCOL *) &VendorDeviceNode\r
1274 );\r
1275 if (CallbackInfo->HiiVendorDevicePath == NULL) {\r
1276 Status = EFI_OUT_OF_RESOURCES;\r
1277 goto Error;\r
1278 }\r
1279\r
1280 ConfigAccess = &CallbackInfo->HiiConfigAccessProtocol;\r
1281 ConfigAccess->ExtractConfig = Ip4FormExtractConfig;\r
1282 ConfigAccess->RouteConfig = Ip4FormRouteConfig;\r
1283 ConfigAccess->Callback = Ip4FormCallback;\r
1284\r
1285 //\r
1286 // Install Device Path Protocol and Config Access protocol on new handle\r
1287 //\r
1288 Status = gBS->InstallMultipleProtocolInterfaces (\r
1289 &CallbackInfo->ChildHandle,\r
1290 &gEfiDevicePathProtocolGuid,\r
1291 CallbackInfo->HiiVendorDevicePath,\r
1292 &gEfiHiiConfigAccessProtocolGuid,\r
1293 ConfigAccess,\r
1294 NULL\r
1295 );\r
1296\r
1297 if (!EFI_ERROR (Status)) {\r
1298 //\r
1299 // Open the Parent Handle for the child\r
1300 //\r
1301 Status = gBS->OpenProtocol (\r
1302 IpSb->Controller,\r
1303 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
1304 (VOID **) &MnpSb,\r
1305 IpSb->Image,\r
1306 CallbackInfo->ChildHandle,\r
1307 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
1308 );\r
1309 }\r
1310\r
1311 if (EFI_ERROR (Status)) {\r
1312 goto Error;\r
1313 }\r
1314\r
1315 //\r
1316 // Publish our HII data\r
1317 //\r
1318 CallbackInfo->RegisteredHandle = HiiAddPackages (\r
1319 &gIp4Config2NvDataGuid,\r
1320 CallbackInfo->ChildHandle,\r
1321 Ip4DxeStrings,\r
1322 Ip4Config2Bin,\r
1323 NULL\r
1324 );\r
1325 if (CallbackInfo->RegisteredHandle == NULL) {\r
1326 Status = EFI_OUT_OF_RESOURCES;\r
1327 goto Error;\r
1328 }\r
1329\r
1330 //\r
1331 // Append MAC string in the menu help string and tile help string\r
1332 //\r
1333 Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &MacString);\r
1334 if (!EFI_ERROR (Status)) {\r
1335 OldMenuString = HiiGetString (\r
1336 CallbackInfo->RegisteredHandle, \r
1337 STRING_TOKEN (STR_IP4_CONFIG2_FORM_HELP), \r
1338 NULL\r
1339 );\r
1340 UnicodeSPrint (MenuString, 128, L"%s (MAC:%s)", OldMenuString, MacString);\r
1341 HiiSetString (\r
1342 CallbackInfo->RegisteredHandle, \r
1343 STRING_TOKEN (STR_IP4_CONFIG2_FORM_HELP), \r
1344 MenuString, \r
1345 NULL\r
1346 );\r
1347\r
1348 UnicodeSPrint (PortString, 128, L"MAC:%s", MacString);\r
1349 HiiSetString (\r
1350 CallbackInfo->RegisteredHandle, \r
1351 STRING_TOKEN (STR_IP4_DEVICE_FORM_HELP), \r
1352 PortString, \r
1353 NULL\r
1354 );\r
1355 \r
1356 FreePool (MacString);\r
1357 FreePool (OldMenuString);\r
1358\r
1359 return EFI_SUCCESS;\r
1360 }\r
1361\r
1362Error:\r
1363 Ip4Config2FormUnload (Instance);\r
1364 return Status;\r
1365}\r
1366\r
1367/**\r
1368 Uninstall the HII Config Access protocol for network devices and free up the resources.\r
1369\r
1370 @param[in, out] Instance The IP4 config2 instance to unload a form.\r
1371\r
1372**/\r
1373VOID\r
1374Ip4Config2FormUnload (\r
1375 IN OUT IP4_CONFIG2_INSTANCE *Instance\r
1376 )\r
1377{\r
1378 IP4_SERVICE *IpSb;\r
1379 IP4_FORM_CALLBACK_INFO *CallbackInfo;\r
1380 IP4_CONFIG2_NVDATA *Ip4NvData;\r
1381\r
1382 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
1383 ASSERT (IpSb != NULL);\r
1384\r
1385 CallbackInfo = &Instance->CallbackInfo;\r
1386\r
1387 if (CallbackInfo->ChildHandle != NULL) {\r
1388 //\r
1389 // Close the child handle\r
1390 //\r
1391 gBS->CloseProtocol (\r
1392 IpSb->Controller,\r
1393 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
1394 IpSb->Image,\r
1395 CallbackInfo->ChildHandle\r
1396 );\r
1397 \r
1398 //\r
1399 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL\r
1400 //\r
1401 gBS->UninstallMultipleProtocolInterfaces (\r
1402 CallbackInfo->ChildHandle,\r
1403 &gEfiDevicePathProtocolGuid,\r
1404 CallbackInfo->HiiVendorDevicePath,\r
1405 &gEfiHiiConfigAccessProtocolGuid,\r
1406 &CallbackInfo->HiiConfigAccessProtocol,\r
1407 NULL\r
1408 );\r
1409 }\r
1410\r
1411 if (CallbackInfo->HiiVendorDevicePath != NULL) {\r
1412 FreePool (CallbackInfo->HiiVendorDevicePath);\r
1413 }\r
1414\r
1415 if (CallbackInfo->RegisteredHandle != NULL) {\r
1416 //\r
1417 // Remove HII package list\r
1418 //\r
1419 HiiRemovePackages (CallbackInfo->RegisteredHandle);\r
1420 }\r
1421\r
1422 Ip4NvData = &Instance->Ip4NvData;\r
1423\r
1424 if(Ip4NvData->ManualAddress != NULL) {\r
1425 FreePool(Ip4NvData->ManualAddress);\r
1426 }\r
1427\r
1428 if(Ip4NvData->GatewayAddress != NULL) {\r
1429 FreePool(Ip4NvData->GatewayAddress);\r
1430 }\r
1431\r
1432 if(Ip4NvData->DnsAddress != NULL) {\r
1433 FreePool(Ip4NvData->DnsAddress);\r
1434 }\r
1435\r
1436 Ip4NvData->ManualAddressCount = 0;\r
1437 Ip4NvData->GatewayAddressCount = 0;\r
1438 Ip4NvData->DnsAddressCount = 0;\r
1439}\r