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