2 The Mac Connection2 Protocol adapter functions for WiFi Connection Manager.
4 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "WifiConnectionMgrDxe.h"
12 EFI_EAP_TYPE mEapAuthMethod
[] = {
18 EFI_EAP_TYPE mEapSecondAuthMethod
[] = {
23 The callback function for scan operation. This function updates networks
24 according to the latest scan result, and trigger UI refresh.
26 ASSERT when errors occur in config token.
28 @param[in] Event The GetNetworks token receive event.
29 @param[in] Context The context of the GetNetworks token.
34 WifiMgrOnScanFinished (
40 WIFI_MGR_MAC_CONFIG_TOKEN
*ConfigToken
;
41 WIFI_MGR_DEVICE_DATA
*Nic
;
42 WIFI_MGR_NETWORK_PROFILE
*Profile
;
43 EFI_80211_NETWORK
*Network
;
45 EFI_80211_NETWORK_DESCRIPTION
*NetworkDescription
;
46 EFI_80211_GET_NETWORKS_RESULT
*Result
;
49 BOOLEAN AKMSuiteSupported
;
50 BOOLEAN CipherSuiteSupported
;
54 ASSERT (Context
!= NULL
);
56 ConfigToken
= (WIFI_MGR_MAC_CONFIG_TOKEN
*) Context
;
57 ASSERT (ConfigToken
->Nic
!= NULL
);
58 ASSERT (ConfigToken
->Type
== TokenTypeGetNetworksToken
);
61 // It is the GetNetworks token, set scan state to "ScanFinished"
63 ConfigToken
->Nic
->ScanState
= WifiMgrScanFinished
;
65 ASSERT (ConfigToken
->Token
.GetNetworksToken
!= NULL
);
66 Result
= ConfigToken
->Token
.GetNetworksToken
->Result
;
67 Nic
= ConfigToken
->Nic
;
70 // Clean previous result, and update network list according to the scan result
72 Nic
->AvailableCount
= 0;
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
;
81 gBS
->SignalEvent (Nic
->Private
->NetworkListRefreshEvent
);
82 WifiMgrFreeToken(ConfigToken
);
86 for (Index
= 0; Index
< Result
->NumOfNetworkDesc
; Index
++) {
88 NetworkDescription
= Result
->NetworkDesc
+ Index
;
89 if (NetworkDescription
== NULL
) {
93 Network
= &NetworkDescription
->Network
;
94 if (Network
== NULL
|| Network
->SSId
.SSIdLen
== 0) {
98 Status
= WifiMgrCheckRSN (
100 Network
->CipherSuite
,
104 &CipherSuiteSupported
106 if (EFI_ERROR (Status
)) {
108 SecurityType
= SECURITY_TYPE_UNKNOWN
;
109 AKMSuiteSupported
= FALSE
;
110 CipherSuiteSupported
= FALSE
;
113 AsciiSSId
= (CHAR8
*) AllocateZeroPool(sizeof (CHAR8
) * (Network
->SSId
.SSIdLen
+ 1));
114 if (AsciiSSId
== NULL
) {
117 CopyMem(AsciiSSId
, (CHAR8
*) Network
->SSId
.SSId
, sizeof (CHAR8
) * Network
->SSId
.SSIdLen
);
118 *(AsciiSSId
+ Network
->SSId
.SSIdLen
) = '\0';
120 Profile
= WifiMgrGetProfileByAsciiSSId (AsciiSSId
, SecurityType
, &Nic
->ProfileList
);
121 if (Profile
== NULL
) {
123 if (Nic
->MaxProfileIndex
>= NETWORK_LIST_COUNT_MAX
) {
124 FreePool (AsciiSSId
);
129 // Create a new profile
131 Profile
= AllocateZeroPool (sizeof (WIFI_MGR_NETWORK_PROFILE
));
132 if (Profile
== NULL
) {
133 FreePool (AsciiSSId
);
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
++;
143 FreePool (AsciiSSId
);
146 //May receive duplicate networks in scan results, check if it has already
149 if (!Profile
->IsAvailable
) {
151 Profile
->IsAvailable
= TRUE
;
152 Profile
->SecurityType
= SecurityType
;
153 Profile
->AKMSuiteSupported
= AKMSuiteSupported
;
154 Profile
->CipherSuiteSupported
= CipherSuiteSupported
;
155 Profile
->NetworkQuality
= NetworkDescription
->NetworkQuality
;
156 Nic
->AvailableCount
++;
159 //Copy BSSType and SSId
161 CopyMem(&Profile
->Network
, Network
, sizeof (EFI_80211_NETWORK
));
166 if (Network
->AKMSuite
!= NULL
) {
168 if (Network
->AKMSuite
->AKMSuiteCount
== 0) {
169 DataSize
= sizeof (EFI_80211_AKM_SUITE_SELECTOR
);
171 DataSize
= sizeof (EFI_80211_AKM_SUITE_SELECTOR
) + sizeof (EFI_80211_SUITE_SELECTOR
)
172 * (Network
->AKMSuite
->AKMSuiteCount
- 1);
174 Profile
->Network
.AKMSuite
= (EFI_80211_AKM_SUITE_SELECTOR
*) AllocateZeroPool (DataSize
);
175 if (Profile
->Network
.AKMSuite
== NULL
) {
178 CopyMem (Profile
->Network
.AKMSuite
, Network
->AKMSuite
, DataSize
);
182 //Copy CipherSuite list
184 if (Network
->CipherSuite
!= NULL
) {
186 if (Network
->CipherSuite
->CipherSuiteCount
== 0) {
187 DataSize
= sizeof (EFI_80211_CIPHER_SUITE_SELECTOR
);
189 DataSize
= sizeof (EFI_80211_CIPHER_SUITE_SELECTOR
) + sizeof (EFI_80211_SUITE_SELECTOR
)
190 * (Network
->CipherSuite
->CipherSuiteCount
- 1);
192 Profile
->Network
.CipherSuite
= (EFI_80211_CIPHER_SUITE_SELECTOR
*) AllocateZeroPool (DataSize
);
193 if (Profile
->Network
.CipherSuite
== NULL
) {
196 CopyMem (Profile
->Network
.CipherSuite
, Network
->CipherSuite
, DataSize
);
200 // A duplicate network, update signal quality
202 if (Profile
->NetworkQuality
< NetworkDescription
->NetworkQuality
) {
203 Profile
->NetworkQuality
= NetworkDescription
->NetworkQuality
;
209 gBS
->SignalEvent (Nic
->Private
->NetworkListRefreshEvent
);
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.
215 if (Nic
->ConnectState
== WifiMgrConnectedToAp
&& Nic
->CurrentOperateNetwork
!= NULL
) {
216 if (!Nic
->CurrentOperateNetwork
->IsAvailable
) {
217 Nic
->CurrentOperateNetwork
->IsAvailable
= TRUE
;
218 Nic
->AvailableCount
++;
222 WifiMgrFreeToken(ConfigToken
);
226 Start scan operation, and send out a token to collect available networks.
228 @param[in] Nic Pointer to the device data of the selected NIC.
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.
239 IN WIFI_MGR_DEVICE_DATA
*Nic
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
;
252 if (Nic
== NULL
|| Nic
->Wmp
== NULL
) {
253 return EFI_INVALID_PARAMETER
;
256 if (Nic
->ScanState
== WifiMgrScanning
) {
257 return EFI_ALREADY_STARTED
;
260 Nic
->ScanState
= WifiMgrScanning
;
261 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
262 Status
= EFI_SUCCESS
;
263 HiddenSSIdList
= NULL
;
264 HiddenSSIdCount
= Nic
->Private
->HiddenNetworkCount
;
268 //create a new get network token
270 ConfigToken
= AllocateZeroPool (sizeof (WIFI_MGR_MAC_CONFIG_TOKEN
));
271 if (ConfigToken
== NULL
) {
272 gBS
->RestoreTPL (OldTpl
);
273 return EFI_OUT_OF_RESOURCES
;
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
;
284 GetNetworksToken
= ConfigToken
->Token
.GetNetworksToken
;
287 // There are some hidden networks to scan, add them into scan list
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
;
298 NET_LIST_FOR_EACH (Entry
, &Nic
->Private
->HiddenNetworkList
) {
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
);
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
;
315 GetNetworksToken
->Data
->NumOfSSID
= HiddenSSIdCount
;
316 CopyMem(GetNetworksToken
->Data
->SSIDList
, HiddenSSIdList
, HiddenSSIdCount
* sizeof (EFI_80211_SSID
));
317 FreePool(HiddenSSIdList
);
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
;
327 GetNetworksToken
->Data
->NumOfSSID
= 0;
331 //Create a handle when scan process ends
333 Status
= gBS
->CreateEvent (
336 WifiMgrOnScanFinished
,
338 &GetNetworksToken
->Event
340 if (EFI_ERROR (Status
)) {
341 WifiMgrFreeToken(ConfigToken
);
342 gBS
->RestoreTPL (OldTpl
);
349 Status
= Nic
->Wmp
->GetNetworks (Nic
->Wmp
, GetNetworksToken
);
350 if (EFI_ERROR (Status
)) {
351 Nic
->ScanState
= WifiMgrScanFinished
;
352 WifiMgrFreeToken(ConfigToken
);
353 gBS
->RestoreTPL (OldTpl
);
357 gBS
->RestoreTPL (OldTpl
);
362 Configure password to supplicant before connecting to a secured network.
364 @param[in] Nic Pointer to the device data of the selected NIC.
365 @param[in] Profile The target network to be connected.
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.
375 WifiMgrConfigPassword (
376 IN WIFI_MGR_DEVICE_DATA
*Nic
,
377 IN WIFI_MGR_NETWORK_PROFILE
*Profile
381 EFI_SUPPLICANT_PROTOCOL
*Supplicant
;
383 UINT8
*AsciiPassword
;
385 if (Nic
== NULL
|| Nic
->Supplicant
== NULL
|| Profile
== NULL
) {
386 return EFI_INVALID_PARAMETER
;
388 Supplicant
= Nic
->Supplicant
;
390 //Set SSId to supplicant
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
)) {
401 //Set password to supplicant
403 if (StrLen (Profile
->Password
) < PASSWORD_MIN_LEN
) {
404 return EFI_NOT_FOUND
;
406 AsciiPassword
= AllocateZeroPool ((StrLen(Profile
->Password
) + 1) * sizeof (UINT8
));
407 if (AsciiPassword
== NULL
) {
408 return EFI_OUT_OF_RESOURCES
;
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
);
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)
426 @param[in] Nic Pointer to the device data of the selected NIC.
427 @param[in] Profile The target network to be connected.
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.
438 IN WIFI_MGR_DEVICE_DATA
*Nic
,
439 IN WIFI_MGR_NETWORK_PROFILE
*Profile
443 EFI_EAP_CONFIGURATION_PROTOCOL
*EapConfig
;
444 EFI_EAP_TYPE EapAuthMethod
;
445 EFI_EAP_TYPE EapSecondAuthMethod
;
446 EFI_EAP_TYPE
*AuthMethodList
;
451 UINTN EncryptPasswordLen
;
452 CHAR8
*AsciiEncryptPassword
;
453 UINTN AuthMethodListSize
;
456 if (Nic
== NULL
|| Nic
->EapConfig
== NULL
|| Profile
== NULL
) {
457 return EFI_INVALID_PARAMETER
;
459 EapConfig
= Nic
->EapConfig
;
461 if (Profile
->EapAuthMethod
>= EAP_AUTH_METHOD_MAX
) {
462 return EFI_INVALID_PARAMETER
;
464 EapAuthMethod
= mEapAuthMethod
[Profile
->EapAuthMethod
];
466 if (EapAuthMethod
!= EFI_EAP_TYPE_EAPTLS
) {
467 if (Profile
->EapSecondAuthMethod
>= EAP_SEAUTH_METHOD_MAX
) {
468 return EFI_INVALID_PARAMETER
;
470 EapSecondAuthMethod
= mEapSecondAuthMethod
[Profile
->EapSecondAuthMethod
];
474 //The first time to get Supported Auth Method list, return the size.
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
) {
482 //No Supported Eap Auth Method
484 return EFI_UNSUPPORTED
;
485 } else if (Status
!= EFI_BUFFER_TOO_SMALL
) {
490 // The second time to get Supported Auth Method list, return the list.
491 // In current design, only EAPTLS, TTLS and PEAP are supported
493 AuthMethodList
= (EFI_EAP_TYPE
*) AllocateZeroPool(AuthMethodListSize
);
494 if (AuthMethodList
== NULL
) {
495 return EFI_OUT_OF_RESOURCES
;
497 Status
= EapConfig
->GetData (EapConfig
, EFI_EAP_TYPE_ATTRIBUTE
, EfiEapConfigEapSupportedAuthMethod
,
498 (VOID
*) AuthMethodList
, &AuthMethodListSize
);
499 if (EFI_ERROR (Status
)) {
500 FreePool (AuthMethodList
);
505 //Check if EapAuthMethod is in supported Auth Method list, if found, skip the loop.
507 for (Index
= 0; Index
< AuthMethodListSize
/ sizeof (EFI_EAP_TYPE
); Index
++) {
508 if (EapAuthMethod
== AuthMethodList
[Index
]) {
512 if (Index
== AuthMethodListSize
/ sizeof (EFI_EAP_TYPE
)) {
513 FreePool (AuthMethodList
);
514 return EFI_UNSUPPORTED
;
516 FreePool (AuthMethodList
);
519 // Set Identity to Eap peer, Mandatory field for PEAP and TTLS
521 if (StrLen (Profile
->EapIdentity
) > 0) {
523 IdentitySize
= sizeof(CHAR8
) * (StrLen(Profile
->EapIdentity
) + 1);
524 Identity
= AllocateZeroPool (IdentitySize
);
525 if (Identity
== NULL
) {
526 return EFI_OUT_OF_RESOURCES
;
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
)) {
537 if (EapAuthMethod
!= EFI_EAP_TYPE_EAPTLS
) {
538 return EFI_INVALID_PARAMETER
;
543 //Set Auth Method to Eap peer, Mandatory field
545 Status
= EapConfig
->SetData (EapConfig
, EFI_EAP_TYPE_ATTRIBUTE
, EfiEapConfigEapAuthMethod
,
546 (VOID
*) &EapAuthMethod
, sizeof (EapAuthMethod
));
547 if (EFI_ERROR(Status
)) {
551 if (EapAuthMethod
== EFI_EAP_TYPE_TTLS
|| EapAuthMethod
== EFI_EAP_TYPE_PEAP
) {
553 Status
= EapConfig
->SetData (EapConfig
, EapAuthMethod
, EfiEapConfigEap2ndAuthMethod
,
554 (VOID
*) &EapSecondAuthMethod
, sizeof (EapSecondAuthMethod
));
555 if (EFI_ERROR(Status
)) {
560 // Set Password to Eap peer
562 if (StrLen (Profile
->EapPassword
) < PASSWORD_MIN_LEN
) {
564 DEBUG ((DEBUG_ERROR
, "[WiFi Connection Manager] Error: No Eap Password for Network: %s.\n", Profile
->SSId
));
565 return EFI_INVALID_PARAMETER
;
568 PasswordSize
= sizeof (CHAR16
) * (StrLen (Profile
->EapPassword
) + 1);
569 Password
= AllocateZeroPool (PasswordSize
);
570 if (Password
== NULL
) {
571 return EFI_OUT_OF_RESOURCES
;
573 StrCpyS (Password
, PasswordSize
, Profile
->EapPassword
);;
574 Status
= EapConfig
->SetData (EapConfig
, EFI_EAP_TYPE_MSCHAPV2
, EfiEapConfigEapMSChapV2Password
,
575 (VOID
*) Password
, PasswordSize
);
576 ZeroMem (Password
, PasswordSize
);
578 if (EFI_ERROR (Status
)) {
583 //If CA cert is required, set it to Eap peer
585 if (Profile
->CACertData
!= NULL
) {
587 Status
= EapConfig
->SetData (EapConfig
, EapAuthMethod
, EfiEapConfigEapTlsCACert
,
588 Profile
->CACertData
, Profile
->CACertSize
);
589 if (EFI_ERROR(Status
)) {
593 return EFI_INVALID_PARAMETER
;
595 } else if (EapAuthMethod
== EFI_EAP_TYPE_EAPTLS
) {
598 //Set CA cert to Eap peer
600 if (Profile
->CACertData
== NULL
) {
601 return EFI_INVALID_PARAMETER
;
603 Status
= EapConfig
->SetData (EapConfig
, EFI_EAP_TYPE_EAPTLS
, EfiEapConfigEapTlsCACert
,
604 Profile
->CACertData
, Profile
->CACertSize
);
605 if (EFI_ERROR(Status
)) {
610 //Set Client cert to Eap peer
612 if (Profile
->ClientCertData
== NULL
) {
613 return EFI_INVALID_PARAMETER
;
615 Status
= EapConfig
->SetData (EapConfig
, EFI_EAP_TYPE_EAPTLS
, EfiEapConfigEapTlsClientCert
,
616 Profile
->ClientCertData
, Profile
->ClientCertSize
);
617 if (EFI_ERROR(Status
)) {
622 //Set Private key to Eap peer
624 if (Profile
->PrivateKeyData
== NULL
) {
626 DEBUG ((DEBUG_ERROR
, "[WiFi Connection Manager] Error: No Private Key for Network: %s.\n", Profile
->SSId
));
627 return EFI_INVALID_PARAMETER
;
630 Status
= EapConfig
->SetData (EapConfig
, EFI_EAP_TYPE_EAPTLS
, EfiEapConfigEapTlsClientPrivateKeyFile
,
631 Profile
->PrivateKeyData
, Profile
->PrivateKeyDataSize
);
632 if (EFI_ERROR(Status
)) {
636 if (StrLen (Profile
->PrivateKeyPassword
) > 0) {
638 EncryptPasswordLen
= StrLen (Profile
->PrivateKeyPassword
);
639 AsciiEncryptPassword
= AllocateZeroPool(EncryptPasswordLen
+ 1);
640 if (AsciiEncryptPassword
== NULL
) {
641 return EFI_OUT_OF_RESOURCES
;
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
)) {
649 ZeroMem (AsciiEncryptPassword
, EncryptPasswordLen
+ 1);
650 FreePool (AsciiEncryptPassword
);
654 ZeroMem (AsciiEncryptPassword
, EncryptPasswordLen
+ 1);
655 FreePool (AsciiEncryptPassword
);
658 return EFI_INVALID_PARAMETER
;
665 Get current link state from low layer.
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.
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.
677 WifiMgrGetLinkState (
678 IN WIFI_MGR_DEVICE_DATA
*Nic
,
679 OUT EFI_ADAPTER_INFO_MEDIA_STATE
*LinkState
685 EFI_ADAPTER_INFO_MEDIA_STATE
*UndiState
;
686 EFI_ADAPTER_INFORMATION_PROTOCOL
*Aip
;
688 if (Nic
== NULL
|| LinkState
== NULL
) {
689 return EFI_INVALID_PARAMETER
;
692 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
693 Status
= gBS
->OpenProtocol (
694 Nic
->ControllerHandle
,
695 &gEfiAdapterInformationProtocolGuid
,
698 Nic
->ControllerHandle
,
699 EFI_OPEN_PROTOCOL_GET_PROTOCOL
701 if (EFI_ERROR (Status
)) {
702 gBS
->RestoreTPL (OldTpl
);
703 return EFI_UNSUPPORTED
;
706 Status
= Aip
->GetInformation(
708 &gEfiAdapterInfoMediaStateGuid
,
709 (VOID
**) &UndiState
,
712 if (EFI_ERROR (Status
)) {
713 gBS
->RestoreTPL (OldTpl
);
716 gBS
->RestoreTPL (OldTpl
);
718 CopyMem (LinkState
, UndiState
, sizeof (EFI_ADAPTER_INFO_MEDIA_STATE
));
719 FreePool (UndiState
);
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.
728 @param[in] Nic Pointer to the device data of the selected NIC.
729 @param[in] Profile The target network to be connected.
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.
737 WifiMgrPrepareConnection (
738 IN WIFI_MGR_DEVICE_DATA
*Nic
,
739 IN WIFI_MGR_NETWORK_PROFILE
*Profile
744 BOOLEAN AKMSuiteSupported
;
745 BOOLEAN CipherSuiteSupported
;
747 if (Profile
== NULL
|| Nic
== NULL
) {
748 return EFI_INVALID_PARAMETER
;
751 Status
= WifiMgrCheckRSN (Profile
->Network
.AKMSuite
, Profile
->Network
.CipherSuite
,
752 Nic
, &SecurityType
, &AKMSuiteSupported
, &CipherSuiteSupported
);
753 if (EFI_ERROR (Status
)) {
757 if (AKMSuiteSupported
&& CipherSuiteSupported
) {
758 switch (SecurityType
) {
759 case SECURITY_TYPE_WPA2_PERSONAL
:
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!");
772 case SECURITY_TYPE_WPA2_ENTERPRISE
:
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!");
785 case SECURITY_TYPE_NONE
:
789 return EFI_UNSUPPORTED
;
792 return EFI_UNSUPPORTED
;
799 The callback function for connect operation.
801 ASSERT when errors occur in config token.
803 @param[in] Event The Connect token receive event.
804 @param[in] Context The context of the connect token.
809 WifiMgrOnConnectFinished (
815 WIFI_MGR_MAC_CONFIG_TOKEN
*ConfigToken
;
816 WIFI_MGR_NETWORK_PROFILE
*ConnectedProfile
;
821 ASSERT (Context
!= NULL
);
823 ConnectedProfile
= NULL
;
824 ConfigToken
= (WIFI_MGR_MAC_CONFIG_TOKEN
*) Context
;
825 ASSERT (ConfigToken
->Nic
!= NULL
);
827 ConfigToken
->Nic
->ConnectState
= WifiMgrDisconnected
;
828 ASSERT (ConfigToken
->Type
== TokenTypeConnectNetworkToken
);
830 ASSERT (ConfigToken
->Token
.ConnectNetworkToken
!= NULL
);
831 if (ConfigToken
->Token
.ConnectNetworkToken
->Status
!= EFI_SUCCESS
) {
833 if (ConfigToken
->Nic
->OneTimeConnectRequest
) {
835 // Only update message for user triggered connection
837 if (ConfigToken
->Token
.ConnectNetworkToken
->Status
== EFI_ACCESS_DENIED
) {
839 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, L
"Connect Failed: Permission Denied!");
841 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, L
"Connect Failed!");
843 ConfigToken
->Nic
->OneTimeConnectRequest
= FALSE
;
845 ConfigToken
->Nic
->CurrentOperateNetwork
= NULL
;
849 if (ConfigToken
->Token
.ConnectNetworkToken
->ResultCode
!= ConnectSuccess
) {
851 if (ConfigToken
->Nic
->OneTimeConnectRequest
) {
853 if (ConfigToken
->Token
.ConnectNetworkToken
->ResultCode
== ConnectFailedReasonUnspecified
) {
854 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, L
"Connect Failed: Wrong Password or Unexpected Error!");
856 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, L
"Connect Failed!");
862 if (ConfigToken
->Token
.ConnectNetworkToken
->Data
== NULL
||
863 ConfigToken
->Token
.ConnectNetworkToken
->Data
->Network
== NULL
) {
866 // An unexpected error occurs, tell low layer to perform a disconnect
868 ConfigToken
->Nic
->HasDisconnectPendingNetwork
= TRUE
;
869 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, NULL
);
874 // A correct connect token received, terminate the connection process
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
;
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
);
891 CopyMem(AsciiSSId
, ConfigToken
->Token
.ConnectNetworkToken
->Data
->Network
->SSId
.SSId
, SSIdLen
);
892 *(AsciiSSId
+ SSIdLen
) = '\0';
894 ConnectedProfile
= WifiMgrGetProfileByAsciiSSId(AsciiSSId
, SecurityType
, &ConfigToken
->Nic
->ProfileList
);
896 if (ConnectedProfile
== NULL
) {
897 ConfigToken
->Nic
->HasDisconnectPendingNetwork
= TRUE
;
898 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, NULL
);
902 ConfigToken
->Nic
->ConnectState
= WifiMgrConnectedToAp
;
903 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, TRUE
, NULL
);
907 if (ConfigToken
->Nic
->ConnectState
== WifiMgrDisconnected
) {
908 ConfigToken
->Nic
->CurrentOperateNetwork
= NULL
;
910 ConfigToken
->Nic
->OneTimeConnectRequest
= FALSE
;
911 WifiMgrFreeToken(ConfigToken
);
915 Start connect operation, and send out a token to connect to a target network.
917 @param[in] Nic Pointer to the device data of the selected NIC.
918 @param[in] Profile The target network to be connected.
920 @retval EFI_SUCCESS The operation is completed.
921 @retval EFI_ALREADY_STARTED Already in "connected" state, need to perform a disconnect
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.
929 WifiMgrConnectToNetwork (
930 IN WIFI_MGR_DEVICE_DATA
*Nic
,
931 IN WIFI_MGR_NETWORK_PROFILE
*Profile
936 EFI_ADAPTER_INFO_MEDIA_STATE LinkState
;
937 WIFI_MGR_MAC_CONFIG_TOKEN
*ConfigToken
;
938 EFI_80211_CONNECT_NETWORK_TOKEN
*ConnectToken
;
940 if (Nic
== NULL
|| Nic
->Wmp
== NULL
|| Profile
== NULL
) {
941 return EFI_INVALID_PARAMETER
;
944 Status
= WifiMgrGetLinkState (Nic
, &LinkState
);
945 if (EFI_ERROR (Status
)) {
948 if (LinkState
.MediaState
== EFI_SUCCESS
) {
949 return EFI_ALREADY_STARTED
;
952 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
953 Status
= WifiMgrPrepareConnection (Nic
, Profile
);
954 if (EFI_ERROR (Status
)) {
955 gBS
->RestoreTPL (OldTpl
);
960 // Create a new connect token
962 ConfigToken
= AllocateZeroPool (sizeof (WIFI_MGR_MAC_CONFIG_TOKEN
));
963 if (ConfigToken
== NULL
) {
964 Status
= EFI_OUT_OF_RESOURCES
;
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
) {
975 ConnectToken
= ConfigToken
->Token
.ConnectNetworkToken
;
976 ConnectToken
->Data
= AllocateZeroPool (sizeof (EFI_80211_CONNECT_NETWORK_DATA
));
977 if (ConnectToken
->Data
== NULL
) {
981 ConnectToken
->Data
->Network
= AllocateZeroPool (sizeof (EFI_80211_NETWORK
));
982 if (ConnectToken
->Data
->Network
== NULL
) {
985 CopyMem(ConnectToken
->Data
->Network
, &Profile
->Network
, sizeof (EFI_80211_NETWORK
));
988 // Add event handle and start to connect
990 Status
= gBS
->CreateEvent (
993 WifiMgrOnConnectFinished
,
997 if (EFI_ERROR (Status
)) {
1001 Nic
->ConnectState
= WifiMgrConnectingToAp
;
1002 Nic
->CurrentOperateNetwork
= Profile
;
1003 WifiMgrUpdateConnectMessage (Nic
, FALSE
, NULL
);
1006 //Start Connecting ...
1008 Status
= Nic
->Wmp
->ConnectNetwork (Nic
->Wmp
, ConnectToken
);
1011 // Erase secrets after connection is triggered
1013 WifiMgrCleanProfileSecrets (Profile
);
1015 if (EFI_ERROR (Status
)) {
1016 if (Status
== EFI_ALREADY_STARTED
) {
1017 Nic
->ConnectState
= WifiMgrConnectedToAp
;
1018 WifiMgrUpdateConnectMessage (Nic
, TRUE
, NULL
);
1021 Nic
->ConnectState
= WifiMgrDisconnected
;
1022 Nic
->CurrentOperateNetwork
= NULL
;
1024 if (Nic
->OneTimeConnectRequest
) {
1025 if (Status
== EFI_NOT_FOUND
) {
1026 WifiMgrUpdateConnectMessage (Nic
, FALSE
, L
"Connect Failed: Not Available!");
1028 WifiMgrUpdateConnectMessage (Nic
, FALSE
, L
"Connect Failed: Unexpected Error!");
1037 if (EFI_ERROR (Status
)) {
1038 WifiMgrFreeToken (ConfigToken
);
1040 gBS
->RestoreTPL (OldTpl
);
1042 DEBUG ((DEBUG_INFO
, "[WiFi Connection Manager] WifiMgrConnectToNetwork: %r\n", Status
));
1047 The callback function for disconnect operation.
1049 ASSERT when errors occur in config token.
1051 @param[in] Event The Disconnect token receive event.
1052 @param[in] Context The context of the Disconnect token.
1057 WifiMgrOnDisconnectFinished (
1062 WIFI_MGR_MAC_CONFIG_TOKEN
*ConfigToken
;
1064 ASSERT (Context
!= NULL
);
1066 ConfigToken
= (WIFI_MGR_MAC_CONFIG_TOKEN
*) Context
;
1067 ASSERT (ConfigToken
->Nic
!= NULL
);
1068 ASSERT (ConfigToken
->Type
== TokenTypeDisconnectNetworkToken
);
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
;
1078 ConfigToken
->Nic
->ConnectState
= WifiMgrDisconnected
;
1079 ConfigToken
->Nic
->CurrentOperateNetwork
= NULL
;
1080 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, TRUE
, NULL
);
1081 ConfigToken
->Nic
->OneTimeDisconnectRequest
= FALSE
;
1084 // Disconnected network may not be in network list now, trigger a scan again!
1086 ConfigToken
->Nic
->OneTimeScanRequest
= TRUE
;
1089 WifiMgrFreeToken(ConfigToken
);
1094 Start disconnect operation, and send out a token to disconnect from current connected
1097 @param[in] Nic Pointer to the device data of the selected NIC.
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.
1106 WifiMgrDisconnectToNetwork (
1107 IN WIFI_MGR_DEVICE_DATA
*Nic
1112 WIFI_MGR_MAC_CONFIG_TOKEN
*ConfigToken
;
1113 EFI_80211_DISCONNECT_NETWORK_TOKEN
*DisconnectToken
;
1116 return EFI_INVALID_PARAMETER
;
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
;
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
;
1136 DisconnectToken
= ConfigToken
->Token
.DisconnectNetworkToken
;
1138 Status
= gBS
->CreateEvent (
1141 WifiMgrOnDisconnectFinished
,
1143 &DisconnectToken
->Event
1145 if (EFI_ERROR (Status
)) {
1146 WifiMgrFreeToken(ConfigToken
);
1147 gBS
->RestoreTPL (OldTpl
);
1151 Nic
->ConnectState
= WifiMgrDisconnectingToAp
;
1152 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, NULL
);
1154 Status
= Nic
->Wmp
->DisconnectNetwork (Nic
->Wmp
, DisconnectToken
);
1155 if (EFI_ERROR (Status
)) {
1156 if (Status
== EFI_NOT_FOUND
) {
1158 Nic
->ConnectState
= WifiMgrDisconnected
;
1159 Nic
->CurrentOperateNetwork
= NULL
;
1162 // This network is not in network list now, trigger a scan again!
1164 Nic
->OneTimeScanRequest
= TRUE
;
1167 // State has been changed from Connected to Disconnected
1169 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, TRUE
, NULL
);
1170 Status
= EFI_SUCCESS
;
1172 if (Nic
->OneTimeDisconnectRequest
) {
1174 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, L
"Disconnect Failed: Unexpected Error!");
1177 Nic
->ConnectState
= WifiMgrConnectedToAp
;
1178 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, NULL
);
1180 WifiMgrFreeToken(ConfigToken
);
1183 gBS
->RestoreTPL (OldTpl
);
1188 The state machine of the connection manager, periodically check the state and
1189 perform a corresponding operation.
1191 @param[in] Event The timer event to be triggered.
1192 @param[in] Context The context of the Nic device data.
1197 WifiMgrOnTimerTick (
1202 WIFI_MGR_DEVICE_DATA
*Nic
;
1204 EFI_ADAPTER_INFO_MEDIA_STATE LinkState
;
1205 WIFI_MGR_NETWORK_PROFILE
*Profile
;
1207 if (Context
== NULL
) {
1211 Nic
= (WIFI_MGR_DEVICE_DATA
*) Context
;
1212 NET_CHECK_SIGNATURE (Nic
, WIFI_MGR_DEVICE_DATA_SIGNATURE
);
1214 Status
= WifiMgrGetLinkState (Nic
, &LinkState
);
1215 if (EFI_ERROR (Status
)) {
1216 DEBUG ((DEBUG_INFO
, "[WiFi Connection Manager] Error: Failed to get link state!\n"));
1220 if (Nic
->LastLinkState
.MediaState
!= LinkState
.MediaState
) {
1221 if (Nic
->LastLinkState
.MediaState
== EFI_SUCCESS
&& LinkState
.MediaState
== EFI_NO_MEDIA
) {
1222 Nic
->HasDisconnectPendingNetwork
= TRUE
;
1224 Nic
->LastLinkState
.MediaState
= LinkState
.MediaState
;
1227 Nic
->ScanTickTime
++;
1228 if ((Nic
->ScanTickTime
> WIFI_SCAN_FREQUENCY
|| Nic
->OneTimeScanRequest
) &&
1229 Nic
->ScanState
== WifiMgrScanFinished
) {
1231 Nic
->OneTimeScanRequest
= FALSE
;
1232 Nic
->ScanTickTime
= 0;
1234 DEBUG ((DEBUG_INFO
, "[WiFi Connection Manager] Scan is triggered.\n"));
1235 WifiMgrStartScan (Nic
);
1238 if (Nic
->AvailableCount
> 0 && Nic
->ScanState
== WifiMgrScanFinished
) {
1240 switch (Nic
->ConnectState
) {
1241 case WifiMgrDisconnected
:
1243 if (Nic
->HasDisconnectPendingNetwork
) {
1244 Nic
->HasDisconnectPendingNetwork
= FALSE
;
1247 if (Nic
->ConnectPendingNetwork
!= NULL
) {
1249 Profile
= Nic
->ConnectPendingNetwork
;
1250 Status
= WifiMgrConnectToNetwork(Nic
, Profile
);
1251 Nic
->ConnectPendingNetwork
= NULL
;
1252 if (EFI_ERROR (Status
)) {
1254 // Some error happened, don't wait for a return connect token!
1256 Nic
->OneTimeConnectRequest
= FALSE
;
1261 case WifiMgrConnectingToAp
:
1264 case WifiMgrDisconnectingToAp
:
1267 case WifiMgrConnectedToAp
:
1269 if (Nic
->ConnectPendingNetwork
!= NULL
|| Nic
->HasDisconnectPendingNetwork
) {
1271 Status
= WifiMgrDisconnectToNetwork(Nic
);
1272 if (EFI_ERROR (Status
)) {
1274 // Some error happened, don't wait for a return disconnect token!
1276 Nic
->OneTimeDisconnectRequest
= FALSE
;