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