Update for NetworkPkg.
[mirror_edk2.git] / NetworkPkg / Ip6Dxe / Ip6ConfigNv.c
CommitLineData
a3bcde70
HT
1/** @file\r
2 Helper functions for configuring or obtaining the parameters relating to IP6.\r
3\r
2d4df339 4 Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>\r
a3bcde70
HT
5\r
6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php.\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "Ip6Impl.h"\r
17\r
a3bcde70
HT
18CHAR16 mIp6ConfigStorageName[] = L"IP6_CONFIG_IFR_NVDATA";\r
19\r
20/**\r
21 The notify function of create event when performing a manual configuration.\r
22\r
23 @param[in] Event The pointer of Event.\r
24 @param[in] Context The pointer of Context.\r
25\r
26**/\r
27VOID\r
28EFIAPI\r
29Ip6ConfigManualAddressNotify (\r
30 IN EFI_EVENT Event,\r
31 IN VOID *Context\r
32 )\r
33{\r
34 *((BOOLEAN *) Context) = TRUE;\r
35}\r
36\r
37/**\r
38 Get the configuration data for the EFI IPv6 network stack running on the\r
39 communication. It is a help function to the call EfiIp6ConfigGetData().\r
40\r
41 @param[in] Ip6Config The pointer to the EFI_IP6_CONFIG_PROTOCOL instance.\r
42 @param[in] DataType The type of data to get.\r
43 @param[out] DataSize The size of buffer required in bytes.\r
44 @param[out] Data The data buffer in which the configuration data is returned. The\r
45 type of the data buffer associated with the DataType.\r
46 It is the caller's responsibility to free the resource.\r
47\r
48 @retval EFI_SUCCESS The specified configuration data was obtained successfully.\r
49 @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:\r
50 - Ip6Config is NULL or invalid.\r
51 - DataSize is NULL.\r
52 - Data is NULL.\r
53 @retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to lack of resources.\r
54 @retval EFI_NOT_READY The specified configuration data is not ready due to an\r
55 asynchronous configuration process already in progress.\r
56 @retval EFI_NOT_FOUND The specified configuration data was not found.\r
57\r
58**/\r
59EFI_STATUS\r
60Ip6ConfigNvGetData (\r
61 IN EFI_IP6_CONFIG_PROTOCOL *Ip6Config,\r
62 IN EFI_IP6_CONFIG_DATA_TYPE DataType,\r
63 OUT UINTN *DataSize,\r
64 OUT VOID **Data\r
65 )\r
66{\r
67 UINTN BufferSize;\r
68 VOID *Buffer;\r
69 EFI_STATUS Status;\r
70\r
71 if ((Ip6Config == NULL) || (Data == NULL) || (DataSize == NULL)) {\r
72 return EFI_INVALID_PARAMETER;\r
73 }\r
74\r
75 BufferSize = 0;\r
76 Status = Ip6Config->GetData (\r
77 Ip6Config,\r
78 DataType,\r
79 &BufferSize,\r
80 NULL\r
81 );\r
82 if (Status != EFI_BUFFER_TOO_SMALL) {\r
83 return Status;\r
84 }\r
85\r
86 Buffer = AllocateZeroPool (BufferSize);\r
87 if (Buffer == NULL) {\r
88 return EFI_OUT_OF_RESOURCES;\r
89 }\r
90\r
91 Status = Ip6Config->GetData (\r
92 Ip6Config,\r
93 DataType,\r
94 &BufferSize,\r
95 Buffer\r
96 );\r
97 if (EFI_ERROR (Status)) {\r
98 FreePool (Buffer);\r
99 return Status;\r
100 }\r
101\r
102 *DataSize = BufferSize;\r
103 *Data = Buffer;\r
104\r
105 return EFI_SUCCESS;\r
106}\r
107\r
108/**\r
109 Free all nodes in IP6_ADDRESS_INFO_ENTRY in the list array specified\r
110 with ListHead.\r
111\r
112 @param[in] ListHead The head of the list array in IP6_ADDRESS_INFO_ENTRY.\r
113\r
114**/\r
115VOID\r
116Ip6FreeAddressInfoList (\r
117 IN LIST_ENTRY *ListHead\r
118 )\r
119{\r
120 IP6_ADDRESS_INFO_ENTRY *Node;\r
121 LIST_ENTRY *Entry;\r
122 LIST_ENTRY *NextEntry;\r
123\r
124 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, ListHead) {\r
125 Node = NET_LIST_USER_STRUCT (Entry, IP6_ADDRESS_INFO_ENTRY, Link);\r
126 RemoveEntryList (&Node->Link);\r
127 FreePool (Node);\r
128 }\r
129}\r
130\r
131/**\r
132 Convert the IPv6 address into a formatted string.\r
133\r
134 @param[in] Ip6 The IPv6 address.\r
135 @param[out] Str The formatted IP string.\r
136\r
137**/\r
138VOID\r
139Ip6ToStr (\r
140 IN EFI_IPv6_ADDRESS *Ip6,\r
141 OUT CHAR16 *Str\r
142 )\r
143{\r
144 UINTN Index;\r
145 BOOLEAN Short;\r
146 UINTN Number;\r
147 CHAR16 FormatString[8];\r
148\r
149 Short = FALSE;\r
150\r
151 for (Index = 0; Index < 15; Index = Index + 2) {\r
152 if (!Short &&\r
153 Index % 2 == 0 &&\r
154 Ip6->Addr[Index] == 0 &&\r
155 Ip6->Addr[Index + 1] == 0\r
156 ) {\r
157 //\r
158 // Deal with the case of ::.\r
159 //\r
160 if (Index == 0) {\r
161 *Str = L':';\r
162 *(Str + 1) = L':';\r
163 Str = Str + 2;\r
164 } else {\r
165 *Str = L':';\r
166 Str = Str + 1;\r
167 }\r
168\r
169 while ((Index < 15) && (Ip6->Addr[Index] == 0) && (Ip6->Addr[Index + 1] == 0)) {\r
170 Index = Index + 2;\r
171 }\r
172\r
173 Short = TRUE;\r
174\r
175 if (Index == 16) {\r
176 //\r
177 // :: is at the end of the address.\r
178 //\r
179 *Str = L'\0';\r
180 break;\r
181 }\r
182 }\r
183\r
184 ASSERT (Index < 15);\r
185\r
186 if (Ip6->Addr[Index] == 0) {\r
187 Number = UnicodeSPrint (Str, 2 * IP6_STR_MAX_SIZE, L"%x:", (UINTN) Ip6->Addr[Index + 1]);\r
188 } else {\r
189 if (Ip6->Addr[Index + 1] < 0x10) {\r
190 CopyMem (FormatString, L"%x0%x:", StrSize (L"%x0%x:"));\r
191 } else {\r
192 CopyMem (FormatString, L"%x%x:", StrSize (L"%x%x:"));\r
193 }\r
194\r
195 Number = UnicodeSPrint (\r
196 Str,\r
197 2 * IP6_STR_MAX_SIZE,\r
198 (CONST CHAR16 *) FormatString,\r
199 (UINTN) Ip6->Addr[Index],\r
200 (UINTN) Ip6->Addr[Index + 1]\r
201 );\r
202 }\r
203\r
204 Str = Str + Number;\r
205\r
206 if (Index + 2 == 16) {\r
207 *Str = L'\0';\r
208 if (*(Str - 1) == L':') {\r
209 *(Str - 1) = L'\0';\r
210 }\r
211 }\r
212 }\r
213}\r
214\r
215/**\r
216 Convert EFI_IP6_CONFIG_INTERFACE_ID to string format.\r
217\r
218 @param[out] String The buffer to store the converted string.\r
219 @param[in] IfId The pointer of EFI_IP6_CONFIG_INTERFACE_ID.\r
220\r
221 @retval EFI_SUCCESS The string converted successfully.\r
222 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
223\r
224**/\r
225EFI_STATUS\r
226Ip6ConvertInterfaceIdToString (\r
227 OUT CHAR16 *String,\r
228 IN EFI_IP6_CONFIG_INTERFACE_ID *IfId\r
229 )\r
230{\r
231 UINT8 Index;\r
232 UINTN Number;\r
233\r
234 if ((String == NULL) || (IfId == NULL)) {\r
235 return EFI_INVALID_PARAMETER;\r
236 }\r
237\r
238 for (Index = 0; Index < 8; Index++) {\r
239 Number = UnicodeSPrint (\r
240 String,\r
241 2 * INTERFACE_ID_STR_STORAGE,\r
242 L"%x:",\r
243 (UINTN) IfId->Id[Index]\r
244 );\r
245 String = String + Number;\r
246 }\r
247\r
248 *(String - 1) = '\0';\r
249\r
250 return EFI_SUCCESS;\r
251}\r
252\r
253/**\r
254 Parse InterfaceId in string format and convert it to EFI_IP6_CONFIG_INTERFACE_ID.\r
255\r
256 @param[in] String The buffer of the string to be parsed.\r
257 @param[out] IfId The pointer of EFI_IP6_CONFIG_INTERFACE_ID.\r
258\r
259 @retval EFI_SUCCESS The operation finished successfully.\r
260 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
261\r
262**/\r
263EFI_STATUS\r
264Ip6ParseInterfaceIdFromString (\r
265 IN CONST CHAR16 *String,\r
266 OUT EFI_IP6_CONFIG_INTERFACE_ID *IfId\r
267 )\r
268{\r
269 UINT8 Index;\r
270 CHAR16 *IfIdStr;\r
271 CHAR16 *TempStr;\r
272 UINTN NodeVal;\r
273\r
274 if ((String == NULL) || (IfId == NULL)) {\r
275 return EFI_INVALID_PARAMETER;\r
276 }\r
277\r
278 IfIdStr = (CHAR16 *) String;\r
279\r
280 ZeroMem (IfId, sizeof (EFI_IP6_CONFIG_INTERFACE_ID));\r
281\r
282 for (Index = 0; Index < 8; Index++) {\r
283 TempStr = IfIdStr;\r
284\r
285 while ((*IfIdStr != L'\0') && (*IfIdStr != L':')) {\r
286 IfIdStr++;\r
287 }\r
288\r
289 //\r
290 // The InterfaceId format is X:X:X:X, the number of X should not exceed 8.\r
291 // If the number of X is less than 8, zero is appended to the InterfaceId.\r
292 //\r
293 if ((*IfIdStr == ':') && (Index == 7)) {\r
294 return EFI_INVALID_PARAMETER;\r
295 }\r
296\r
297 //\r
298 // Convert the string to interface id. AsciiStrHexToUintn stops at the\r
299 // first character that is not a valid hex character, ':' or '\0' here.\r
300 //\r
301 NodeVal = StrHexToUintn (TempStr);\r
302 if (NodeVal > 0xFF) {\r
303 return EFI_INVALID_PARAMETER;\r
304 }\r
305\r
306 IfId->Id[Index] = (UINT8) NodeVal;\r
307\r
308 IfIdStr++;\r
309 }\r
310\r
311 return EFI_SUCCESS;\r
312}\r
313\r
314/**\r
315 Create Hii Extend Label OpCode as the start opcode and end opcode. It is\r
316 a help function.\r
317\r
318 @param[in] StartLabelNumber The number of start label.\r
319 @param[out] StartOpCodeHandle Points to the start opcode handle.\r
320 @param[out] StartLabel Points to the created start opcode.\r
321 @param[out] EndOpCodeHandle Points to the end opcode handle.\r
322 @param[out] EndLabel Points to the created end opcode.\r
323\r
324 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this\r
325 operation.\r
326 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
327 @retval EFI_SUCCESS The operation completed successfully.\r
328\r
329**/\r
330EFI_STATUS\r
331Ip6CreateOpCode (\r
332 IN UINT16 StartLabelNumber,\r
333 OUT VOID **StartOpCodeHandle,\r
334 OUT EFI_IFR_GUID_LABEL **StartLabel,\r
335 OUT VOID **EndOpCodeHandle,\r
336 OUT EFI_IFR_GUID_LABEL **EndLabel\r
337 )\r
338{\r
339 EFI_STATUS Status;\r
340 EFI_IFR_GUID_LABEL *InternalStartLabel;\r
341 EFI_IFR_GUID_LABEL *InternalEndLabel;\r
342\r
343 if (StartOpCodeHandle == NULL || StartLabel == NULL || EndOpCodeHandle == NULL || EndLabel == NULL) {\r
344 return EFI_INVALID_PARAMETER;\r
345 }\r
346\r
347 *StartOpCodeHandle = NULL;\r
348 *EndOpCodeHandle = NULL;\r
349 Status = EFI_OUT_OF_RESOURCES;\r
350\r
351 //\r
352 // Initialize the container for dynamic opcodes.\r
353 //\r
354 *StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
355 if (*StartOpCodeHandle == NULL) {\r
356 return Status;\r
357 }\r
358\r
359 *EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
360 if (*EndOpCodeHandle == NULL) {\r
361 goto Exit;\r
362 }\r
363\r
364 //\r
365 // Create Hii Extend Label OpCode as the start opcode.\r
366 //\r
367 InternalStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
368 *StartOpCodeHandle,\r
369 &gEfiIfrTianoGuid,\r
370 NULL,\r
371 sizeof (EFI_IFR_GUID_LABEL)\r
372 );\r
373 if (InternalStartLabel == NULL) {\r
374 goto Exit;\r
375 }\r
376\r
377 InternalStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
378 InternalStartLabel->Number = StartLabelNumber;\r
379\r
380 //\r
381 // Create Hii Extend Label OpCode as the end opcode.\r
382 //\r
383 InternalEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
384 *EndOpCodeHandle,\r
385 &gEfiIfrTianoGuid,\r
386 NULL,\r
387 sizeof (EFI_IFR_GUID_LABEL)\r
388 );\r
389 if (InternalEndLabel == NULL) {\r
390 goto Exit;\r
391 }\r
392\r
393 InternalEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
394 InternalEndLabel->Number = LABEL_END;\r
395\r
396 *StartLabel = InternalStartLabel;\r
397 *EndLabel = InternalEndLabel;\r
398\r
399 return EFI_SUCCESS;\r
400\r
401Exit:\r
402\r
403 if (*StartOpCodeHandle != NULL) {\r
404 HiiFreeOpCodeHandle (*StartOpCodeHandle);\r
405 }\r
406\r
407 if (*EndOpCodeHandle != NULL) {\r
408 HiiFreeOpCodeHandle (*EndOpCodeHandle);\r
409 }\r
410\r
411 return Status;\r
412}\r
413\r
414/**\r
415 This function converts the different format of address list to string format and\r
416 then generates the corresponding text opcode to illustarate the address info in\r
417 IP6 configuration page. Currently, the following formats are supported:\r
418 EFI_IP6_ADDRESS_INFO AddressType: Ip6ConfigNvHostAddress;\r
419 EFI_IPv6_ADDRESS AddressType: Ip6ConfigNvGatewayAddress and Ip6ConfigNvDnsAddress;\r
420 EFI_IP6_ROUTE_TABLE AddressType: Ip6ConfigNvRouteTable.\r
421\r
422 @param[in, out] String The pointer to the buffer to store the converted\r
423 string.\r
424 @param[in] HiiHandle A handle that was previously registered in the\r
425 HII Database.\r
426 @param[in] AddressType The address type.\r
427 @param[in] AddressInfo Pointer to the address list.\r
428 @param[in] AddressCount The address count of the address list.\r
429\r
430 @retval EFI_SUCCESS The operation finished successfully.\r
431 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
432 @retval EFI_UNSUPPORTED The AddressType is not supported.\r
433\r
434\r
435**/\r
436EFI_STATUS\r
437Ip6ConvertAddressListToString (\r
438 IN OUT CHAR16 *String,\r
439 IN EFI_HII_HANDLE HiiHandle,\r
440 IN IP6_CONFIG_NV_ADDRESS_TYPE AddressType,\r
441 IN VOID *AddressInfo,\r
442 IN UINTN AddressCount\r
443 )\r
444{\r
445 UINTN Index;\r
446 UINTN Number;\r
447 CHAR16 *TempStr;\r
448 EFI_STATUS Status;\r
449 VOID *StartOpCodeHandle;\r
450 EFI_IFR_GUID_LABEL *StartLabel;\r
451 VOID *EndOpCodeHandle;\r
452 EFI_IFR_GUID_LABEL *EndLabel;\r
453 UINT16 StartLabelNumber;\r
454 EFI_STRING_ID TextTwo;\r
455 UINT8 *AddressHead;\r
456 UINT8 PrefixLength;\r
457 EFI_IPv6_ADDRESS *Address;\r
458\r
459 if ((String == NULL) || (HiiHandle == NULL) || (AddressInfo == NULL)) {\r
460 return EFI_INVALID_PARAMETER;\r
461 }\r
462\r
463 if (AddressType == Ip6ConfigNvHostAddress) {\r
464 StartLabelNumber = HOST_ADDRESS_LABEL;\r
465 } else if (AddressType == Ip6ConfigNvGatewayAddress) {\r
466 StartLabelNumber = GATEWAY_ADDRESS_LABEL;\r
467 } else if (AddressType == Ip6ConfigNvDnsAddress) {\r
468 StartLabelNumber = DNS_ADDRESS_LABEL;\r
469 } else if (AddressType == Ip6ConfigNvRouteTable) {\r
470 StartLabelNumber = ROUTE_TABLE_LABEL;\r
471 } else {\r
472 ASSERT (FALSE);\r
473 return EFI_UNSUPPORTED;\r
474 }\r
475\r
476 Status = Ip6CreateOpCode (\r
477 StartLabelNumber,\r
478 &StartOpCodeHandle,\r
479 &StartLabel,\r
480 &EndOpCodeHandle,\r
481 &EndLabel\r
482 );\r
483 if (EFI_ERROR (Status)) {\r
484 return Status;\r
485 }\r
486\r
487 AddressHead = (UINT8 *) AddressInfo;\r
488\r
489 for (Index = 0; Index < AddressCount; Index++) {\r
490 if (AddressType == Ip6ConfigNvHostAddress) {\r
491 AddressInfo = AddressHead + sizeof (EFI_IP6_ADDRESS_INFO) * Index;\r
492 Address = &((EFI_IP6_ADDRESS_INFO *) AddressInfo)->Address;\r
493 } else if (AddressType == Ip6ConfigNvRouteTable) {\r
494 AddressInfo = AddressHead + sizeof (EFI_IP6_ROUTE_TABLE) * Index;\r
495 Address = &((EFI_IP6_ROUTE_TABLE *) AddressInfo)->Destination;\r
496 } else {\r
497 AddressInfo = AddressHead + sizeof (EFI_IPv6_ADDRESS) * Index;\r
498 Address = AddressInfo;\r
499 }\r
500\r
501 //\r
502 // Convert the IP address info to string.\r
503 //\r
504 Ip6ToStr (Address, String);\r
505 TempStr = String + StrLen (String);\r
506\r
507 if ((AddressType == Ip6ConfigNvHostAddress) || (AddressType == Ip6ConfigNvRouteTable)) {\r
508 if (AddressType == Ip6ConfigNvHostAddress) {\r
509 PrefixLength = ((EFI_IP6_ADDRESS_INFO *) AddressInfo)->PrefixLength;\r
510 } else {\r
511 PrefixLength = ((EFI_IP6_ROUTE_TABLE *) AddressInfo)->PrefixLength;\r
512 }\r
513\r
514 //\r
515 // Append the prefix length to the string.\r
516 //\r
517 *TempStr = L'/';\r
518 TempStr++;\r
519 Number = UnicodeSPrint (TempStr, 6, L"%d", PrefixLength);\r
520 TempStr = TempStr + Number;\r
521 }\r
522\r
523 if (AddressType == Ip6ConfigNvRouteTable) {\r
524 //\r
525 // Append " >> " to the string.\r
526 //\r
527 Number = UnicodeSPrint (TempStr, 8, L" >> ");\r
528 TempStr = TempStr + Number;\r
529\r
530 //\r
531 // Append the gateway address to the string.\r
532 //\r
533 Ip6ToStr (&((EFI_IP6_ROUTE_TABLE *) AddressInfo)->Gateway, TempStr);\r
534 TempStr = TempStr + StrLen (TempStr);\r
535 }\r
536\r
537 //\r
538 // Generate a text opcode and update the UI.\r
539 //\r
540 TextTwo = HiiSetString (HiiHandle, 0, String, NULL);\r
541 if (TextTwo == 0) {\r
542 Status = EFI_INVALID_PARAMETER;\r
543 goto Exit;\r
544 }\r
545\r
546 HiiCreateTextOpCode (StartOpCodeHandle, STR_NULL, STR_NULL, TextTwo);\r
547\r
548 String = TempStr;\r
549 *String = IP6_ADDRESS_DELIMITER;\r
550 String++;\r
551 }\r
552\r
553 *(String - 1) = '\0';\r
554\r
555 Status = HiiUpdateForm (\r
556 HiiHandle, // HII handle\r
9bdc6592 557 &gIp6ConfigNvDataGuid, // Formset GUID\r
a3bcde70
HT
558 FORMID_MAIN_FORM, // Form ID\r
559 StartOpCodeHandle, // Label for where to insert opcodes\r
560 EndOpCodeHandle // Replace data\r
561 );\r
562\r
563Exit:\r
564 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
565 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
566\r
567 return Status;\r
568}\r
569\r
570/**\r
571 Parse address list in string format and convert it to a list array of node in\r
572 IP6_ADDRESS_INFO_ENTRY.\r
573\r
574 @param[in] String The buffer to string to be parsed.\r
575 @param[out] ListHead The list head of array.\r
576 @param[out] AddressCount The number of list nodes in the array.\r
577\r
578 @retval EFI_SUCCESS The operation finished successfully.\r
579 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
580 @retval EFI_OUT_OF_RESOURCES Failed to perform the operation due to lack of resource.\r
581\r
582**/\r
583EFI_STATUS\r
584Ip6ParseAddressListFromString (\r
585 IN CONST CHAR16 *String,\r
586 OUT LIST_ENTRY *ListHead,\r
587 OUT UINT32 *AddressCount\r
588 )\r
589{\r
590 EFI_STATUS Status;\r
591 CHAR16 *LocalString;\r
592 CHAR16 *Temp;\r
593 CHAR16 *TempStr;\r
594 EFI_IP6_ADDRESS_INFO AddressInfo;\r
595 IP6_ADDRESS_INFO_ENTRY *Node;\r
596 BOOLEAN Last;\r
597 UINT32 Count;\r
598\r
599 if ((String == NULL) || (ListHead == NULL) || (AddressCount == NULL)) {\r
600 return EFI_INVALID_PARAMETER;\r
601 }\r
602\r
603 LocalString = (CHAR16 *) AllocateCopyPool (StrSize (String), String);\r
604 if (LocalString == NULL) {\r
605 return EFI_OUT_OF_RESOURCES;\r
606 }\r
607\r
608 //\r
609 // Clean the original address list.\r
610 //\r
611 Ip6FreeAddressInfoList (ListHead);\r
612\r
613 Temp = LocalString;\r
614 Last = FALSE;\r
615 Count = 0;\r
616\r
617 while (*LocalString != L'\0') {\r
618 TempStr = LocalString;\r
619 while ((*LocalString != L'\0') && (*LocalString != IP6_ADDRESS_DELIMITER)) {\r
620 LocalString++;\r
621 }\r
622\r
623 if (*LocalString == L'\0') {\r
624 Last = TRUE;\r
625 }\r
626\r
627 *LocalString = L'\0';\r
628\r
629 Status = NetLibStrToIp6andPrefix (TempStr, &AddressInfo.Address, &AddressInfo.PrefixLength);\r
630 if (EFI_ERROR (Status)) {\r
631 goto Error;\r
632 }\r
633\r
634 if (AddressInfo.PrefixLength == 0xFF) {\r
635 AddressInfo.PrefixLength = 0;\r
636 }\r
637\r
638 if (!NetIp6IsValidUnicast (&AddressInfo.Address)) {\r
639 Status = EFI_INVALID_PARAMETER;\r
640 goto Error;\r
641 }\r
642\r
643 Node = AllocatePool (sizeof (IP6_ADDRESS_INFO_ENTRY));\r
644 if (Node == NULL) {\r
645 Status = EFI_OUT_OF_RESOURCES;\r
646 goto Error;\r
647 }\r
648\r
649 CopyMem (&Node->AddrInfo, &AddressInfo, sizeof (EFI_IP6_ADDRESS_INFO));\r
650 InsertTailList (ListHead, &Node->Link);\r
651 Count++;\r
652\r
653 if (Last) {\r
654 break;\r
655 }\r
656\r
657 LocalString++;\r
658 }\r
659\r
660 FreePool (Temp);\r
661 *AddressCount = Count;\r
662 return EFI_SUCCESS;\r
663\r
664Error:\r
665 Ip6FreeAddressInfoList (ListHead);\r
666 FreePool (Temp);\r
667 return Status;\r
668}\r
669\r
670/**\r
671 This function converts the interface info to string and draws it to the IP6 UI.\r
672 The interface information includes interface name, interface type, hardware address,\r
673 address info, and route table information. The address information is also used as the\r
674 content of manual addresses in IP6 UI.\r
675\r
676 @param[in] IfInfo The pointer of EFI_IP6_CONFIG_INTERFACE_INFO.\r
677 @param[in] HiiHandle The handle that was previously registered in the\r
678 HII Database.\r
679 @param[in, out] IfrNvData Points to IP6_CONFIG_IFR_NVDATA.\r
680\r
681 @retval EFI_SUCCESS The operation finished successfully.\r
682 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
683 @retval EFI_OUT_OF_RESOURCES The operation failed due to lack of resources.\r
684\r
685**/\r
686EFI_STATUS\r
687Ip6ConvertInterfaceInfoToString (\r
688 IN EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo,\r
689 IN EFI_HII_HANDLE HiiHandle,\r
690 IN OUT IP6_CONFIG_IFR_NVDATA *IfrNvData\r
691 )\r
692{\r
693 UINT32 Index;\r
694 UINTN Number;\r
695 CHAR16 *String;\r
696 CHAR16 *LinkLocalStr;\r
697 CHAR16 PortString[ADDRESS_STR_MAX_SIZE];\r
698 CHAR16 FormatString[8];\r
699 EFI_STRING_ID StringId;\r
700 EFI_STATUS Status;\r
701\r
702 if ((IfInfo == NULL) || (HiiHandle == NULL) || (IfrNvData == NULL)) {\r
703 return EFI_INVALID_PARAMETER;\r
704 }\r
705\r
706 //\r
707 // Print the interface name.\r
708 //\r
709 StringId = HiiSetString (\r
710 HiiHandle,\r
711 STRING_TOKEN (STR_IP6_INTERFACE_NAME_CONTENT),\r
712 IfInfo->Name,\r
713 NULL\r
714 );\r
715 if (StringId == 0) {\r
716 return EFI_OUT_OF_RESOURCES;\r
717 }\r
718\r
719 //\r
720 // Print the interface type.\r
721 //\r
722 if (IfInfo->IfType == Ip6InterfaceTypeEthernet) {\r
723 StrCpy (PortString, IP6_ETHERNET);\r
724 } else if (IfInfo->IfType == Ip6InterfaceTypeExperimentalEthernet) {\r
725 StrCpy (PortString, IP6_EXPERIMENTAL_ETHERNET);\r
726 } else {\r
727 //\r
728 // Refer to RFC1700, chapter Number Hardware Type.\r
729 //\r
730 UnicodeSPrint (PortString, 6, L"%d", IfInfo->IfType);\r
731 }\r
732\r
733 StringId = HiiSetString (\r
734 HiiHandle,\r
735 STRING_TOKEN (STR_IP6_INTERFACE_TYPE_CONTENT),\r
736 PortString,\r
737 NULL\r
738 );\r
739 if (StringId == 0) {\r
740 return EFI_OUT_OF_RESOURCES;\r
741 }\r
742\r
743 //\r
744 // Convert the hardware address.\r
745 //\r
746 String = PortString;\r
747 ASSERT (IfInfo->HwAddressSize <= 32);\r
748\r
749 for (Index = 0; Index < IfInfo->HwAddressSize; Index++) {\r
750\r
751 if (IfInfo->HwAddress.Addr[Index] < 0x10) {\r
752 StrCpy (FormatString, L"0%x-");\r
753 } else {\r
754 StrCpy (FormatString, L"%x-");\r
755 }\r
756\r
757 Number = UnicodeSPrint (\r
758 String,\r
759 8,\r
760 (CONST CHAR16 *) FormatString,\r
761 (UINTN) IfInfo->HwAddress.Addr[Index]\r
762 );\r
763 String = String + Number;\r
764 }\r
765\r
766 if (Index != 0) {\r
767 ASSERT (String > PortString);\r
768 String--;\r
769 *String = '\0';\r
770 }\r
771\r
772 //\r
773 // Print the hardware address.\r
774 //\r
775 StringId = HiiSetString (\r
776 HiiHandle,\r
777 STRING_TOKEN (STR_IP6_MAC_ADDRESS_CONTENT),\r
778 PortString,\r
779 NULL\r
780 );\r
781 if (StringId == 0) {\r
782 return EFI_OUT_OF_RESOURCES;\r
783 }\r
784\r
785 //\r
786 // Print the host address Information.\r
787 //\r
788 Status = Ip6ConvertAddressListToString (\r
789 PortString,\r
790 HiiHandle,\r
791 Ip6ConfigNvHostAddress,\r
792 IfInfo->AddressInfo,\r
793 IfInfo->AddressInfoCount\r
794 );\r
795 if (EFI_ERROR (Status)) {\r
796 return Status;\r
797 }\r
798\r
799 //\r
800 // Copy the Host Address Info to manual address field.\r
801 // Do not copy the link local address.\r
802 //\r
803 LinkLocalStr = StrStr (PortString, IP6_LINK_LOCAL_PREFIX);\r
804 if (LinkLocalStr != NULL) {\r
805 Number = LinkLocalStr - PortString;\r
806 if (Number > 0) {\r
807 CopyMem (IfrNvData->ManualAddress, PortString, Number * sizeof (CHAR16));\r
808 }\r
809\r
810 while ((*LinkLocalStr != L' ') && (*LinkLocalStr != L'\0')) {\r
811 LinkLocalStr++;\r
812 }\r
813\r
814 if (*LinkLocalStr != L'\0') {\r
815 LinkLocalStr++;\r
816 StrCat (IfrNvData->ManualAddress, LinkLocalStr);\r
817 }\r
818 } else {\r
819 StrCpy (IfrNvData->ManualAddress, PortString);\r
820 }\r
821\r
822 //\r
823 // Print the route table information.\r
824 //\r
825 Status = Ip6ConvertAddressListToString (\r
826 PortString,\r
827 HiiHandle,\r
828 Ip6ConfigNvRouteTable,\r
829 IfInfo->RouteTable,\r
830 IfInfo->RouteCount\r
831 );\r
832 return Status;\r
833}\r
834\r
835/**\r
836 Build the address info list from list array of node in IP6_ADDRESS_INFO_ENTRY.\r
837\r
838 @param[in] Instance Points to IP6 config instance data.\r
839 @param[in] AddressType The address type.\r
840 @param[out] AddressInfo The pointer to the buffer to store the address list.\r
841 @param[out] AddressSize The address size of the address list.\r
842\r
843 @retval EFI_SUCCESS The operation finished successfully.\r
844 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
845 @retval EFI_UNSUPPORTED The AddressType is not supported.\r
846\r
847**/\r
848EFI_STATUS\r
849Ip6BuildNvAddressInfo (\r
850 IN IP6_CONFIG_INSTANCE *Instance,\r
851 IN IP6_CONFIG_NV_ADDRESS_TYPE AddressType,\r
852 OUT VOID **AddressInfo,\r
853 OUT UINTN *AddressSize\r
854 )\r
855{\r
856 IP6_CONFIG_NVDATA *Ip6NvData;\r
857 LIST_ENTRY *Entry;\r
858 LIST_ENTRY *ListHead;\r
859 IP6_ADDRESS_INFO_ENTRY *Node;\r
860 VOID *AddressList;\r
861 VOID *TmpStr;\r
862 UINTN DataSize;\r
863 EFI_IPv6_ADDRESS *Ip6Address;\r
864 EFI_IP6_CONFIG_MANUAL_ADDRESS *ManualAddress;\r
865\r
866 if ((Instance == NULL) || (AddressInfo == NULL) || (AddressSize == NULL)) {\r
867 return EFI_INVALID_PARAMETER;\r
868 }\r
869\r
870 NET_CHECK_SIGNATURE (Instance, IP6_CONFIG_INSTANCE_SIGNATURE);\r
871\r
872 Ip6NvData = &Instance->Ip6NvData;\r
873\r
874 if (AddressType == Ip6ConfigNvHostAddress) {\r
875 ListHead = &Ip6NvData->ManualAddress;\r
876 DataSize = sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS) * Ip6NvData->ManualAddressCount;\r
877 } else if (AddressType == Ip6ConfigNvGatewayAddress) {\r
878 ListHead = &Ip6NvData->GatewayAddress;\r
879 DataSize = sizeof (EFI_IPv6_ADDRESS) * Ip6NvData->GatewayAddressCount;\r
880 } else if (AddressType == Ip6ConfigNvDnsAddress) {\r
881 ListHead = &Ip6NvData->DnsAddress;\r
882 DataSize = sizeof (EFI_IPv6_ADDRESS) * Ip6NvData->DnsAddressCount;\r
883 } else {\r
884 return EFI_UNSUPPORTED;\r
885 }\r
886\r
887 AddressList = AllocateZeroPool (DataSize);\r
888 if (AddressList == NULL) {\r
889 return EFI_OUT_OF_RESOURCES;\r
890 }\r
891\r
892 TmpStr = AddressList;\r
893\r
894 NET_LIST_FOR_EACH (Entry, ListHead) {\r
895 Node = NET_LIST_USER_STRUCT (Entry, IP6_ADDRESS_INFO_ENTRY, Link);\r
896 if (AddressType == Ip6ConfigNvHostAddress) {\r
897 ManualAddress = (EFI_IP6_CONFIG_MANUAL_ADDRESS *) AddressList;\r
898 IP6_COPY_ADDRESS (&ManualAddress->Address, &Node->AddrInfo.Address);\r
899 ManualAddress->PrefixLength = Node->AddrInfo.PrefixLength;\r
900 AddressList = (UINT8 *) AddressList + sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS);\r
901 } else {\r
902 Ip6Address = (EFI_IPv6_ADDRESS *) AddressList;\r
903 IP6_COPY_ADDRESS (Ip6Address, &Node->AddrInfo.Address);\r
904 AddressList = (UINT8 *) AddressList + sizeof (EFI_IPv6_ADDRESS);\r
905 }\r
906 }\r
907\r
908 *AddressInfo = TmpStr;\r
909 *AddressSize = DataSize;\r
910 return EFI_SUCCESS;\r
911}\r
912\r
913/**\r
914 Convert the IP6 configuration data into the IFR data.\r
915\r
916 @param[in, out] IfrNvData The IFR NV data.\r
917 @param[in] Instance The IP6 config instance data.\r
918\r
919 @retval EFI_SUCCESS The operation finished successfully.\r
920 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
921 @retval EFI_UNSUPPORTED The policy is not supported in the current implementation.\r
922 @retval Others Other errors as indicated.\r
923\r
924**/\r
925EFI_STATUS\r
926Ip6ConvertConfigNvDataToIfrNvData (\r
927 IN OUT IP6_CONFIG_IFR_NVDATA *IfrNvData,\r
928 IN IP6_CONFIG_INSTANCE *Instance\r
929 )\r
930{\r
931 EFI_IP6_CONFIG_PROTOCOL *Ip6Config;\r
932 UINTN DataSize;\r
933 VOID *Data;\r
934 EFI_STATUS Status;\r
935 EFI_IP6_CONFIG_INTERFACE_ID InterfaceId;\r
936 EFI_IP6_CONFIG_POLICY Policy;\r
937 EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS DadXmits;\r
938 EFI_HII_HANDLE HiiHandle;\r
939\r
940 if ((IfrNvData == NULL) || (Instance == NULL)) {\r
941 return EFI_INVALID_PARAMETER;\r
942 }\r
943\r
944 NET_CHECK_SIGNATURE (Instance, IP6_CONFIG_INSTANCE_SIGNATURE);\r
945\r
946 Ip6Config = &Instance->Ip6Config;\r
947 Data = NULL;\r
948 DataSize = 0;\r
949 HiiHandle = Instance->CallbackInfo.RegisteredHandle;\r
950\r
951 //\r
952 // Get the current interface info.\r
953 //\r
954 Status = Ip6ConfigNvGetData (\r
955 Ip6Config,\r
956 Ip6ConfigDataTypeInterfaceInfo,\r
957 &DataSize,\r
958 (VOID **) &Data\r
959 );\r
960 if (EFI_ERROR (Status)) {\r
961 goto Exit;\r
962 }\r
963\r
964 //\r
965 // Convert the interface info to string and print.\r
966 //\r
967 Status = Ip6ConvertInterfaceInfoToString (\r
968 (EFI_IP6_CONFIG_INTERFACE_INFO *) Data,\r
969 HiiHandle,\r
970 IfrNvData\r
971 );\r
972 if (EFI_ERROR (Status)) {\r
973 goto Exit;\r
974 }\r
975\r
976 //\r
977 // Get the interface id.\r
978 //\r
979 DataSize = sizeof (EFI_IP6_CONFIG_INTERFACE_ID);\r
980 ZeroMem (&InterfaceId, DataSize);\r
981 Status = Ip6Config->GetData (\r
982 Ip6Config,\r
983 Ip6ConfigDataTypeAltInterfaceId,\r
984 &DataSize,\r
985 &InterfaceId\r
986 );\r
987 if (EFI_ERROR (Status)) {\r
988 goto Exit;\r
989 }\r
990\r
991 Ip6ConvertInterfaceIdToString (IfrNvData->InterfaceId, &InterfaceId);\r
992\r
993 //\r
994 // Get current policy.\r
995 //\r
996 DataSize = sizeof (EFI_IP6_CONFIG_POLICY);\r
997 Status = Ip6Config->GetData (\r
998 Ip6Config,\r
999 Ip6ConfigDataTypePolicy,\r
1000 &DataSize,\r
1001 &Policy\r
1002 );\r
1003\r
1004 if (EFI_ERROR (Status)) {\r
1005 goto Exit;\r
1006 }\r
1007\r
1008 if (Policy == Ip6ConfigPolicyManual) {\r
1009 IfrNvData->Policy = IP6_POLICY_MANUAL;\r
1010 } else if (Policy == Ip6ConfigPolicyAutomatic) {\r
1011 IfrNvData->Policy = IP6_POLICY_AUTO;\r
1012 } else {\r
1013 ASSERT (FALSE);\r
1014 Status = EFI_UNSUPPORTED;\r
1015 goto Exit;\r
1016 }\r
1017\r
1018 //\r
1019 // Get Duplicate Address Detection Transmits count.\r
1020 //\r
1021 DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);\r
1022 Status = Ip6Config->GetData (\r
1023 Ip6Config,\r
1024 Ip6ConfigDataTypeDupAddrDetectTransmits,\r
1025 &DataSize,\r
1026 &DadXmits\r
1027 );\r
1028\r
1029 if (EFI_ERROR (Status)) {\r
1030 goto Exit;\r
1031 }\r
1032\r
1033 IfrNvData->DadTransmitCount = DadXmits.DupAddrDetectTransmits;\r
1034\r
1035 //\r
1036 // Get DNS server list.\r
1037 //\r
1038 FreePool (Data);\r
1039 Data = NULL;\r
1040 DataSize = 0;\r
1041 Status = Ip6ConfigNvGetData (\r
1042 Ip6Config,\r
1043 Ip6ConfigDataTypeDnsServer,\r
1044 &DataSize,\r
1045 (VOID **) &Data\r
1046 );\r
1047\r
1048 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
1049 goto Exit;\r
1050 }\r
1051\r
1052 if (DataSize > 0) {\r
1053 //\r
1054 // Convert the DNS server address to string and draw it to UI.\r
1055 //\r
1056 Status = Ip6ConvertAddressListToString (\r
1057 IfrNvData->DnsAddress,\r
1058 HiiHandle,\r
1059 Ip6ConfigNvDnsAddress,\r
1060 Data,\r
1061 DataSize / sizeof (EFI_IPv6_ADDRESS)\r
1062 );\r
1063 if (EFI_ERROR (Status)) {\r
1064 goto Exit;\r
1065 }\r
1066\r
1067 FreePool (Data);\r
1068 Data = NULL;\r
1069 }\r
1070\r
1071 //\r
1072 // Get gateway adderss list.\r
1073 //\r
1074 DataSize = 0;\r
1075 Status = Ip6ConfigNvGetData (\r
1076 Ip6Config,\r
1077 Ip6ConfigDataTypeGateway,\r
1078 &DataSize,\r
1079 (VOID **) &Data\r
1080 );\r
1081\r
1082 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
1083 goto Exit;\r
1084 }\r
1085\r
1086 if (DataSize > 0) {\r
1087 //\r
1088 // Convert the gateway address to string and draw it to UI.\r
1089 //\r
1090 Status = Ip6ConvertAddressListToString (\r
1091 IfrNvData->GatewayAddress,\r
1092 HiiHandle,\r
1093 Ip6ConfigNvGatewayAddress,\r
1094 Data,\r
1095 DataSize / sizeof (EFI_IPv6_ADDRESS)\r
1096 );\r
1097 if (EFI_ERROR (Status)) {\r
1098 goto Exit;\r
1099 }\r
1100 }\r
1101\r
1102 Status = EFI_SUCCESS;\r
1103\r
1104Exit:\r
1105 if (Data != NULL) {\r
1106 FreePool (Data);\r
1107 }\r
1108\r
1109 return Status;\r
1110}\r
1111\r
1112/**\r
1113 Convert IFR data into IP6 configuration data. The policy, alternative interface\r
1114 ID, and DAD transmit counts, and will be saved. If under manual policy, the configured\r
1115 manual address, gateway address, and DNS server address will be saved.\r
1116\r
1117 @param[in] IfrNvData The IFR NV data.\r
1118 @param[in, out] Instance The IP6 config instance data.\r
1119\r
1120 @retval EFI_SUCCESS The operation finished successfully.\r
1121 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
1122 @retval Others Other errors as indicated.\r
1123\r
1124**/\r
1125EFI_STATUS\r
1126Ip6ConvertIfrNvDataToConfigNvData (\r
1127 IN IP6_CONFIG_IFR_NVDATA *IfrNvData,\r
1128 IN OUT IP6_CONFIG_INSTANCE *Instance\r
1129 )\r
1130{\r
1131 IP6_CONFIG_NVDATA *Ip6NvData;\r
1132 EFI_IP6_CONFIG_PROTOCOL *Ip6Config;\r
1133 EFI_STATUS Status;\r
1134 EFI_IP6_CONFIG_MANUAL_ADDRESS *ManualAddress;\r
1135 EFI_IPv6_ADDRESS *Address;\r
1136 BOOLEAN IsAddressOk;\r
1137 EFI_EVENT SetAddressEvent;\r
1138 EFI_EVENT TimeoutEvent;\r
1139 UINTN DataSize;\r
1140\r
1141 if ((IfrNvData == NULL) || (Instance == NULL)) {\r
1142 return EFI_INVALID_PARAMETER;\r
1143 }\r
1144\r
1145 NET_CHECK_SIGNATURE (Instance, IP6_CONFIG_INSTANCE_SIGNATURE);\r
1146 Ip6NvData = &Instance->Ip6NvData;\r
1147 Ip6Config = &Instance->Ip6Config;\r
1148\r
1149 //\r
1150 // Update those fields which don't have INTERACTIVE attribute.\r
1151 //\r
1152 if (IfrNvData->Policy == IP6_POLICY_AUTO) {\r
1153 Ip6NvData->Policy = Ip6ConfigPolicyAutomatic;\r
1154 } else if (IfrNvData->Policy == IP6_POLICY_MANUAL) {\r
1155 Ip6NvData->Policy = Ip6ConfigPolicyManual;\r
1156 }\r
1157\r
1158 Ip6NvData->DadTransmitCount.DupAddrDetectTransmits = IfrNvData->DadTransmitCount;\r
1159\r
1160 //\r
1161 // Set the configured policy.\r
1162 //\r
1163 Status = Ip6Config->SetData (\r
1164 Ip6Config,\r
1165 Ip6ConfigDataTypePolicy,\r
1166 sizeof (EFI_IP6_CONFIG_POLICY),\r
1167 &Ip6NvData->Policy\r
1168 );\r
1169 if (EFI_ERROR (Status)) {\r
1170 return Status;\r
1171 }\r
1172\r
1173 //\r
1174 // Set the duplicate address detection transmits count.\r
1175 //\r
1176 Status = Ip6Config->SetData (\r
1177 Ip6Config,\r
1178 Ip6ConfigDataTypeDupAddrDetectTransmits,\r
1179 sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS),\r
1180 &Ip6NvData->DadTransmitCount\r
1181 );\r
1182 if (EFI_ERROR (Status)) {\r
1183 return Status;\r
1184 }\r
1185\r
1186 //\r
1187 // Set the alternative interface ID\r
1188 //\r
1189 Status = Ip6Config->SetData (\r
1190 Ip6Config,\r
1191 Ip6ConfigDataTypeAltInterfaceId,\r
1192 sizeof (EFI_IP6_CONFIG_INTERFACE_ID),\r
1193 &Ip6NvData->InterfaceId\r
1194 );\r
1195 if (EFI_ERROR (Status)) {\r
1196 return Status;\r
1197 }\r
1198\r
1199\r
1200 if (Ip6NvData->Policy == Ip6ConfigPolicyAutomatic) {\r
1201 return EFI_SUCCESS;\r
1202 }\r
1203\r
1204 //\r
1205 // Create events & timers for asynchronous settings.\r
1206 //\r
1207 SetAddressEvent = NULL;\r
1208 TimeoutEvent = NULL;\r
1209 ManualAddress = NULL;\r
1210 Address = NULL;\r
1211\r
1212 Status = gBS->CreateEvent (\r
1213 EVT_NOTIFY_SIGNAL,\r
1214 TPL_NOTIFY,\r
1215 Ip6ConfigManualAddressNotify,\r
1216 &IsAddressOk,\r
1217 &SetAddressEvent\r
1218 );\r
1219 if (EFI_ERROR (Status)) {\r
1220 goto Exit;\r
1221 }\r
1222\r
1223 Status = gBS->CreateEvent (\r
1224 EVT_TIMER,\r
1225 TPL_CALLBACK,\r
1226 NULL,\r
1227 NULL,\r
1228 &TimeoutEvent\r
1229 );\r
1230 if (EFI_ERROR (Status)) {\r
1231 goto Exit;\r
1232 }\r
1233\r
1234 //\r
1235 // Set the manual address list. This is an asynchronous process.\r
1236 //\r
1237 if (!IsListEmpty (&Ip6NvData->ManualAddress) && (Ip6NvData->ManualAddressCount != 0)) {\r
1238 Status = Ip6BuildNvAddressInfo (\r
1239 Instance,\r
1240 Ip6ConfigNvHostAddress,\r
1241 (VOID **) &ManualAddress,\r
1242 &DataSize\r
1243 );\r
1244 if (EFI_ERROR (Status)) {\r
1245 goto Exit;\r
1246 }\r
1247\r
1248 IsAddressOk = FALSE;\r
1249\r
1250 Status = Ip6Config->RegisterDataNotify (\r
1251 Ip6Config,\r
1252 Ip6ConfigDataTypeManualAddress,\r
1253 SetAddressEvent\r
1254 );\r
1255 if (EFI_ERROR (Status)) {\r
1256 goto Exit;\r
1257 }\r
1258\r
1259 Status = Ip6Config->SetData (\r
1260 Ip6Config,\r
1261 Ip6ConfigDataTypeManualAddress,\r
1262 DataSize,\r
1263 (VOID *) ManualAddress\r
1264 );\r
1265 if (Status == EFI_NOT_READY) {\r
1266 gBS->SetTimer (TimeoutEvent, TimerRelative, 50000000);\r
1267 while (EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {\r
1268 if (IsAddressOk) {\r
1269 Status = EFI_SUCCESS;\r
1270 }\r
1271 break;\r
1272 }\r
1273 }\r
1274\r
1275 Status = Ip6Config->UnregisterDataNotify (\r
1276 Ip6Config,\r
1277 Ip6ConfigDataTypeManualAddress,\r
1278 SetAddressEvent\r
1279 );\r
1280 if (EFI_ERROR (Status)) {\r
1281 goto Exit;\r
1282 }\r
1283 }\r
1284\r
1285 //\r
1286 // Set gateway address list.\r
1287 //\r
1288 if (!IsListEmpty (&Ip6NvData->GatewayAddress) && (Ip6NvData->GatewayAddressCount != 0)) {\r
1289 Status = Ip6BuildNvAddressInfo (\r
1290 Instance,\r
1291 Ip6ConfigNvGatewayAddress,\r
1292 (VOID **) &Address,\r
1293 &DataSize\r
1294 );\r
1295 if (EFI_ERROR (Status)) {\r
1296 goto Exit;\r
1297 }\r
1298\r
1299 Status = Ip6Config->SetData (\r
1300 Ip6Config,\r
1301 Ip6ConfigDataTypeGateway,\r
1302 DataSize,\r
1303 (VOID *) Address\r
1304 );\r
1305 if (EFI_ERROR (Status)) {\r
1306 goto Exit;\r
1307 }\r
1308\r
1309 FreePool (Address);\r
1310 Address = NULL;\r
1311 }\r
1312\r
1313 //\r
1314 // Set DNS server address list.\r
1315 //\r
1316 if (!IsListEmpty (&Ip6NvData->DnsAddress) && (Ip6NvData->DnsAddressCount != 0)) {\r
1317 Status = Ip6BuildNvAddressInfo (\r
1318 Instance,\r
1319 Ip6ConfigNvDnsAddress,\r
1320 (VOID **) &Address,\r
1321 &DataSize\r
1322 );\r
1323 if (EFI_ERROR (Status)) {\r
1324 goto Exit;\r
1325 }\r
1326\r
1327 Status = Ip6Config->SetData (\r
1328 Ip6Config,\r
1329 Ip6ConfigDataTypeDnsServer,\r
1330 DataSize,\r
1331 (VOID *) Address\r
1332 );\r
1333 if (EFI_ERROR (Status)) {\r
1334 goto Exit;\r
1335 }\r
1336 }\r
1337\r
1338 Status = EFI_SUCCESS;\r
1339\r
1340Exit:\r
1341 if (SetAddressEvent != NULL) {\r
1342 gBS->CloseEvent (SetAddressEvent);\r
1343 }\r
1344\r
1345 if (TimeoutEvent != NULL) {\r
1346 gBS->CloseEvent (TimeoutEvent);\r
1347 }\r
1348\r
1349 if (ManualAddress != NULL) {\r
1350 FreePool (ManualAddress);\r
1351 }\r
1352\r
1353 if (Address != NULL) {\r
1354 FreePool (Address);\r
1355 }\r
1356\r
1357 return Status;\r
1358}\r
1359\r
1360/**\r
1361 This function allows the caller to request the current\r
1362 configuration for one or more named elements. The resulting\r
1363 string is in <ConfigAltResp> format. Any and all alternative\r
1364 configuration strings shall also be appended to the end of the\r
1365 current configuration string. If they are, they must appear\r
1366 after the current configuration. They must contain the same\r
1367 routing (GUID, NAME, PATH) as the current configuration string.\r
1368 They must have an additional description indicating the type of\r
1369 alternative configuration the string represents,\r
1370 "ALTCFG=<StringToken>". That <StringToken> (when\r
1371 converted from Hex UNICODE to binary) is a reference to a\r
1372 string in the associated string pack.\r
1373\r
1374 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
1375 @param[in] Request A null-terminated Unicode string in\r
1376 <ConfigRequest> format. Note that this\r
1377 includes the routing information as well as\r
1378 the configurable name / value pairs. It is\r
1379 invalid for this string to be in\r
1380 <MultiConfigRequest> format.\r
1381 @param[out] Progress On return, points to a character in the\r
1382 Request string. Points to the string's null\r
1383 terminator if request was successful. Points\r
1384 to the most recent "&" before the first\r
1385 failing name / value pair (or the beginning\r
1386 of the string if the failure is in the first\r
1387 name / value pair) if the request was not\r
1388 successful.\r
1389 @param[out] Results A null-terminated Unicode string in\r
1390 <ConfigAltResp> format which has all values\r
1391 filled in for the names in the Request string.\r
1392 String to be allocated by the called function.\r
1393\r
1394 @retval EFI_SUCCESS The Results string is filled with the\r
1395 values corresponding to all requested\r
1396 names.\r
1397 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the\r
1398 parts of the results that must be\r
1399 stored awaiting possible future\r
1400 protocols.\r
1401 @retval EFI_INVALID_PARAMETER For example, passing in a NULL\r
1402 for the Request parameter\r
1403 would result in this type of\r
1404 error. In this case, the\r
1405 Progress parameter would be\r
1406 set to NULL.\r
1407 @retval EFI_NOT_FOUND Routing data doesn't match any\r
1408 known driver. Progress set to the\r
1409 first character in the routing header.\r
1410 Note: There is no requirement that the\r
1411 driver validate the routing data. It\r
1412 must skip the <ConfigHdr> in order to\r
1413 process the names.\r
1414 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set\r
1415 to most recent & before the\r
1416 error or the beginning of the\r
1417 string.\r
1418 @retval EFI_INVALID_PARAMETER Unknown name. Progress points\r
1419 to the & before the name in\r
1420 question. Currently not implemented.\r
1421**/\r
1422EFI_STATUS\r
1423EFIAPI\r
1424Ip6FormExtractConfig (\r
1425 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
1426 IN CONST EFI_STRING Request,\r
1427 OUT EFI_STRING *Progress,\r
1428 OUT EFI_STRING *Results\r
1429 )\r
1430{\r
1431\r
1432 EFI_STATUS Status;\r
1433 IP6_FORM_CALLBACK_INFO *Private;\r
1434 IP6_CONFIG_INSTANCE *Ip6ConfigInstance;\r
1435 IP6_CONFIG_IFR_NVDATA *IfrNvData;\r
1436 EFI_STRING ConfigRequestHdr;\r
1437 EFI_STRING ConfigRequest;\r
1438 BOOLEAN AllocatedRequest;\r
1439 UINTN Size;\r
1440 UINTN BufferSize;\r
1441\r
1442 if (This == NULL || Progress == NULL || Results == NULL) {\r
1443 return EFI_INVALID_PARAMETER;\r
1444 }\r
1445\r
1446 *Progress = Request;\r
1447 if ((Request != NULL) &&\r
9bdc6592 1448 !HiiIsConfigHdrMatch (Request, &gIp6ConfigNvDataGuid, mIp6ConfigStorageName)) {\r
a3bcde70
HT
1449 return EFI_NOT_FOUND;\r
1450 }\r
1451\r
1452 ConfigRequestHdr = NULL;\r
1453 ConfigRequest = NULL;\r
1454 AllocatedRequest = FALSE;\r
1455 Size = 0;\r
1456\r
1457 Private = IP6_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This);\r
1458 Ip6ConfigInstance = IP6_CONFIG_INSTANCE_FROM_FORM_CALLBACK (Private);\r
1459 BufferSize = sizeof (IP6_CONFIG_IFR_NVDATA);\r
1460\r
1461 IfrNvData = (IP6_CONFIG_IFR_NVDATA *) AllocateZeroPool (BufferSize);\r
1462 if (IfrNvData == NULL) {\r
1463 return EFI_OUT_OF_RESOURCES;\r
1464 }\r
1465\r
1466 Status = Ip6ConvertConfigNvDataToIfrNvData (IfrNvData, Ip6ConfigInstance);\r
1467 if (EFI_ERROR (Status)) {\r
1468 goto Exit;\r
1469 }\r
1470\r
1471 ConfigRequest = Request;\r
1472 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
1473 //\r
1474 // Request has no request element, construct full request string.\r
1475 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
1476 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator.\r
1477 //\r
1478 ConfigRequestHdr = HiiConstructConfigHdr (\r
9bdc6592 1479 &gIp6ConfigNvDataGuid,\r
a3bcde70
HT
1480 mIp6ConfigStorageName,\r
1481 Private->ChildHandle\r
1482 );\r
1483 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
1484 ConfigRequest = AllocateZeroPool (Size);\r
1485 ASSERT (ConfigRequest != NULL);\r
1486 AllocatedRequest = TRUE;\r
1487 UnicodeSPrint (\r
1488 ConfigRequest,\r
1489 Size,\r
1490 L"%s&OFFSET=0&WIDTH=%016LX",\r
1491 ConfigRequestHdr,\r
1492 (UINT64) BufferSize\r
1493 );\r
1494 FreePool (ConfigRequestHdr);\r
1495 }\r
1496\r
1497 //\r
1498 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
1499 //\r
1500 Status = gHiiConfigRouting->BlockToConfig (\r
1501 gHiiConfigRouting,\r
1502 ConfigRequest,\r
1503 (UINT8 *) IfrNvData,\r
1504 BufferSize,\r
1505 Results,\r
1506 Progress\r
1507 );\r
1508\r
1509Exit:\r
1510 FreePool (IfrNvData);\r
1511 //\r
1512 // Free the allocated config request string.\r
1513 //\r
1514 if (AllocatedRequest) {\r
1515 FreePool (ConfigRequest);\r
1516 ConfigRequest = NULL;\r
1517 }\r
1518 //\r
1519 // Set Progress string to the original request string.\r
1520 //\r
1521 if (Request == NULL) {\r
1522 *Progress = NULL;\r
1523 } else if (StrStr (Request, L"OFFSET") == NULL) {\r
1524 *Progress = Request + StrLen (Request);\r
1525 }\r
1526\r
1527 return Status;\r
1528}\r
1529\r
1530/**\r
1531 This function applies changes in a driver's configuration.\r
1532 Input is a Configuration, which has the routing data for this\r
1533 driver followed by name / value configuration pairs. The driver\r
1534 must apply those pairs to its configurable storage. If the\r
1535 driver's configuration is stored in a linear block of data\r
1536 and the driver's name / value pairs are in <BlockConfig>\r
1537 format, it may use the ConfigToBlock helper function (above) to\r
1538 simplify the job. Currently not implemented.\r
1539\r
1540 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
1541 @param[in] Configuration A null-terminated Unicode string in\r
1542 <ConfigString> format.\r
1543 @param[out] Progress A pointer to a string filled in with the\r
1544 offset of the most recent '&' before the\r
1545 first failing name / value pair (or the\r
1546 beginn ing of the string if the failure\r
1547 is in the first name / value pair) or\r
1548 the terminating NULL if all was\r
1549 successful.\r
1550\r
1551 @retval EFI_SUCCESS The results have been distributed or are\r
1552 awaiting distribution.\r
1553 @retval EFI_OUT_OF_MEMORY Not enough memory to store the\r
1554 parts of the results that must be\r
1555 stored awaiting possible future\r
1556 protocols.\r
1557 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the\r
1558 Results parameter would result\r
1559 in this type of error.\r
1560 @retval EFI_NOT_FOUND Target for the specified routing data\r
1561 was not found.\r
1562**/\r
1563EFI_STATUS\r
1564EFIAPI\r
1565Ip6FormRouteConfig (\r
1566 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
1567 IN CONST EFI_STRING Configuration,\r
1568 OUT EFI_STRING *Progress\r
1569 )\r
1570{\r
1571 if (This == NULL || Configuration == NULL || Progress == NULL) {\r
1572 return EFI_INVALID_PARAMETER;\r
1573 }\r
1574\r
1575 //\r
1576 // Check routing data in <ConfigHdr>.\r
1577 // Note: if only one Storage is used, then this checking could be skipped.\r
1578 //\r
9bdc6592 1579 if (!HiiIsConfigHdrMatch (Configuration, &gIp6ConfigNvDataGuid, mIp6ConfigStorageName)) {\r
a3bcde70
HT
1580 *Progress = Configuration;\r
1581 return EFI_NOT_FOUND;\r
1582 }\r
1583\r
1584 *Progress = Configuration + StrLen (Configuration);\r
1585\r
1586 return EFI_SUCCESS;\r
1587}\r
1588\r
1589/**\r
1590 This function is called to provide results data to the driver.\r
1591 This data consists of a unique key that is used to identify\r
1592 which data is either being passed back or being asked for.\r
1593\r
1594 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
1595 @param[in] Action Specifies the type of action taken by the browser.\r
1596 @param[in] QuestionId A unique value which is sent to the original\r
1597 exporting driver so that it can identify the type\r
1598 of data to expect. The format of the data tends to\r
1599 vary based on the opcode that generated the callback.\r
1600 @param[in] Type The type of value for the question.\r
1601 @param[in] Value A pointer to the data being sent to the original\r
1602 exporting driver.\r
1603 @param[out] ActionRequest On return, points to the action requested by the\r
1604 callback function.\r
1605\r
1606 @retval EFI_SUCCESS The callback successfully handled the action.\r
1607 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the\r
1608 variable and its data.\r
1609 @retval EFI_DEVICE_ERROR The variable could not be saved.\r
1610 @retval EFI_UNSUPPORTED The specified Action is not supported by the\r
1611 callback. Currently not implemented.\r
1612 @retval EFI_INVALID_PARAMETER Passed in the wrong parameter.\r
1613 @retval Others Other errors as indicated.\r
1614\r
1615**/\r
1616EFI_STATUS\r
1617EFIAPI\r
1618Ip6FormCallback (\r
1619 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
1620 IN EFI_BROWSER_ACTION Action,\r
1621 IN EFI_QUESTION_ID QuestionId,\r
1622 IN UINT8 Type,\r
1623 IN EFI_IFR_TYPE_VALUE *Value,\r
1624 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
1625 )\r
1626{\r
1627 IP6_FORM_CALLBACK_INFO *Private;\r
1628 UINTN BufferSize;\r
1629 IP6_CONFIG_IFR_NVDATA *IfrNvData;\r
1630 IP6_CONFIG_IFR_NVDATA OldIfrNvData;\r
1631 EFI_STATUS Status;\r
1632 EFI_INPUT_KEY Key;\r
1633 IP6_CONFIG_INSTANCE *Instance;\r
1634 IP6_CONFIG_NVDATA *Ip6NvData;\r
1635 EFI_IP6_CONFIG_PROTOCOL *Ip6Config;\r
1636 EFI_IP6_CONFIG_INTERFACE_INFO *Data;\r
1637 UINTN DataSize;\r
1638 CHAR16 PortString[ADDRESS_STR_MAX_SIZE];\r
1639 EFI_HII_HANDLE HiiHandle;\r
1640 EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo;\r
1641\r
1642 if (This == NULL) {\r
1643 return EFI_INVALID_PARAMETER;\r
1644 }\r
1645\r
1646 Private = IP6_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This);\r
1647 Instance = IP6_CONFIG_INSTANCE_FROM_FORM_CALLBACK (Private);\r
1648 Ip6NvData = &Instance->Ip6NvData;\r
1649\r
e0afa489 1650 if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)){\r
1651 return EFI_SUCCESS;\r
1652 }\r
1653\r
639a76d1 1654 if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) {\r
e0afa489 1655 return EFI_UNSUPPORTED;\r
1656 }\r
1657\r
1658 if ((Value == NULL) || (ActionRequest == NULL)) {\r
1659 return EFI_INVALID_PARAMETER;\r
1660 }\r
1661\r
1662 //\r
1663 // Retrieve uncommitted data from Browser\r
1664 //\r
1665\r
1666 BufferSize = sizeof (IP6_CONFIG_IFR_NVDATA);\r
1667 IfrNvData = AllocateZeroPool (BufferSize);\r
1668 if (IfrNvData == NULL) {\r
1669 return EFI_OUT_OF_RESOURCES;\r
1670 }\r
1671\r
1672 Status = EFI_SUCCESS;\r
1673\r
1674 ZeroMem (&OldIfrNvData, BufferSize);\r
1675\r
1676 HiiGetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData);\r
1677\r
1678 CopyMem (&OldIfrNvData, IfrNvData, BufferSize);\r
1679\r
639a76d1
ED
1680 if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
1681 switch (QuestionId) {\r
1682 case KEY_GET_CURRENT_SETTING:\r
1683 Ip6Config = &Instance->Ip6Config;\r
1684 HiiHandle = Instance->CallbackInfo.RegisteredHandle;\r
1685 Data = NULL;\r
a3bcde70 1686\r
639a76d1
ED
1687 //\r
1688 // Get current interface info.\r
1689 //\r
1690 Status = Ip6ConfigNvGetData (\r
1691 Ip6Config,\r
1692 Ip6ConfigDataTypeInterfaceInfo,\r
1693 &DataSize,\r
1694 (VOID **) &Data\r
1695 );\r
1696 if (EFI_ERROR (Status)) {\r
1697 return Status;\r
e0afa489 1698 }\r
a3bcde70 1699\r
a3bcde70 1700 //\r
639a76d1 1701 // Generate dynamic text opcode for host address and draw it.\r
a3bcde70 1702 //\r
639a76d1 1703 IfInfo = (EFI_IP6_CONFIG_INTERFACE_INFO *) Data;\r
a3bcde70
HT
1704 Status = Ip6ConvertAddressListToString (\r
1705 PortString,\r
1706 HiiHandle,\r
639a76d1
ED
1707 Ip6ConfigNvHostAddress,\r
1708 IfInfo->AddressInfo,\r
1709 IfInfo->AddressInfoCount\r
a3bcde70
HT
1710 );\r
1711 if (EFI_ERROR (Status)) {\r
e0afa489 1712 FreePool (Data);\r
1713 return Status;\r
a3bcde70 1714 }\r
a3bcde70 1715\r
a3bcde70 1716 //\r
639a76d1 1717 // Generate the dynamic text opcode for route table and draw it.\r
a3bcde70
HT
1718 //\r
1719 Status = Ip6ConvertAddressListToString (\r
1720 PortString,\r
1721 HiiHandle,\r
639a76d1
ED
1722 Ip6ConfigNvRouteTable,\r
1723 IfInfo->RouteTable,\r
1724 IfInfo->RouteCount\r
a3bcde70
HT
1725 );\r
1726 if (EFI_ERROR (Status)) {\r
e0afa489 1727 FreePool (Data);\r
1728 return Status;\r
a3bcde70 1729 }\r
a3bcde70 1730\r
639a76d1
ED
1731 //\r
1732 // Get DNS server list.\r
1733 //\r
e0afa489 1734 FreePool (Data);\r
639a76d1
ED
1735 DataSize = 0;\r
1736 Data = NULL;\r
1737 Status = Ip6ConfigNvGetData (\r
1738 Ip6Config,\r
1739 Ip6ConfigDataTypeDnsServer,\r
1740 &DataSize,\r
1741 (VOID **) &Data\r
1742 );\r
1743 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
1744 if (Data != NULL) {\r
1745 FreePool (Data);\r
1746 }\r
1747 return Status;\r
1748 }\r
1749\r
1750 if (DataSize > 0) {\r
1751 //\r
1752 // Generate the dynamic text opcode for DNS server and draw it.\r
1753 //\r
1754 Status = Ip6ConvertAddressListToString (\r
1755 PortString,\r
1756 HiiHandle,\r
1757 Ip6ConfigNvDnsAddress,\r
1758 Data,\r
1759 DataSize / sizeof (EFI_IPv6_ADDRESS)\r
1760 );\r
1761 if (EFI_ERROR (Status)) {\r
1762 FreePool (Data);\r
1763 return Status;\r
1764 }\r
1765 }\r
1766\r
1767 //\r
1768 // Get gateway adderss list.\r
1769 //\r
1770 if (Data != NULL) {\r
1771 FreePool (Data);\r
1772 }\r
1773\r
1774 DataSize = 0;\r
1775 Data = NULL;\r
1776 Status = Ip6ConfigNvGetData (\r
1777 Ip6Config,\r
1778 Ip6ConfigDataTypeGateway,\r
1779 &DataSize,\r
1780 (VOID **) &Data\r
1781 );\r
1782 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
1783 if (Data != NULL) {\r
1784 FreePool (Data);\r
1785 }\r
1786 return Status;\r
1787 }\r
1788\r
1789 if (DataSize > 0) {\r
1790 //\r
1791 // Generate the dynamic text opcode for gateway and draw it.\r
1792 //\r
1793 Status = Ip6ConvertAddressListToString (\r
1794 PortString,\r
1795 HiiHandle,\r
1796 Ip6ConfigNvGatewayAddress,\r
1797 Data,\r
1798 DataSize / sizeof (EFI_IPv6_ADDRESS)\r
1799 );\r
1800 if (EFI_ERROR (Status)) {\r
1801 FreePool (Data);\r
1802 return Status;\r
1803 }\r
1804 }\r
1805\r
1806 if (Data != NULL) {\r
1807 FreePool (Data);\r
1808 }\r
1809\r
1810 Status = EFI_SUCCESS;\r
1811\r
1812 break;\r
1813\r
1814 default:\r
1815 break;\r
2d4df339 1816 }\r
639a76d1
ED
1817 } else if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
1818 switch (QuestionId) {\r
1819 case KEY_SAVE_CONFIG_CHANGES:\r
1820 CopyMem (&OldIfrNvData, IfrNvData, sizeof (IP6_CONFIG_IFR_NVDATA));\r
1821 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;\r
1822 break;\r
a3bcde70 1823\r
639a76d1
ED
1824 case KEY_IGNORE_CONFIG_CHANGES:\r
1825 CopyMem (IfrNvData, &OldIfrNvData, sizeof (IP6_CONFIG_IFR_NVDATA));\r
1826 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;\r
1827 break;\r
a3bcde70 1828\r
639a76d1
ED
1829 case KEY_SAVE_CHANGES:\r
1830 Status = Ip6ConvertIfrNvDataToConfigNvData (IfrNvData, Instance);\r
1831 if (EFI_ERROR (Status)) {\r
1832 break;\r
1833 }\r
1834 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
1835 break;\r
1836 \r
1837 case KEY_INTERFACE_ID:\r
1838 Status = Ip6ParseInterfaceIdFromString (IfrNvData->InterfaceId, &Ip6NvData->InterfaceId);\r
1839 if (EFI_ERROR (Status)) {\r
1840 CreatePopUp (\r
1841 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1842 &Key,\r
1843 L"Invalid Interface ID!",\r
1844 NULL\r
1845 );\r
1846 }\r
1847 \r
1848 break;\r
1849 \r
1850 case KEY_MANUAL_ADDRESS:\r
1851 Status = Ip6ParseAddressListFromString (\r
1852 IfrNvData->ManualAddress,\r
1853 &Ip6NvData->ManualAddress,\r
1854 &Ip6NvData->ManualAddressCount\r
1855 );\r
1856 if (EFI_ERROR (Status)) {\r
1857 CreatePopUp (\r
1858 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1859 &Key,\r
1860 L"Invalid Host Addresses!",\r
1861 NULL\r
1862 );\r
1863 }\r
1864 \r
1865 break;\r
1866 \r
1867 case KEY_GATEWAY_ADDRESS:\r
1868 Status = Ip6ParseAddressListFromString (\r
1869 IfrNvData->GatewayAddress,\r
1870 &Ip6NvData->GatewayAddress,\r
1871 &Ip6NvData->GatewayAddressCount\r
1872 );\r
1873 if (EFI_ERROR (Status)) {\r
1874 CreatePopUp (\r
1875 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1876 &Key,\r
1877 L"Invalid Gateway Addresses!",\r
1878 NULL\r
1879 );\r
1880 }\r
1881 \r
1882 break;\r
1883 \r
1884 case KEY_DNS_ADDRESS:\r
1885 Status = Ip6ParseAddressListFromString (\r
1886 IfrNvData->DnsAddress,\r
1887 &Ip6NvData->DnsAddress,\r
1888 &Ip6NvData->DnsAddressCount\r
1889 );\r
1890 if (EFI_ERROR (Status)) {\r
1891 CreatePopUp (\r
1892 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1893 &Key,\r
1894 L"Invalid DNS Addresses!",\r
1895 NULL\r
1896 );\r
1897 }\r
1898 \r
1899 break;\r
a3bcde70 1900\r
639a76d1
ED
1901 default:\r
1902 break;\r
1903 }\r
e0afa489 1904 }\r
a3bcde70 1905\r
e0afa489 1906 if (!EFI_ERROR (Status)) {\r
1907 //\r
1908 // Pass changed uncommitted data back to Form Browser.\r
1909 //\r
1910 BufferSize = sizeof (IP6_CONFIG_IFR_NVDATA);\r
1911 HiiSetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData, NULL);\r
a3bcde70
HT
1912 }\r
1913\r
e0afa489 1914 FreePool (IfrNvData);\r
1915 return Status;\r
a3bcde70
HT
1916}\r
1917\r
1918/**\r
1919 Install HII Config Access protocol for network device and allocate resources.\r
1920\r
1921 @param[in, out] Instance The IP6_CONFIG_INSTANCE to create a form.\r
1922\r
1923 @retval EFI_SUCCESS The HII Config Access protocol is installed.\r
1924 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
1925 @retval Others Other errors as indicated.\r
1926\r
1927**/\r
1928EFI_STATUS\r
1929Ip6ConfigFormInit (\r
1930 IN OUT IP6_CONFIG_INSTANCE *Instance\r
1931 )\r
1932{\r
1933 EFI_STATUS Status;\r
1934 IP6_SERVICE *IpSb;\r
1935 IP6_FORM_CALLBACK_INFO *CallbackInfo;\r
1936 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
1937 VENDOR_DEVICE_PATH VendorDeviceNode;\r
1938 EFI_SERVICE_BINDING_PROTOCOL *MnpSb;\r
1939 CHAR16 *MacString;\r
1940 CHAR16 MenuString[128];\r
1941 CHAR16 PortString[128];\r
1942 CHAR16 *OldMenuString;\r
1943 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
1944\r
1945 IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);\r
1946 ASSERT (IpSb != NULL);\r
1947\r
1948 Status = gBS->HandleProtocol (\r
1949 IpSb->Controller,\r
1950 &gEfiDevicePathProtocolGuid,\r
1951 (VOID **) &ParentDevicePath\r
1952 );\r
1953 if (EFI_ERROR (Status)) {\r
1954 return Status;\r
1955 }\r
1956\r
1957 CallbackInfo = &Instance->CallbackInfo;\r
1958 CallbackInfo->Signature = IP6_FORM_CALLBACK_INFO_SIGNATURE;\r
1959\r
1960 //\r
1961 // Construct device path node for EFI HII Config Access protocol,\r
1962 // which consists of controller physical device path and one hardware\r
1963 // vendor guid node.\r
1964 //\r
1965 ZeroMem (&VendorDeviceNode, sizeof (VENDOR_DEVICE_PATH));\r
1966 VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH;\r
1967 VendorDeviceNode.Header.SubType = HW_VENDOR_DP;\r
1968\r
9bdc6592 1969 CopyGuid (&VendorDeviceNode.Guid, &gEfiCallerIdGuid);\r
a3bcde70
HT
1970\r
1971 SetDevicePathNodeLength (&VendorDeviceNode.Header, sizeof (VENDOR_DEVICE_PATH));\r
1972 CallbackInfo->HiiVendorDevicePath = AppendDevicePathNode (\r
1973 ParentDevicePath,\r
1974 (EFI_DEVICE_PATH_PROTOCOL *) &VendorDeviceNode\r
1975 );\r
1976 if (CallbackInfo->HiiVendorDevicePath == NULL) {\r
1977 Status = EFI_OUT_OF_RESOURCES;\r
1978 goto Error;\r
1979 }\r
1980\r
1981 ConfigAccess = &CallbackInfo->HiiConfigAccess;\r
1982 ConfigAccess->ExtractConfig = Ip6FormExtractConfig;\r
1983 ConfigAccess->RouteConfig = Ip6FormRouteConfig;\r
1984 ConfigAccess->Callback = Ip6FormCallback;\r
1985\r
1986 //\r
1987 // Install Device Path Protocol and Config Access protocol on new handle\r
1988 //\r
1989 Status = gBS->InstallMultipleProtocolInterfaces (\r
1990 &CallbackInfo->ChildHandle,\r
1991 &gEfiDevicePathProtocolGuid,\r
1992 CallbackInfo->HiiVendorDevicePath,\r
1993 &gEfiHiiConfigAccessProtocolGuid,\r
1994 ConfigAccess,\r
1995 NULL\r
1996 );\r
1997 if (!EFI_ERROR (Status)) {\r
1998 //\r
1999 // Open the Parent Handle for the child\r
2000 //\r
2001 Status = gBS->OpenProtocol (\r
2002 IpSb->Controller,\r
2003 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
2004 (VOID **) &MnpSb,\r
2005 IpSb->Image,\r
2006 CallbackInfo->ChildHandle,\r
2007 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
2008 );\r
2009 }\r
2010\r
2011 if (EFI_ERROR (Status)) {\r
2012 goto Error;\r
2013 }\r
2014\r
2015 //\r
2016 // Publish our HII data\r
2017 //\r
2018 CallbackInfo->RegisteredHandle = HiiAddPackages (\r
9bdc6592 2019 &gIp6ConfigNvDataGuid,\r
a3bcde70
HT
2020 CallbackInfo->ChildHandle,\r
2021 Ip6DxeStrings,\r
2022 Ip6ConfigBin,\r
2023 NULL\r
2024 );\r
2025 if (CallbackInfo->RegisteredHandle == NULL) {\r
2026 Status = EFI_OUT_OF_RESOURCES;\r
2027 goto Error;\r
2028 }\r
2029\r
2030 //\r
969ebd26 2031 // Append MAC string in the menu help string and tile help string\r
a3bcde70
HT
2032 //\r
2033 Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &MacString);\r
2034 if (!EFI_ERROR (Status)) {\r
2035 OldMenuString = HiiGetString (\r
2036 CallbackInfo->RegisteredHandle,\r
e07404fe 2037 STRING_TOKEN (STR_IP6_CONFIG_FORM_HELP),\r
a3bcde70
HT
2038 NULL)\r
2039 ;\r
2040 UnicodeSPrint (MenuString, 128, L"%s (MAC:%s)", OldMenuString, MacString);\r
2041 HiiSetString (\r
2042 CallbackInfo->RegisteredHandle,\r
e07404fe 2043 STRING_TOKEN (STR_IP6_CONFIG_FORM_HELP),\r
a3bcde70
HT
2044 MenuString,\r
2045 NULL\r
2046 );\r
2047 UnicodeSPrint (PortString, 128, L"MAC:%s", MacString);\r
2048 HiiSetString (\r
2049 CallbackInfo->RegisteredHandle,\r
e07404fe 2050 STRING_TOKEN (STR_IP6_DEVICE_FORM_HELP),\r
a3bcde70
HT
2051 PortString,\r
2052 NULL\r
2053 );\r
2054\r
2055 FreePool (MacString);\r
2056 FreePool (OldMenuString);\r
2057\r
2058 InitializeListHead (&Instance->Ip6NvData.ManualAddress);\r
2059 InitializeListHead (&Instance->Ip6NvData.GatewayAddress);\r
2060 InitializeListHead (&Instance->Ip6NvData.DnsAddress);\r
2061\r
2062 return EFI_SUCCESS;\r
2063 }\r
2064\r
2065Error:\r
2066 Ip6ConfigFormUnload (Instance);\r
2067 return Status;\r
2068}\r
2069\r
2070/**\r
2071 Uninstall the HII Config Access protocol for network devices and free up the resources.\r
2072\r
2073 @param[in, out] Instance The IP6_CONFIG_INSTANCE to unload a form.\r
2074\r
2075**/\r
2076VOID\r
2077Ip6ConfigFormUnload (\r
2078 IN OUT IP6_CONFIG_INSTANCE *Instance\r
2079 )\r
2080{\r
2081 IP6_SERVICE *IpSb;\r
2082 IP6_FORM_CALLBACK_INFO *CallbackInfo;\r
2083 IP6_CONFIG_NVDATA *Ip6NvData;\r
2084\r
2085 IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);\r
2086 ASSERT (IpSb != NULL);\r
2087\r
2088 CallbackInfo = &Instance->CallbackInfo;\r
2089\r
2090 if (CallbackInfo->ChildHandle != NULL) {\r
2091\r
2092 //\r
2093 // Close the child handle\r
2094 //\r
2095 gBS->CloseProtocol (\r
2096 IpSb->Controller,\r
2097 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
2098 IpSb->Image,\r
2099 CallbackInfo->ChildHandle\r
2100 );\r
2101 //\r
2102 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL\r
2103 //\r
2104 gBS->UninstallMultipleProtocolInterfaces (\r
2105 CallbackInfo->ChildHandle,\r
2106 &gEfiDevicePathProtocolGuid,\r
2107 CallbackInfo->HiiVendorDevicePath,\r
2108 &gEfiHiiConfigAccessProtocolGuid,\r
2109 &CallbackInfo->HiiConfigAccess,\r
2110 NULL\r
2111 );\r
2112 }\r
2113\r
2114 if (CallbackInfo->HiiVendorDevicePath != NULL) {\r
2115 FreePool (CallbackInfo->HiiVendorDevicePath);\r
2116 }\r
2117\r
2118 if (CallbackInfo->RegisteredHandle != NULL) {\r
2119 //\r
2120 // Remove HII package list\r
2121 //\r
2122 HiiRemovePackages (CallbackInfo->RegisteredHandle);\r
2123 }\r
2124\r
2125 Ip6NvData = &Instance->Ip6NvData;\r
2126\r
2127 Ip6FreeAddressInfoList (&Ip6NvData->ManualAddress);\r
2128 Ip6FreeAddressInfoList (&Ip6NvData->GatewayAddress);\r
2129 Ip6FreeAddressInfoList (&Ip6NvData->DnsAddress);\r
2130\r
2131 Ip6NvData->ManualAddressCount = 0;\r
2132 Ip6NvData->GatewayAddressCount = 0;\r
2133 Ip6NvData->DnsAddressCount = 0;\r
2134}\r