]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Nv.c
MdeModulePkg: Fix issue about current Ip4Dxe implementation for DHCP DORA process
[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
4Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "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
611 Status = Ip4Config2StrToIp (IfrFormNvData->StationAddress, &StationAddress.v4);\r
612 if (EFI_ERROR (Status) || !NetIp4IsUnicast (NTOHL (StationAddress.Addr[0]), 0)) {\r
613 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);\r
614 return EFI_INVALID_PARAMETER;\r
615 }\r
616 \r
617 Status = Ip4Config2StrToIp (IfrFormNvData->SubnetMask, &SubnetMask.v4);\r
618 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (GetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {\r
619 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL);\r
620 return EFI_INVALID_PARAMETER;\r
621 }\r
622 \r
623 Status = Ip4Config2StrToIp (IfrFormNvData->GatewayAddress, &Gateway.v4);\r
624 if (EFI_ERROR (Status) || ((Gateway.Addr[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), 0))) {\r
625 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL);\r
626 return EFI_INVALID_PARAMETER;\r
627 }\r
628\r
629 Status = Ip4Config2StrToIpList (IfrFormNvData->DnsAddress, &DnsAddress, &DnsCount);\r
630 if (!EFI_ERROR (Status) && DnsCount > 0) {\r
631 for (Index = 0; Index < DnsCount; Index ++) {\r
632 CopyMem (&Ip, &DnsAddress[Index], sizeof (IP4_ADDR));\r
633 if (!NetIp4IsUnicast (NTOHL (Ip), 0)) {\r
634 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL);\r
635 FreePool(DnsAddress);\r
636 return EFI_INVALID_PARAMETER;\r
637 } \r
638 } \r
639 } else {\r
640 if (EFI_ERROR (Status)) {\r
641 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL);\r
642 }\r
643 }\r
644 \r
645 if (Ip4NvData->ManualAddress != NULL) {\r
646 FreePool(Ip4NvData->ManualAddress); \r
647 }\r
648 Ip4NvData->ManualAddressCount = 1;\r
649 Ip4NvData->ManualAddress = AllocateZeroPool(sizeof(EFI_IP4_CONFIG2_MANUAL_ADDRESS));\r
650 if (Ip4NvData->ManualAddress == NULL) {\r
651 if (DnsAddress != NULL) {\r
652 FreePool(DnsAddress);\r
653 }\r
654 \r
655 return EFI_OUT_OF_RESOURCES;\r
656 }\r
657 CopyMem(&Ip4NvData->ManualAddress->Address, &StationAddress.v4, sizeof(EFI_IPv4_ADDRESS));\r
658 CopyMem(&Ip4NvData->ManualAddress->SubnetMask, &SubnetMask.v4, sizeof(EFI_IPv4_ADDRESS));\r
659 \r
660 if (Ip4NvData->GatewayAddress != NULL) {\r
661 FreePool(Ip4NvData->GatewayAddress); \r
662 }\r
663 Ip4NvData->GatewayAddressCount = 1;\r
664 Ip4NvData->GatewayAddress = AllocateZeroPool(sizeof(EFI_IPv4_ADDRESS));\r
665 if (Ip4NvData->GatewayAddress == NULL) {\r
666 if (DnsAddress != NULL) {\r
667 FreePool(DnsAddress);\r
668 }\r
669 return EFI_OUT_OF_RESOURCES;\r
670 }\r
671 CopyMem(Ip4NvData->GatewayAddress, &Gateway.v4, sizeof(EFI_IPv4_ADDRESS));\r
672 \r
673 if (Ip4NvData->DnsAddress != NULL) {\r
674 FreePool(Ip4NvData->DnsAddress); \r
675 }\r
676 Ip4NvData->DnsAddressCount = (UINT32) DnsCount;\r
677 Ip4NvData->DnsAddress = DnsAddress;\r
678\r
679 //\r
680 // Setting Ip4NvData.\r
681 //\r
682 Status = Ip4Cfg2->SetData (\r
683 Ip4Cfg2,\r
684 Ip4Config2DataTypePolicy,\r
685 sizeof (EFI_IP4_CONFIG2_POLICY),\r
686 &Ip4NvData->Policy\r
687 );\r
688 if (EFI_ERROR(Status)) {\r
689 return Status;\r
690 }\r
691\r
692 //\r
693 // Create events & timers for asynchronous settings.\r
694 //\r
695 Status = gBS->CreateEvent (\r
696 EVT_TIMER,\r
697 TPL_CALLBACK,\r
698 NULL,\r
699 NULL,\r
700 &TimeoutEvent\r
701 );\r
702 if (EFI_ERROR (Status)) {\r
703 return EFI_OUT_OF_RESOURCES;\r
704 }\r
705\r
706 Status = gBS->CreateEvent (\r
707 EVT_NOTIFY_SIGNAL,\r
708 TPL_NOTIFY,\r
709 Ip4Config2ManualAddressNotify,\r
710 &IsAddressOk,\r
711 &SetAddressEvent\r
712 );\r
713 if (EFI_ERROR (Status)) {\r
714 goto Exit;\r
715 }\r
716\r
717 IsAddressOk = FALSE;\r
718 \r
719 Status = Ip4Cfg2->RegisterDataNotify (\r
720 Ip4Cfg2,\r
721 Ip4Config2DataTypeManualAddress,\r
722 SetAddressEvent\r
723 );\r
724 if (EFI_ERROR (Status)) {\r
725 goto Exit;\r
726 }\r
727\r
728 //\r
729 // Set ManualAddress.\r
730 //\r
731 DataSize = Ip4NvData->ManualAddressCount * sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS);\r
732 Status = Ip4Cfg2->SetData (\r
733 Ip4Cfg2,\r
734 Ip4Config2DataTypeManualAddress,\r
735 DataSize,\r
736 (VOID *) Ip4NvData->ManualAddress\r
737 );\r
738\r
739 if (Status == EFI_NOT_READY) {\r
740 gBS->SetTimer (TimeoutEvent, TimerRelative, 50000000);\r
741 while (EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {\r
742 if (IsAddressOk) {\r
743 Status = EFI_SUCCESS;\r
744 break;\r
745 }\r
746 }\r
747 }\r
748\r
749 Ip4Cfg2->UnregisterDataNotify (\r
750 Ip4Cfg2,\r
751 Ip4Config2DataTypeManualAddress,\r
752 SetAddressEvent\r
753 );\r
754 if (EFI_ERROR (Status)) {\r
755 goto Exit;\r
756 }\r
757\r
758 //\r
759 // Set gateway.\r
760 //\r
761 DataSize = Ip4NvData->GatewayAddressCount * sizeof (EFI_IPv4_ADDRESS);\r
762 Status = Ip4Cfg2->SetData (\r
763 Ip4Cfg2,\r
764 Ip4Config2DataTypeGateway,\r
765 DataSize,\r
766 Ip4NvData->GatewayAddress\r
767 );\r
768 if (EFI_ERROR (Status)) {\r
769 goto Exit;\r
770 }\r
771\r
772 //\r
773 // Set DNS addresses.\r
774 //\r
775 if (Ip4NvData->DnsAddressCount > 0 && Ip4NvData->DnsAddress != NULL) {\r
776 DataSize = Ip4NvData->DnsAddressCount * sizeof (EFI_IPv4_ADDRESS);\r
777 Status = Ip4Cfg2->SetData (\r
778 Ip4Cfg2,\r
779 Ip4Config2DataTypeDnsServer,\r
780 DataSize,\r
781 Ip4NvData->DnsAddress\r
782 );\r
783 \r
784 if (EFI_ERROR (Status)) {\r
785 goto Exit;\r
786 } \r
787 } \r
788 } \r
789\r
790Exit:\r
791 if (SetAddressEvent != NULL) {\r
792 gBS->CloseEvent (SetAddressEvent);\r
793 }\r
794\r
795 if (TimeoutEvent != NULL) {\r
796 gBS->CloseEvent (TimeoutEvent);\r
797 }\r
798\r
799 return Status;\r
800}\r
801\r
802/**\r
803 This function allows the caller to request the current\r
804 configuration for one or more named elements. The resulting\r
805 string is in <ConfigAltResp> format. Any and all alternative\r
806 configuration strings shall also be appended to the end of the\r
807 current configuration string. If they are, they must appear\r
808 after the current configuration. They must contain the same\r
809 routing (GUID, NAME, PATH) as the current configuration string.\r
810 They must have an additional description indicating the type of\r
811 alternative configuration the string represents,\r
812 "ALTCFG=<StringToken>". That <StringToken> (when\r
813 converted from Hex UNICODE to binary) is a reference to a\r
814 string in the associated string pack.\r
815\r
816 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
817 @param[in] Request A null-terminated Unicode string in\r
818 <ConfigRequest> format. Note that this\r
819 includes the routing information as well as\r
820 the configurable name / value pairs. It is\r
821 invalid for this string to be in\r
822 <MultiConfigRequest> format.\r
823 @param[out] Progress On return, points to a character in the\r
824 Request string. Points to the string's null\r
825 terminator if request was successful. Points\r
826 to the most recent "&" before the first\r
827 failing name / value pair (or the beginning\r
828 of the string if the failure is in the first\r
829 name / value pair) if the request was not\r
830 successful.\r
831 @param[out] Results A null-terminated Unicode string in\r
832 <ConfigAltResp> format which has all values\r
833 filled in for the names in the Request string.\r
834 String to be allocated by the called function.\r
835\r
836 @retval EFI_SUCCESS The Results string is filled with the\r
837 values corresponding to all requested\r
838 names.\r
839 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the\r
840 parts of the results that must be\r
841 stored awaiting possible future\r
842 protocols.\r
843 @retval EFI_NOT_FOUND Routing data doesn't match any\r
844 known driver. Progress set to the\r
845 first character in the routing header.\r
846 Note: There is no requirement that the\r
847 driver validate the routing data. It\r
848 must skip the <ConfigHdr> in order to\r
849 process the names.\r
850 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set\r
851 to most recent & before the\r
852 error or the beginning of the\r
853 string.\r
854 @retval EFI_INVALID_PARAMETER Unknown name. Progress points\r
855 to the & before the name in\r
856 question.Currently not implemented.\r
857**/\r
858EFI_STATUS\r
859EFIAPI\r
860Ip4FormExtractConfig (\r
861 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
862 IN CONST EFI_STRING Request,\r
863 OUT EFI_STRING *Progress,\r
864 OUT EFI_STRING *Results\r
865 )\r
866{\r
867 EFI_STATUS Status; \r
868 IP4_CONFIG2_INSTANCE *Ip4Config2Instance;\r
869 IP4_FORM_CALLBACK_INFO *Private; \r
870 IP4_CONFIG2_IFR_NVDATA *IfrFormNvData;\r
871 EFI_STRING ConfigRequestHdr;\r
872 EFI_STRING ConfigRequest; \r
873 BOOLEAN AllocatedRequest;\r
874 EFI_STRING FormResult;\r
875 UINTN Size;\r
876 UINTN BufferSize;\r
b1d4218a 877\r
878 if (Progress == NULL || Results == NULL) {\r
879 return EFI_INVALID_PARAMETER;\r
880 }\r
1f6729ff 881 \r
882 Status = EFI_SUCCESS; \r
883 IfrFormNvData = NULL;\r
884 ConfigRequest = NULL;\r
885 FormResult = NULL; \r
886 Size = 0;\r
887 AllocatedRequest = FALSE; \r
888 ConfigRequest = Request; \r
889 Private = IP4_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS(This);\r
890 Ip4Config2Instance = IP4_CONFIG2_INSTANCE_FROM_FORM_CALLBACK(Private);\r
891 BufferSize = sizeof (IP4_CONFIG2_IFR_NVDATA);\r
892 *Progress = Request;\r
893 \r
1f6729ff 894 //\r
895 // Check Request data in <ConfigHdr>.\r
896 //\r
897 if ((Request == NULL) || HiiIsConfigHdrMatch (Request, &gIp4Config2NvDataGuid, mIp4Config2StorageName)) {\r
898 IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG2_IFR_NVDATA));\r
899 if (IfrFormNvData == NULL) {\r
900 return EFI_OUT_OF_RESOURCES;\r
901 }\r
902 \r
903 Ip4Config2ConvertConfigNvDataToIfrNvData (Ip4Config2Instance, IfrFormNvData);\r
904 \r
905 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
906 //\r
907 // Request has no request element, construct full request string.\r
908 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
909 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
910 //\r
911 ConfigRequestHdr = HiiConstructConfigHdr (&gIp4Config2NvDataGuid, mIp4Config2StorageName, Private->ChildHandle);\r
912 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
913 ConfigRequest = AllocateZeroPool (Size);\r
914 ASSERT (ConfigRequest != NULL);\r
915 AllocatedRequest = TRUE;\r
916 \r
917 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
918 FreePool (ConfigRequestHdr);\r
919 }\r
920\r
921 //\r
922 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
923 //\r
924 Status = gHiiConfigRouting->BlockToConfig (\r
925 gHiiConfigRouting,\r
926 ConfigRequest,\r
927 (UINT8 *) IfrFormNvData,\r
928 BufferSize,\r
929 &FormResult,\r
930 Progress\r
931 );\r
932\r
933 FreePool (IfrFormNvData);\r
934 \r
935 //\r
936 // Free the allocated config request string.\r
937 //\r
938 if (AllocatedRequest) {\r
939 FreePool (ConfigRequest);\r
940 ConfigRequest = NULL;\r
941 }\r
942\r
943 if (EFI_ERROR (Status)) {\r
944 goto Failure;\r
945 }\r
946 }\r
947 \r
948 if (Request == NULL || HiiIsConfigHdrMatch (Request, &gIp4Config2NvDataGuid, mIp4Config2StorageName)) {\r
949 *Results = FormResult;\r
950 } else {\r
951 return EFI_NOT_FOUND;\r
952 }\r
953\r
954Failure:\r
955 //\r
956 // Set Progress string to the original request string.\r
957 //\r
958 if (Request == NULL) {\r
959 *Progress = NULL;\r
960 } else if (StrStr (Request, L"OFFSET") == NULL) {\r
961 *Progress = Request + StrLen (Request);\r
962 }\r
963\r
964 return Status;\r
965}\r
966\r
967/**\r
968 This function applies changes in a driver's configuration.\r
969 Input is a Configuration, which has the routing data for this\r
970 driver followed by name / value configuration pairs. The driver\r
971 must apply those pairs to its configurable storage. If the\r
972 driver's configuration is stored in a linear block of data\r
973 and the driver's name / value pairs are in <BlockConfig>\r
974 format, it may use the ConfigToBlock helper function (above) to\r
975 simplify the job. Currently not implemented.\r
976\r
977 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
978 @param[in] Configuration A null-terminated Unicode string in\r
979 <ConfigString> format.\r
980 @param[out] Progress A pointer to a string filled in with the\r
981 offset of the most recent '&' before the\r
982 first failing name / value pair (or the\r
983 beginn ing of the string if the failure\r
984 is in the first name / value pair) or\r
985 the terminating NULL if all was\r
986 successful.\r
987\r
988 @retval EFI_SUCCESS The results have been distributed or are\r
989 awaiting distribution.\r
990 @retval EFI_OUT_OF_MEMORY Not enough memory to store the\r
991 parts of the results that must be\r
992 stored awaiting possible future\r
993 protocols.\r
994 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the\r
995 Results parameter would result\r
996 in this type of error.\r
997 @retval EFI_NOT_FOUND Target for the specified routing data\r
998 was not found.\r
999**/\r
1000EFI_STATUS\r
1001EFIAPI\r
1002Ip4FormRouteConfig (\r
1003 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
1004 IN CONST EFI_STRING Configuration,\r
1005 OUT EFI_STRING *Progress\r
1006 )\r
1007{\r
1008 EFI_STATUS Status;\r
1009 UINTN BufferSize;\r
1010 IP4_CONFIG2_IFR_NVDATA *IfrFormNvData;\r
1011 IP4_CONFIG2_INSTANCE *Ip4Config2Instance;\r
1012 IP4_FORM_CALLBACK_INFO *Private;\r
1013\r
1014 Status = EFI_SUCCESS;\r
1015 IfrFormNvData = NULL;\r
1016\r
1017 if (Configuration == NULL || Progress == NULL) {\r
1018 return EFI_INVALID_PARAMETER;\r
1019 }\r
1020\r
1021 *Progress = Configuration;\r
1022\r
1023 Private = IP4_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS(This);\r
1024 Ip4Config2Instance = IP4_CONFIG2_INSTANCE_FROM_FORM_CALLBACK(Private);\r
1025\r
1026 //\r
1027 // Check Routing data in <ConfigHdr>.\r
1028 //\r
1029 if (HiiIsConfigHdrMatch (Configuration, &gIp4Config2NvDataGuid, mIp4Config2StorageName)) {\r
1030 //\r
1031 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
1032 //\r
1033 IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG2_IFR_NVDATA));\r
1034 if (IfrFormNvData == NULL) {\r
1035 return EFI_OUT_OF_RESOURCES;\r
1036 }\r
1037\r
1038 BufferSize = 0;\r
1039\r
1040 Status = gHiiConfigRouting->ConfigToBlock (\r
1041 gHiiConfigRouting,\r
1042 Configuration,\r
1043 (UINT8 *) IfrFormNvData,\r
1044 &BufferSize,\r
1045 Progress\r
1046 );\r
1047 if (Status != EFI_BUFFER_TOO_SMALL) {\r
1048 return Status;\r
1049 }\r
1050\r
1051 Status = gHiiConfigRouting->ConfigToBlock (\r
1052 gHiiConfigRouting,\r
1053 Configuration,\r
1054 (UINT8 *) IfrFormNvData,\r
1055 &BufferSize,\r
1056 Progress\r
1057 );\r
1058 if (!EFI_ERROR (Status)) {\r
1059 Status = Ip4Config2ConvertIfrNvDataToConfigNvData (IfrFormNvData, Ip4Config2Instance);\r
1060 }\r
1061\r
1062 FreePool (IfrFormNvData);\r
1063 } else {\r
1064 return EFI_NOT_FOUND;\r
1065 }\r
1066\r
1067 return Status;\r
1068\r
1069}\r
1070\r
1071/**\r
1072 This function is called to provide results data to the driver.\r
1073 This data consists of a unique key that is used to identify\r
1074 which data is either being passed back or being asked for.\r
1075\r
1076 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
1077 @param[in] Action Specifies the type of action taken by the browser.\r
1078 @param[in] QuestionId A unique value which is sent to the original\r
1079 exporting driver so that it can identify the type\r
1080 of data to expect. The format of the data tends to\r
1081 vary based on the opcode that enerated the callback.\r
1082 @param[in] Type The type of value for the question.\r
1083 @param[in] Value A pointer to the data being sent to the original\r
1084 exporting driver.\r
1085 @param[out] ActionRequest On return, points to the action requested by the\r
1086 callback function.\r
1087\r
1088 @retval EFI_SUCCESS The callback successfully handled the action.\r
1089 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the\r
1090 variable and its data.\r
1091 @retval EFI_DEVICE_ERROR The variable could not be saved.\r
1092 @retval EFI_UNSUPPORTED The specified Action is not supported by the\r
1093 callback.Currently not implemented.\r
1094 @retval EFI_INVALID_PARAMETERS Passing in wrong parameter.\r
1095 @retval Others Other errors as indicated.\r
1096 \r
1097**/\r
1098EFI_STATUS\r
1099EFIAPI\r
1100Ip4FormCallback (\r
1101 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
1102 IN EFI_BROWSER_ACTION Action,\r
1103 IN EFI_QUESTION_ID QuestionId,\r
1104 IN UINT8 Type,\r
1105 IN EFI_IFR_TYPE_VALUE *Value,\r
1106 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
1107 )\r
1108{\r
1109 EFI_STATUS Status;\r
1110 IP4_CONFIG2_INSTANCE *Instance;\r
1111 IP4_CONFIG2_IFR_NVDATA *IfrFormNvData;\r
1112 IP4_FORM_CALLBACK_INFO *Private;\r
1113 \r
1114 EFI_IP_ADDRESS StationAddress;\r
1115 EFI_IP_ADDRESS SubnetMask;\r
1116 EFI_IP_ADDRESS Gateway;\r
1117 IP4_ADDR Ip;\r
1118 EFI_IPv4_ADDRESS *DnsAddress;\r
1119 UINTN DnsCount;\r
1120 UINTN Index;\r
1121 EFI_INPUT_KEY Key;\r
1122 \r
1123 IfrFormNvData = NULL;\r
1124 DnsCount = 0;\r
1125 DnsAddress = NULL; \r
1126\r
1127 if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
1128 Private = IP4_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS(This);\r
1129 Instance = IP4_CONFIG2_INSTANCE_FROM_FORM_CALLBACK(Private);\r
1130 \r
1131 IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG2_IFR_NVDATA));\r
1132 if (IfrFormNvData == NULL) {\r
1133 return EFI_OUT_OF_RESOURCES;\r
1134 }\r
1135\r
1136 //\r
1137 // Retrive uncommitted data from Browser\r
1138 //\r
1139 if (!HiiGetBrowserData (&gIp4Config2NvDataGuid, mIp4Config2StorageName, sizeof (IP4_CONFIG2_IFR_NVDATA), (UINT8 *) IfrFormNvData)) {\r
1140 FreePool (IfrFormNvData);\r
1141 return EFI_NOT_FOUND;\r
1142 }\r
1143\r
1144 Status = EFI_SUCCESS;\r
1145\r
1146 switch (QuestionId) {\r
1147 case KEY_LOCAL_IP:\r
1148 Status = Ip4Config2StrToIp (IfrFormNvData->StationAddress, &StationAddress.v4);\r
1149 if (EFI_ERROR (Status) || !NetIp4IsUnicast (NTOHL (StationAddress.Addr[0]), 0)) {\r
1150 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);\r
1151 Status = EFI_INVALID_PARAMETER;\r
1152 }\r
1153 break;\r
1154\r
1155 case KEY_SUBNET_MASK:\r
1156 Status = Ip4Config2StrToIp (IfrFormNvData->SubnetMask, &SubnetMask.v4);\r
1157 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (GetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {\r
1158 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL);\r
1159 Status = EFI_INVALID_PARAMETER;\r
1160 }\r
1161 break;\r
1162\r
1163 case KEY_GATE_WAY:\r
1164 Status = Ip4Config2StrToIp (IfrFormNvData->GatewayAddress, &Gateway.v4);\r
1165 if (EFI_ERROR (Status) || ((Gateway.Addr[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), 0))) {\r
1166 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL);\r
1167 Status = EFI_INVALID_PARAMETER;\r
1168 }\r
1169 break;\r
1170 \r
1171 case KEY_DNS:\r
1172 Status = Ip4Config2StrToIpList (IfrFormNvData->DnsAddress, &DnsAddress, &DnsCount);\r
1173 if (!EFI_ERROR (Status) && DnsCount > 0) {\r
1174 for (Index = 0; Index < DnsCount; Index ++) {\r
1175 CopyMem (&Ip, &DnsAddress[Index], sizeof (IP4_ADDR));\r
1176 if (!NetIp4IsUnicast (NTOHL (Ip), 0)) {\r
1177 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL);\r
1178 Status = EFI_INVALID_PARAMETER;\r
1179 break;\r
1180 } \r
1181 }\r
1182 } else {\r
1183 if (EFI_ERROR (Status)) {\r
1184 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL);\r
1185 }\r
1186 }\r
1187 \r
1188 if(DnsAddress != NULL) { \r
1189 FreePool(DnsAddress);\r
1190 }\r
1191 break;\r
1192 \r
1193 case KEY_SAVE_CHANGES:\r
1194 Status = Ip4Config2ConvertIfrNvDataToConfigNvData (IfrFormNvData, Instance);\r
1195 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
1196 break;\r
1197\r
1198 default:\r
1199 break;\r
1200 }\r
1201\r
1202 FreePool (IfrFormNvData);\r
1203\r
1204 return Status;\r
1205 }\r
1206\r
1207 //\r
1208 // All other action return unsupported.\r
1209 //\r
1210 return EFI_UNSUPPORTED;\r
1211}\r
1212\r
1213/**\r
1214 Install HII Config Access protocol for network device and allocate resource.\r
1215\r
1216 @param[in, out] Instance The IP4 config2 Instance.\r
1217\r
1218 @retval EFI_SUCCESS The HII Config Access protocol is installed.\r
1219 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
1220 @retval Others Other errors as indicated.\r
1221 \r
1222**/\r
1223EFI_STATUS\r
1224Ip4Config2FormInit (\r
1225 IN OUT IP4_CONFIG2_INSTANCE *Instance\r
1226 )\r
1227{\r
1228 EFI_STATUS Status;\r
1229 IP4_SERVICE *IpSb;\r
1230 IP4_FORM_CALLBACK_INFO *CallbackInfo;\r
1231 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
1232 VENDOR_DEVICE_PATH VendorDeviceNode;\r
1233 EFI_SERVICE_BINDING_PROTOCOL *MnpSb;\r
1234 CHAR16 *MacString;\r
1235 CHAR16 MenuString[128];\r
1236 CHAR16 PortString[128];\r
1237 CHAR16 *OldMenuString;\r
1238 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
1239\r
1240 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
1241 ASSERT (IpSb != NULL);\r
1242 \r
1243 CallbackInfo = &Instance->CallbackInfo;\r
1244 \r
1245 CallbackInfo->Signature = IP4_FORM_CALLBACK_INFO_SIGNATURE;\r
1246\r
1247 Status = gBS->HandleProtocol (\r
1248 IpSb->Controller,\r
1249 &gEfiDevicePathProtocolGuid,\r
1250 (VOID **) &ParentDevicePath\r
1251 );\r
1252 if (EFI_ERROR (Status)) {\r
1253 return Status;\r
1254 }\r
1255\r
1256 //\r
1257 // Construct device path node for EFI HII Config Access protocol,\r
1258 // which consists of controller physical device path and one hardware\r
1259 // vendor guid node.\r
1260 //\r
1261 ZeroMem (&VendorDeviceNode, sizeof (VENDOR_DEVICE_PATH));\r
1262 VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH;\r
1263 VendorDeviceNode.Header.SubType = HW_VENDOR_DP;\r
1264\r
1265 CopyGuid (&VendorDeviceNode.Guid, &gEfiCallerIdGuid);\r
1266\r
1267 SetDevicePathNodeLength (&VendorDeviceNode.Header, sizeof (VENDOR_DEVICE_PATH));\r
1268 CallbackInfo->HiiVendorDevicePath = AppendDevicePathNode (\r
1269 ParentDevicePath,\r
1270 (EFI_DEVICE_PATH_PROTOCOL *) &VendorDeviceNode\r
1271 );\r
1272 if (CallbackInfo->HiiVendorDevicePath == NULL) {\r
1273 Status = EFI_OUT_OF_RESOURCES;\r
1274 goto Error;\r
1275 }\r
1276\r
1277 ConfigAccess = &CallbackInfo->HiiConfigAccessProtocol;\r
1278 ConfigAccess->ExtractConfig = Ip4FormExtractConfig;\r
1279 ConfigAccess->RouteConfig = Ip4FormRouteConfig;\r
1280 ConfigAccess->Callback = Ip4FormCallback;\r
1281\r
1282 //\r
1283 // Install Device Path Protocol and Config Access protocol on new handle\r
1284 //\r
1285 Status = gBS->InstallMultipleProtocolInterfaces (\r
1286 &CallbackInfo->ChildHandle,\r
1287 &gEfiDevicePathProtocolGuid,\r
1288 CallbackInfo->HiiVendorDevicePath,\r
1289 &gEfiHiiConfigAccessProtocolGuid,\r
1290 ConfigAccess,\r
1291 NULL\r
1292 );\r
1293\r
1294 if (!EFI_ERROR (Status)) {\r
1295 //\r
1296 // Open the Parent Handle for the child\r
1297 //\r
1298 Status = gBS->OpenProtocol (\r
1299 IpSb->Controller,\r
1300 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
1301 (VOID **) &MnpSb,\r
1302 IpSb->Image,\r
1303 CallbackInfo->ChildHandle,\r
1304 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
1305 );\r
1306 }\r
1307\r
1308 if (EFI_ERROR (Status)) {\r
1309 goto Error;\r
1310 }\r
1311\r
1312 //\r
1313 // Publish our HII data\r
1314 //\r
1315 CallbackInfo->RegisteredHandle = HiiAddPackages (\r
1316 &gIp4Config2NvDataGuid,\r
1317 CallbackInfo->ChildHandle,\r
1318 Ip4DxeStrings,\r
1319 Ip4Config2Bin,\r
1320 NULL\r
1321 );\r
1322 if (CallbackInfo->RegisteredHandle == NULL) {\r
1323 Status = EFI_OUT_OF_RESOURCES;\r
1324 goto Error;\r
1325 }\r
1326\r
1327 //\r
1328 // Append MAC string in the menu help string and tile help string\r
1329 //\r
1330 Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &MacString);\r
1331 if (!EFI_ERROR (Status)) {\r
1332 OldMenuString = HiiGetString (\r
1333 CallbackInfo->RegisteredHandle, \r
1334 STRING_TOKEN (STR_IP4_CONFIG2_FORM_HELP), \r
1335 NULL\r
1336 );\r
1337 UnicodeSPrint (MenuString, 128, L"%s (MAC:%s)", OldMenuString, MacString);\r
1338 HiiSetString (\r
1339 CallbackInfo->RegisteredHandle, \r
1340 STRING_TOKEN (STR_IP4_CONFIG2_FORM_HELP), \r
1341 MenuString, \r
1342 NULL\r
1343 );\r
1344\r
1345 UnicodeSPrint (PortString, 128, L"MAC:%s", MacString);\r
1346 HiiSetString (\r
1347 CallbackInfo->RegisteredHandle, \r
1348 STRING_TOKEN (STR_IP4_DEVICE_FORM_HELP), \r
1349 PortString, \r
1350 NULL\r
1351 );\r
1352 \r
1353 FreePool (MacString);\r
1354 FreePool (OldMenuString);\r
1355\r
1356 return EFI_SUCCESS;\r
1357 }\r
1358\r
1359Error:\r
1360 Ip4Config2FormUnload (Instance);\r
1361 return Status;\r
1362}\r
1363\r
1364/**\r
1365 Uninstall the HII Config Access protocol for network devices and free up the resources.\r
1366\r
1367 @param[in, out] Instance The IP4 config2 instance to unload a form.\r
1368\r
1369**/\r
1370VOID\r
1371Ip4Config2FormUnload (\r
1372 IN OUT IP4_CONFIG2_INSTANCE *Instance\r
1373 )\r
1374{\r
1375 IP4_SERVICE *IpSb;\r
1376 IP4_FORM_CALLBACK_INFO *CallbackInfo;\r
1377 IP4_CONFIG2_NVDATA *Ip4NvData;\r
1378\r
1379 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
1380 ASSERT (IpSb != NULL);\r
1381\r
1382 CallbackInfo = &Instance->CallbackInfo;\r
1383\r
1384 if (CallbackInfo->ChildHandle != NULL) {\r
1385 //\r
1386 // Close the child handle\r
1387 //\r
1388 gBS->CloseProtocol (\r
1389 IpSb->Controller,\r
1390 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
1391 IpSb->Image,\r
1392 CallbackInfo->ChildHandle\r
1393 );\r
1394 \r
1395 //\r
1396 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL\r
1397 //\r
1398 gBS->UninstallMultipleProtocolInterfaces (\r
1399 CallbackInfo->ChildHandle,\r
1400 &gEfiDevicePathProtocolGuid,\r
1401 CallbackInfo->HiiVendorDevicePath,\r
1402 &gEfiHiiConfigAccessProtocolGuid,\r
1403 &CallbackInfo->HiiConfigAccessProtocol,\r
1404 NULL\r
1405 );\r
1406 }\r
1407\r
1408 if (CallbackInfo->HiiVendorDevicePath != NULL) {\r
1409 FreePool (CallbackInfo->HiiVendorDevicePath);\r
1410 }\r
1411\r
1412 if (CallbackInfo->RegisteredHandle != NULL) {\r
1413 //\r
1414 // Remove HII package list\r
1415 //\r
1416 HiiRemovePackages (CallbackInfo->RegisteredHandle);\r
1417 }\r
1418\r
1419 Ip4NvData = &Instance->Ip4NvData;\r
1420\r
1421 if(Ip4NvData->ManualAddress != NULL) {\r
1422 FreePool(Ip4NvData->ManualAddress);\r
1423 }\r
1424\r
1425 if(Ip4NvData->GatewayAddress != NULL) {\r
1426 FreePool(Ip4NvData->GatewayAddress);\r
1427 }\r
1428\r
1429 if(Ip4NvData->DnsAddress != NULL) {\r
1430 FreePool(Ip4NvData->DnsAddress);\r
1431 }\r
1432\r
1433 Ip4NvData->ManualAddressCount = 0;\r
1434 Ip4NvData->GatewayAddressCount = 0;\r
1435 Ip4NvData->DnsAddressCount = 0;\r
1436}\r