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