]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrImpl.c
NetworkPkg: Apply uncrustify changes
[mirror_edk2.git] / NetworkPkg / WifiConnectionManagerDxe / WifiConnectionMgrImpl.c
CommitLineData
90b24889
WF
1/** @file\r
2 The Mac Connection2 Protocol adapter functions for WiFi Connection Manager.\r
3\r
4 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
5\r
ecf98fbc 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
90b24889
WF
7\r
8**/\r
9\r
10#include "WifiConnectionMgrDxe.h"\r
11\r
d1050b9d 12EFI_EAP_TYPE mEapAuthMethod[] = {\r
90b24889
WF
13 EFI_EAP_TYPE_TTLS,\r
14 EFI_EAP_TYPE_PEAP,\r
15 EFI_EAP_TYPE_EAPTLS\r
16};\r
17\r
d1050b9d 18EFI_EAP_TYPE mEapSecondAuthMethod[] = {\r
90b24889
WF
19 EFI_EAP_TYPE_MSCHAPV2\r
20};\r
21\r
22/**\r
23 The callback function for scan operation. This function updates networks\r
24 according to the latest scan result, and trigger UI refresh.\r
25\r
26 ASSERT when errors occur in config token.\r
27\r
28 @param[in] Event The GetNetworks token receive event.\r
29 @param[in] Context The context of the GetNetworks token.\r
30\r
31**/\r
32VOID\r
33EFIAPI\r
34WifiMgrOnScanFinished (\r
d1050b9d
MK
35 IN EFI_EVENT Event,\r
36 IN VOID *Context\r
90b24889
WF
37 )\r
38{\r
d1050b9d
MK
39 EFI_STATUS Status;\r
40 WIFI_MGR_MAC_CONFIG_TOKEN *ConfigToken;\r
41 WIFI_MGR_DEVICE_DATA *Nic;\r
42 WIFI_MGR_NETWORK_PROFILE *Profile;\r
43 EFI_80211_NETWORK *Network;\r
44 UINTN DataSize;\r
45 EFI_80211_NETWORK_DESCRIPTION *NetworkDescription;\r
46 EFI_80211_GET_NETWORKS_RESULT *Result;\r
47 LIST_ENTRY *Entry;\r
48 UINT8 SecurityType;\r
49 BOOLEAN AKMSuiteSupported;\r
50 BOOLEAN CipherSuiteSupported;\r
51 CHAR8 *AsciiSSId;\r
52 UINTN Index;\r
90b24889
WF
53\r
54 ASSERT (Context != NULL);\r
55\r
d1050b9d 56 ConfigToken = (WIFI_MGR_MAC_CONFIG_TOKEN *)Context;\r
90b24889
WF
57 ASSERT (ConfigToken->Nic != NULL);\r
58 ASSERT (ConfigToken->Type == TokenTypeGetNetworksToken);\r
59\r
60 //\r
61 // It is the GetNetworks token, set scan state to "ScanFinished"\r
62 //\r
63 ConfigToken->Nic->ScanState = WifiMgrScanFinished;\r
64\r
65 ASSERT (ConfigToken->Token.GetNetworksToken != NULL);\r
66 Result = ConfigToken->Token.GetNetworksToken->Result;\r
67 Nic = ConfigToken->Nic;\r
68\r
69 //\r
70 // Clean previous result, and update network list according to the scan result\r
71 //\r
d1050b9d 72 Nic->AvailableCount = 0;\r
90b24889
WF
73\r
74 NET_LIST_FOR_EACH (Entry, &Nic->ProfileList) {\r
d1050b9d
MK
75 Profile = NET_LIST_USER_STRUCT_S (\r
76 Entry,\r
77 WIFI_MGR_NETWORK_PROFILE,\r
78 Link,\r
79 WIFI_MGR_PROFILE_SIGNATURE\r
80 );\r
90b24889
WF
81 Profile->IsAvailable = FALSE;\r
82 }\r
83\r
84 if (Result == NULL) {\r
85 gBS->SignalEvent (Nic->Private->NetworkListRefreshEvent);\r
d1050b9d 86 WifiMgrFreeToken (ConfigToken);\r
90b24889
WF
87 return;\r
88 }\r
89\r
d1050b9d 90 for (Index = 0; Index < Result->NumOfNetworkDesc; Index++) {\r
90b24889
WF
91 NetworkDescription = Result->NetworkDesc + Index;\r
92 if (NetworkDescription == NULL) {\r
93 continue;\r
94 }\r
95\r
96 Network = &NetworkDescription->Network;\r
d1050b9d 97 if ((Network == NULL) || (Network->SSId.SSIdLen == 0)) {\r
90b24889
WF
98 continue;\r
99 }\r
100\r
101 Status = WifiMgrCheckRSN (\r
102 Network->AKMSuite,\r
103 Network->CipherSuite,\r
104 Nic,\r
105 &SecurityType,\r
106 &AKMSuiteSupported,\r
107 &CipherSuiteSupported\r
108 );\r
109 if (EFI_ERROR (Status)) {\r
d1050b9d
MK
110 SecurityType = SECURITY_TYPE_UNKNOWN;\r
111 AKMSuiteSupported = FALSE;\r
112 CipherSuiteSupported = FALSE;\r
90b24889
WF
113 }\r
114\r
d1050b9d 115 AsciiSSId = (CHAR8 *)AllocateZeroPool (sizeof (CHAR8) * (Network->SSId.SSIdLen + 1));\r
90b24889
WF
116 if (AsciiSSId == NULL) {\r
117 continue;\r
118 }\r
d1050b9d
MK
119\r
120 CopyMem (AsciiSSId, (CHAR8 *)Network->SSId.SSId, sizeof (CHAR8) * Network->SSId.SSIdLen);\r
90b24889
WF
121 *(AsciiSSId + Network->SSId.SSIdLen) = '\0';\r
122\r
123 Profile = WifiMgrGetProfileByAsciiSSId (AsciiSSId, SecurityType, &Nic->ProfileList);\r
124 if (Profile == NULL) {\r
90b24889
WF
125 if (Nic->MaxProfileIndex >= NETWORK_LIST_COUNT_MAX) {\r
126 FreePool (AsciiSSId);\r
127 continue;\r
128 }\r
129\r
130 //\r
131 // Create a new profile\r
132 //\r
133 Profile = AllocateZeroPool (sizeof (WIFI_MGR_NETWORK_PROFILE));\r
134 if (Profile == NULL) {\r
135 FreePool (AsciiSSId);\r
136 continue;\r
137 }\r
d1050b9d 138\r
90b24889
WF
139 Profile->Signature = WIFI_MGR_PROFILE_SIGNATURE;\r
140 Profile->NicIndex = Nic->NicIndex;\r
141 Profile->ProfileIndex = Nic->MaxProfileIndex + 1;\r
142 AsciiStrToUnicodeStrS (AsciiSSId, Profile->SSId, SSID_STORAGE_SIZE);\r
143 InsertTailList (&Nic->ProfileList, &Profile->Link);\r
d1050b9d 144 Nic->MaxProfileIndex++;\r
90b24889 145 }\r
d1050b9d 146\r
90b24889
WF
147 FreePool (AsciiSSId);\r
148\r
149 //\r
d1050b9d
MK
150 // May receive duplicate networks in scan results, check if it has already\r
151 // been processed.\r
90b24889
WF
152 //\r
153 if (!Profile->IsAvailable) {\r
90b24889
WF
154 Profile->IsAvailable = TRUE;\r
155 Profile->SecurityType = SecurityType;\r
156 Profile->AKMSuiteSupported = AKMSuiteSupported;\r
157 Profile->CipherSuiteSupported = CipherSuiteSupported;\r
158 Profile->NetworkQuality = NetworkDescription->NetworkQuality;\r
d1050b9d 159 Nic->AvailableCount++;\r
90b24889
WF
160\r
161 //\r
d1050b9d 162 // Copy BSSType and SSId\r
90b24889 163 //\r
d1050b9d 164 CopyMem (&Profile->Network, Network, sizeof (EFI_80211_NETWORK));\r
90b24889
WF
165\r
166 //\r
d1050b9d 167 // Copy AKMSuite list\r
90b24889
WF
168 //\r
169 if (Network->AKMSuite != NULL) {\r
90b24889
WF
170 if (Network->AKMSuite->AKMSuiteCount == 0) {\r
171 DataSize = sizeof (EFI_80211_AKM_SUITE_SELECTOR);\r
172 } else {\r
173 DataSize = sizeof (EFI_80211_AKM_SUITE_SELECTOR) + sizeof (EFI_80211_SUITE_SELECTOR)\r
d1050b9d 174 * (Network->AKMSuite->AKMSuiteCount - 1);\r
90b24889 175 }\r
d1050b9d
MK
176\r
177 Profile->Network.AKMSuite = (EFI_80211_AKM_SUITE_SELECTOR *)AllocateZeroPool (DataSize);\r
90b24889
WF
178 if (Profile->Network.AKMSuite == NULL) {\r
179 continue;\r
180 }\r
d1050b9d 181\r
90b24889
WF
182 CopyMem (Profile->Network.AKMSuite, Network->AKMSuite, DataSize);\r
183 }\r
184\r
185 //\r
d1050b9d 186 // Copy CipherSuite list\r
90b24889
WF
187 //\r
188 if (Network->CipherSuite != NULL) {\r
90b24889
WF
189 if (Network->CipherSuite->CipherSuiteCount == 0) {\r
190 DataSize = sizeof (EFI_80211_CIPHER_SUITE_SELECTOR);\r
191 } else {\r
192 DataSize = sizeof (EFI_80211_CIPHER_SUITE_SELECTOR) + sizeof (EFI_80211_SUITE_SELECTOR)\r
d1050b9d 193 * (Network->CipherSuite->CipherSuiteCount - 1);\r
90b24889 194 }\r
d1050b9d
MK
195\r
196 Profile->Network.CipherSuite = (EFI_80211_CIPHER_SUITE_SELECTOR *)AllocateZeroPool (DataSize);\r
90b24889
WF
197 if (Profile->Network.CipherSuite == NULL) {\r
198 continue;\r
199 }\r
d1050b9d 200\r
90b24889
WF
201 CopyMem (Profile->Network.CipherSuite, Network->CipherSuite, DataSize);\r
202 }\r
203 } else {\r
204 //\r
205 // A duplicate network, update signal quality\r
206 //\r
207 if (Profile->NetworkQuality < NetworkDescription->NetworkQuality) {\r
208 Profile->NetworkQuality = NetworkDescription->NetworkQuality;\r
209 }\r
d1050b9d 210\r
90b24889
WF
211 continue;\r
212 }\r
213 }\r
214\r
90b24889
WF
215 gBS->SignalEvent (Nic->Private->NetworkListRefreshEvent);\r
216\r
217 //\r
218 // The current connected network should always be available until disconnection\r
219 // happens in Wifi FW layer, even when it is not in this time's scan result.\r
220 //\r
d1050b9d 221 if ((Nic->ConnectState == WifiMgrConnectedToAp) && (Nic->CurrentOperateNetwork != NULL)) {\r
90b24889
WF
222 if (!Nic->CurrentOperateNetwork->IsAvailable) {\r
223 Nic->CurrentOperateNetwork->IsAvailable = TRUE;\r
d1050b9d 224 Nic->AvailableCount++;\r
90b24889
WF
225 }\r
226 }\r
227\r
d1050b9d 228 WifiMgrFreeToken (ConfigToken);\r
90b24889
WF
229}\r
230\r
231/**\r
232 Start scan operation, and send out a token to collect available networks.\r
233\r
234 @param[in] Nic Pointer to the device data of the selected NIC.\r
235\r
236 @retval EFI_SUCCESS The operation is completed.\r
237 @retval EFI_ALREADY_STARTED A former scan operation is already ongoing.\r
238 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
239 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
240 @retval Other Errors Return errors when getting networks from low layer.\r
241\r
242**/\r
243EFI_STATUS\r
244WifiMgrStartScan (\r
d1050b9d 245 IN WIFI_MGR_DEVICE_DATA *Nic\r
90b24889
WF
246 )\r
247{\r
d1050b9d
MK
248 EFI_STATUS Status;\r
249 EFI_TPL OldTpl;\r
250 WIFI_MGR_MAC_CONFIG_TOKEN *ConfigToken;\r
251 EFI_80211_GET_NETWORKS_TOKEN *GetNetworksToken;\r
252 UINT32 HiddenSSIdIndex;\r
253 UINT32 HiddenSSIdCount;\r
254 EFI_80211_SSID *HiddenSSIdList;\r
255 WIFI_HIDDEN_NETWORK_DATA *HiddenNetwork;\r
256 LIST_ENTRY *Entry;\r
257\r
258 if ((Nic == NULL) || (Nic->Wmp == NULL)) {\r
90b24889
WF
259 return EFI_INVALID_PARAMETER;\r
260 }\r
261\r
262 if (Nic->ScanState == WifiMgrScanning) {\r
263 return EFI_ALREADY_STARTED;\r
264 }\r
265\r
266 Nic->ScanState = WifiMgrScanning;\r
267 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
268 Status = EFI_SUCCESS;\r
269 HiddenSSIdList = NULL;\r
270 HiddenSSIdCount = Nic->Private->HiddenNetworkCount;\r
271 HiddenSSIdIndex = 0;\r
272\r
273 //\r
d1050b9d 274 // create a new get network token\r
90b24889 275 //\r
d1050b9d 276 ConfigToken = AllocateZeroPool (sizeof (WIFI_MGR_MAC_CONFIG_TOKEN));\r
90b24889
WF
277 if (ConfigToken == NULL) {\r
278 gBS->RestoreTPL (OldTpl);\r
279 return EFI_OUT_OF_RESOURCES;\r
280 }\r
281\r
d1050b9d
MK
282 ConfigToken->Type = TokenTypeGetNetworksToken;\r
283 ConfigToken->Nic = Nic;\r
90b24889
WF
284 ConfigToken->Token.GetNetworksToken = AllocateZeroPool (sizeof (EFI_80211_GET_NETWORKS_TOKEN));\r
285 if (ConfigToken->Token.GetNetworksToken == NULL) {\r
d1050b9d 286 WifiMgrFreeToken (ConfigToken);\r
90b24889
WF
287 gBS->RestoreTPL (OldTpl);\r
288 return EFI_OUT_OF_RESOURCES;\r
289 }\r
d1050b9d 290\r
90b24889
WF
291 GetNetworksToken = ConfigToken->Token.GetNetworksToken;\r
292\r
293 //\r
294 // There are some hidden networks to scan, add them into scan list\r
295 //\r
296 if (HiddenSSIdCount > 0) {\r
d1050b9d 297 HiddenSSIdList = AllocateZeroPool (HiddenSSIdCount * sizeof (EFI_80211_SSID));\r
90b24889 298 if (HiddenSSIdList == NULL) {\r
d1050b9d 299 WifiMgrFreeToken (ConfigToken);\r
90b24889
WF
300 gBS->RestoreTPL (OldTpl);\r
301 return EFI_OUT_OF_RESOURCES;\r
302 }\r
303\r
304 HiddenSSIdIndex = 0;\r
305 NET_LIST_FOR_EACH (Entry, &Nic->Private->HiddenNetworkList) {\r
d1050b9d
MK
306 HiddenNetwork = NET_LIST_USER_STRUCT_S (\r
307 Entry,\r
308 WIFI_HIDDEN_NETWORK_DATA,\r
309 Link,\r
310 WIFI_MGR_HIDDEN_NETWORK_SIGNATURE\r
311 );\r
312 HiddenSSIdList[HiddenSSIdIndex].SSIdLen = (UINT8)StrLen (HiddenNetwork->SSId);\r
313 UnicodeStrToAsciiStrS (\r
314 HiddenNetwork->SSId,\r
315 (CHAR8 *)HiddenSSIdList[HiddenSSIdIndex].SSId,\r
316 SSID_STORAGE_SIZE\r
317 );\r
318 HiddenSSIdIndex++;\r
90b24889 319 }\r
d1050b9d
MK
320 GetNetworksToken->Data = AllocateZeroPool (\r
321 sizeof (EFI_80211_GET_NETWORKS_DATA) +\r
322 (HiddenSSIdCount - 1) * sizeof (EFI_80211_SSID)\r
323 );\r
90b24889
WF
324 if (GetNetworksToken->Data == NULL) {\r
325 FreePool (HiddenSSIdList);\r
d1050b9d 326 WifiMgrFreeToken (ConfigToken);\r
90b24889
WF
327 gBS->RestoreTPL (OldTpl);\r
328 return EFI_OUT_OF_RESOURCES;\r
329 }\r
d1050b9d 330\r
90b24889 331 GetNetworksToken->Data->NumOfSSID = HiddenSSIdCount;\r
d1050b9d
MK
332 CopyMem (GetNetworksToken->Data->SSIDList, HiddenSSIdList, HiddenSSIdCount * sizeof (EFI_80211_SSID));\r
333 FreePool (HiddenSSIdList);\r
90b24889 334 } else {\r
90b24889
WF
335 GetNetworksToken->Data = AllocateZeroPool (sizeof (EFI_80211_GET_NETWORKS_DATA));\r
336 if (GetNetworksToken->Data == NULL) {\r
d1050b9d 337 WifiMgrFreeToken (ConfigToken);\r
90b24889
WF
338 gBS->RestoreTPL (OldTpl);\r
339 return EFI_OUT_OF_RESOURCES;\r
340 }\r
341\r
342 GetNetworksToken->Data->NumOfSSID = 0;\r
343 }\r
344\r
345 //\r
d1050b9d 346 // Create a handle when scan process ends\r
90b24889
WF
347 //\r
348 Status = gBS->CreateEvent (\r
349 EVT_NOTIFY_SIGNAL,\r
350 TPL_CALLBACK,\r
351 WifiMgrOnScanFinished,\r
352 ConfigToken,\r
353 &GetNetworksToken->Event\r
354 );\r
355 if (EFI_ERROR (Status)) {\r
d1050b9d 356 WifiMgrFreeToken (ConfigToken);\r
90b24889
WF
357 gBS->RestoreTPL (OldTpl);\r
358 return Status;\r
359 }\r
360\r
361 //\r
d1050b9d 362 // Start scan ...\r
90b24889
WF
363 //\r
364 Status = Nic->Wmp->GetNetworks (Nic->Wmp, GetNetworksToken);\r
365 if (EFI_ERROR (Status)) {\r
d1050b9d
MK
366 Nic->ScanState = WifiMgrScanFinished;\r
367 WifiMgrFreeToken (ConfigToken);\r
90b24889
WF
368 gBS->RestoreTPL (OldTpl);\r
369 return Status;\r
370 }\r
371\r
372 gBS->RestoreTPL (OldTpl);\r
373 return EFI_SUCCESS;\r
374}\r
375\r
376/**\r
377 Configure password to supplicant before connecting to a secured network.\r
378\r
379 @param[in] Nic Pointer to the device data of the selected NIC.\r
380 @param[in] Profile The target network to be connected.\r
381\r
382 @retval EFI_SUCCESS The operation is completed.\r
383 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
384 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
385 @retval EFI_NOT_FOUND No valid password is found to configure.\r
386 @retval Other Errors Returned errors when setting data to supplicant.\r
387\r
388**/\r
389EFI_STATUS\r
390WifiMgrConfigPassword (\r
d1050b9d
MK
391 IN WIFI_MGR_DEVICE_DATA *Nic,\r
392 IN WIFI_MGR_NETWORK_PROFILE *Profile\r
90b24889
WF
393 )\r
394{\r
d1050b9d
MK
395 EFI_STATUS Status;\r
396 EFI_SUPPLICANT_PROTOCOL *Supplicant;\r
397 EFI_80211_SSID SSId;\r
398 UINT8 *AsciiPassword;\r
90b24889 399\r
d1050b9d 400 if ((Nic == NULL) || (Nic->Supplicant == NULL) || (Profile == NULL)) {\r
90b24889
WF
401 return EFI_INVALID_PARAMETER;\r
402 }\r
d1050b9d 403\r
90b24889
WF
404 Supplicant = Nic->Supplicant;\r
405 //\r
d1050b9d 406 // Set SSId to supplicant\r
90b24889
WF
407 //\r
408 SSId.SSIdLen = Profile->Network.SSId.SSIdLen;\r
d1050b9d
MK
409 CopyMem (SSId.SSId, Profile->Network.SSId.SSId, sizeof (Profile->Network.SSId.SSId));\r
410 Status = Supplicant->SetData (\r
411 Supplicant,\r
412 EfiSupplicant80211TargetSSIDName,\r
413 (VOID *)&SSId,\r
414 sizeof (EFI_80211_SSID)\r
415 );\r
416 if (EFI_ERROR (Status)) {\r
90b24889
WF
417 return Status;\r
418 }\r
419\r
420 //\r
d1050b9d 421 // Set password to supplicant\r
90b24889
WF
422 //\r
423 if (StrLen (Profile->Password) < PASSWORD_MIN_LEN) {\r
424 return EFI_NOT_FOUND;\r
425 }\r
d1050b9d
MK
426\r
427 AsciiPassword = AllocateZeroPool ((StrLen (Profile->Password) + 1) * sizeof (UINT8));\r
90b24889
WF
428 if (AsciiPassword == NULL) {\r
429 return EFI_OUT_OF_RESOURCES;\r
430 }\r
d1050b9d
MK
431\r
432 UnicodeStrToAsciiStrS (Profile->Password, (CHAR8 *)AsciiPassword, PASSWORD_STORAGE_SIZE);\r
433 Status = Supplicant->SetData (\r
434 Supplicant,\r
435 EfiSupplicant80211PskPassword,\r
436 AsciiPassword,\r
437 (StrLen (Profile->Password) + 1) * sizeof (UINT8)\r
438 );\r
439 ZeroMem (AsciiPassword, AsciiStrLen ((CHAR8 *)AsciiPassword) + 1);\r
440 FreePool (AsciiPassword);\r
90b24889
WF
441\r
442 return Status;\r
443}\r
444\r
445/**\r
446 Conduct EAP configuration to supplicant before connecting to a EAP network.\r
447 Current WiFi Connection Manager only supports three kinds of EAP networks:\r
448 1). EAP-TLS (Two-Way Authentication is required in our implementation)\r
449 2). EAP-TTLS/MSCHAPv2 (One-Way Authentication is required in our implementation)\r
450 3). PEAPv0/MSCHAPv2 (One-Way Authentication is required in our implementation)\r
451\r
452 @param[in] Nic Pointer to the device data of the selected NIC.\r
453 @param[in] Profile The target network to be connected.\r
454\r
455 @retval EFI_SUCCESS The operation is completed.\r
456 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
457 @retval EFI_UNSUPPORTED The expected EAP method is not supported.\r
458 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
459 @retval Other Errors Returned errors when setting data to supplicant.\r
460\r
461**/\r
462EFI_STATUS\r
463WifiMgrConfigEap (\r
d1050b9d
MK
464 IN WIFI_MGR_DEVICE_DATA *Nic,\r
465 IN WIFI_MGR_NETWORK_PROFILE *Profile\r
90b24889
WF
466 )\r
467{\r
d1050b9d
MK
468 EFI_STATUS Status;\r
469 EFI_EAP_CONFIGURATION_PROTOCOL *EapConfig;\r
470 EFI_EAP_TYPE EapAuthMethod;\r
471 EFI_EAP_TYPE EapSecondAuthMethod;\r
472 EFI_EAP_TYPE *AuthMethodList;\r
473 CHAR8 *Identity;\r
474 UINTN IdentitySize;\r
475 CHAR16 *Password;\r
476 UINTN PasswordSize;\r
477 UINTN EncryptPasswordLen;\r
478 CHAR8 *AsciiEncryptPassword;\r
479 UINTN AuthMethodListSize;\r
480 UINTN Index;\r
481\r
482 if ((Nic == NULL) || (Nic->EapConfig == NULL) || (Profile == NULL)) {\r
90b24889
WF
483 return EFI_INVALID_PARAMETER;\r
484 }\r
d1050b9d 485\r
90b24889
WF
486 EapConfig = Nic->EapConfig;\r
487\r
488 if (Profile->EapAuthMethod >= EAP_AUTH_METHOD_MAX) {\r
489 return EFI_INVALID_PARAMETER;\r
490 }\r
d1050b9d 491\r
90b24889
WF
492 EapAuthMethod = mEapAuthMethod[Profile->EapAuthMethod];\r
493\r
494 if (EapAuthMethod != EFI_EAP_TYPE_EAPTLS) {\r
495 if (Profile->EapSecondAuthMethod >= EAP_SEAUTH_METHOD_MAX) {\r
496 return EFI_INVALID_PARAMETER;\r
497 }\r
d1050b9d 498\r
90b24889
WF
499 EapSecondAuthMethod = mEapSecondAuthMethod[Profile->EapSecondAuthMethod];\r
500 }\r
501\r
502 //\r
d1050b9d 503 // The first time to get Supported Auth Method list, return the size.\r
90b24889 504 //\r
d1050b9d
MK
505 AuthMethodListSize = 0;\r
506 AuthMethodList = NULL;\r
507 Status = EapConfig->GetData (\r
508 EapConfig,\r
509 EFI_EAP_TYPE_ATTRIBUTE,\r
510 EfiEapConfigEapSupportedAuthMethod,\r
511 (VOID *)AuthMethodList,\r
512 &AuthMethodListSize\r
513 );\r
90b24889
WF
514 if (Status == EFI_SUCCESS) {\r
515 //\r
d1050b9d 516 // No Supported Eap Auth Method\r
90b24889
WF
517 //\r
518 return EFI_UNSUPPORTED;\r
519 } else if (Status != EFI_BUFFER_TOO_SMALL) {\r
520 return Status;\r
521 }\r
522\r
523 //\r
524 // The second time to get Supported Auth Method list, return the list.\r
525 // In current design, only EAPTLS, TTLS and PEAP are supported\r
526 //\r
d1050b9d 527 AuthMethodList = (EFI_EAP_TYPE *)AllocateZeroPool (AuthMethodListSize);\r
90b24889
WF
528 if (AuthMethodList == NULL) {\r
529 return EFI_OUT_OF_RESOURCES;\r
530 }\r
d1050b9d
MK
531\r
532 Status = EapConfig->GetData (\r
533 EapConfig,\r
534 EFI_EAP_TYPE_ATTRIBUTE,\r
535 EfiEapConfigEapSupportedAuthMethod,\r
536 (VOID *)AuthMethodList,\r
537 &AuthMethodListSize\r
538 );\r
90b24889
WF
539 if (EFI_ERROR (Status)) {\r
540 FreePool (AuthMethodList);\r
541 return Status;\r
542 }\r
543\r
544 //\r
d1050b9d 545 // Check if EapAuthMethod is in supported Auth Method list, if found, skip the loop.\r
90b24889 546 //\r
d1050b9d 547 for (Index = 0; Index < AuthMethodListSize / sizeof (EFI_EAP_TYPE); Index++) {\r
90b24889
WF
548 if (EapAuthMethod == AuthMethodList[Index]) {\r
549 break;\r
550 }\r
551 }\r
d1050b9d 552\r
90b24889
WF
553 if (Index == AuthMethodListSize / sizeof (EFI_EAP_TYPE)) {\r
554 FreePool (AuthMethodList);\r
555 return EFI_UNSUPPORTED;\r
556 }\r
d1050b9d 557\r
90b24889
WF
558 FreePool (AuthMethodList);\r
559\r
560 //\r
561 // Set Identity to Eap peer, Mandatory field for PEAP and TTLS\r
562 //\r
563 if (StrLen (Profile->EapIdentity) > 0) {\r
d1050b9d
MK
564 IdentitySize = sizeof (CHAR8) * (StrLen (Profile->EapIdentity) + 1);\r
565 Identity = AllocateZeroPool (IdentitySize);\r
90b24889
WF
566 if (Identity == NULL) {\r
567 return EFI_OUT_OF_RESOURCES;\r
568 }\r
d1050b9d
MK
569\r
570 UnicodeStrToAsciiStrS (Profile->EapIdentity, Identity, IdentitySize);\r
571 Status = EapConfig->SetData (\r
572 EapConfig,\r
573 EFI_EAP_TYPE_IDENTITY,\r
574 EfiEapConfigIdentityString,\r
575 (VOID *)Identity,\r
576 IdentitySize - 1\r
577 );\r
578 if (EFI_ERROR (Status)) {\r
90b24889
WF
579 FreePool (Identity);\r
580 return Status;\r
581 }\r
d1050b9d 582\r
90b24889
WF
583 FreePool (Identity);\r
584 } else {\r
585 if (EapAuthMethod != EFI_EAP_TYPE_EAPTLS) {\r
586 return EFI_INVALID_PARAMETER;\r
587 }\r
588 }\r
589\r
590 //\r
d1050b9d 591 // Set Auth Method to Eap peer, Mandatory field\r
90b24889 592 //\r
d1050b9d
MK
593 Status = EapConfig->SetData (\r
594 EapConfig,\r
595 EFI_EAP_TYPE_ATTRIBUTE,\r
596 EfiEapConfigEapAuthMethod,\r
597 (VOID *)&EapAuthMethod,\r
598 sizeof (EapAuthMethod)\r
599 );\r
600 if (EFI_ERROR (Status)) {\r
90b24889
WF
601 return Status;\r
602 }\r
603\r
d1050b9d
MK
604 if ((EapAuthMethod == EFI_EAP_TYPE_TTLS) || (EapAuthMethod == EFI_EAP_TYPE_PEAP)) {\r
605 Status = EapConfig->SetData (\r
606 EapConfig,\r
607 EapAuthMethod,\r
608 EfiEapConfigEap2ndAuthMethod,\r
609 (VOID *)&EapSecondAuthMethod,\r
610 sizeof (EapSecondAuthMethod)\r
611 );\r
612 if (EFI_ERROR (Status)) {\r
90b24889
WF
613 return Status;\r
614 }\r
615\r
616 //\r
617 // Set Password to Eap peer\r
618 //\r
619 if (StrLen (Profile->EapPassword) < PASSWORD_MIN_LEN) {\r
90b24889
WF
620 DEBUG ((DEBUG_ERROR, "[WiFi Connection Manager] Error: No Eap Password for Network: %s.\n", Profile->SSId));\r
621 return EFI_INVALID_PARAMETER;\r
622 }\r
623\r
624 PasswordSize = sizeof (CHAR16) * (StrLen (Profile->EapPassword) + 1);\r
d1050b9d 625 Password = AllocateZeroPool (PasswordSize);\r
90b24889
WF
626 if (Password == NULL) {\r
627 return EFI_OUT_OF_RESOURCES;\r
628 }\r
d1050b9d
MK
629\r
630 StrCpyS (Password, PasswordSize, Profile->EapPassword);\r
631 Status = EapConfig->SetData (\r
632 EapConfig,\r
633 EFI_EAP_TYPE_MSCHAPV2,\r
634 EfiEapConfigEapMSChapV2Password,\r
635 (VOID *)Password,\r
636 PasswordSize\r
637 );\r
90b24889
WF
638 ZeroMem (Password, PasswordSize);\r
639 FreePool (Password);\r
640 if (EFI_ERROR (Status)) {\r
641 return Status;\r
642 }\r
643\r
644 //\r
d1050b9d 645 // If CA cert is required, set it to Eap peer\r
90b24889
WF
646 //\r
647 if (Profile->CACertData != NULL) {\r
d1050b9d
MK
648 Status = EapConfig->SetData (\r
649 EapConfig,\r
650 EapAuthMethod,\r
651 EfiEapConfigEapTlsCACert,\r
652 Profile->CACertData,\r
653 Profile->CACertSize\r
654 );\r
655 if (EFI_ERROR (Status)) {\r
90b24889
WF
656 return Status;\r
657 }\r
658 } else {\r
659 return EFI_INVALID_PARAMETER;\r
660 }\r
661 } else if (EapAuthMethod == EFI_EAP_TYPE_EAPTLS) {\r
90b24889 662 //\r
d1050b9d 663 // Set CA cert to Eap peer\r
90b24889
WF
664 //\r
665 if (Profile->CACertData == NULL) {\r
666 return EFI_INVALID_PARAMETER;\r
667 }\r
d1050b9d
MK
668\r
669 Status = EapConfig->SetData (\r
670 EapConfig,\r
671 EFI_EAP_TYPE_EAPTLS,\r
672 EfiEapConfigEapTlsCACert,\r
673 Profile->CACertData,\r
674 Profile->CACertSize\r
675 );\r
676 if (EFI_ERROR (Status)) {\r
90b24889
WF
677 return Status;\r
678 }\r
679\r
680 //\r
d1050b9d 681 // Set Client cert to Eap peer\r
90b24889
WF
682 //\r
683 if (Profile->ClientCertData == NULL) {\r
684 return EFI_INVALID_PARAMETER;\r
685 }\r
d1050b9d
MK
686\r
687 Status = EapConfig->SetData (\r
688 EapConfig,\r
689 EFI_EAP_TYPE_EAPTLS,\r
690 EfiEapConfigEapTlsClientCert,\r
691 Profile->ClientCertData,\r
692 Profile->ClientCertSize\r
693 );\r
694 if (EFI_ERROR (Status)) {\r
90b24889
WF
695 return Status;\r
696 }\r
697\r
698 //\r
d1050b9d 699 // Set Private key to Eap peer\r
90b24889
WF
700 //\r
701 if (Profile->PrivateKeyData == NULL) {\r
90b24889
WF
702 DEBUG ((DEBUG_ERROR, "[WiFi Connection Manager] Error: No Private Key for Network: %s.\n", Profile->SSId));\r
703 return EFI_INVALID_PARAMETER;\r
704 }\r
705\r
d1050b9d
MK
706 Status = EapConfig->SetData (\r
707 EapConfig,\r
708 EFI_EAP_TYPE_EAPTLS,\r
709 EfiEapConfigEapTlsClientPrivateKeyFile,\r
710 Profile->PrivateKeyData,\r
711 Profile->PrivateKeyDataSize\r
712 );\r
713 if (EFI_ERROR (Status)) {\r
90b24889
WF
714 return Status;\r
715 }\r
716\r
717 if (StrLen (Profile->PrivateKeyPassword) > 0) {\r
d1050b9d
MK
718 EncryptPasswordLen = StrLen (Profile->PrivateKeyPassword);\r
719 AsciiEncryptPassword = AllocateZeroPool (EncryptPasswordLen + 1);\r
90b24889
WF
720 if (AsciiEncryptPassword == NULL) {\r
721 return EFI_OUT_OF_RESOURCES;\r
722 }\r
90b24889 723\r
d1050b9d
MK
724 UnicodeStrToAsciiStrS (Profile->PrivateKeyPassword, AsciiEncryptPassword, EncryptPasswordLen + 1);\r
725 Status = EapConfig->SetData (\r
726 EapConfig,\r
727 EFI_EAP_TYPE_EAPTLS,\r
728 EfiEapConfigEapTlsClientPrivateKeyFilePassword,\r
729 (VOID *)AsciiEncryptPassword,\r
730 EncryptPasswordLen + 1\r
731 );\r
732 if (EFI_ERROR (Status)) {\r
90b24889
WF
733 ZeroMem (AsciiEncryptPassword, EncryptPasswordLen + 1);\r
734 FreePool (AsciiEncryptPassword);\r
735 return Status;\r
736 }\r
737\r
738 ZeroMem (AsciiEncryptPassword, EncryptPasswordLen + 1);\r
739 FreePool (AsciiEncryptPassword);\r
740 }\r
741 } else {\r
742 return EFI_INVALID_PARAMETER;\r
743 }\r
744\r
745 return EFI_SUCCESS;\r
746}\r
747\r
748/**\r
749 Get current link state from low layer.\r
750\r
751 @param[in] Nic Pointer to the device data of the selected NIC.\r
752 @param[out] LinkState The pointer to buffer to retrieve link state.\r
753\r
754 @retval EFI_SUCCESS The operation is completed.\r
755 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
756 @retval EFI_UNSUPPORTED Adapter information protocol is not supported.\r
757 @retval Other Errors Returned errors when retrieving link state from low layer.\r
758\r
759**/\r
760EFI_STATUS\r
761WifiMgrGetLinkState (\r
d1050b9d
MK
762 IN WIFI_MGR_DEVICE_DATA *Nic,\r
763 OUT EFI_ADAPTER_INFO_MEDIA_STATE *LinkState\r
90b24889
WF
764 )\r
765{\r
d1050b9d
MK
766 EFI_STATUS Status;\r
767 EFI_TPL OldTpl;\r
768 UINTN DataSize;\r
769 EFI_ADAPTER_INFO_MEDIA_STATE *UndiState;\r
770 EFI_ADAPTER_INFORMATION_PROTOCOL *Aip;\r
90b24889 771\r
d1050b9d 772 if ((Nic == NULL) || (LinkState == NULL)) {\r
90b24889
WF
773 return EFI_INVALID_PARAMETER;\r
774 }\r
775\r
776 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
777 Status = gBS->OpenProtocol (\r
778 Nic->ControllerHandle,\r
779 &gEfiAdapterInformationProtocolGuid,\r
d1050b9d 780 (VOID **)&Aip,\r
90b24889
WF
781 Nic->DriverHandle,\r
782 Nic->ControllerHandle,\r
783 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
784 );\r
785 if (EFI_ERROR (Status)) {\r
786 gBS->RestoreTPL (OldTpl);\r
787 return EFI_UNSUPPORTED;\r
788 }\r
789\r
d1050b9d 790 Status = Aip->GetInformation (\r
90b24889
WF
791 Aip,\r
792 &gEfiAdapterInfoMediaStateGuid,\r
d1050b9d 793 (VOID **)&UndiState,\r
90b24889
WF
794 &DataSize\r
795 );\r
796 if (EFI_ERROR (Status)) {\r
797 gBS->RestoreTPL (OldTpl);\r
798 return Status;\r
799 }\r
d1050b9d 800\r
90b24889
WF
801 gBS->RestoreTPL (OldTpl);\r
802\r
803 CopyMem (LinkState, UndiState, sizeof (EFI_ADAPTER_INFO_MEDIA_STATE));\r
804 FreePool (UndiState);\r
805 return EFI_SUCCESS;\r
806}\r
807\r
808/**\r
809 Prepare configuration work before connecting to the target network.\r
810 For WPA2 Personal networks, password should be checked; and for EAP networks, parameters\r
811 are different for different networks.\r
812\r
813 @param[in] Nic Pointer to the device data of the selected NIC.\r
814 @param[in] Profile The target network to be connected.\r
815\r
816 @retval EFI_SUCCESS The operation is completed.\r
817 @retval EFI_UNSUPPORTED This network is not supported.\r
818 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
819\r
820**/\r
821EFI_STATUS\r
822WifiMgrPrepareConnection (\r
d1050b9d
MK
823 IN WIFI_MGR_DEVICE_DATA *Nic,\r
824 IN WIFI_MGR_NETWORK_PROFILE *Profile\r
90b24889
WF
825 )\r
826{\r
d1050b9d
MK
827 EFI_STATUS Status;\r
828 UINT8 SecurityType;\r
829 BOOLEAN AKMSuiteSupported;\r
830 BOOLEAN CipherSuiteSupported;\r
90b24889 831\r
d1050b9d 832 if ((Profile == NULL) || (Nic == NULL)) {\r
90b24889
WF
833 return EFI_INVALID_PARAMETER;\r
834 }\r
835\r
d1050b9d
MK
836 Status = WifiMgrCheckRSN (\r
837 Profile->Network.AKMSuite,\r
838 Profile->Network.CipherSuite,\r
839 Nic,\r
840 &SecurityType,\r
841 &AKMSuiteSupported,\r
842 &CipherSuiteSupported\r
843 );\r
90b24889
WF
844 if (EFI_ERROR (Status)) {\r
845 return Status;\r
846 }\r
847\r
848 if (AKMSuiteSupported && CipherSuiteSupported) {\r
849 switch (SecurityType) {\r
850 case SECURITY_TYPE_WPA2_PERSONAL:\r
851\r
852 Status = WifiMgrConfigPassword (Nic, Profile);\r
853 if (EFI_ERROR (Status)) {\r
854 if (Status == EFI_NOT_FOUND) {\r
855 if (Nic->OneTimeConnectRequest) {\r
856 WifiMgrUpdateConnectMessage (Nic, FALSE, L"Connect Failed: Invalid Password!");\r
857 }\r
858 }\r
d1050b9d 859\r
90b24889
WF
860 return Status;\r
861 }\r
d1050b9d 862\r
90b24889
WF
863 break;\r
864\r
865 case SECURITY_TYPE_WPA2_ENTERPRISE:\r
866\r
867 Status = WifiMgrConfigEap (Nic, Profile);\r
868 if (EFI_ERROR (Status)) {\r
869 if (Status == EFI_INVALID_PARAMETER) {\r
870 if (Nic->OneTimeConnectRequest) {\r
871 WifiMgrUpdateConnectMessage (Nic, FALSE, L"Connect Failed: Invalid Configuration!");\r
872 }\r
873 }\r
d1050b9d 874\r
90b24889
WF
875 return Status;\r
876 }\r
d1050b9d 877\r
90b24889
WF
878 break;\r
879\r
880 case SECURITY_TYPE_NONE:\r
881 break;\r
882\r
883 default:\r
884 return EFI_UNSUPPORTED;\r
885 }\r
886 } else {\r
887 return EFI_UNSUPPORTED;\r
888 }\r
889\r
890 return EFI_SUCCESS;\r
891}\r
892\r
893/**\r
894 The callback function for connect operation.\r
895\r
896 ASSERT when errors occur in config token.\r
897\r
898 @param[in] Event The Connect token receive event.\r
899 @param[in] Context The context of the connect token.\r
900\r
901**/\r
902VOID\r
903EFIAPI\r
904WifiMgrOnConnectFinished (\r
d1050b9d
MK
905 IN EFI_EVENT Event,\r
906 IN VOID *Context\r
90b24889
WF
907 )\r
908{\r
d1050b9d
MK
909 EFI_STATUS Status;\r
910 WIFI_MGR_MAC_CONFIG_TOKEN *ConfigToken;\r
911 WIFI_MGR_NETWORK_PROFILE *ConnectedProfile;\r
912 UINT8 SecurityType;\r
913 UINT8 SSIdLen;\r
914 CHAR8 *AsciiSSId;\r
90b24889
WF
915\r
916 ASSERT (Context != NULL);\r
917\r
918 ConnectedProfile = NULL;\r
d1050b9d 919 ConfigToken = (WIFI_MGR_MAC_CONFIG_TOKEN *)Context;\r
90b24889
WF
920 ASSERT (ConfigToken->Nic != NULL);\r
921\r
922 ConfigToken->Nic->ConnectState = WifiMgrDisconnected;\r
923 ASSERT (ConfigToken->Type == TokenTypeConnectNetworkToken);\r
924\r
925 ASSERT (ConfigToken->Token.ConnectNetworkToken != NULL);\r
926 if (ConfigToken->Token.ConnectNetworkToken->Status != EFI_SUCCESS) {\r
90b24889
WF
927 if (ConfigToken->Nic->OneTimeConnectRequest) {\r
928 //\r
929 // Only update message for user triggered connection\r
930 //\r
931 if (ConfigToken->Token.ConnectNetworkToken->Status == EFI_ACCESS_DENIED) {\r
90b24889
WF
932 WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, L"Connect Failed: Permission Denied!");\r
933 } else {\r
934 WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, L"Connect Failed!");\r
935 }\r
d1050b9d 936\r
90b24889
WF
937 ConfigToken->Nic->OneTimeConnectRequest = FALSE;\r
938 }\r
d1050b9d 939\r
90b24889
WF
940 ConfigToken->Nic->CurrentOperateNetwork = NULL;\r
941 return;\r
942 }\r
943\r
944 if (ConfigToken->Token.ConnectNetworkToken->ResultCode != ConnectSuccess) {\r
90b24889 945 if (ConfigToken->Nic->OneTimeConnectRequest) {\r
90b24889
WF
946 if (ConfigToken->Token.ConnectNetworkToken->ResultCode == ConnectFailedReasonUnspecified) {\r
947 WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, L"Connect Failed: Wrong Password or Unexpected Error!");\r
948 } else {\r
949 WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, L"Connect Failed!");\r
950 }\r
951 }\r
d1050b9d 952\r
90b24889
WF
953 goto Exit;\r
954 }\r
955\r
d1050b9d
MK
956 if ((ConfigToken->Token.ConnectNetworkToken->Data == NULL) ||\r
957 (ConfigToken->Token.ConnectNetworkToken->Data->Network == NULL))\r
958 {\r
90b24889
WF
959 //\r
960 // An unexpected error occurs, tell low layer to perform a disconnect\r
961 //\r
962 ConfigToken->Nic->HasDisconnectPendingNetwork = TRUE;\r
963 WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, NULL);\r
964 goto Exit;\r
965 }\r
966\r
967 //\r
968 // A correct connect token received, terminate the connection process\r
969 //\r
d1050b9d
MK
970 Status = WifiMgrCheckRSN (\r
971 ConfigToken->Token.ConnectNetworkToken->Data->Network->AKMSuite,\r
90b24889 972 ConfigToken->Token.ConnectNetworkToken->Data->Network->CipherSuite,\r
d1050b9d
MK
973 ConfigToken->Nic,\r
974 &SecurityType,\r
975 NULL,\r
976 NULL\r
977 );\r
978 if (EFI_ERROR (Status)) {\r
90b24889
WF
979 SecurityType = SECURITY_TYPE_UNKNOWN;\r
980 }\r
981\r
982 SSIdLen = ConfigToken->Token.ConnectNetworkToken->Data->Network->SSId.SSIdLen;\r
d1050b9d 983 AsciiSSId = (CHAR8 *)AllocateZeroPool (sizeof (CHAR8) * (SSIdLen + 1));\r
90b24889
WF
984 if (AsciiSSId == NULL) {\r
985 ConfigToken->Nic->HasDisconnectPendingNetwork = TRUE;\r
986 WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, NULL);\r
987 goto Exit;\r
988 }\r
989\r
d1050b9d 990 CopyMem (AsciiSSId, ConfigToken->Token.ConnectNetworkToken->Data->Network->SSId.SSId, SSIdLen);\r
90b24889
WF
991 *(AsciiSSId + SSIdLen) = '\0';\r
992\r
d1050b9d
MK
993 ConnectedProfile = WifiMgrGetProfileByAsciiSSId (AsciiSSId, SecurityType, &ConfigToken->Nic->ProfileList);\r
994 FreePool (AsciiSSId);\r
90b24889
WF
995 if (ConnectedProfile == NULL) {\r
996 ConfigToken->Nic->HasDisconnectPendingNetwork = TRUE;\r
997 WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, NULL);\r
998 goto Exit;\r
999 }\r
1000\r
1001 ConfigToken->Nic->ConnectState = WifiMgrConnectedToAp;\r
1002 WifiMgrUpdateConnectMessage (ConfigToken->Nic, TRUE, NULL);\r
1003\r
1004Exit:\r
1005\r
1006 if (ConfigToken->Nic->ConnectState == WifiMgrDisconnected) {\r
1007 ConfigToken->Nic->CurrentOperateNetwork = NULL;\r
1008 }\r
d1050b9d 1009\r
90b24889 1010 ConfigToken->Nic->OneTimeConnectRequest = FALSE;\r
d1050b9d 1011 WifiMgrFreeToken (ConfigToken);\r
90b24889
WF
1012}\r
1013\r
1014/**\r
1015 Start connect operation, and send out a token to connect to a target network.\r
1016\r
1017 @param[in] Nic Pointer to the device data of the selected NIC.\r
1018 @param[in] Profile The target network to be connected.\r
1019\r
1020 @retval EFI_SUCCESS The operation is completed.\r
1021 @retval EFI_ALREADY_STARTED Already in "connected" state, need to perform a disconnect\r
1022 operation first.\r
1023 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
1024 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
1025 @retval Other Errors Return errors when connecting network on low layer.\r
1026\r
1027**/\r
1028EFI_STATUS\r
1029WifiMgrConnectToNetwork (\r
d1050b9d
MK
1030 IN WIFI_MGR_DEVICE_DATA *Nic,\r
1031 IN WIFI_MGR_NETWORK_PROFILE *Profile\r
90b24889
WF
1032 )\r
1033{\r
d1050b9d
MK
1034 EFI_STATUS Status;\r
1035 EFI_TPL OldTpl;\r
1036 EFI_ADAPTER_INFO_MEDIA_STATE LinkState;\r
1037 WIFI_MGR_MAC_CONFIG_TOKEN *ConfigToken;\r
1038 EFI_80211_CONNECT_NETWORK_TOKEN *ConnectToken;\r
90b24889 1039\r
d1050b9d 1040 if ((Nic == NULL) || (Nic->Wmp == NULL) || (Profile == NULL)) {\r
90b24889
WF
1041 return EFI_INVALID_PARAMETER;\r
1042 }\r
1043\r
1044 Status = WifiMgrGetLinkState (Nic, &LinkState);\r
1045 if (EFI_ERROR (Status)) {\r
1046 return Status;\r
1047 }\r
d1050b9d 1048\r
90b24889
WF
1049 if (LinkState.MediaState == EFI_SUCCESS) {\r
1050 return EFI_ALREADY_STARTED;\r
1051 }\r
1052\r
1053 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1054 Status = WifiMgrPrepareConnection (Nic, Profile);\r
1055 if (EFI_ERROR (Status)) {\r
1056 gBS->RestoreTPL (OldTpl);\r
1057 return Status;\r
1058 }\r
1059\r
1060 //\r
1061 // Create a new connect token\r
1062 //\r
1063 ConfigToken = AllocateZeroPool (sizeof (WIFI_MGR_MAC_CONFIG_TOKEN));\r
1064 if (ConfigToken == NULL) {\r
1065 Status = EFI_OUT_OF_RESOURCES;\r
1066 goto Exit;\r
1067 }\r
1068\r
d1050b9d
MK
1069 ConfigToken->Type = TokenTypeConnectNetworkToken;\r
1070 ConfigToken->Nic = Nic;\r
1071 ConfigToken->Token.ConnectNetworkToken = AllocateZeroPool (sizeof (EFI_80211_CONNECT_NETWORK_TOKEN));\r
90b24889
WF
1072 if (ConfigToken->Token.ConnectNetworkToken == NULL) {\r
1073 goto Exit;\r
1074 }\r
1075\r
d1050b9d
MK
1076 ConnectToken = ConfigToken->Token.ConnectNetworkToken;\r
1077 ConnectToken->Data = AllocateZeroPool (sizeof (EFI_80211_CONNECT_NETWORK_DATA));\r
90b24889
WF
1078 if (ConnectToken->Data == NULL) {\r
1079 goto Exit;\r
1080 }\r
1081\r
1082 ConnectToken->Data->Network = AllocateZeroPool (sizeof (EFI_80211_NETWORK));\r
1083 if (ConnectToken->Data->Network == NULL) {\r
1084 goto Exit;\r
1085 }\r
d1050b9d
MK
1086\r
1087 CopyMem (ConnectToken->Data->Network, &Profile->Network, sizeof (EFI_80211_NETWORK));\r
90b24889
WF
1088\r
1089 //\r
1090 // Add event handle and start to connect\r
1091 //\r
1092 Status = gBS->CreateEvent (\r
1093 EVT_NOTIFY_SIGNAL,\r
1094 TPL_CALLBACK,\r
1095 WifiMgrOnConnectFinished,\r
1096 ConfigToken,\r
1097 &ConnectToken->Event\r
1098 );\r
1099 if (EFI_ERROR (Status)) {\r
1100 goto Exit;\r
1101 }\r
1102\r
d1050b9d 1103 Nic->ConnectState = WifiMgrConnectingToAp;\r
90b24889
WF
1104 Nic->CurrentOperateNetwork = Profile;\r
1105 WifiMgrUpdateConnectMessage (Nic, FALSE, NULL);\r
1106\r
1107 //\r
d1050b9d 1108 // Start Connecting ...\r
90b24889
WF
1109 //\r
1110 Status = Nic->Wmp->ConnectNetwork (Nic->Wmp, ConnectToken);\r
1111\r
1112 //\r
1113 // Erase secrets after connection is triggered\r
1114 //\r
1115 WifiMgrCleanProfileSecrets (Profile);\r
1116\r
1117 if (EFI_ERROR (Status)) {\r
1118 if (Status == EFI_ALREADY_STARTED) {\r
1119 Nic->ConnectState = WifiMgrConnectedToAp;\r
1120 WifiMgrUpdateConnectMessage (Nic, TRUE, NULL);\r
1121 } else {\r
90b24889
WF
1122 Nic->ConnectState = WifiMgrDisconnected;\r
1123 Nic->CurrentOperateNetwork = NULL;\r
1124\r
1125 if (Nic->OneTimeConnectRequest) {\r
1126 if (Status == EFI_NOT_FOUND) {\r
1127 WifiMgrUpdateConnectMessage (Nic, FALSE, L"Connect Failed: Not Available!");\r
1128 } else {\r
1129 WifiMgrUpdateConnectMessage (Nic, FALSE, L"Connect Failed: Unexpected Error!");\r
1130 }\r
1131 }\r
1132 }\r
d1050b9d 1133\r
90b24889
WF
1134 goto Exit;\r
1135 }\r
1136\r
1137Exit:\r
1138\r
1139 if (EFI_ERROR (Status)) {\r
1140 WifiMgrFreeToken (ConfigToken);\r
1141 }\r
d1050b9d 1142\r
90b24889
WF
1143 gBS->RestoreTPL (OldTpl);\r
1144\r
1145 DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] WifiMgrConnectToNetwork: %r\n", Status));\r
1146 return Status;\r
1147}\r
1148\r
1149/**\r
1150 The callback function for disconnect operation.\r
1151\r
1152 ASSERT when errors occur in config token.\r
1153\r
1154 @param[in] Event The Disconnect token receive event.\r
1155 @param[in] Context The context of the Disconnect token.\r
1156\r
1157**/\r
1158VOID\r
1159EFIAPI\r
1160WifiMgrOnDisconnectFinished (\r
d1050b9d
MK
1161 IN EFI_EVENT Event,\r
1162 IN VOID *Context\r
90b24889
WF
1163 )\r
1164{\r
d1050b9d 1165 WIFI_MGR_MAC_CONFIG_TOKEN *ConfigToken;\r
90b24889
WF
1166\r
1167 ASSERT (Context != NULL);\r
1168\r
d1050b9d 1169 ConfigToken = (WIFI_MGR_MAC_CONFIG_TOKEN *)Context;\r
90b24889
WF
1170 ASSERT (ConfigToken->Nic != NULL);\r
1171 ASSERT (ConfigToken->Type == TokenTypeDisconnectNetworkToken);\r
1172\r
1173 ASSERT (ConfigToken->Token.DisconnectNetworkToken != NULL);\r
1174 if (ConfigToken->Token.DisconnectNetworkToken->Status != EFI_SUCCESS) {\r
d1050b9d 1175 ConfigToken->Nic->ConnectState = WifiMgrConnectedToAp;\r
90b24889
WF
1176 WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, NULL);\r
1177 ConfigToken->Nic->OneTimeDisconnectRequest = FALSE;\r
1178 goto Exit;\r
1179 }\r
1180\r
1181 ConfigToken->Nic->ConnectState = WifiMgrDisconnected;\r
1182 ConfigToken->Nic->CurrentOperateNetwork = NULL;\r
1183 WifiMgrUpdateConnectMessage (ConfigToken->Nic, TRUE, NULL);\r
1184 ConfigToken->Nic->OneTimeDisconnectRequest = FALSE;\r
1185\r
1186 //\r
1187 // Disconnected network may not be in network list now, trigger a scan again!\r
1188 //\r
d1050b9d 1189 ConfigToken->Nic->OneTimeScanRequest = TRUE;\r
90b24889 1190\r
d1050b9d
MK
1191Exit:\r
1192 WifiMgrFreeToken (ConfigToken);\r
1193 return;\r
90b24889
WF
1194}\r
1195\r
1196/**\r
1197 Start disconnect operation, and send out a token to disconnect from current connected\r
1198 network.\r
1199\r
1200 @param[in] Nic Pointer to the device data of the selected NIC.\r
1201\r
1202 @retval EFI_SUCCESS The operation is completed.\r
1203 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
1204 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
1205 @retval Other Errors Return errors when disconnecting a network on low layer.\r
1206\r
1207**/\r
1208EFI_STATUS\r
1209WifiMgrDisconnectToNetwork (\r
d1050b9d 1210 IN WIFI_MGR_DEVICE_DATA *Nic\r
90b24889
WF
1211 )\r
1212{\r
d1050b9d
MK
1213 EFI_STATUS Status;\r
1214 EFI_TPL OldTpl;\r
1215 WIFI_MGR_MAC_CONFIG_TOKEN *ConfigToken;\r
1216 EFI_80211_DISCONNECT_NETWORK_TOKEN *DisconnectToken;\r
90b24889
WF
1217\r
1218 if (Nic == NULL) {\r
1219 return EFI_INVALID_PARAMETER;\r
1220 }\r
1221\r
1222 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1223 Status = EFI_SUCCESS;\r
1224 ConfigToken = AllocateZeroPool (sizeof (WIFI_MGR_MAC_CONFIG_TOKEN));\r
1225 if (ConfigToken == NULL) {\r
1226 gBS->RestoreTPL (OldTpl);\r
1227 return EFI_OUT_OF_RESOURCES;\r
1228 }\r
1229\r
d1050b9d
MK
1230 ConfigToken->Type = TokenTypeDisconnectNetworkToken;\r
1231 ConfigToken->Nic = Nic;\r
90b24889
WF
1232 ConfigToken->Token.DisconnectNetworkToken = AllocateZeroPool (sizeof (EFI_80211_DISCONNECT_NETWORK_TOKEN));\r
1233 if (ConfigToken->Token.DisconnectNetworkToken == NULL) {\r
d1050b9d 1234 WifiMgrFreeToken (ConfigToken);\r
90b24889
WF
1235 gBS->RestoreTPL (OldTpl);\r
1236 return EFI_OUT_OF_RESOURCES;\r
1237 }\r
1238\r
1239 DisconnectToken = ConfigToken->Token.DisconnectNetworkToken;\r
1240\r
1241 Status = gBS->CreateEvent (\r
1242 EVT_NOTIFY_SIGNAL,\r
1243 TPL_CALLBACK,\r
1244 WifiMgrOnDisconnectFinished,\r
1245 ConfigToken,\r
1246 &DisconnectToken->Event\r
1247 );\r
1248 if (EFI_ERROR (Status)) {\r
d1050b9d 1249 WifiMgrFreeToken (ConfigToken);\r
90b24889
WF
1250 gBS->RestoreTPL (OldTpl);\r
1251 return Status;\r
1252 }\r
1253\r
1254 Nic->ConnectState = WifiMgrDisconnectingToAp;\r
1255 WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, NULL);\r
1256\r
1257 Status = Nic->Wmp->DisconnectNetwork (Nic->Wmp, DisconnectToken);\r
1258 if (EFI_ERROR (Status)) {\r
1259 if (Status == EFI_NOT_FOUND) {\r
90b24889
WF
1260 Nic->ConnectState = WifiMgrDisconnected;\r
1261 Nic->CurrentOperateNetwork = NULL;\r
1262\r
1263 //\r
1264 // This network is not in network list now, trigger a scan again!\r
1265 //\r
d1050b9d 1266 Nic->OneTimeScanRequest = TRUE;\r
90b24889
WF
1267\r
1268 //\r
1269 // State has been changed from Connected to Disconnected\r
1270 //\r
1271 WifiMgrUpdateConnectMessage (ConfigToken->Nic, TRUE, NULL);\r
d1050b9d 1272 Status = EFI_SUCCESS;\r
90b24889
WF
1273 } else {\r
1274 if (Nic->OneTimeDisconnectRequest) {\r
90b24889
WF
1275 WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, L"Disconnect Failed: Unexpected Error!");\r
1276 }\r
1277\r
d1050b9d 1278 Nic->ConnectState = WifiMgrConnectedToAp;\r
90b24889
WF
1279 WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, NULL);\r
1280 }\r
d1050b9d
MK
1281\r
1282 WifiMgrFreeToken (ConfigToken);\r
90b24889
WF
1283 }\r
1284\r
1285 gBS->RestoreTPL (OldTpl);\r
1286 return Status;\r
1287}\r
1288\r
1289/**\r
1290 The state machine of the connection manager, periodically check the state and\r
1291 perform a corresponding operation.\r
1292\r
1293 @param[in] Event The timer event to be triggered.\r
1294 @param[in] Context The context of the Nic device data.\r
1295\r
1296**/\r
1297VOID\r
1298EFIAPI\r
1299WifiMgrOnTimerTick (\r
d1050b9d
MK
1300 IN EFI_EVENT Event,\r
1301 IN VOID *Context\r
90b24889
WF
1302 )\r
1303{\r
d1050b9d
MK
1304 WIFI_MGR_DEVICE_DATA *Nic;\r
1305 EFI_STATUS Status;\r
1306 EFI_ADAPTER_INFO_MEDIA_STATE LinkState;\r
1307 WIFI_MGR_NETWORK_PROFILE *Profile;\r
90b24889
WF
1308\r
1309 if (Context == NULL) {\r
1310 return;\r
1311 }\r
1312\r
d1050b9d 1313 Nic = (WIFI_MGR_DEVICE_DATA *)Context;\r
90b24889
WF
1314 NET_CHECK_SIGNATURE (Nic, WIFI_MGR_DEVICE_DATA_SIGNATURE);\r
1315\r
1316 Status = WifiMgrGetLinkState (Nic, &LinkState);\r
1317 if (EFI_ERROR (Status)) {\r
1318 DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] Error: Failed to get link state!\n"));\r
1319 return;\r
1320 }\r
1321\r
1322 if (Nic->LastLinkState.MediaState != LinkState.MediaState) {\r
d1050b9d 1323 if ((Nic->LastLinkState.MediaState == EFI_SUCCESS) && (LinkState.MediaState == EFI_NO_MEDIA)) {\r
90b24889
WF
1324 Nic->HasDisconnectPendingNetwork = TRUE;\r
1325 }\r
d1050b9d 1326\r
90b24889
WF
1327 Nic->LastLinkState.MediaState = LinkState.MediaState;\r
1328 }\r
1329\r
d1050b9d
MK
1330 Nic->ScanTickTime++;\r
1331 if (((Nic->ScanTickTime > WIFI_SCAN_FREQUENCY) || Nic->OneTimeScanRequest) &&\r
1332 (Nic->ScanState == WifiMgrScanFinished))\r
1333 {\r
90b24889 1334 Nic->OneTimeScanRequest = FALSE;\r
d1050b9d 1335 Nic->ScanTickTime = 0;\r
90b24889
WF
1336\r
1337 DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] Scan is triggered.\n"));\r
1338 WifiMgrStartScan (Nic);\r
1339 }\r
1340\r
d1050b9d 1341 if ((Nic->AvailableCount > 0) && (Nic->ScanState == WifiMgrScanFinished)) {\r
90b24889 1342 switch (Nic->ConnectState) {\r
d1050b9d 1343 case WifiMgrDisconnected:\r
90b24889 1344\r
d1050b9d
MK
1345 if (Nic->HasDisconnectPendingNetwork) {\r
1346 Nic->HasDisconnectPendingNetwork = FALSE;\r
1347 }\r
90b24889 1348\r
d1050b9d
MK
1349 if (Nic->ConnectPendingNetwork != NULL) {\r
1350 Profile = Nic->ConnectPendingNetwork;\r
1351 Status = WifiMgrConnectToNetwork (Nic, Profile);\r
1352 Nic->ConnectPendingNetwork = NULL;\r
1353 if (EFI_ERROR (Status)) {\r
1354 //\r
1355 // Some error happened, don't wait for a return connect token!\r
1356 //\r
1357 Nic->OneTimeConnectRequest = FALSE;\r
1358 }\r
90b24889 1359 }\r
90b24889 1360\r
d1050b9d 1361 break;\r
90b24889 1362\r
d1050b9d
MK
1363 case WifiMgrConnectingToAp:\r
1364 break;\r
90b24889 1365\r
d1050b9d
MK
1366 case WifiMgrDisconnectingToAp:\r
1367 break;\r
90b24889 1368\r
d1050b9d 1369 case WifiMgrConnectedToAp:\r
90b24889 1370\r
d1050b9d
MK
1371 if ((Nic->ConnectPendingNetwork != NULL) || Nic->HasDisconnectPendingNetwork) {\r
1372 Status = WifiMgrDisconnectToNetwork (Nic);\r
1373 if (EFI_ERROR (Status)) {\r
1374 //\r
1375 // Some error happened, don't wait for a return disconnect token!\r
1376 //\r
1377 Nic->OneTimeDisconnectRequest = FALSE;\r
1378 }\r
90b24889 1379 }\r
90b24889 1380\r
d1050b9d
MK
1381 break;\r
1382\r
1383 default:\r
1384 break;\r
90b24889
WF
1385 }\r
1386 }\r
1387}\r