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