VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrImpl.c@ 102797

Last change on this file since 102797 was 101291, checked in by vboxsync, 19 months ago

EFI/FirmwareNew: Make edk2-stable202308 build on all supported platforms (using gcc at least, msvc not tested yet), bugref:4643

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette