]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrImpl.c
.azurepipelines: Add IntelFsp2Pkg and IntelFsp2WrapperPkg to CI
[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
e1eef3a8 4 Copyright (c) 2019 - 2022, Intel Corporation. All rights reserved.<BR>\r
90b24889 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
e1eef3a8 851 case SECURITY_TYPE_WPA3_PERSONAL:\r
90b24889
WF
852\r
853 Status = WifiMgrConfigPassword (Nic, Profile);\r
854 if (EFI_ERROR (Status)) {\r
855 if (Status == EFI_NOT_FOUND) {\r
856 if (Nic->OneTimeConnectRequest) {\r
857 WifiMgrUpdateConnectMessage (Nic, FALSE, L"Connect Failed: Invalid Password!");\r
858 }\r
859 }\r
d1050b9d 860\r
90b24889
WF
861 return Status;\r
862 }\r
d1050b9d 863\r
90b24889
WF
864 break;\r
865\r
866 case SECURITY_TYPE_WPA2_ENTERPRISE:\r
e1eef3a8 867 case SECURITY_TYPE_WPA3_ENTERPRISE:\r
90b24889
WF
868\r
869 Status = WifiMgrConfigEap (Nic, Profile);\r
870 if (EFI_ERROR (Status)) {\r
871 if (Status == EFI_INVALID_PARAMETER) {\r
872 if (Nic->OneTimeConnectRequest) {\r
873 WifiMgrUpdateConnectMessage (Nic, FALSE, L"Connect Failed: Invalid Configuration!");\r
874 }\r
875 }\r
d1050b9d 876\r
90b24889
WF
877 return Status;\r
878 }\r
d1050b9d 879\r
90b24889
WF
880 break;\r
881\r
882 case SECURITY_TYPE_NONE:\r
883 break;\r
884\r
885 default:\r
886 return EFI_UNSUPPORTED;\r
887 }\r
888 } else {\r
889 return EFI_UNSUPPORTED;\r
890 }\r
891\r
892 return EFI_SUCCESS;\r
893}\r
894\r
895/**\r
896 The callback function for connect operation.\r
897\r
898 ASSERT when errors occur in config token.\r
899\r
900 @param[in] Event The Connect token receive event.\r
901 @param[in] Context The context of the connect token.\r
902\r
903**/\r
904VOID\r
905EFIAPI\r
906WifiMgrOnConnectFinished (\r
d1050b9d
MK
907 IN EFI_EVENT Event,\r
908 IN VOID *Context\r
90b24889
WF
909 )\r
910{\r
d1050b9d
MK
911 EFI_STATUS Status;\r
912 WIFI_MGR_MAC_CONFIG_TOKEN *ConfigToken;\r
913 WIFI_MGR_NETWORK_PROFILE *ConnectedProfile;\r
914 UINT8 SecurityType;\r
915 UINT8 SSIdLen;\r
916 CHAR8 *AsciiSSId;\r
90b24889
WF
917\r
918 ASSERT (Context != NULL);\r
919\r
920 ConnectedProfile = NULL;\r
d1050b9d 921 ConfigToken = (WIFI_MGR_MAC_CONFIG_TOKEN *)Context;\r
90b24889
WF
922 ASSERT (ConfigToken->Nic != NULL);\r
923\r
924 ConfigToken->Nic->ConnectState = WifiMgrDisconnected;\r
925 ASSERT (ConfigToken->Type == TokenTypeConnectNetworkToken);\r
926\r
927 ASSERT (ConfigToken->Token.ConnectNetworkToken != NULL);\r
928 if (ConfigToken->Token.ConnectNetworkToken->Status != EFI_SUCCESS) {\r
90b24889
WF
929 if (ConfigToken->Nic->OneTimeConnectRequest) {\r
930 //\r
931 // Only update message for user triggered connection\r
932 //\r
933 if (ConfigToken->Token.ConnectNetworkToken->Status == EFI_ACCESS_DENIED) {\r
90b24889
WF
934 WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, L"Connect Failed: Permission Denied!");\r
935 } else {\r
936 WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, L"Connect Failed!");\r
937 }\r
d1050b9d 938\r
90b24889
WF
939 ConfigToken->Nic->OneTimeConnectRequest = FALSE;\r
940 }\r
d1050b9d 941\r
90b24889
WF
942 ConfigToken->Nic->CurrentOperateNetwork = NULL;\r
943 return;\r
944 }\r
945\r
946 if (ConfigToken->Token.ConnectNetworkToken->ResultCode != ConnectSuccess) {\r
90b24889 947 if (ConfigToken->Nic->OneTimeConnectRequest) {\r
90b24889
WF
948 if (ConfigToken->Token.ConnectNetworkToken->ResultCode == ConnectFailedReasonUnspecified) {\r
949 WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, L"Connect Failed: Wrong Password or Unexpected Error!");\r
950 } else {\r
951 WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, L"Connect Failed!");\r
952 }\r
953 }\r
d1050b9d 954\r
90b24889
WF
955 goto Exit;\r
956 }\r
957\r
d1050b9d
MK
958 if ((ConfigToken->Token.ConnectNetworkToken->Data == NULL) ||\r
959 (ConfigToken->Token.ConnectNetworkToken->Data->Network == NULL))\r
960 {\r
90b24889
WF
961 //\r
962 // An unexpected error occurs, tell low layer to perform a disconnect\r
963 //\r
964 ConfigToken->Nic->HasDisconnectPendingNetwork = TRUE;\r
965 WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, NULL);\r
966 goto Exit;\r
967 }\r
968\r
969 //\r
970 // A correct connect token received, terminate the connection process\r
971 //\r
d1050b9d
MK
972 Status = WifiMgrCheckRSN (\r
973 ConfigToken->Token.ConnectNetworkToken->Data->Network->AKMSuite,\r
90b24889 974 ConfigToken->Token.ConnectNetworkToken->Data->Network->CipherSuite,\r
d1050b9d
MK
975 ConfigToken->Nic,\r
976 &SecurityType,\r
977 NULL,\r
978 NULL\r
979 );\r
980 if (EFI_ERROR (Status)) {\r
90b24889
WF
981 SecurityType = SECURITY_TYPE_UNKNOWN;\r
982 }\r
983\r
984 SSIdLen = ConfigToken->Token.ConnectNetworkToken->Data->Network->SSId.SSIdLen;\r
d1050b9d 985 AsciiSSId = (CHAR8 *)AllocateZeroPool (sizeof (CHAR8) * (SSIdLen + 1));\r
90b24889
WF
986 if (AsciiSSId == NULL) {\r
987 ConfigToken->Nic->HasDisconnectPendingNetwork = TRUE;\r
988 WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, NULL);\r
989 goto Exit;\r
990 }\r
991\r
d1050b9d 992 CopyMem (AsciiSSId, ConfigToken->Token.ConnectNetworkToken->Data->Network->SSId.SSId, SSIdLen);\r
90b24889
WF
993 *(AsciiSSId + SSIdLen) = '\0';\r
994\r
d1050b9d
MK
995 ConnectedProfile = WifiMgrGetProfileByAsciiSSId (AsciiSSId, SecurityType, &ConfigToken->Nic->ProfileList);\r
996 FreePool (AsciiSSId);\r
90b24889
WF
997 if (ConnectedProfile == NULL) {\r
998 ConfigToken->Nic->HasDisconnectPendingNetwork = TRUE;\r
999 WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, NULL);\r
1000 goto Exit;\r
1001 }\r
1002\r
1003 ConfigToken->Nic->ConnectState = WifiMgrConnectedToAp;\r
1004 WifiMgrUpdateConnectMessage (ConfigToken->Nic, TRUE, NULL);\r
1005\r
1006Exit:\r
1007\r
1008 if (ConfigToken->Nic->ConnectState == WifiMgrDisconnected) {\r
1009 ConfigToken->Nic->CurrentOperateNetwork = NULL;\r
1010 }\r
d1050b9d 1011\r
90b24889 1012 ConfigToken->Nic->OneTimeConnectRequest = FALSE;\r
d1050b9d 1013 WifiMgrFreeToken (ConfigToken);\r
90b24889
WF
1014}\r
1015\r
1016/**\r
1017 Start connect operation, and send out a token to connect to a target network.\r
1018\r
1019 @param[in] Nic Pointer to the device data of the selected NIC.\r
1020 @param[in] Profile The target network to be connected.\r
1021\r
1022 @retval EFI_SUCCESS The operation is completed.\r
1023 @retval EFI_ALREADY_STARTED Already in "connected" state, need to perform a disconnect\r
1024 operation first.\r
1025 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
1026 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
1027 @retval Other Errors Return errors when connecting network on low layer.\r
1028\r
1029**/\r
1030EFI_STATUS\r
1031WifiMgrConnectToNetwork (\r
d1050b9d
MK
1032 IN WIFI_MGR_DEVICE_DATA *Nic,\r
1033 IN WIFI_MGR_NETWORK_PROFILE *Profile\r
90b24889
WF
1034 )\r
1035{\r
d1050b9d
MK
1036 EFI_STATUS Status;\r
1037 EFI_TPL OldTpl;\r
1038 EFI_ADAPTER_INFO_MEDIA_STATE LinkState;\r
1039 WIFI_MGR_MAC_CONFIG_TOKEN *ConfigToken;\r
1040 EFI_80211_CONNECT_NETWORK_TOKEN *ConnectToken;\r
90b24889 1041\r
d1050b9d 1042 if ((Nic == NULL) || (Nic->Wmp == NULL) || (Profile == NULL)) {\r
90b24889
WF
1043 return EFI_INVALID_PARAMETER;\r
1044 }\r
1045\r
1046 Status = WifiMgrGetLinkState (Nic, &LinkState);\r
1047 if (EFI_ERROR (Status)) {\r
1048 return Status;\r
1049 }\r
d1050b9d 1050\r
90b24889
WF
1051 if (LinkState.MediaState == EFI_SUCCESS) {\r
1052 return EFI_ALREADY_STARTED;\r
1053 }\r
1054\r
1055 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1056 Status = WifiMgrPrepareConnection (Nic, Profile);\r
1057 if (EFI_ERROR (Status)) {\r
1058 gBS->RestoreTPL (OldTpl);\r
1059 return Status;\r
1060 }\r
1061\r
1062 //\r
1063 // Create a new connect token\r
1064 //\r
1065 ConfigToken = AllocateZeroPool (sizeof (WIFI_MGR_MAC_CONFIG_TOKEN));\r
1066 if (ConfigToken == NULL) {\r
1067 Status = EFI_OUT_OF_RESOURCES;\r
1068 goto Exit;\r
1069 }\r
1070\r
d1050b9d
MK
1071 ConfigToken->Type = TokenTypeConnectNetworkToken;\r
1072 ConfigToken->Nic = Nic;\r
1073 ConfigToken->Token.ConnectNetworkToken = AllocateZeroPool (sizeof (EFI_80211_CONNECT_NETWORK_TOKEN));\r
90b24889
WF
1074 if (ConfigToken->Token.ConnectNetworkToken == NULL) {\r
1075 goto Exit;\r
1076 }\r
1077\r
d1050b9d
MK
1078 ConnectToken = ConfigToken->Token.ConnectNetworkToken;\r
1079 ConnectToken->Data = AllocateZeroPool (sizeof (EFI_80211_CONNECT_NETWORK_DATA));\r
90b24889
WF
1080 if (ConnectToken->Data == NULL) {\r
1081 goto Exit;\r
1082 }\r
1083\r
1084 ConnectToken->Data->Network = AllocateZeroPool (sizeof (EFI_80211_NETWORK));\r
1085 if (ConnectToken->Data->Network == NULL) {\r
1086 goto Exit;\r
1087 }\r
d1050b9d
MK
1088\r
1089 CopyMem (ConnectToken->Data->Network, &Profile->Network, sizeof (EFI_80211_NETWORK));\r
90b24889
WF
1090\r
1091 //\r
1092 // Add event handle and start to connect\r
1093 //\r
1094 Status = gBS->CreateEvent (\r
1095 EVT_NOTIFY_SIGNAL,\r
1096 TPL_CALLBACK,\r
1097 WifiMgrOnConnectFinished,\r
1098 ConfigToken,\r
1099 &ConnectToken->Event\r
1100 );\r
1101 if (EFI_ERROR (Status)) {\r
1102 goto Exit;\r
1103 }\r
1104\r
d1050b9d 1105 Nic->ConnectState = WifiMgrConnectingToAp;\r
90b24889
WF
1106 Nic->CurrentOperateNetwork = Profile;\r
1107 WifiMgrUpdateConnectMessage (Nic, FALSE, NULL);\r
1108\r
1109 //\r
d1050b9d 1110 // Start Connecting ...\r
90b24889
WF
1111 //\r
1112 Status = Nic->Wmp->ConnectNetwork (Nic->Wmp, ConnectToken);\r
1113\r
1114 //\r
1115 // Erase secrets after connection is triggered\r
1116 //\r
1117 WifiMgrCleanProfileSecrets (Profile);\r
1118\r
1119 if (EFI_ERROR (Status)) {\r
1120 if (Status == EFI_ALREADY_STARTED) {\r
1121 Nic->ConnectState = WifiMgrConnectedToAp;\r
1122 WifiMgrUpdateConnectMessage (Nic, TRUE, NULL);\r
1123 } else {\r
90b24889
WF
1124 Nic->ConnectState = WifiMgrDisconnected;\r
1125 Nic->CurrentOperateNetwork = NULL;\r
1126\r
1127 if (Nic->OneTimeConnectRequest) {\r
1128 if (Status == EFI_NOT_FOUND) {\r
1129 WifiMgrUpdateConnectMessage (Nic, FALSE, L"Connect Failed: Not Available!");\r
1130 } else {\r
1131 WifiMgrUpdateConnectMessage (Nic, FALSE, L"Connect Failed: Unexpected Error!");\r
1132 }\r
1133 }\r
1134 }\r
d1050b9d 1135\r
90b24889
WF
1136 goto Exit;\r
1137 }\r
1138\r
1139Exit:\r
1140\r
1141 if (EFI_ERROR (Status)) {\r
1142 WifiMgrFreeToken (ConfigToken);\r
1143 }\r
d1050b9d 1144\r
90b24889
WF
1145 gBS->RestoreTPL (OldTpl);\r
1146\r
1147 DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] WifiMgrConnectToNetwork: %r\n", Status));\r
1148 return Status;\r
1149}\r
1150\r
1151/**\r
1152 The callback function for disconnect operation.\r
1153\r
1154 ASSERT when errors occur in config token.\r
1155\r
1156 @param[in] Event The Disconnect token receive event.\r
1157 @param[in] Context The context of the Disconnect token.\r
1158\r
1159**/\r
1160VOID\r
1161EFIAPI\r
1162WifiMgrOnDisconnectFinished (\r
d1050b9d
MK
1163 IN EFI_EVENT Event,\r
1164 IN VOID *Context\r
90b24889
WF
1165 )\r
1166{\r
d1050b9d 1167 WIFI_MGR_MAC_CONFIG_TOKEN *ConfigToken;\r
90b24889
WF
1168\r
1169 ASSERT (Context != NULL);\r
1170\r
d1050b9d 1171 ConfigToken = (WIFI_MGR_MAC_CONFIG_TOKEN *)Context;\r
90b24889
WF
1172 ASSERT (ConfigToken->Nic != NULL);\r
1173 ASSERT (ConfigToken->Type == TokenTypeDisconnectNetworkToken);\r
1174\r
1175 ASSERT (ConfigToken->Token.DisconnectNetworkToken != NULL);\r
1176 if (ConfigToken->Token.DisconnectNetworkToken->Status != EFI_SUCCESS) {\r
d1050b9d 1177 ConfigToken->Nic->ConnectState = WifiMgrConnectedToAp;\r
90b24889
WF
1178 WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, NULL);\r
1179 ConfigToken->Nic->OneTimeDisconnectRequest = FALSE;\r
1180 goto Exit;\r
1181 }\r
1182\r
1183 ConfigToken->Nic->ConnectState = WifiMgrDisconnected;\r
1184 ConfigToken->Nic->CurrentOperateNetwork = NULL;\r
1185 WifiMgrUpdateConnectMessage (ConfigToken->Nic, TRUE, NULL);\r
1186 ConfigToken->Nic->OneTimeDisconnectRequest = FALSE;\r
1187\r
1188 //\r
1189 // Disconnected network may not be in network list now, trigger a scan again!\r
1190 //\r
d1050b9d 1191 ConfigToken->Nic->OneTimeScanRequest = TRUE;\r
90b24889 1192\r
d1050b9d
MK
1193Exit:\r
1194 WifiMgrFreeToken (ConfigToken);\r
1195 return;\r
90b24889
WF
1196}\r
1197\r
1198/**\r
1199 Start disconnect operation, and send out a token to disconnect from current connected\r
1200 network.\r
1201\r
1202 @param[in] Nic Pointer to the device data of the selected NIC.\r
1203\r
1204 @retval EFI_SUCCESS The operation is completed.\r
1205 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
1206 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
1207 @retval Other Errors Return errors when disconnecting a network on low layer.\r
1208\r
1209**/\r
1210EFI_STATUS\r
1211WifiMgrDisconnectToNetwork (\r
d1050b9d 1212 IN WIFI_MGR_DEVICE_DATA *Nic\r
90b24889
WF
1213 )\r
1214{\r
d1050b9d
MK
1215 EFI_STATUS Status;\r
1216 EFI_TPL OldTpl;\r
1217 WIFI_MGR_MAC_CONFIG_TOKEN *ConfigToken;\r
1218 EFI_80211_DISCONNECT_NETWORK_TOKEN *DisconnectToken;\r
90b24889
WF
1219\r
1220 if (Nic == NULL) {\r
1221 return EFI_INVALID_PARAMETER;\r
1222 }\r
1223\r
1224 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1225 Status = EFI_SUCCESS;\r
1226 ConfigToken = AllocateZeroPool (sizeof (WIFI_MGR_MAC_CONFIG_TOKEN));\r
1227 if (ConfigToken == NULL) {\r
1228 gBS->RestoreTPL (OldTpl);\r
1229 return EFI_OUT_OF_RESOURCES;\r
1230 }\r
1231\r
d1050b9d
MK
1232 ConfigToken->Type = TokenTypeDisconnectNetworkToken;\r
1233 ConfigToken->Nic = Nic;\r
90b24889
WF
1234 ConfigToken->Token.DisconnectNetworkToken = AllocateZeroPool (sizeof (EFI_80211_DISCONNECT_NETWORK_TOKEN));\r
1235 if (ConfigToken->Token.DisconnectNetworkToken == NULL) {\r
d1050b9d 1236 WifiMgrFreeToken (ConfigToken);\r
90b24889
WF
1237 gBS->RestoreTPL (OldTpl);\r
1238 return EFI_OUT_OF_RESOURCES;\r
1239 }\r
1240\r
1241 DisconnectToken = ConfigToken->Token.DisconnectNetworkToken;\r
1242\r
1243 Status = gBS->CreateEvent (\r
1244 EVT_NOTIFY_SIGNAL,\r
1245 TPL_CALLBACK,\r
1246 WifiMgrOnDisconnectFinished,\r
1247 ConfigToken,\r
1248 &DisconnectToken->Event\r
1249 );\r
1250 if (EFI_ERROR (Status)) {\r
d1050b9d 1251 WifiMgrFreeToken (ConfigToken);\r
90b24889
WF
1252 gBS->RestoreTPL (OldTpl);\r
1253 return Status;\r
1254 }\r
1255\r
1256 Nic->ConnectState = WifiMgrDisconnectingToAp;\r
1257 WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, NULL);\r
1258\r
1259 Status = Nic->Wmp->DisconnectNetwork (Nic->Wmp, DisconnectToken);\r
1260 if (EFI_ERROR (Status)) {\r
1261 if (Status == EFI_NOT_FOUND) {\r
90b24889
WF
1262 Nic->ConnectState = WifiMgrDisconnected;\r
1263 Nic->CurrentOperateNetwork = NULL;\r
1264\r
1265 //\r
1266 // This network is not in network list now, trigger a scan again!\r
1267 //\r
d1050b9d 1268 Nic->OneTimeScanRequest = TRUE;\r
90b24889
WF
1269\r
1270 //\r
1271 // State has been changed from Connected to Disconnected\r
1272 //\r
1273 WifiMgrUpdateConnectMessage (ConfigToken->Nic, TRUE, NULL);\r
d1050b9d 1274 Status = EFI_SUCCESS;\r
90b24889
WF
1275 } else {\r
1276 if (Nic->OneTimeDisconnectRequest) {\r
90b24889
WF
1277 WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, L"Disconnect Failed: Unexpected Error!");\r
1278 }\r
1279\r
d1050b9d 1280 Nic->ConnectState = WifiMgrConnectedToAp;\r
90b24889
WF
1281 WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, NULL);\r
1282 }\r
d1050b9d
MK
1283\r
1284 WifiMgrFreeToken (ConfigToken);\r
90b24889
WF
1285 }\r
1286\r
1287 gBS->RestoreTPL (OldTpl);\r
1288 return Status;\r
1289}\r
1290\r
1291/**\r
1292 The state machine of the connection manager, periodically check the state and\r
1293 perform a corresponding operation.\r
1294\r
1295 @param[in] Event The timer event to be triggered.\r
1296 @param[in] Context The context of the Nic device data.\r
1297\r
1298**/\r
1299VOID\r
1300EFIAPI\r
1301WifiMgrOnTimerTick (\r
d1050b9d
MK
1302 IN EFI_EVENT Event,\r
1303 IN VOID *Context\r
90b24889
WF
1304 )\r
1305{\r
d1050b9d
MK
1306 WIFI_MGR_DEVICE_DATA *Nic;\r
1307 EFI_STATUS Status;\r
1308 EFI_ADAPTER_INFO_MEDIA_STATE LinkState;\r
1309 WIFI_MGR_NETWORK_PROFILE *Profile;\r
90b24889
WF
1310\r
1311 if (Context == NULL) {\r
1312 return;\r
1313 }\r
1314\r
d1050b9d 1315 Nic = (WIFI_MGR_DEVICE_DATA *)Context;\r
90b24889
WF
1316 NET_CHECK_SIGNATURE (Nic, WIFI_MGR_DEVICE_DATA_SIGNATURE);\r
1317\r
1318 Status = WifiMgrGetLinkState (Nic, &LinkState);\r
1319 if (EFI_ERROR (Status)) {\r
1320 DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] Error: Failed to get link state!\n"));\r
1321 return;\r
1322 }\r
1323\r
1324 if (Nic->LastLinkState.MediaState != LinkState.MediaState) {\r
d1050b9d 1325 if ((Nic->LastLinkState.MediaState == EFI_SUCCESS) && (LinkState.MediaState == EFI_NO_MEDIA)) {\r
90b24889
WF
1326 Nic->HasDisconnectPendingNetwork = TRUE;\r
1327 }\r
d1050b9d 1328\r
90b24889
WF
1329 Nic->LastLinkState.MediaState = LinkState.MediaState;\r
1330 }\r
1331\r
d1050b9d
MK
1332 Nic->ScanTickTime++;\r
1333 if (((Nic->ScanTickTime > WIFI_SCAN_FREQUENCY) || Nic->OneTimeScanRequest) &&\r
1334 (Nic->ScanState == WifiMgrScanFinished))\r
1335 {\r
90b24889 1336 Nic->OneTimeScanRequest = FALSE;\r
d1050b9d 1337 Nic->ScanTickTime = 0;\r
90b24889
WF
1338\r
1339 DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] Scan is triggered.\n"));\r
1340 WifiMgrStartScan (Nic);\r
1341 }\r
1342\r
d1050b9d 1343 if ((Nic->AvailableCount > 0) && (Nic->ScanState == WifiMgrScanFinished)) {\r
90b24889 1344 switch (Nic->ConnectState) {\r
d1050b9d 1345 case WifiMgrDisconnected:\r
90b24889 1346\r
d1050b9d
MK
1347 if (Nic->HasDisconnectPendingNetwork) {\r
1348 Nic->HasDisconnectPendingNetwork = FALSE;\r
1349 }\r
90b24889 1350\r
d1050b9d
MK
1351 if (Nic->ConnectPendingNetwork != NULL) {\r
1352 Profile = Nic->ConnectPendingNetwork;\r
1353 Status = WifiMgrConnectToNetwork (Nic, Profile);\r
1354 Nic->ConnectPendingNetwork = NULL;\r
1355 if (EFI_ERROR (Status)) {\r
1356 //\r
1357 // Some error happened, don't wait for a return connect token!\r
1358 //\r
1359 Nic->OneTimeConnectRequest = FALSE;\r
1360 }\r
90b24889 1361 }\r
90b24889 1362\r
d1050b9d 1363 break;\r
90b24889 1364\r
d1050b9d
MK
1365 case WifiMgrConnectingToAp:\r
1366 break;\r
90b24889 1367\r
d1050b9d
MK
1368 case WifiMgrDisconnectingToAp:\r
1369 break;\r
90b24889 1370\r
d1050b9d 1371 case WifiMgrConnectedToAp:\r
90b24889 1372\r
d1050b9d
MK
1373 if ((Nic->ConnectPendingNetwork != NULL) || Nic->HasDisconnectPendingNetwork) {\r
1374 Status = WifiMgrDisconnectToNetwork (Nic);\r
1375 if (EFI_ERROR (Status)) {\r
1376 //\r
1377 // Some error happened, don't wait for a return disconnect token!\r
1378 //\r
1379 Nic->OneTimeDisconnectRequest = FALSE;\r
1380 }\r
90b24889 1381 }\r
90b24889 1382\r
d1050b9d
MK
1383 break;\r
1384\r
1385 default:\r
1386 break;\r
90b24889
WF
1387 }\r
1388 }\r
1389}\r