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