1 /** @file
2   The Hii functions for WiFi Connection Manager.
3 
4   Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
5 
6   SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 #include "WifiConnectionMgrDxe.h"
11 
12 CHAR16  mVendorStorageName[] = L"WIFI_MANAGER_IFR_NVDATA";
13 
14 HII_VENDOR_DEVICE_PATH  mWifiMgrDxeHiiVendorDevicePath = {
15   {
16     {
17       HARDWARE_DEVICE_PATH,
18       HW_VENDOR_DP,
19       {
20         (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
21         (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
22       }
23     },
24     WIFI_CONNECTION_MANAGER_CONFIG_GUID
25   },
26   {
27     END_DEVICE_PATH_TYPE,
28     END_ENTIRE_DEVICE_PATH_SUBTYPE,
29     {
30       (UINT8) (END_DEVICE_PATH_LENGTH),
31       (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
32     }
33   }
34 };
35 
36 //
37 // HII Config Access Protocol instance
38 //
39 GLOBAL_REMOVE_IF_UNREFERENCED
40 EFI_HII_CONFIG_ACCESS_PROTOCOL gWifiMgrDxeHiiConfigAccess = {
41   WifiMgrDxeHiiConfigAccessExtractConfig,
42   WifiMgrDxeHiiConfigAccessRouteConfig,
43   WifiMgrDxeHiiConfigAccessCallback
44 };
45 
46 CHAR16*   mSecurityType[] = {
47   L"OPEN           ",
48   L"WPA-Enterprise ",
49   L"WPA2-Enterprise",
50   L"WPA-Personal   ",
51   L"WPA2-Personal  ",
52   L"WEP            ",
53   L"UnKnown        "
54 };
55 
56 CHAR16*  mSignalStrengthBar[] = {
57   L"[-----]",
58   L"[*----]",
59   L"[**---]",
60   L"[***--]",
61   L"[****-]",
62   L"[*****]"
63 };
64 
65 #define  RSSI_TO_SIGNAL_STRENGTH_BAR(Rssi)  mSignalStrengthBar[((Rssi + 19)/20)]
66 
67 #define  NET_LIST_FOR_EACH_FROM_NODE(Entry, Node, ListHead) \
68   for(Entry = Node->ForwardLink; Entry != (ListHead); Entry = Entry->ForwardLink)
69 
70 extern EFI_GUID    gWifiConfigFormSetGuid;
71 
72 /**
73   Create Hii Extend Label OpCode as the start opcode and end opcode.
74   The caller is responsible for freeing the OpCode with HiiFreeOpCodeHandle().
75 
76   @param[in]  StartLabelNumber   The number of start label.
77   @param[out] StartOpCodeHandle  Points to the start opcode handle.
78   @param[out] EndOpCodeHandle    Points to the end opcode handle.
79 
80   @retval EFI_OUT_OF_RESOURCES   Do not have sufficient resource to finish this
81                                  operation.
82   @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.
83   @retval EFI_SUCCESS            The operation is completed successfully.
84   @retval Other Errors           Returned errors when updating the HII form.
85 
86 **/
87 EFI_STATUS
WifiMgrCreateOpCode(IN UINT16 StartLabelNumber,OUT VOID ** StartOpCodeHandle,OUT VOID ** EndOpCodeHandle)88 WifiMgrCreateOpCode (
89   IN  UINT16    StartLabelNumber,
90   OUT VOID      **StartOpCodeHandle,
91   OUT VOID      **EndOpCodeHandle
92   )
93 {
94   EFI_STATUS            Status;
95   EFI_IFR_GUID_LABEL    *InternalStartLabel;
96   EFI_IFR_GUID_LABEL    *InternalEndLabel;
97 
98   if (StartOpCodeHandle == NULL || EndOpCodeHandle == NULL) {
99     return EFI_INVALID_PARAMETER;
100   }
101 
102   Status             = EFI_OUT_OF_RESOURCES;
103   *StartOpCodeHandle = NULL;
104   *EndOpCodeHandle   = NULL;
105 
106   //
107   // Initialize the container for dynamic opcodes.
108   //
109   *StartOpCodeHandle = HiiAllocateOpCodeHandle ();
110   if (*StartOpCodeHandle == NULL) {
111     goto Exit;
112   }
113   *EndOpCodeHandle = HiiAllocateOpCodeHandle ();
114   if (*EndOpCodeHandle == NULL) {
115     goto Exit;
116   }
117 
118   //
119   // Create Hii Extend Label OpCode as the start opcode.
120   //
121   InternalStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
122                                                 *StartOpCodeHandle,
123                                                 &gEfiIfrTianoGuid,
124                                                 NULL,
125                                                 sizeof (EFI_IFR_GUID_LABEL)
126                                                 );
127   if (InternalStartLabel == NULL) {
128     goto Exit;
129   }
130   InternalStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
131   InternalStartLabel->Number       = StartLabelNumber;
132 
133   //
134   // Create Hii Extend Label OpCode as the end opcode.
135   //
136   InternalEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
137                                               *EndOpCodeHandle,
138                                               &gEfiIfrTianoGuid,
139                                               NULL,
140                                               sizeof (EFI_IFR_GUID_LABEL)
141                                               );
142   if (InternalEndLabel == NULL) {
143     goto Exit;
144   }
145   InternalEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
146   InternalEndLabel->Number       = LABEL_END;
147 
148   return EFI_SUCCESS;
149 
150 Exit:
151 
152   if (*StartOpCodeHandle != NULL) {
153     HiiFreeOpCodeHandle (*StartOpCodeHandle);
154   }
155   if (*EndOpCodeHandle != NULL) {
156     HiiFreeOpCodeHandle (*EndOpCodeHandle);
157   }
158   return Status;
159 }
160 
161 /**
162   Display the Nic list contains all available Nics.
163 
164   @param[in]  Private            The pointer to the global private data structure.
165 
166   @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.
167   @retval EFI_SUCCESS            The operation is completed successfully.
168 
169 **/
170 EFI_STATUS
WifiMgrShowNicList(IN WIFI_MGR_PRIVATE_DATA * Private)171 WifiMgrShowNicList (
172   IN  WIFI_MGR_PRIVATE_DATA    *Private
173 )
174 {
175   EFI_STATUS              Status;
176   CHAR16                  MacString[WIFI_MGR_MAX_MAC_STRING_LEN];
177   CHAR16                  PortString[WIFI_STR_MAX_SIZE];
178   EFI_STRING_ID           PortTitleToken;
179   EFI_STRING_ID           PortTitleHelpToken;
180   WIFI_MGR_DEVICE_DATA    *Nic;
181   LIST_ENTRY              *Entry;
182   VOID                    *StartOpCodeHandle;
183   VOID                    *EndOpCodeHandle;
184 
185   if (Private == NULL) {
186     return EFI_INVALID_PARAMETER;
187   }
188 
189   Status = WifiMgrCreateOpCode (
190              LABEL_MAC_ENTRY,
191              &StartOpCodeHandle,
192              &EndOpCodeHandle
193              );
194   if (EFI_ERROR (Status)) {
195     return Status;
196   }
197 
198   NET_LIST_FOR_EACH (Entry, &Private->NicList) {
199     Nic = NET_LIST_USER_STRUCT_S (Entry, WIFI_MGR_DEVICE_DATA, Link, WIFI_MGR_DEVICE_DATA_SIGNATURE);
200     WifiMgrMacAddrToStr (&Nic->MacAddress, sizeof (MacString), MacString);
201     UnicodeSPrint (PortString, sizeof (PortString), L"MAC %s", MacString);
202     PortTitleToken = HiiSetString (
203                        Private->RegisteredHandle,
204                        0,
205                        PortString,
206                        NULL
207                        );
208     if (PortTitleToken == 0) {
209       Status = EFI_INVALID_PARAMETER;
210       goto Exit;
211     }
212 
213     UnicodeSPrint (PortString, sizeof (PortString), L"MAC Address");
214     PortTitleHelpToken = HiiSetString (
215                            Private->RegisteredHandle,
216                            0,
217                            PortString,
218                            NULL
219                            );
220     if (PortTitleHelpToken == 0) {
221       Status = EFI_INVALID_PARAMETER;
222       goto Exit;
223     }
224 
225     HiiCreateGotoOpCode (
226       StartOpCodeHandle,
227       FORMID_WIFI_MAINPAGE,
228       PortTitleToken,
229       PortTitleHelpToken,
230       EFI_IFR_FLAG_CALLBACK,
231       (UINT16) (KEY_MAC_ENTRY_BASE + Nic->NicIndex)
232       );
233   }
234 
235   Status = HiiUpdateForm (
236              Private->RegisteredHandle,       // HII handle
237              &gWifiConfigFormSetGuid,         // Formset GUID
238              FORMID_MAC_SELECTION,            // Form ID
239              StartOpCodeHandle,               // Label for where to insert opcodes
240              EndOpCodeHandle                  // Replace data
241              );
242 
243 Exit:
244 
245   HiiFreeOpCodeHandle (StartOpCodeHandle);
246   HiiFreeOpCodeHandle (EndOpCodeHandle);
247   return Status;
248 }
249 
250 /**
251   Retreive the unicode string of the AKM Suite list of a profile.
252   The caller is responsible for freeing the string with FreePool().
253 
254   @param[in]  Profile           The network profile contains a AKM suite list.
255 
256   @return the unicode string of AKM suite list or "None".
257 
258 **/
259 CHAR16*
WifiMgrGetStrAKMList(IN WIFI_MGR_NETWORK_PROFILE * Profile)260 WifiMgrGetStrAKMList (
261   IN  WIFI_MGR_NETWORK_PROFILE         *Profile
262 )
263 {
264   UINT8     Index;
265   UINT16    AKMSuiteCount;
266   CHAR16    *AKMListDisplay;
267 
268   AKMListDisplay = NULL;
269   if (Profile == NULL || Profile->Network.AKMSuite == NULL) {
270     goto Exit;
271   }
272 
273   AKMSuiteCount = Profile->Network.AKMSuite->AKMSuiteCount;
274   if (AKMSuiteCount != 0) {
275 
276     //
277     // Current AKM Suite is between 1-9
278     //
279     AKMListDisplay = (CHAR16 *) AllocateZeroPool(sizeof (CHAR16) * AKMSuiteCount * 2);
280     if (AKMListDisplay != NULL) {
281       for (Index = 0; Index < AKMSuiteCount; Index ++) {
282         UnicodeSPrint (
283           AKMListDisplay + (Index * 2),
284           sizeof (CHAR16) * 2,
285           L"%d ",
286           Profile->Network.AKMSuite->AKMSuiteList[Index].SuiteType
287           );
288         if (Index == AKMSuiteCount - 1) {
289           *(AKMListDisplay + (Index * 2 + 1)) = L'\0';
290         }
291       }
292     }
293   }
294 
295 Exit:
296 
297   if (AKMListDisplay == NULL) {
298     AKMListDisplay = AllocateCopyPool (sizeof (L"None"), L"None");
299   }
300   return AKMListDisplay;
301 }
302 
303 /**
304   Retreive the unicode string of the Cipher Suite list of a profile.
305   The caller is responsible for freeing the string with FreePool().
306 
307   @param[in]  Profile           The network profile contains a Cipher suite list.
308 
309   @return the unicode string of Cipher suite list or "None".
310 
311 **/
312 CHAR16*
WifiMgrGetStrCipherList(IN WIFI_MGR_NETWORK_PROFILE * Profile)313 WifiMgrGetStrCipherList (
314   IN  WIFI_MGR_NETWORK_PROFILE          *Profile
315 )
316 {
317   UINT8     Index;
318   UINT16    CipherSuiteCount;
319   CHAR16    *CipherListDisplay;
320 
321   CipherListDisplay = NULL;
322   if (Profile == NULL || Profile->Network.CipherSuite == NULL) {
323     goto Exit;
324   }
325 
326   CipherSuiteCount   = Profile->Network.CipherSuite->CipherSuiteCount;
327   if (CipherSuiteCount != 0) {
328 
329     //
330     // Current Cipher Suite is between 1-9
331     //
332     CipherListDisplay = (CHAR16 *) AllocateZeroPool(sizeof (CHAR16) * CipherSuiteCount * 2);
333     if (CipherListDisplay != NULL) {
334       for (Index = 0; Index < CipherSuiteCount; Index ++) {
335         UnicodeSPrint (
336           CipherListDisplay + (Index * 2),
337           sizeof (CHAR16) * 2,
338           L"%d ",
339           Profile->Network.CipherSuite->CipherSuiteList[Index].SuiteType
340           );
341         if (Index == CipherSuiteCount - 1) {
342           *(CipherListDisplay + (Index * 2 + 1)) = L'\0';
343         }
344       }
345     }
346   }
347 
348 Exit:
349 
350   if (CipherListDisplay == NULL) {
351     CipherListDisplay = AllocateCopyPool (sizeof (L"None"), L"None");
352   }
353   return CipherListDisplay;
354 }
355 
356 /**
357   Refresh the network list display of the current Nic.
358 
359   @param[in]   Private           The pointer to the global private data structure.
360   @param[out]  IfrNvData         The IFR NV data.
361 
362   @retval EFI_SUCCESS            The operation is completed successfully.
363   @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
364   @retval Other Errors           Returned errors when creating Opcodes or updating the
365                                  Hii form.
366 
367 **/
368 EFI_STATUS
WifiMgrRefreshNetworkList(IN WIFI_MGR_PRIVATE_DATA * Private,OUT WIFI_MANAGER_IFR_NVDATA * IfrNvData)369 WifiMgrRefreshNetworkList (
370   IN    WIFI_MGR_PRIVATE_DATA      *Private,
371   OUT   WIFI_MANAGER_IFR_NVDATA    *IfrNvData
372   )
373 {
374   EFI_STATUS                         Status;
375   EFI_TPL                            OldTpl;
376   UINT32                             AvailableCount;
377   EFI_STRING_ID                      PortPromptToken;
378   EFI_STRING_ID                      PortTextToken;
379   EFI_STRING_ID                      PortHelpToken;
380   WIFI_MGR_NETWORK_PROFILE           *Profile;
381   LIST_ENTRY                         *Entry;
382   VOID                               *StartOpCodeHandle;
383   VOID                               *EndOpCodeHandle;
384   CHAR16                             *AKMListDisplay;
385   CHAR16                             *CipherListDisplay;
386   CHAR16                             PortString[WIFI_STR_MAX_SIZE];
387   UINTN                              PortStringSize;
388   WIFI_MGR_NETWORK_PROFILE           *ConnectedProfile;
389 
390   if (Private->CurrentNic == NULL) {
391     return EFI_SUCCESS;
392   }
393 
394   Status = WifiMgrCreateOpCode (
395              LABEL_NETWORK_LIST_ENTRY,
396              &StartOpCodeHandle,
397              &EndOpCodeHandle
398              );
399   if (EFI_ERROR (Status)) {
400     return Status;
401   }
402 
403   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
404   AvailableCount    = 0;
405   PortStringSize    = sizeof (PortString);
406   ConnectedProfile  = NULL;
407   AKMListDisplay    = NULL;
408   CipherListDisplay = NULL;
409 
410   if (Private->CurrentNic->ConnectState == WifiMgrConnectedToAp) {
411 
412     //
413     // Display the current connected network.
414     // Find the current operate network under connected status.
415     //
416     if (Private->CurrentNic->CurrentOperateNetwork != NULL &&
417       Private->CurrentNic->CurrentOperateNetwork->IsAvailable) {
418 
419       Profile = Private->CurrentNic->CurrentOperateNetwork;
420       AvailableCount ++;
421 
422       AKMListDisplay = WifiMgrGetStrAKMList (Profile);
423       if (AKMListDisplay == NULL) {
424         Status = EFI_OUT_OF_RESOURCES;
425         goto Exit;
426       }
427       CipherListDisplay = WifiMgrGetStrCipherList(Profile);
428       if (CipherListDisplay == NULL) {
429         Status = EFI_OUT_OF_RESOURCES;
430         goto Exit;
431       }
432 
433       UnicodeSPrint (PortString, PortStringSize, L"%s (Connected)", Profile->SSId);
434       PortPromptToken = HiiSetString (Private->RegisteredHandle, 0, PortString, NULL);
435 
436       if (Profile->SecurityType == SECURITY_TYPE_NONE) {
437         PortHelpToken = 0;
438       } else {
439         UnicodeSPrint (PortString, PortStringSize, L"AKMSuite: %s CipherSuite: %s", AKMListDisplay, CipherListDisplay);
440         PortHelpToken = HiiSetString (Private->RegisteredHandle, 0, PortString, NULL);
441       }
442       FreePool (AKMListDisplay);
443       FreePool (CipherListDisplay);
444       AKMListDisplay    = NULL;
445       CipherListDisplay = NULL;
446 
447       HiiCreateGotoOpCode (
448         StartOpCodeHandle,
449         FORMID_CONNECT_NETWORK,
450         PortPromptToken,
451         PortHelpToken,
452         EFI_IFR_FLAG_CALLBACK,
453         (UINT16) (KEY_AVAILABLE_NETWORK_ENTRY_BASE + Profile->ProfileIndex)
454         );
455 
456       UnicodeSPrint (
457         PortString,
458         PortStringSize,
459         L"%s       %s %s",
460         (Profile->SecurityType != SECURITY_TYPE_NONE ? L"Secured" : L"Open   "),
461         mSecurityType[Profile->SecurityType],
462         RSSI_TO_SIGNAL_STRENGTH_BAR(Profile->NetworkQuality)
463         );
464       PortTextToken = HiiSetString (Private->RegisteredHandle, 0, PortString, NULL);
465 
466       HiiCreateTextOpCode (
467         StartOpCodeHandle,
468         PortTextToken,
469         0,
470         0
471       );
472 
473       ConnectedProfile = Profile;
474     } else {
475       Private->CurrentNic->HasDisconnectPendingNetwork = TRUE;
476     }
477   }
478 
479   //
480   // Display all supported available networks.
481   //
482   NET_LIST_FOR_EACH (Entry, &Private->CurrentNic->ProfileList) {
483 
484     Profile = NET_LIST_USER_STRUCT_S (
485                 Entry,
486                 WIFI_MGR_NETWORK_PROFILE,
487                 Link,
488                 WIFI_MGR_PROFILE_SIGNATURE
489                 );
490     if (ConnectedProfile == Profile) {
491       continue;
492     }
493     if (Profile->IsAvailable && Profile->CipherSuiteSupported) {
494 
495       AvailableCount ++;
496 
497       AKMListDisplay = WifiMgrGetStrAKMList (Profile);
498       if (AKMListDisplay == NULL) {
499         Status = EFI_OUT_OF_RESOURCES;
500         goto Exit;
501       }
502       CipherListDisplay = WifiMgrGetStrCipherList(Profile);
503       if (CipherListDisplay == NULL) {
504         Status = EFI_OUT_OF_RESOURCES;
505         goto Exit;
506       }
507 
508       PortPromptToken = HiiSetString (Private->RegisteredHandle, 0, Profile->SSId, NULL);
509       if (PortPromptToken == 0) {
510         Status = EFI_OUT_OF_RESOURCES;
511         goto Exit;
512       }
513 
514       if (Profile->SecurityType == SECURITY_TYPE_NONE) {
515         PortHelpToken = 0;
516       } else {
517         UnicodeSPrint (
518           PortString,
519           PortStringSize,
520           L"AKMSuite: %s CipherSuite: %s",
521           AKMListDisplay, CipherListDisplay
522           );
523         PortHelpToken = HiiSetString (Private->RegisteredHandle, 0, PortString, NULL);
524         if (PortHelpToken == 0) {
525           Status = EFI_OUT_OF_RESOURCES;
526           goto Exit;
527         }
528       }
529       FreePool (AKMListDisplay);
530       FreePool (CipherListDisplay);
531       AKMListDisplay    = NULL;
532       CipherListDisplay = NULL;
533 
534       HiiCreateGotoOpCode (
535         StartOpCodeHandle,
536         FORMID_CONNECT_NETWORK,
537         PortPromptToken,
538         PortHelpToken,
539         EFI_IFR_FLAG_CALLBACK,
540         (UINT16) (KEY_AVAILABLE_NETWORK_ENTRY_BASE + Profile->ProfileIndex)
541         );
542 
543       UnicodeSPrint (
544         PortString,
545         PortStringSize,
546         L"%s       %s %s",
547         (Profile->SecurityType != SECURITY_TYPE_NONE ? L"Secured" : L"Open   "),
548         mSecurityType[Profile->SecurityType],
549         RSSI_TO_SIGNAL_STRENGTH_BAR(Profile->NetworkQuality)
550         );
551       PortTextToken = HiiSetString (Private->RegisteredHandle, 0, PortString, NULL);
552       if (PortTextToken == 0) {
553         Status = EFI_OUT_OF_RESOURCES;
554         goto Exit;
555       }
556       HiiCreateTextOpCode (
557         StartOpCodeHandle,
558         PortTextToken,
559         0,
560         0
561         );
562     }
563   }
564 
565   //
566   // Display all Unsupported available networks.
567   //
568   NET_LIST_FOR_EACH (Entry, &Private->CurrentNic->ProfileList) {
569 
570     Profile = NET_LIST_USER_STRUCT_S (
571                 Entry,
572                 WIFI_MGR_NETWORK_PROFILE,
573                 Link,
574                 WIFI_MGR_PROFILE_SIGNATURE
575                 );
576     if (ConnectedProfile == Profile) {
577       continue;
578     }
579     if (Profile->IsAvailable && !Profile->CipherSuiteSupported) {
580 
581       AvailableCount ++;
582 
583       AKMListDisplay = WifiMgrGetStrAKMList (Profile);
584       if (AKMListDisplay == NULL) {
585         Status = EFI_OUT_OF_RESOURCES;
586         goto Exit;
587       }
588       CipherListDisplay = WifiMgrGetStrCipherList(Profile);
589       if (CipherListDisplay == NULL) {
590         Status = EFI_OUT_OF_RESOURCES;
591         goto Exit;
592       }
593 
594       PortPromptToken = HiiSetString (Private->RegisteredHandle, 0, Profile->SSId, NULL);
595 
596       if (Profile->AKMSuiteSupported) {
597         UnicodeSPrint (
598           PortString,
599           PortStringSize,
600           L"AKMSuite: %s CipherSuite(UnSupported): %s",
601           AKMListDisplay, CipherListDisplay
602           );
603       } else {
604         UnicodeSPrint (
605           PortString,
606           PortStringSize,
607           L"AKMSuite(UnSupported): %s CipherSuite(UnSupported): %s",
608           AKMListDisplay, CipherListDisplay
609           );
610       }
611       FreePool (AKMListDisplay);
612       FreePool (CipherListDisplay);
613       AKMListDisplay    = NULL;
614       CipherListDisplay = NULL;
615 
616       PortHelpToken = HiiSetString (Private->RegisteredHandle, 0, PortString, NULL);
617 
618       HiiCreateGotoOpCode (
619         StartOpCodeHandle,
620         FORMID_CONNECT_NETWORK,
621         PortPromptToken,
622         PortHelpToken,
623         EFI_IFR_FLAG_CALLBACK,
624         (UINT16) (KEY_AVAILABLE_NETWORK_ENTRY_BASE + Profile->ProfileIndex)
625         );
626 
627       UnicodeSPrint (
628         PortString,
629         PortStringSize,
630         L"%s       %s %s",
631         L"UnSupported",
632         mSecurityType[Profile->SecurityType],
633         RSSI_TO_SIGNAL_STRENGTH_BAR(Profile->NetworkQuality)
634         );
635       PortTextToken = HiiSetString (Private->RegisteredHandle, 0, PortString, NULL);
636 
637       HiiCreateTextOpCode (
638         StartOpCodeHandle,
639         PortTextToken,
640         0,
641         0
642         );
643     }
644   }
645 
646   Status = HiiUpdateForm (
647              Private->RegisteredHandle,       // HII handle
648              &gWifiConfigFormSetGuid,         // Formset GUID
649              FORMID_NETWORK_LIST,             // Form ID
650              StartOpCodeHandle,               // Label for where to insert opcodes
651              EndOpCodeHandle                  // Replace data
652              );
653 
654 Exit:
655 
656   gBS->RestoreTPL (OldTpl);
657 
658   if (AKMListDisplay != NULL) {
659     FreePool (AKMListDisplay);
660   }
661   if (CipherListDisplay != NULL) {
662     FreePool (CipherListDisplay);
663   }
664 
665   HiiFreeOpCodeHandle (StartOpCodeHandle);
666   HiiFreeOpCodeHandle (EndOpCodeHandle);
667 
668   DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] Network List is Refreshed!\n"));
669   return Status;
670 }
671 
672 /**
673   Refresh the hidden network list configured by user.
674 
675   @param[in]   Private           The pointer to the global private data structure.
676 
677   @retval EFI_SUCCESS            The operation is completed successfully.
678   @retval Other Errors           Returned errors when creating Opcodes or updating the
679                                  Hii form.
680 **/
681 EFI_STATUS
WifiMgrRefreshHiddenList(IN WIFI_MGR_PRIVATE_DATA * Private)682 WifiMgrRefreshHiddenList (
683   IN    WIFI_MGR_PRIVATE_DATA      *Private
684   )
685 {
686   EFI_STATUS                       Status;
687   EFI_TPL                          OldTpl;
688   UINTN                            Index;
689   EFI_STRING_ID                    StringId;
690   VOID                             *StartOpCodeHandle;
691   VOID                             *EndOpCodeHandle;
692   WIFI_HIDDEN_NETWORK_DATA         *HiddenNetwork;
693   LIST_ENTRY                       *Entry;
694 
695   if (Private == NULL) {
696     return EFI_SUCCESS;
697   }
698 
699   Status = WifiMgrCreateOpCode (
700              LABEL_HIDDEN_NETWORK_ENTRY,
701              &StartOpCodeHandle,
702              &EndOpCodeHandle
703              );
704   if (EFI_ERROR (Status)) {
705     return Status;
706   }
707 
708   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
709   Index  = 0;
710 
711   NET_LIST_FOR_EACH (Entry, &Private->HiddenNetworkList) {
712 
713     HiddenNetwork = NET_LIST_USER_STRUCT_S (
714                       Entry,
715                       WIFI_HIDDEN_NETWORK_DATA,
716                       Link,
717                       WIFI_MGR_HIDDEN_NETWORK_SIGNATURE
718                       );
719     StringId = HiiSetString (Private->RegisteredHandle, 0, HiddenNetwork->SSId, NULL);
720 
721     HiiCreateCheckBoxOpCode (
722       StartOpCodeHandle,
723       (EFI_QUESTION_ID) (KEY_HIDDEN_NETWORK_ENTRY_BASE + Index),
724       MANAGER_VARSTORE_ID,
725       (UINT16) (HIDDEN_NETWORK_LIST_VAR_OFFSET + Index),
726       StringId,
727       0,
728       0,
729       0,
730       NULL
731       );
732     Index ++;
733   }
734 
735   Status = HiiUpdateForm (
736              Private->RegisteredHandle,       // HII handle
737              &gWifiConfigFormSetGuid,         // Formset GUID
738              FORMID_HIDDEN_NETWORK_LIST,      // Form ID
739              StartOpCodeHandle,               // Label for where to insert opcodes
740              EndOpCodeHandle                  // Replace data
741              );
742 
743   gBS->RestoreTPL (OldTpl);
744   HiiFreeOpCodeHandle (StartOpCodeHandle);
745   HiiFreeOpCodeHandle (EndOpCodeHandle);
746   return Status;
747 }
748 
749 
750 /**
751   Callback function for user to select a Nic.
752 
753   @param[in]  Private            The pointer to the global private data structure.
754   @param[in]  KeyValue           The key value received from HII input.
755 
756   @retval EFI_NOT_FOUND          The corresponding Nic is not found.
757   @retval EFI_SUCCESS            The operation is completed successfully.
758 
759 **/
760 EFI_STATUS
WifiMgrSelectNic(IN WIFI_MGR_PRIVATE_DATA * Private,IN EFI_QUESTION_ID KeyValue)761 WifiMgrSelectNic (
762   IN     WIFI_MGR_PRIVATE_DATA         *Private,
763   IN     EFI_QUESTION_ID               KeyValue
764   )
765 {
766   WIFI_MGR_DEVICE_DATA    *Nic;
767   UINT32                  NicIndex;
768   CHAR16                  MacString[WIFI_MGR_MAX_MAC_STRING_LEN];
769 
770   NicIndex = KeyValue - KEY_MAC_ENTRY_BASE;
771   Nic      = WifiMgrGetNicByIndex (Private, NicIndex);
772   if (Nic == NULL) {
773     return EFI_NOT_FOUND;
774   }
775   Private->CurrentNic = Nic;
776 
777   WifiMgrMacAddrToStr (&Nic->MacAddress, sizeof (MacString), MacString);
778   HiiSetString (Private->RegisteredHandle, STRING_TOKEN(STR_MAC_ADDRESS), MacString, NULL);
779   return EFI_SUCCESS;
780 }
781 
782 /**
783   Restore the NV data to be default.
784 
785   @param[in]  Private             The pointer to the global private data structure.
786   @param[out] IfrNvData           The IFR NV data.
787 
788 **/
789 VOID
WifiMgrCleanUserInput(IN WIFI_MGR_PRIVATE_DATA * Private)790 WifiMgrCleanUserInput (
791   IN  WIFI_MGR_PRIVATE_DATA      *Private
792   )
793 {
794   Private->SecurityType        = SECURITY_TYPE_NONE;
795   Private->EapAuthMethod       = EAP_AUTH_METHOD_TTLS;
796   Private->EapSecondAuthMethod = EAP_SEAUTH_METHOD_MSCHAPV2;
797   Private->FileType            = FileTypeMax;
798 }
799 
800 /**
801   UI handle function when user select a network to connect.
802 
803   @param[in]  Private             The pointer to the global private data structure.
804   @param[in]  ProfileIndex        The profile index user selected to connect.
805 
806   @retval EFI_INVALID_PARAMETER   Nic is null.
807   @retval EFI_NOT_FOUND           Profile could not be found.
808   @retval EFI_SUCCESS             The operation is completed successfully.
809 
810 **/
811 EFI_STATUS
WifiMgrUserSelectProfileToConnect(IN WIFI_MGR_PRIVATE_DATA * Private,IN UINT32 ProfileIndex)812 WifiMgrUserSelectProfileToConnect(
813   IN     WIFI_MGR_PRIVATE_DATA         *Private,
814   IN     UINT32                        ProfileIndex
815   )
816 {
817   WIFI_MGR_NETWORK_PROFILE         *Profile;
818   WIFI_MGR_DEVICE_DATA             *Nic;
819 
820   Nic = Private->CurrentNic;
821   if (Nic == NULL) {
822     return EFI_INVALID_PARAMETER;
823   }
824 
825   //
826   //Initialize the connection page
827   //
828   WifiMgrCleanUserInput(Private);
829 
830   Profile = WifiMgrGetProfileByProfileIndex (ProfileIndex, &Nic->ProfileList);
831   if (Profile == NULL) {
832     return EFI_NOT_FOUND;
833   }
834   Private->CurrentNic->UserSelectedProfile = Profile;
835 
836   return EFI_SUCCESS;
837 }
838 
839 /**
840   Record password from a HII input string.
841 
842   @param[in]  Private             The pointer to the global private data structure.
843   @param[in]  StringId            The QuestionId received from HII input.
844   @param[in]  StringBuffer        The unicode string buffer to store password.
845   @param[in]  StringBufferLen     The len of unicode string buffer.
846 
847   @retval EFI_INVALID_PARAMETER   Any input parameter is invalid.
848   @retval EFI_NOT_FOUND           The password string is not found or invalid.
849   @retval EFI_SUCCESS             The operation is completed successfully.
850 
851 **/
852 EFI_STATUS
WifiMgrRecordPassword(IN WIFI_MGR_PRIVATE_DATA * Private,IN EFI_STRING_ID StringId,IN CHAR16 * StringBuffer,IN UINTN StringBufferLen)853 WifiMgrRecordPassword (
854   IN   WIFI_MGR_PRIVATE_DATA      *Private,
855   IN   EFI_STRING_ID              StringId,
856   IN   CHAR16                     *StringBuffer,
857   IN   UINTN                      StringBufferLen
858   )
859 {
860   CHAR16                          *Password;
861 
862   if (StringId == 0 || StringBuffer == NULL || StringBufferLen <= 0) {
863     return EFI_INVALID_PARAMETER;
864   }
865 
866   Password = HiiGetString (Private->RegisteredHandle, StringId, NULL);
867   if (Password == NULL) {
868     return EFI_NOT_FOUND;
869   }
870   if (StrLen (Password) > StringBufferLen) {
871     FreePool (Password);
872     return EFI_NOT_FOUND;
873   }
874   StrnCpyS (StringBuffer, StringBufferLen, Password, StrLen (Password));
875   ZeroMem (Password, (StrLen (Password) + 1) * sizeof (CHAR16));
876   FreePool (Password);
877 
878   //
879   // Clean password in string package
880   //
881   HiiSetString (Private->RegisteredHandle, StringId, L"", NULL);
882   return EFI_SUCCESS;
883 }
884 
885 /**
886   Update connection message on connect configuration page, and trigger related form refresh.
887 
888   @param[in]   Nic                        The related Nic for updating message.
889   @param[in]   ConnectStateChanged        The tag to tell if the connection state has been changed, only
890                                           when the connection changes from "Connected" or "Disconnecting"
891                                           to "Disconnected", or from "Disconnected" or "Connecting" to
892                                           "Connected", this tag can be set as TRUE.
893   @param[in]   ConnectStatusMessage       The message to show on connected status bar, if NULL, will
894                                           use default message.
895 
896 **/
897 VOID
WifiMgrUpdateConnectMessage(IN WIFI_MGR_DEVICE_DATA * Nic,IN BOOLEAN ConnectStateChanged,IN EFI_STRING ConnectStatusMessage)898 WifiMgrUpdateConnectMessage (
899   IN  WIFI_MGR_DEVICE_DATA      *Nic,
900   IN  BOOLEAN                   ConnectStateChanged,
901   IN  EFI_STRING                ConnectStatusMessage
902   )
903 {
904   CHAR16                   ConnectStatusStr[WIFI_STR_MAX_SIZE];
905   WIFI_MGR_PRIVATE_DATA    *Private;
906 
907   Private = Nic->Private;
908   if (Private == NULL || Private->CurrentNic != Nic) {
909     return;
910   }
911 
912   //
913   // Update Connection Status Bar
914   //
915   if (ConnectStatusMessage != NULL) {
916     HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECT_STATUS), ConnectStatusMessage, NULL);
917   } else {
918     if (Nic->ConnectState == WifiMgrConnectedToAp) {
919 
920       UnicodeSPrint (ConnectStatusStr, sizeof (ConnectStatusStr), L"Connected to %s",
921         Nic->CurrentOperateNetwork->SSId);
922       HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECT_STATUS), ConnectStatusStr, NULL);
923     } else if (Nic->ConnectState == WifiMgrDisconnected) {
924 
925       HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECT_STATUS), L"Disconnected", NULL);
926     } else if (Nic->ConnectState == WifiMgrConnectingToAp) {
927 
928       UnicodeSPrint (ConnectStatusStr, sizeof (ConnectStatusStr), L"Connecting to %s ...",
929         Nic->CurrentOperateNetwork->SSId);
930       HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECT_STATUS), ConnectStatusStr, NULL);
931     } else if (Nic->ConnectState == WifiMgrDisconnectingToAp) {
932 
933       UnicodeSPrint (ConnectStatusStr, sizeof (ConnectStatusStr), L"Disconnecting from %s ...",
934         Nic->CurrentOperateNetwork->SSId);
935       HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECT_STATUS), ConnectStatusStr, NULL);
936     } else {
937       return;
938     }
939   }
940 
941   //
942   // Update Connect Button
943   //
944   if (Nic->ConnectState == WifiMgrConnectedToAp && Nic->UserSelectedProfile == Nic->CurrentOperateNetwork) {
945 
946     HiiSetString (Private->RegisteredHandle,
947       STRING_TOKEN (STR_CONNECT_NOW), L"Disconnect from this Network", NULL);
948   } else {
949     HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECT_NOW), L"Connect to this Network", NULL);
950   }
951   gBS->SignalEvent (Private->ConnectFormRefreshEvent);
952 
953   //
954   // Update Main Page and Network List
955   //
956   if (ConnectStateChanged) {
957 
958     if (Nic->ConnectState == WifiMgrConnectedToAp) {
959 
960       HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECTION_INFO), L"Connected to", NULL);
961       HiiSetString (Private->RegisteredHandle,
962         STRING_TOKEN (STR_CONNECTED_SSID), Nic->CurrentOperateNetwork->SSId, NULL);
963     } else {
964       HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECTION_INFO), L"Disconnected", NULL);
965       HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECTED_SSID), L"", NULL);
966     }
967 
968     gBS->SignalEvent (Private->NetworkListRefreshEvent);
969     gBS->SignalEvent (Private->MainPageRefreshEvent);
970   }
971 }
972 
973 /**
974   Convert the driver configuration data into the IFR data.
975 
976   @param[in]   Private            The pointer to the global private data structure.
977   @param[out]  IfrNvData          The IFR NV data.
978 
979   @retval EFI_SUCCESS             The operation is completed successfully.
980 
981 **/
982 EFI_STATUS
WifiMgrConvertConfigDataToIfrNvData(IN WIFI_MGR_PRIVATE_DATA * Private,OUT WIFI_MANAGER_IFR_NVDATA * IfrNvData)983 WifiMgrConvertConfigDataToIfrNvData (
984   IN   WIFI_MGR_PRIVATE_DATA      *Private,
985   OUT  WIFI_MANAGER_IFR_NVDATA    *IfrNvData
986   )
987 {
988   //
989   // Private shouldn't be NULL here, assert if Private is NULL.
990   //
991   ASSERT (Private != NULL);
992 
993   if (Private->CurrentNic != NULL) {
994     IfrNvData->ProfileCount = Private->CurrentNic->AvailableCount;
995   } else {
996     IfrNvData->ProfileCount = 0;
997   }
998 
999   return EFI_SUCCESS;
1000 }
1001 
1002 /**
1003   Convert the IFR data into the driver configuration data.
1004 
1005   @param[in]       Private             The pointer to the global private data structure.
1006   @param[in, out]  IfrNvData           The IFR NV data.
1007 
1008   @retval EFI_SUCCESS                  The operation is completed successfully.
1009 
1010 **/
1011 EFI_STATUS
WifiMgrConvertIfrNvDataToConfigData(IN WIFI_MGR_PRIVATE_DATA * Private,IN OUT WIFI_MANAGER_IFR_NVDATA * IfrNvData)1012 WifiMgrConvertIfrNvDataToConfigData (
1013   IN     WIFI_MGR_PRIVATE_DATA         *Private,
1014   IN OUT WIFI_MANAGER_IFR_NVDATA       *IfrNvData
1015   )
1016 {
1017   return EFI_SUCCESS;
1018 }
1019 
1020 /**
1021   This function allows the caller to request the current
1022   configuration for one or more named elements. The resulting
1023   string is in <ConfigAltResp> format. Any and all alternative
1024   configuration strings shall also be appended to the end of the
1025   current configuration string. If they are, they must appear
1026   after the current configuration. They must contain the same
1027   routing (GUID, NAME, PATH) as the current configuration string.
1028   They must have an additional description indicating the type of
1029   alternative configuration the string represents,
1030   "ALTCFG=<StringToken>". That <StringToken> (when
1031   converted from Hex UNICODE to binary) is a reference to a
1032   string in the associated string pack.
1033 
1034   @param This       Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1035 
1036   @param Request    A null-terminated Unicode string in
1037                     <ConfigRequest> format. Note that this
1038                     includes the routing information as well as
1039                     the configurable name / value pairs. It is
1040                     invalid for this string to be in
1041                     <MultiConfigRequest> format.
1042                     If a NULL is passed in for the Request field,
1043                     all of the settings being abstracted by this function
1044                     will be returned in the Results field.  In addition,
1045                     if a ConfigHdr is passed in with no request elements,
1046                     all of the settings being abstracted for that particular
1047                     ConfigHdr reference will be returned in the Results Field.
1048 
1049   @param Progress   On return, points to a character in the
1050                     Request string. Points to the string's null
1051                     terminator if request was successful. Points
1052                     to the most recent "&" before the first
1053                     failing name / value pair (or the beginning
1054                     of the string if the failure is in the first
1055                     name / value pair) if the request was not
1056                     successful.
1057 
1058   @param Results    A null-terminated Unicode string in
1059                     <MultiConfigAltResp> format which has all values
1060                     filled in for the names in the Request string.
1061                     String to be allocated by the called function.
1062 
1063   @retval EFI_SUCCESS             The Results string is filled with the
1064                                   values corresponding to all requested
1065                                   names.
1066 
1067   @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
1068                                   parts of the results that must be
1069                                   stored awaiting possible future
1070                                   protocols.
1071 
1072   @retval EFI_NOT_FOUND           Routing data doesn't match any
1073                                   known driver. Progress set to the
1074                                   first character in the routing header.
1075                                   Note: There is no requirement that the
1076                                   driver validate the routing data. It
1077                                   must skip the <ConfigHdr> in order to
1078                                   process the names.
1079 
1080   @retval EFI_INVALID_PARAMETER   Illegal syntax. Progress set
1081                                   to most recent "&" before the
1082                                   error or the beginning of the
1083                                   string.
1084 
1085   @retval EFI_INVALID_PARAMETER   Unknown name. Progress points
1086                                   to the & before the name in
1087                                   question.
1088 
1089 **/
1090 EFI_STATUS
1091 EFIAPI
WifiMgrDxeHiiConfigAccessExtractConfig(IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL * This,IN CONST EFI_STRING Request,OUT EFI_STRING * Progress,OUT EFI_STRING * Results)1092 WifiMgrDxeHiiConfigAccessExtractConfig (
1093   IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
1094   IN CONST  EFI_STRING                      Request,
1095   OUT       EFI_STRING                      *Progress,
1096   OUT       EFI_STRING                      *Results
1097   )
1098 {
1099   WIFI_MGR_PRIVATE_DATA             *Private;
1100   WIFI_MANAGER_IFR_NVDATA           *IfrNvData;
1101   EFI_STRING                        ConfigRequestHdr;
1102   EFI_STRING                        ConfigRequest;
1103   UINTN                             Size;
1104   BOOLEAN                           AllocatedRequest;
1105   UINTN                             BufferSize;
1106   EFI_STATUS                        Status;
1107 
1108   if (This == NULL || Progress == NULL || Results == NULL) {
1109     return EFI_INVALID_PARAMETER;
1110   }
1111 
1112   *Progress = Request;
1113   if ((Request != NULL) &&
1114       !HiiIsConfigHdrMatch (Request, &gWifiConfigFormSetGuid, mVendorStorageName)) {
1115     return EFI_NOT_FOUND;
1116   }
1117 
1118   ConfigRequestHdr = NULL;
1119   ConfigRequest    = NULL;
1120   AllocatedRequest = FALSE;
1121   Size             = 0;
1122 
1123   Private   = WIFI_MGR_PRIVATE_DATA_FROM_CONFIG_ACCESS (This);
1124 
1125   BufferSize = sizeof (WIFI_MANAGER_IFR_NVDATA);
1126   IfrNvData = AllocateZeroPool (BufferSize);
1127   if (IfrNvData == NULL) {
1128     return EFI_OUT_OF_RESOURCES;
1129   }
1130 
1131   WifiMgrConvertConfigDataToIfrNvData (Private, IfrNvData);
1132 
1133   ConfigRequest = Request;
1134   if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
1135     //
1136     // Request has no request element, construct full request string.
1137     // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
1138     // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator.
1139     //
1140     ConfigRequestHdr = HiiConstructConfigHdr (
1141                          &gWifiConfigFormSetGuid,
1142                          mVendorStorageName,
1143                          Private->DriverHandle);
1144     if (ConfigRequestHdr == NULL) {
1145       FreePool (IfrNvData);
1146       return EFI_OUT_OF_RESOURCES;
1147     }
1148 
1149     Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
1150     ConfigRequest = AllocateZeroPool (Size);
1151     if (ConfigRequest == NULL) {
1152 
1153       FreePool (IfrNvData);
1154       FreePool (ConfigRequestHdr);
1155       return EFI_OUT_OF_RESOURCES;
1156     }
1157 
1158     AllocatedRequest = TRUE;
1159     UnicodeSPrint (
1160       ConfigRequest,
1161       Size,
1162       L"%s&OFFSET=0&WIDTH=%016LX",
1163       ConfigRequestHdr,
1164       (UINT64) BufferSize
1165       );
1166     FreePool (ConfigRequestHdr);
1167   }
1168 
1169   //
1170   // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
1171   //
1172   Status = gHiiConfigRouting->BlockToConfig (
1173                                 gHiiConfigRouting,
1174                                 ConfigRequest,
1175                                 (UINT8 *) IfrNvData,
1176                                 BufferSize,
1177                                 Results,
1178                                 Progress
1179                                 );
1180 
1181   FreePool (IfrNvData);
1182   //
1183   // Free the allocated config request string.
1184   //
1185   if (AllocatedRequest) {
1186     FreePool (ConfigRequest);
1187     ConfigRequest = NULL;
1188   }
1189   //
1190   // Set Progress string to the original request string.
1191   //
1192   if (Request == NULL) {
1193     *Progress = NULL;
1194   } else if (StrStr (Request, L"OFFSET") == NULL) {
1195     *Progress = Request + StrLen (Request);
1196   }
1197 
1198   return Status;
1199 }
1200 
1201 /**
1202   This function applies changes in a driver's configuration.
1203   Input is a Configuration, which has the routing data for this
1204   driver followed by name / value configuration pairs. The driver
1205   must apply those pairs to its configurable storage. If the
1206   driver's configuration is stored in a linear block of data
1207   and the driver's name / value pairs are in <BlockConfig>
1208   format, it may use the ConfigToBlock helper function (above) to
1209   simplify the job.
1210 
1211   @param This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1212 
1213   @param Configuration  A null-terminated Unicode string in
1214                         <ConfigString> format.
1215 
1216   @param Progress       A pointer to a string filled in with the
1217                         offset of the most recent '&' before the
1218                         first failing name / value pair (or the
1219                         beginn ing of the string if the failure
1220                         is in the first name / value pair) or
1221                         the terminating NULL if all was
1222                         successful.
1223 
1224   @retval EFI_SUCCESS             The results have been distributed or are
1225                                   awaiting distribution.
1226 
1227   @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
1228                                   parts of the results that must be
1229                                   stored awaiting possible future
1230                                   protocols.
1231 
1232   @retval EFI_INVALID_PARAMETERS  Passing in a NULL for the
1233                                   Results parameter would result
1234                                   in this type of error.
1235 
1236   @retval EFI_NOT_FOUND           Target for the specified routing data
1237                                   was not found
1238 
1239 **/
1240 EFI_STATUS
1241 EFIAPI
WifiMgrDxeHiiConfigAccessRouteConfig(IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL * This,IN CONST EFI_STRING Configuration,OUT EFI_STRING * Progress)1242 WifiMgrDxeHiiConfigAccessRouteConfig (
1243   IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
1244   IN CONST  EFI_STRING                      Configuration,
1245   OUT       EFI_STRING                      *Progress
1246   )
1247 {
1248   EFI_STATUS                     Status;
1249   UINTN                          BufferSize;
1250   WIFI_MGR_PRIVATE_DATA          *Private;
1251   WIFI_MANAGER_IFR_NVDATA        *IfrNvData;
1252 
1253   if (Configuration == NULL || Progress == NULL) {
1254     return EFI_INVALID_PARAMETER;
1255   }
1256 
1257   IfrNvData  = NULL;
1258   *Progress  = Configuration;
1259   BufferSize = sizeof (WIFI_MANAGER_IFR_NVDATA);
1260   Private    = WIFI_MGR_PRIVATE_DATA_FROM_CONFIG_ACCESS (This);
1261 
1262   if (!HiiIsConfigHdrMatch (Configuration, &gWifiConfigFormSetGuid, mVendorStorageName)) {
1263     return EFI_NOT_FOUND;
1264   }
1265 
1266   IfrNvData = AllocateZeroPool (BufferSize);
1267   if (IfrNvData == NULL) {
1268     return EFI_OUT_OF_RESOURCES;
1269   }
1270 
1271   WifiMgrConvertConfigDataToIfrNvData (Private, IfrNvData);
1272 
1273   Status = gHiiConfigRouting->ConfigToBlock (
1274                                 gHiiConfigRouting,
1275                                 Configuration,
1276                                 (UINT8*) IfrNvData,
1277                                 &BufferSize,
1278                                 Progress
1279                                 );
1280   if (EFI_ERROR (Status)) {
1281     return Status;
1282   }
1283 
1284   Status = WifiMgrConvertIfrNvDataToConfigData (Private, IfrNvData);
1285   ZeroMem (IfrNvData, sizeof (WIFI_MANAGER_IFR_NVDATA));
1286   FreePool (IfrNvData);
1287 
1288   return Status;
1289 }
1290 
1291 /**
1292   This function is called to provide results data to the driver.
1293   This data consists of a unique key that is used to identify
1294   which data is either being passed back or being asked for.
1295 
1296   @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1297   @param  Action                 Specifies the type of action taken by the browser.
1298   @param  QuestionId             A unique value which is sent to the original
1299                                  exporting driver so that it can identify the type
1300                                  of data to expect. The format of the data tends to
1301                                  vary based on the opcode that generated the callback.
1302   @param  Type                   The type of value for the question.
1303   @param  Value                  A pointer to the data being sent to the original
1304                                  exporting driver.
1305   @param  ActionRequest          On return, points to the action requested by the
1306                                  callback function.
1307 
1308   @retval EFI_SUCCESS            The callback successfully handled the action.
1309   @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the
1310                                  variable and its data.
1311   @retval EFI_DEVICE_ERROR       The variable could not be saved.
1312   @retval EFI_UNSUPPORTED        The specified Action is not supported by the
1313                                  callback.
1314 
1315 **/
1316 EFI_STATUS
1317 EFIAPI
WifiMgrDxeHiiConfigAccessCallback(IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL * This,IN EFI_BROWSER_ACTION Action,IN EFI_QUESTION_ID QuestionId,IN UINT8 Type,IN OUT EFI_IFR_TYPE_VALUE * Value,OUT EFI_BROWSER_ACTION_REQUEST * ActionRequest)1318 WifiMgrDxeHiiConfigAccessCallback (
1319   IN     CONST EFI_HII_CONFIG_ACCESS_PROTOCOL    *This,
1320   IN     EFI_BROWSER_ACTION                      Action,
1321   IN     EFI_QUESTION_ID                         QuestionId,
1322   IN     UINT8                                   Type,
1323   IN OUT EFI_IFR_TYPE_VALUE                      *Value,
1324   OUT    EFI_BROWSER_ACTION_REQUEST              *ActionRequest
1325   )
1326 {
1327   EFI_STATUS                         Status;
1328   EFI_INPUT_KEY                      Key;
1329   UINTN                              BufferSize;
1330   WIFI_MGR_PRIVATE_DATA              *Private;
1331   WIFI_MANAGER_IFR_NVDATA            *IfrNvData;
1332   EFI_DEVICE_PATH_PROTOCOL           *FilePath;
1333   WIFI_MGR_NETWORK_PROFILE           *Profile;
1334   WIFI_MGR_NETWORK_PROFILE           *ProfileToConnect;
1335   WIFI_HIDDEN_NETWORK_DATA           *HiddenNetwork;
1336   UINTN                              TempDataSize;
1337   VOID                               *TempData;
1338   LIST_ENTRY                         *Entry;
1339   UINT32                             Index;
1340   UINT32                             RemoveCount;
1341   CHAR16                             *TempPassword;
1342   CHAR16                             *ErrorMessage;
1343 
1344   if (Action != EFI_BROWSER_ACTION_FORM_OPEN &&
1345       Action != EFI_BROWSER_ACTION_FORM_CLOSE &&
1346       Action != EFI_BROWSER_ACTION_CHANGING &&
1347       Action != EFI_BROWSER_ACTION_CHANGED &&
1348       Action != EFI_BROWSER_ACTION_RETRIEVE) {
1349 
1350     return EFI_UNSUPPORTED;
1351   }
1352   if ((Value == NULL) || (ActionRequest == NULL)) {
1353     return EFI_INVALID_PARAMETER;
1354   }
1355 
1356   Status  = EFI_SUCCESS;
1357   Private = WIFI_MGR_PRIVATE_DATA_FROM_CONFIG_ACCESS (This);
1358   if (Private->CurrentNic == NULL) {
1359     return EFI_DEVICE_ERROR;
1360   }
1361 
1362   //
1363   // Retrieve uncommitted data from Browser
1364   //
1365   BufferSize = sizeof (WIFI_MANAGER_IFR_NVDATA);
1366   IfrNvData = AllocateZeroPool (BufferSize);
1367   if (IfrNvData == NULL) {
1368     return EFI_OUT_OF_RESOURCES;
1369   }
1370   HiiGetBrowserData (&gWifiConfigFormSetGuid, mVendorStorageName, BufferSize, (UINT8 *) IfrNvData);
1371 
1372   if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {
1373     switch (QuestionId) {
1374 
1375     case KEY_MAC_LIST:
1376 
1377       Status = WifiMgrShowNicList (Private);
1378       break;
1379 
1380     case KEY_REFRESH_NETWORK_LIST:
1381 
1382       if (Private->CurrentNic->UserSelectedProfile != NULL) {
1383 
1384         Profile = Private->CurrentNic->UserSelectedProfile;
1385 
1386         //
1387         // Erase secrets since user has left Connection Page
1388         // Connection Page may direct to Network List Page or Eap Configuration Page,
1389         // secrets only need to be erased when head to Network List Page
1390         //
1391         WifiMgrCleanProfileSecrets (Profile);
1392 
1393         Private->CurrentNic->UserSelectedProfile = NULL;
1394       }
1395 
1396       break;
1397 
1398     case KEY_CONNECT_ACTION:
1399 
1400       if (Private->CurrentNic->UserSelectedProfile == NULL) {
1401         break;
1402       }
1403       Profile = Private->CurrentNic->UserSelectedProfile;
1404 
1405       //
1406       //Enter the network connection configuration page
1407       //Recovery from restored data
1408       //
1409       if (HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_SSID), Profile->SSId, NULL) == 0) {
1410         return EFI_OUT_OF_RESOURCES;
1411       }
1412       IfrNvData->SecurityType = Profile->SecurityType;
1413       if (HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_SECURITY_TYPE),
1414             mSecurityType[IfrNvData->SecurityType], NULL) == 0) {
1415         return EFI_OUT_OF_RESOURCES;
1416       }
1417 
1418       if (IfrNvData->SecurityType == SECURITY_TYPE_WPA2_ENTERPRISE) {
1419 
1420         IfrNvData->EapAuthMethod        = Profile->EapAuthMethod;
1421         IfrNvData->EapSecondAuthMethod  = Profile->EapSecondAuthMethod;
1422         StrCpyS (IfrNvData->EapIdentity, EAP_IDENTITY_SIZE, Profile->EapIdentity);
1423       }
1424 
1425       break;
1426 
1427     case KEY_ENROLLED_CERT_NAME:
1428 
1429       if (Private->CurrentNic->UserSelectedProfile == NULL) {
1430         break;
1431       }
1432       Profile = Private->CurrentNic->UserSelectedProfile;
1433 
1434       //
1435       //Enter the key enrollment page
1436       //For TTLS and PEAP, only CA cert needs to be cared
1437       //
1438       if (Private->FileType == FileTypeCACert) {
1439 
1440         if (Profile->CACertData != NULL) {
1441           HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_EAP_ENROLLED_CERT_NAME), Profile->CACertName, NULL);
1442         } else {
1443           HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_EAP_ENROLLED_CERT_NAME), L"", NULL);
1444         }
1445       } else if (Private->FileType == FileTypeClientCert) {
1446 
1447         if (Profile->ClientCertData != NULL) {
1448           HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_EAP_ENROLLED_CERT_NAME), Profile->ClientCertName, NULL);
1449         } else {
1450           HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_EAP_ENROLLED_CERT_NAME), L"", NULL);
1451         }
1452       }
1453       break;
1454 
1455     case KEY_ENROLLED_PRIVATE_KEY_NAME:
1456 
1457       if (Private->CurrentNic->UserSelectedProfile == NULL) {
1458         break;
1459       }
1460       Profile = Private->CurrentNic->UserSelectedProfile;
1461 
1462       if (Profile->PrivateKeyData != NULL) {
1463         HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_EAP_ENROLLED_PRIVATE_KEY_NAME), Profile->PrivateKeyName, NULL);
1464       } else {
1465         HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_EAP_ENROLLED_PRIVATE_KEY_NAME), L"", NULL);
1466       }
1467       break;
1468 
1469     default:
1470       break;
1471     }
1472   } else if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) {
1473     switch (QuestionId) {
1474 
1475     case KEY_CONNECT_ACTION:
1476 
1477       if (Private->CurrentNic->UserSelectedProfile == NULL) {
1478         break;
1479       }
1480       Profile = Private->CurrentNic->UserSelectedProfile;
1481 
1482       //
1483       //Restore User Config Data for Page recovery
1484       //
1485       if (IfrNvData->SecurityType == SECURITY_TYPE_WPA2_ENTERPRISE) {
1486 
1487         Profile->EapAuthMethod        = IfrNvData->EapAuthMethod;
1488         Profile->EapSecondAuthMethod  = IfrNvData->EapSecondAuthMethod;
1489         StrCpyS (Profile->EapIdentity, EAP_IDENTITY_SIZE, IfrNvData->EapIdentity);
1490       }
1491       break;
1492 
1493     default:
1494       break;
1495     }
1496   } else if (Action == EFI_BROWSER_ACTION_CHANGING) {
1497     switch (QuestionId) {
1498 
1499     case KEY_NETWORK_LIST:
1500 
1501       //
1502       //User triggered a scan process.
1503       //
1504       Private->CurrentNic->OneTimeScanRequest = TRUE;
1505       break;
1506 
1507     case KEY_PASSWORD_CONNECT_NETWORK:
1508     case KEY_EAP_PASSWORD_CONNECT_NETWORK:
1509     case KEY_PRIVATE_KEY_PASSWORD:
1510 
1511       if (Private->CurrentNic->UserSelectedProfile == NULL) {
1512         break;
1513       }
1514       Profile = Private->CurrentNic->UserSelectedProfile;
1515 
1516       if (QuestionId == KEY_PASSWORD_CONNECT_NETWORK) {
1517         TempPassword = Profile->Password;
1518       } else if (QuestionId == KEY_EAP_PASSWORD_CONNECT_NETWORK) {
1519         TempPassword = Profile->EapPassword;
1520       } else {
1521         TempPassword = Profile->PrivateKeyPassword;
1522       }
1523 
1524       Status = WifiMgrRecordPassword (Private, Value->string, TempPassword, PASSWORD_STORAGE_SIZE);
1525       if (EFI_ERROR (Status)) {
1526         DEBUG ((DEBUG_ERROR, "[WiFi Connection Manager] Error: Failed to input password!"));
1527         break;
1528       }
1529 
1530       //
1531       // This password is not a new created password, so no need to confirm.
1532       //
1533       Status = EFI_NOT_FOUND;
1534       break;
1535 
1536     case KEY_CONNECT_ACTION:
1537 
1538       ErrorMessage     = NULL;
1539       ProfileToConnect = NULL;
1540 
1541       if (Private->CurrentNic->UserSelectedProfile == NULL) {
1542         break;
1543       }
1544       Profile = Private->CurrentNic->UserSelectedProfile;
1545 
1546       if (Private->CurrentNic->ConnectState == WifiMgrDisconnected ||
1547         Profile != Private->CurrentNic->CurrentOperateNetwork) {
1548 
1549         //
1550         // When this network is not currently connected, pend it to connect.
1551         //
1552         if (Profile->AKMSuiteSupported && Profile->CipherSuiteSupported) {
1553 
1554           if (Profile->SecurityType == SECURITY_TYPE_NONE || Profile->SecurityType == SECURITY_TYPE_WPA2_PERSONAL) {
1555 
1556             //
1557             // For Open network, connect directly.
1558             //
1559             ProfileToConnect = Profile;
1560 
1561           } else if (Profile->SecurityType == SECURITY_TYPE_WPA2_ENTERPRISE) {
1562 
1563             //
1564             // For WPA/WPA2-Enterprise network, conduct eap configuration first.
1565             // Only EAP-TLS, TTLS and PEAP is supported now!
1566             //
1567             Profile->EapAuthMethod = IfrNvData->EapAuthMethod;
1568             StrCpyS (Profile->EapIdentity, EAP_IDENTITY_SIZE, IfrNvData->EapIdentity);
1569 
1570             if (IfrNvData->EapAuthMethod == EAP_AUTH_METHOD_TTLS || IfrNvData->EapAuthMethod == EAP_AUTH_METHOD_PEAP) {
1571 
1572               Profile->EapSecondAuthMethod = IfrNvData->EapSecondAuthMethod;
1573               ProfileToConnect = Profile;
1574             } else if (IfrNvData->EapAuthMethod == EAP_AUTH_METHOD_TLS) {
1575               ProfileToConnect = Profile;
1576             } else {
1577               ErrorMessage = L"ERROR: Only EAP-TLS, TTLS or PEAP is supported now!";
1578             }
1579           } else {
1580             ErrorMessage = L"ERROR: Can't connect to this network!";
1581           }
1582         } else {
1583           ErrorMessage = L"ERROR: This network is not supported!";
1584         }
1585 
1586         if (ErrorMessage != NULL) {
1587           CreatePopUp (
1588             EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1589             &Key,
1590             ErrorMessage,
1591             NULL
1592             );
1593         }
1594 
1595         if (ProfileToConnect != NULL) {
1596 
1597           Private->CurrentNic->OneTimeConnectRequest = TRUE;
1598           Private->CurrentNic->ConnectPendingNetwork = ProfileToConnect;
1599         }
1600       } else if (Private->CurrentNic->ConnectState == WifiMgrConnectedToAp) {
1601 
1602         //
1603         // This network is currently connected, just disconnect from it.
1604         //
1605         Private->CurrentNic->OneTimeDisconnectRequest    = TRUE;
1606         Private->CurrentNic->HasDisconnectPendingNetwork = TRUE;
1607       }
1608       break;
1609 
1610     case KEY_ENROLL_CA_CERT_CONNECT_NETWORK:
1611 
1612       Private->FileType = FileTypeCACert;
1613       break;
1614 
1615     case KEY_ENROLL_CLIENT_CERT_CONNECT_NETWORK:
1616 
1617       Private->FileType = FileTypeClientCert;
1618       break;
1619 
1620     case KEY_EAP_ENROLL_PRIVATE_KEY_FROM_FILE:
1621 
1622       FilePath = NULL;
1623       ChooseFile (NULL, NULL, NULL, &FilePath);
1624 
1625       if (FilePath != NULL) {
1626 
1627         UpdatePrivateKeyFromFile(Private, FilePath);
1628         FreePool (FilePath);
1629       }
1630       break;
1631 
1632     case KEY_EAP_ENROLL_CERT_FROM_FILE:
1633 
1634       //
1635       //User will select a cert file from File Explore
1636       //
1637       FilePath = NULL;
1638       ChooseFile( NULL, NULL, NULL, &FilePath);
1639 
1640       if (FilePath != NULL) {
1641 
1642         UpdateCAFromFile(Private, FilePath);
1643         FreePool (FilePath);
1644       }
1645       break;
1646 
1647     case KEY_SAVE_PRIVATE_KEY_TO_MEM:
1648 
1649       if (Private->FileContext != NULL && Private->FileContext->FHandle != NULL &&
1650         Private->CurrentNic->UserSelectedProfile != NULL) {
1651 
1652         //
1653         // Read Private Key file to Buffer
1654         //
1655         Profile = Private->CurrentNic->UserSelectedProfile;
1656         if (Profile->PrivateKeyData != NULL) {
1657 
1658           ZeroMem (Profile->PrivateKeyData, Profile->PrivateKeyDataSize);
1659           FreePool (Profile->PrivateKeyData);
1660           Profile->PrivateKeyData = NULL;
1661         }
1662 
1663         Status = WifiMgrReadFileToBuffer (
1664                    Private->FileContext,
1665                    &TempData,
1666                    &TempDataSize
1667                    );
1668         if (EFI_ERROR (Status)) {
1669           CreatePopUp (
1670             EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1671             &Key,
1672             L"ERROR: Can't read this private key file!",
1673             NULL
1674             );
1675         } else {
1676 
1677           ASSERT (Private->FileContext->FileName != NULL);
1678 
1679           Profile->PrivateKeyData = TempData;
1680           Profile->PrivateKeyDataSize = TempDataSize;
1681           StrCpyS(Profile->PrivateKeyName, WIFI_FILENAME_STR_MAX_SIZE, Private->FileContext->FileName);
1682 
1683           DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] Private Key: %s has been enrolled! Size: %d\n",
1684             Profile->PrivateKeyName, Profile->PrivateKeyDataSize));
1685         }
1686       }
1687       break;
1688 
1689     case KEY_SAVE_CERT_TO_MEM:
1690 
1691       if (Private->FileContext != NULL && Private->FileContext->FHandle != NULL &&
1692         Private->CurrentNic->UserSelectedProfile != NULL) {
1693 
1694         //
1695         // Read Cert file to Buffer
1696         //
1697         Profile = Private->CurrentNic->UserSelectedProfile;
1698 
1699         if (Private->FileType == FileTypeCACert) {
1700           if (Profile->CACertData != NULL) {
1701 
1702             ZeroMem (Profile->CACertData, Profile->CACertSize);
1703             FreePool (Profile->CACertData);
1704             Profile->CACertData = NULL;
1705           }
1706         } else if (Private->FileType == FileTypeClientCert) {
1707           if (Profile->ClientCertData != NULL) {
1708 
1709             ZeroMem (Profile->ClientCertData, Profile->ClientCertSize);
1710             FreePool (Profile->ClientCertData);
1711             Profile->ClientCertData = NULL;
1712           }
1713         } else {
1714           break;
1715         }
1716 
1717         Status = WifiMgrReadFileToBuffer (
1718                    Private->FileContext,
1719                    &TempData,
1720                    &TempDataSize
1721                    );
1722         if (EFI_ERROR (Status)) {
1723           CreatePopUp (
1724             EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1725             &Key,
1726             L"ERROR: Can't read this certificate file!",
1727             NULL
1728             );
1729         } else {
1730 
1731           ASSERT (Private->FileContext->FileName != NULL);
1732           if (Private->FileType == FileTypeCACert) {
1733 
1734             Profile->CACertData = TempData;
1735             Profile->CACertSize = TempDataSize;
1736             StrCpyS(Profile->CACertName, WIFI_FILENAME_STR_MAX_SIZE, Private->FileContext->FileName);
1737             DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] CA Cert: %s has been enrolled! Size: %d\n",
1738               Profile->CACertName, Profile->CACertSize));
1739           } else {
1740 
1741             Profile->ClientCertData = TempData;
1742             Profile->ClientCertSize = TempDataSize;
1743             StrCpyS(Profile->ClientCertName, WIFI_FILENAME_STR_MAX_SIZE, Private->FileContext->FileName);
1744             DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] Client Cert: %s has been enrolled! Size: %d\n",
1745               Profile->ClientCertName, Profile->ClientCertSize));
1746           }
1747         }
1748       }
1749       break;
1750 
1751     case KEY_ADD_HIDDEN_NETWORK:
1752 
1753       //
1754       // Add a Hidden Network
1755       //
1756       if (StrLen (IfrNvData->SSId) < SSID_MIN_LEN ||
1757         Private->HiddenNetworkCount >= HIDDEN_NETWORK_LIST_COUNT_MAX) {
1758 
1759         Status = EFI_ABORTED;
1760         break;
1761       } else {
1762 
1763         //
1764         // Check if this SSId is already in Hidden Network List
1765         //
1766         NET_LIST_FOR_EACH (Entry, &Private->HiddenNetworkList) {
1767 
1768           HiddenNetwork = NET_LIST_USER_STRUCT_S (Entry, WIFI_HIDDEN_NETWORK_DATA,
1769                             Link, WIFI_MGR_HIDDEN_NETWORK_SIGNATURE);
1770           if (StrCmp (HiddenNetwork->SSId, IfrNvData->SSId) == 0) {
1771 
1772             Status = EFI_ABORTED;
1773             break;
1774           }
1775         }
1776       }
1777 
1778       HiddenNetwork = (WIFI_HIDDEN_NETWORK_DATA *) AllocateZeroPool (sizeof (WIFI_HIDDEN_NETWORK_DATA));
1779       if (HiddenNetwork == NULL) {
1780 
1781         Status = EFI_OUT_OF_RESOURCES;
1782         break;
1783       }
1784       HiddenNetwork->Signature = WIFI_MGR_HIDDEN_NETWORK_SIGNATURE;
1785       StrCpyS (HiddenNetwork->SSId, SSID_STORAGE_SIZE, IfrNvData->SSId);
1786 
1787       InsertTailList (&Private->HiddenNetworkList, &HiddenNetwork->Link);
1788       Private->HiddenNetworkCount ++;
1789 
1790       WifiMgrRefreshHiddenList (Private);
1791       break;
1792 
1793     case KEY_REMOVE_HIDDEN_NETWORK:
1794 
1795       //
1796       // Remove Hidden Networks
1797       //
1798       Entry = GetFirstNode (&Private->HiddenNetworkList);
1799       RemoveCount = 0;
1800       for (Index = 0; Index < Private->HiddenNetworkCount; Index ++) {
1801         if (IfrNvData->HiddenNetworkList[Index] != 0) {
1802 
1803           HiddenNetwork = NET_LIST_USER_STRUCT_S (Entry, WIFI_HIDDEN_NETWORK_DATA, Link, WIFI_MGR_HIDDEN_NETWORK_SIGNATURE);
1804           Entry = RemoveEntryList (Entry);
1805           RemoveCount ++;
1806 
1807           FreePool (HiddenNetwork);
1808         } else {
1809           Entry = GetNextNode (&Private->HiddenNetworkList, Entry);
1810         }
1811       }
1812 
1813       Private->HiddenNetworkCount -= RemoveCount;
1814       WifiMgrRefreshHiddenList (Private);
1815       break;
1816 
1817     default:
1818 
1819       if (QuestionId >= KEY_MAC_ENTRY_BASE && QuestionId < KEY_MAC_ENTRY_BASE + Private->NicCount) {
1820         //
1821         // User selects a wireless NIC.
1822         //
1823         Status = WifiMgrSelectNic (Private, QuestionId);
1824         if (EFI_ERROR (Status)) {
1825           CreatePopUp (
1826             EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1827             &Key,
1828             L"ERROR: Fail to operate the wireless NIC!",
1829             NULL
1830           );
1831         }
1832       } else if (Private->CurrentNic != NULL) {
1833         if (QuestionId >= KEY_AVAILABLE_NETWORK_ENTRY_BASE &&
1834           QuestionId <= KEY_AVAILABLE_NETWORK_ENTRY_BASE + Private->CurrentNic->MaxProfileIndex) {
1835 
1836           Status = WifiMgrUserSelectProfileToConnect (Private, QuestionId - KEY_AVAILABLE_NETWORK_ENTRY_BASE);
1837           if (!EFI_ERROR (Status)) {
1838             WifiMgrUpdateConnectMessage(Private->CurrentNic, FALSE, NULL);
1839           }
1840         }
1841 
1842         if (EFI_ERROR (Status)) {
1843           CreatePopUp (
1844             EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1845             &Key,
1846             L"ERROR: Fail to operate this profile!",
1847             NULL
1848           );
1849         }
1850       }
1851 
1852       break;
1853     }
1854   } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
1855     switch (QuestionId) {
1856 
1857     case KEY_SAVE_CERT_TO_MEM:
1858     case KEY_SAVE_PRIVATE_KEY_TO_MEM:
1859 
1860       *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
1861       break;
1862 
1863     case KEY_NO_SAVE_CERT_TO_MEM:
1864     case KEY_NO_SAVE_PRIVATE_KEY_TO_MEM:
1865 
1866       *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
1867       break;
1868 
1869     default:
1870 
1871       *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
1872       break;
1873     }
1874   } else if (Action == EFI_BROWSER_ACTION_RETRIEVE) {
1875 
1876     switch (QuestionId) {
1877 
1878     case KEY_REFRESH_NETWORK_LIST:
1879 
1880       WifiMgrRefreshNetworkList (Private, IfrNvData);
1881       break;
1882 
1883     default:
1884       break;
1885     }
1886   }
1887 
1888   if (!EFI_ERROR (Status)) {
1889     //
1890     // Pass changed uncommitted data back to Form Browser.
1891     //
1892     BufferSize = sizeof (WIFI_MANAGER_IFR_NVDATA);
1893     HiiSetBrowserData (&gWifiConfigFormSetGuid, mVendorStorageName, BufferSize, (UINT8 *) IfrNvData, NULL);
1894   }
1895 
1896   ZeroMem (IfrNvData, sizeof (WIFI_MANAGER_IFR_NVDATA));
1897   FreePool (IfrNvData);
1898   return Status;
1899 }
1900 
1901 /**
1902   Initialize the WiFi configuration form.
1903 
1904   @param[in]  Private             The pointer to the global private data structure.
1905 
1906   @retval EFI_SUCCESS             The configuration form is initialized.
1907   @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
1908   @retval EFI_INVALID_PARAMETER   Any input parameter is invalid.
1909   @retval Other Erros             Returned Errors when installing protocols.
1910 
1911 **/
1912 EFI_STATUS
WifiMgrDxeConfigFormInit(WIFI_MGR_PRIVATE_DATA * Private)1913 WifiMgrDxeConfigFormInit (
1914   WIFI_MGR_PRIVATE_DATA    *Private
1915 )
1916 {
1917   EFI_STATUS                      Status;
1918 
1919   if (Private == NULL) {
1920     return EFI_INVALID_PARAMETER;
1921   }
1922 
1923   Private->ConfigAccess.ExtractConfig = WifiMgrDxeHiiConfigAccessExtractConfig;
1924   Private->ConfigAccess.RouteConfig   = WifiMgrDxeHiiConfigAccessRouteConfig;
1925   Private->ConfigAccess.Callback      = WifiMgrDxeHiiConfigAccessCallback;
1926 
1927   //
1928   // Install Device Path Protocol and Config Access protocol to driver handle.
1929   //
1930   Status = gBS->InstallMultipleProtocolInterfaces (
1931                   &Private->DriverHandle,
1932                   &gEfiDevicePathProtocolGuid,
1933                   &mWifiMgrDxeHiiVendorDevicePath,
1934                   &gEfiHiiConfigAccessProtocolGuid,
1935                   &Private->ConfigAccess,
1936                   NULL
1937                   );
1938   if (EFI_ERROR (Status)) {
1939     return Status;
1940   }
1941 
1942   //
1943   // Publish our HII data.
1944   //
1945   Private->RegisteredHandle = HiiAddPackages (
1946                                 &gWifiConfigFormSetGuid,
1947                                 Private->DriverHandle,
1948                                 WifiConnectionManagerDxeStrings,
1949                                 WifiConnectionManagerDxeBin,
1950                                 NULL
1951                                 );
1952   if (Private->RegisteredHandle == NULL) {
1953     gBS->UninstallMultipleProtocolInterfaces (
1954            Private->DriverHandle,
1955            &gEfiDevicePathProtocolGuid,
1956            &mWifiMgrDxeHiiVendorDevicePath,
1957            &gEfiHiiConfigAccessProtocolGuid,
1958            &Private->ConfigAccess,
1959            NULL
1960            );
1961     return EFI_OUT_OF_RESOURCES;
1962   }
1963 
1964   Private->FileContext = AllocateZeroPool (sizeof (WIFI_MGR_FILE_CONTEXT));
1965   if (Private->FileContext == NULL) {
1966     return EFI_OUT_OF_RESOURCES;
1967   }
1968 
1969   return EFI_SUCCESS;
1970 }
1971 
1972 /**
1973   Unload the WiFi configuration form.
1974 
1975   @param[in]  Private             The pointer to the global private data structure.
1976 
1977   @retval EFI_SUCCESS             The configuration form is unloaded successfully.
1978   @retval EFI_INVALID_PARAMETER   Any input parameter is invalid.
1979   @retval Other Errors            Returned Erros when uninstalling protocols.
1980 
1981 **/
1982 EFI_STATUS
WifiMgrDxeConfigFormUnload(WIFI_MGR_PRIVATE_DATA * Private)1983 WifiMgrDxeConfigFormUnload (
1984   WIFI_MGR_PRIVATE_DATA    *Private
1985 )
1986 {
1987   EFI_STATUS    Status;
1988 
1989   if (Private == NULL) {
1990     return EFI_INVALID_PARAMETER;
1991   }
1992 
1993   if (Private->FileContext != NULL) {
1994 
1995     if (Private->FileContext->FHandle != NULL) {
1996       Private->FileContext->FHandle->Close (Private->FileContext->FHandle);
1997     }
1998 
1999     if (Private->FileContext->FileName != NULL) {
2000       FreePool (Private->FileContext->FileName);
2001     }
2002     FreePool (Private->FileContext);
2003   }
2004 
2005   HiiRemovePackages(Private->RegisteredHandle);
2006 
2007   Status = gBS->UninstallMultipleProtocolInterfaces (
2008              Private->DriverHandle,
2009              &gEfiDevicePathProtocolGuid,
2010              &mWifiMgrDxeHiiVendorDevicePath,
2011              &gEfiHiiConfigAccessProtocolGuid,
2012              &Private->ConfigAccess,
2013              NULL
2014              );
2015 
2016   return Status;
2017 }
2018