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