2 The Mac Connection2 Protocol adapter functions for WiFi Connection Manager.
4 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
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.
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.
16 #include "WifiConnectionMgrDxe.h"
18 EFI_EAP_TYPE mEapAuthMethod
[] = {
24 EFI_EAP_TYPE mEapSecondAuthMethod
[] = {
29 The callback function for scan operation. This function updates networks
30 according to the latest scan result, and trigger UI refresh.
32 ASSERT when errors occur in config token.
34 @param[in] Event The GetNetworks token receive event.
35 @param[in] Context The context of the GetNetworks token.
40 WifiMgrOnScanFinished (
46 WIFI_MGR_MAC_CONFIG_TOKEN
*ConfigToken
;
47 WIFI_MGR_DEVICE_DATA
*Nic
;
48 WIFI_MGR_NETWORK_PROFILE
*Profile
;
49 EFI_80211_NETWORK
*Network
;
51 EFI_80211_NETWORK_DESCRIPTION
*NetworkDescription
;
52 EFI_80211_GET_NETWORKS_RESULT
*Result
;
55 BOOLEAN AKMSuiteSupported
;
56 BOOLEAN CipherSuiteSupported
;
60 ASSERT (Context
!= NULL
);
62 ConfigToken
= (WIFI_MGR_MAC_CONFIG_TOKEN
*) Context
;
63 ASSERT (ConfigToken
->Nic
!= NULL
);
64 ASSERT (ConfigToken
->Type
== TokenTypeGetNetworksToken
);
67 // It is the GetNetworks token, set scan state to "ScanFinished"
69 ConfigToken
->Nic
->ScanState
= WifiMgrScanFinished
;
71 ASSERT (ConfigToken
->Token
.GetNetworksToken
!= NULL
);
72 Result
= ConfigToken
->Token
.GetNetworksToken
->Result
;
73 Nic
= ConfigToken
->Nic
;
76 // Clean previous result, and update network list according to the scan result
78 Nic
->AvailableCount
= 0;
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
;
87 gBS
->SignalEvent (Nic
->Private
->NetworkListRefreshEvent
);
88 WifiMgrFreeToken(ConfigToken
);
92 for (Index
= 0; Index
< Result
->NumOfNetworkDesc
; Index
++) {
94 NetworkDescription
= Result
->NetworkDesc
+ Index
;
95 if (NetworkDescription
== NULL
) {
99 Network
= &NetworkDescription
->Network
;
100 if (Network
== NULL
|| Network
->SSId
.SSIdLen
== 0) {
104 Status
= WifiMgrCheckRSN (
106 Network
->CipherSuite
,
110 &CipherSuiteSupported
112 if (EFI_ERROR (Status
)) {
114 SecurityType
= SECURITY_TYPE_UNKNOWN
;
115 AKMSuiteSupported
= FALSE
;
116 CipherSuiteSupported
= FALSE
;
119 AsciiSSId
= (CHAR8
*) AllocateZeroPool(sizeof (CHAR8
) * (Network
->SSId
.SSIdLen
+ 1));
120 if (AsciiSSId
== NULL
) {
123 CopyMem(AsciiSSId
, (CHAR8
*) Network
->SSId
.SSId
, sizeof (CHAR8
) * Network
->SSId
.SSIdLen
);
124 *(AsciiSSId
+ Network
->SSId
.SSIdLen
) = '\0';
126 Profile
= WifiMgrGetProfileByAsciiSSId (AsciiSSId
, SecurityType
, &Nic
->ProfileList
);
127 if (Profile
== NULL
) {
129 if (Nic
->MaxProfileIndex
>= NETWORK_LIST_COUNT_MAX
) {
130 FreePool (AsciiSSId
);
135 // Create a new profile
137 Profile
= AllocateZeroPool (sizeof (WIFI_MGR_NETWORK_PROFILE
));
138 if (Profile
== NULL
) {
139 FreePool (AsciiSSId
);
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
++;
149 FreePool (AsciiSSId
);
152 //May receive duplicate networks in scan results, check if it has already
155 if (!Profile
->IsAvailable
) {
157 Profile
->IsAvailable
= TRUE
;
158 Profile
->SecurityType
= SecurityType
;
159 Profile
->AKMSuiteSupported
= AKMSuiteSupported
;
160 Profile
->CipherSuiteSupported
= CipherSuiteSupported
;
161 Profile
->NetworkQuality
= NetworkDescription
->NetworkQuality
;
162 Nic
->AvailableCount
++;
165 //Copy BSSType and SSId
167 CopyMem(&Profile
->Network
, Network
, sizeof (EFI_80211_NETWORK
));
172 if (Network
->AKMSuite
!= NULL
) {
174 if (Network
->AKMSuite
->AKMSuiteCount
== 0) {
175 DataSize
= sizeof (EFI_80211_AKM_SUITE_SELECTOR
);
177 DataSize
= sizeof (EFI_80211_AKM_SUITE_SELECTOR
) + sizeof (EFI_80211_SUITE_SELECTOR
)
178 * (Network
->AKMSuite
->AKMSuiteCount
- 1);
180 Profile
->Network
.AKMSuite
= (EFI_80211_AKM_SUITE_SELECTOR
*) AllocateZeroPool (DataSize
);
181 if (Profile
->Network
.AKMSuite
== NULL
) {
184 CopyMem (Profile
->Network
.AKMSuite
, Network
->AKMSuite
, DataSize
);
188 //Copy CipherSuite list
190 if (Network
->CipherSuite
!= NULL
) {
192 if (Network
->CipherSuite
->CipherSuiteCount
== 0) {
193 DataSize
= sizeof (EFI_80211_CIPHER_SUITE_SELECTOR
);
195 DataSize
= sizeof (EFI_80211_CIPHER_SUITE_SELECTOR
) + sizeof (EFI_80211_SUITE_SELECTOR
)
196 * (Network
->CipherSuite
->CipherSuiteCount
- 1);
198 Profile
->Network
.CipherSuite
= (EFI_80211_CIPHER_SUITE_SELECTOR
*) AllocateZeroPool (DataSize
);
199 if (Profile
->Network
.CipherSuite
== NULL
) {
202 CopyMem (Profile
->Network
.CipherSuite
, Network
->CipherSuite
, DataSize
);
206 // A duplicate network, update signal quality
208 if (Profile
->NetworkQuality
< NetworkDescription
->NetworkQuality
) {
209 Profile
->NetworkQuality
= NetworkDescription
->NetworkQuality
;
215 gBS
->SignalEvent (Nic
->Private
->NetworkListRefreshEvent
);
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.
221 if (Nic
->ConnectState
== WifiMgrConnectedToAp
&& Nic
->CurrentOperateNetwork
!= NULL
) {
222 if (!Nic
->CurrentOperateNetwork
->IsAvailable
) {
223 Nic
->CurrentOperateNetwork
->IsAvailable
= TRUE
;
224 Nic
->AvailableCount
++;
228 WifiMgrFreeToken(ConfigToken
);
232 Start scan operation, and send out a token to collect available networks.
234 @param[in] Nic Pointer to the device data of the selected NIC.
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.
245 IN WIFI_MGR_DEVICE_DATA
*Nic
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
;
258 if (Nic
== NULL
|| Nic
->Wmp
== NULL
) {
259 return EFI_INVALID_PARAMETER
;
262 if (Nic
->ScanState
== WifiMgrScanning
) {
263 return EFI_ALREADY_STARTED
;
266 Nic
->ScanState
= WifiMgrScanning
;
267 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
268 Status
= EFI_SUCCESS
;
269 HiddenSSIdList
= NULL
;
270 HiddenSSIdCount
= Nic
->Private
->HiddenNetworkCount
;
274 //create a new get network token
276 ConfigToken
= AllocateZeroPool (sizeof (WIFI_MGR_MAC_CONFIG_TOKEN
));
277 if (ConfigToken
== NULL
) {
278 gBS
->RestoreTPL (OldTpl
);
279 return EFI_OUT_OF_RESOURCES
;
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
;
290 GetNetworksToken
= ConfigToken
->Token
.GetNetworksToken
;
293 // There are some hidden networks to scan, add them into scan list
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
;
304 NET_LIST_FOR_EACH (Entry
, &Nic
->Private
->HiddenNetworkList
) {
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
);
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
;
321 GetNetworksToken
->Data
->NumOfSSID
= HiddenSSIdCount
;
322 CopyMem(GetNetworksToken
->Data
->SSIDList
, HiddenSSIdList
, HiddenSSIdCount
* sizeof (EFI_80211_SSID
));
323 FreePool(HiddenSSIdList
);
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
;
333 GetNetworksToken
->Data
->NumOfSSID
= 0;
337 //Create a handle when scan process ends
339 Status
= gBS
->CreateEvent (
342 WifiMgrOnScanFinished
,
344 &GetNetworksToken
->Event
346 if (EFI_ERROR (Status
)) {
347 WifiMgrFreeToken(ConfigToken
);
348 gBS
->RestoreTPL (OldTpl
);
355 Status
= Nic
->Wmp
->GetNetworks (Nic
->Wmp
, GetNetworksToken
);
356 if (EFI_ERROR (Status
)) {
357 Nic
->ScanState
= WifiMgrScanFinished
;
358 WifiMgrFreeToken(ConfigToken
);
359 gBS
->RestoreTPL (OldTpl
);
363 gBS
->RestoreTPL (OldTpl
);
368 Configure password to supplicant before connecting to a secured network.
370 @param[in] Nic Pointer to the device data of the selected NIC.
371 @param[in] Profile The target network to be connected.
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.
381 WifiMgrConfigPassword (
382 IN WIFI_MGR_DEVICE_DATA
*Nic
,
383 IN WIFI_MGR_NETWORK_PROFILE
*Profile
387 EFI_SUPPLICANT_PROTOCOL
*Supplicant
;
389 UINT8
*AsciiPassword
;
391 if (Nic
== NULL
|| Nic
->Supplicant
== NULL
|| Profile
== NULL
) {
392 return EFI_INVALID_PARAMETER
;
394 Supplicant
= Nic
->Supplicant
;
396 //Set SSId to supplicant
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
)) {
407 //Set password to supplicant
409 if (StrLen (Profile
->Password
) < PASSWORD_MIN_LEN
) {
410 return EFI_NOT_FOUND
;
412 AsciiPassword
= AllocateZeroPool ((StrLen(Profile
->Password
) + 1) * sizeof (UINT8
));
413 if (AsciiPassword
== NULL
) {
414 return EFI_OUT_OF_RESOURCES
;
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
);
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)
432 @param[in] Nic Pointer to the device data of the selected NIC.
433 @param[in] Profile The target network to be connected.
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.
444 IN WIFI_MGR_DEVICE_DATA
*Nic
,
445 IN WIFI_MGR_NETWORK_PROFILE
*Profile
449 EFI_EAP_CONFIGURATION_PROTOCOL
*EapConfig
;
450 EFI_EAP_TYPE EapAuthMethod
;
451 EFI_EAP_TYPE EapSecondAuthMethod
;
452 EFI_EAP_TYPE
*AuthMethodList
;
457 UINTN EncryptPasswordLen
;
458 CHAR8
*AsciiEncryptPassword
;
459 UINTN AuthMethodListSize
;
462 if (Nic
== NULL
|| Nic
->EapConfig
== NULL
|| Profile
== NULL
) {
463 return EFI_INVALID_PARAMETER
;
465 EapConfig
= Nic
->EapConfig
;
467 if (Profile
->EapAuthMethod
>= EAP_AUTH_METHOD_MAX
) {
468 return EFI_INVALID_PARAMETER
;
470 EapAuthMethod
= mEapAuthMethod
[Profile
->EapAuthMethod
];
472 if (EapAuthMethod
!= EFI_EAP_TYPE_EAPTLS
) {
473 if (Profile
->EapSecondAuthMethod
>= EAP_SEAUTH_METHOD_MAX
) {
474 return EFI_INVALID_PARAMETER
;
476 EapSecondAuthMethod
= mEapSecondAuthMethod
[Profile
->EapSecondAuthMethod
];
480 //The first time to get Supported Auth Method list, return the size.
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
) {
488 //No Supported Eap Auth Method
490 return EFI_UNSUPPORTED
;
491 } else if (Status
!= EFI_BUFFER_TOO_SMALL
) {
496 // The second time to get Supported Auth Method list, return the list.
497 // In current design, only EAPTLS, TTLS and PEAP are supported
499 AuthMethodList
= (EFI_EAP_TYPE
*) AllocateZeroPool(AuthMethodListSize
);
500 if (AuthMethodList
== NULL
) {
501 return EFI_OUT_OF_RESOURCES
;
503 Status
= EapConfig
->GetData (EapConfig
, EFI_EAP_TYPE_ATTRIBUTE
, EfiEapConfigEapSupportedAuthMethod
,
504 (VOID
*) AuthMethodList
, &AuthMethodListSize
);
505 if (EFI_ERROR (Status
)) {
506 FreePool (AuthMethodList
);
511 //Check if EapAuthMethod is in supported Auth Method list, if found, skip the loop.
513 for (Index
= 0; Index
< AuthMethodListSize
/ sizeof (EFI_EAP_TYPE
); Index
++) {
514 if (EapAuthMethod
== AuthMethodList
[Index
]) {
518 if (Index
== AuthMethodListSize
/ sizeof (EFI_EAP_TYPE
)) {
519 FreePool (AuthMethodList
);
520 return EFI_UNSUPPORTED
;
522 FreePool (AuthMethodList
);
525 // Set Identity to Eap peer, Mandatory field for PEAP and TTLS
527 if (StrLen (Profile
->EapIdentity
) > 0) {
529 IdentitySize
= sizeof(CHAR8
) * (StrLen(Profile
->EapIdentity
) + 1);
530 Identity
= AllocateZeroPool (IdentitySize
);
531 if (Identity
== NULL
) {
532 return EFI_OUT_OF_RESOURCES
;
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
)) {
543 if (EapAuthMethod
!= EFI_EAP_TYPE_EAPTLS
) {
544 return EFI_INVALID_PARAMETER
;
549 //Set Auth Method to Eap peer, Mandatory field
551 Status
= EapConfig
->SetData (EapConfig
, EFI_EAP_TYPE_ATTRIBUTE
, EfiEapConfigEapAuthMethod
,
552 (VOID
*) &EapAuthMethod
, sizeof (EapAuthMethod
));
553 if (EFI_ERROR(Status
)) {
557 if (EapAuthMethod
== EFI_EAP_TYPE_TTLS
|| EapAuthMethod
== EFI_EAP_TYPE_PEAP
) {
559 Status
= EapConfig
->SetData (EapConfig
, EapAuthMethod
, EfiEapConfigEap2ndAuthMethod
,
560 (VOID
*) &EapSecondAuthMethod
, sizeof (EapSecondAuthMethod
));
561 if (EFI_ERROR(Status
)) {
566 // Set Password to Eap peer
568 if (StrLen (Profile
->EapPassword
) < PASSWORD_MIN_LEN
) {
570 DEBUG ((DEBUG_ERROR
, "[WiFi Connection Manager] Error: No Eap Password for Network: %s.\n", Profile
->SSId
));
571 return EFI_INVALID_PARAMETER
;
574 PasswordSize
= sizeof (CHAR16
) * (StrLen (Profile
->EapPassword
) + 1);
575 Password
= AllocateZeroPool (PasswordSize
);
576 if (Password
== NULL
) {
577 return EFI_OUT_OF_RESOURCES
;
579 StrCpyS (Password
, PasswordSize
, Profile
->EapPassword
);;
580 Status
= EapConfig
->SetData (EapConfig
, EFI_EAP_TYPE_MSCHAPV2
, EfiEapConfigEapMSChapV2Password
,
581 (VOID
*) Password
, PasswordSize
);
582 ZeroMem (Password
, PasswordSize
);
584 if (EFI_ERROR (Status
)) {
589 //If CA cert is required, set it to Eap peer
591 if (Profile
->CACertData
!= NULL
) {
593 Status
= EapConfig
->SetData (EapConfig
, EapAuthMethod
, EfiEapConfigEapTlsCACert
,
594 Profile
->CACertData
, Profile
->CACertSize
);
595 if (EFI_ERROR(Status
)) {
599 return EFI_INVALID_PARAMETER
;
601 } else if (EapAuthMethod
== EFI_EAP_TYPE_EAPTLS
) {
604 //Set CA cert to Eap peer
606 if (Profile
->CACertData
== NULL
) {
607 return EFI_INVALID_PARAMETER
;
609 Status
= EapConfig
->SetData (EapConfig
, EFI_EAP_TYPE_EAPTLS
, EfiEapConfigEapTlsCACert
,
610 Profile
->CACertData
, Profile
->CACertSize
);
611 if (EFI_ERROR(Status
)) {
616 //Set Client cert to Eap peer
618 if (Profile
->ClientCertData
== NULL
) {
619 return EFI_INVALID_PARAMETER
;
621 Status
= EapConfig
->SetData (EapConfig
, EFI_EAP_TYPE_EAPTLS
, EfiEapConfigEapTlsClientCert
,
622 Profile
->ClientCertData
, Profile
->ClientCertSize
);
623 if (EFI_ERROR(Status
)) {
628 //Set Private key to Eap peer
630 if (Profile
->PrivateKeyData
== NULL
) {
632 DEBUG ((DEBUG_ERROR
, "[WiFi Connection Manager] Error: No Private Key for Network: %s.\n", Profile
->SSId
));
633 return EFI_INVALID_PARAMETER
;
636 Status
= EapConfig
->SetData (EapConfig
, EFI_EAP_TYPE_EAPTLS
, EfiEapConfigEapTlsClientPrivateKeyFile
,
637 Profile
->PrivateKeyData
, Profile
->PrivateKeyDataSize
);
638 if (EFI_ERROR(Status
)) {
642 if (StrLen (Profile
->PrivateKeyPassword
) > 0) {
644 EncryptPasswordLen
= StrLen (Profile
->PrivateKeyPassword
);
645 AsciiEncryptPassword
= AllocateZeroPool(EncryptPasswordLen
+ 1);
646 if (AsciiEncryptPassword
== NULL
) {
647 return EFI_OUT_OF_RESOURCES
;
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
)) {
655 ZeroMem (AsciiEncryptPassword
, EncryptPasswordLen
+ 1);
656 FreePool (AsciiEncryptPassword
);
660 ZeroMem (AsciiEncryptPassword
, EncryptPasswordLen
+ 1);
661 FreePool (AsciiEncryptPassword
);
664 return EFI_INVALID_PARAMETER
;
671 Get current link state from low layer.
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.
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.
683 WifiMgrGetLinkState (
684 IN WIFI_MGR_DEVICE_DATA
*Nic
,
685 OUT EFI_ADAPTER_INFO_MEDIA_STATE
*LinkState
691 EFI_ADAPTER_INFO_MEDIA_STATE
*UndiState
;
692 EFI_ADAPTER_INFORMATION_PROTOCOL
*Aip
;
694 if (Nic
== NULL
|| LinkState
== NULL
) {
695 return EFI_INVALID_PARAMETER
;
698 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
699 Status
= gBS
->OpenProtocol (
700 Nic
->ControllerHandle
,
701 &gEfiAdapterInformationProtocolGuid
,
704 Nic
->ControllerHandle
,
705 EFI_OPEN_PROTOCOL_GET_PROTOCOL
707 if (EFI_ERROR (Status
)) {
708 gBS
->RestoreTPL (OldTpl
);
709 return EFI_UNSUPPORTED
;
712 Status
= Aip
->GetInformation(
714 &gEfiAdapterInfoMediaStateGuid
,
715 (VOID
**) &UndiState
,
718 if (EFI_ERROR (Status
)) {
719 gBS
->RestoreTPL (OldTpl
);
722 gBS
->RestoreTPL (OldTpl
);
724 CopyMem (LinkState
, UndiState
, sizeof (EFI_ADAPTER_INFO_MEDIA_STATE
));
725 FreePool (UndiState
);
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.
734 @param[in] Nic Pointer to the device data of the selected NIC.
735 @param[in] Profile The target network to be connected.
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.
743 WifiMgrPrepareConnection (
744 IN WIFI_MGR_DEVICE_DATA
*Nic
,
745 IN WIFI_MGR_NETWORK_PROFILE
*Profile
750 BOOLEAN AKMSuiteSupported
;
751 BOOLEAN CipherSuiteSupported
;
753 if (Profile
== NULL
|| Nic
== NULL
) {
754 return EFI_INVALID_PARAMETER
;
757 Status
= WifiMgrCheckRSN (Profile
->Network
.AKMSuite
, Profile
->Network
.CipherSuite
,
758 Nic
, &SecurityType
, &AKMSuiteSupported
, &CipherSuiteSupported
);
759 if (EFI_ERROR (Status
)) {
763 if (AKMSuiteSupported
&& CipherSuiteSupported
) {
764 switch (SecurityType
) {
765 case SECURITY_TYPE_WPA2_PERSONAL
:
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!");
778 case SECURITY_TYPE_WPA2_ENTERPRISE
:
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!");
791 case SECURITY_TYPE_NONE
:
795 return EFI_UNSUPPORTED
;
798 return EFI_UNSUPPORTED
;
805 The callback function for connect operation.
807 ASSERT when errors occur in config token.
809 @param[in] Event The Connect token receive event.
810 @param[in] Context The context of the connect token.
815 WifiMgrOnConnectFinished (
821 WIFI_MGR_MAC_CONFIG_TOKEN
*ConfigToken
;
822 WIFI_MGR_NETWORK_PROFILE
*ConnectedProfile
;
827 ASSERT (Context
!= NULL
);
829 ConnectedProfile
= NULL
;
830 ConfigToken
= (WIFI_MGR_MAC_CONFIG_TOKEN
*) Context
;
831 ASSERT (ConfigToken
->Nic
!= NULL
);
833 ConfigToken
->Nic
->ConnectState
= WifiMgrDisconnected
;
834 ASSERT (ConfigToken
->Type
== TokenTypeConnectNetworkToken
);
836 ASSERT (ConfigToken
->Token
.ConnectNetworkToken
!= NULL
);
837 if (ConfigToken
->Token
.ConnectNetworkToken
->Status
!= EFI_SUCCESS
) {
839 if (ConfigToken
->Nic
->OneTimeConnectRequest
) {
841 // Only update message for user triggered connection
843 if (ConfigToken
->Token
.ConnectNetworkToken
->Status
== EFI_ACCESS_DENIED
) {
845 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, L
"Connect Failed: Permission Denied!");
847 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, L
"Connect Failed!");
849 ConfigToken
->Nic
->OneTimeConnectRequest
= FALSE
;
851 ConfigToken
->Nic
->CurrentOperateNetwork
= NULL
;
855 if (ConfigToken
->Token
.ConnectNetworkToken
->ResultCode
!= ConnectSuccess
) {
857 if (ConfigToken
->Nic
->OneTimeConnectRequest
) {
859 if (ConfigToken
->Token
.ConnectNetworkToken
->ResultCode
== ConnectFailedReasonUnspecified
) {
860 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, L
"Connect Failed: Wrong Password or Unexpected Error!");
862 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, L
"Connect Failed!");
868 if (ConfigToken
->Token
.ConnectNetworkToken
->Data
== NULL
||
869 ConfigToken
->Token
.ConnectNetworkToken
->Data
->Network
== NULL
) {
872 // An unexpected error occurs, tell low layer to perform a disconnect
874 ConfigToken
->Nic
->HasDisconnectPendingNetwork
= TRUE
;
875 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, NULL
);
880 // A correct connect token received, terminate the connection process
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
;
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
);
897 CopyMem(AsciiSSId
, ConfigToken
->Token
.ConnectNetworkToken
->Data
->Network
->SSId
.SSId
, SSIdLen
);
898 *(AsciiSSId
+ SSIdLen
) = '\0';
900 ConnectedProfile
= WifiMgrGetProfileByAsciiSSId(AsciiSSId
, SecurityType
, &ConfigToken
->Nic
->ProfileList
);
902 if (ConnectedProfile
== NULL
) {
903 ConfigToken
->Nic
->HasDisconnectPendingNetwork
= TRUE
;
904 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, NULL
);
908 ConfigToken
->Nic
->ConnectState
= WifiMgrConnectedToAp
;
909 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, TRUE
, NULL
);
913 if (ConfigToken
->Nic
->ConnectState
== WifiMgrDisconnected
) {
914 ConfigToken
->Nic
->CurrentOperateNetwork
= NULL
;
916 ConfigToken
->Nic
->OneTimeConnectRequest
= FALSE
;
917 WifiMgrFreeToken(ConfigToken
);
921 Start connect operation, and send out a token to connect to a target network.
923 @param[in] Nic Pointer to the device data of the selected NIC.
924 @param[in] Profile The target network to be connected.
926 @retval EFI_SUCCESS The operation is completed.
927 @retval EFI_ALREADY_STARTED Already in "connected" state, need to perform a disconnect
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.
935 WifiMgrConnectToNetwork (
936 IN WIFI_MGR_DEVICE_DATA
*Nic
,
937 IN WIFI_MGR_NETWORK_PROFILE
*Profile
942 EFI_ADAPTER_INFO_MEDIA_STATE LinkState
;
943 WIFI_MGR_MAC_CONFIG_TOKEN
*ConfigToken
;
944 EFI_80211_CONNECT_NETWORK_TOKEN
*ConnectToken
;
946 if (Nic
== NULL
|| Nic
->Wmp
== NULL
|| Profile
== NULL
) {
947 return EFI_INVALID_PARAMETER
;
950 Status
= WifiMgrGetLinkState (Nic
, &LinkState
);
951 if (EFI_ERROR (Status
)) {
954 if (LinkState
.MediaState
== EFI_SUCCESS
) {
955 return EFI_ALREADY_STARTED
;
958 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
959 Status
= WifiMgrPrepareConnection (Nic
, Profile
);
960 if (EFI_ERROR (Status
)) {
961 gBS
->RestoreTPL (OldTpl
);
966 // Create a new connect token
968 ConfigToken
= AllocateZeroPool (sizeof (WIFI_MGR_MAC_CONFIG_TOKEN
));
969 if (ConfigToken
== NULL
) {
970 Status
= EFI_OUT_OF_RESOURCES
;
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
) {
981 ConnectToken
= ConfigToken
->Token
.ConnectNetworkToken
;
982 ConnectToken
->Data
= AllocateZeroPool (sizeof (EFI_80211_CONNECT_NETWORK_DATA
));
983 if (ConnectToken
->Data
== NULL
) {
987 ConnectToken
->Data
->Network
= AllocateZeroPool (sizeof (EFI_80211_NETWORK
));
988 if (ConnectToken
->Data
->Network
== NULL
) {
991 CopyMem(ConnectToken
->Data
->Network
, &Profile
->Network
, sizeof (EFI_80211_NETWORK
));
994 // Add event handle and start to connect
996 Status
= gBS
->CreateEvent (
999 WifiMgrOnConnectFinished
,
1001 &ConnectToken
->Event
1003 if (EFI_ERROR (Status
)) {
1007 Nic
->ConnectState
= WifiMgrConnectingToAp
;
1008 Nic
->CurrentOperateNetwork
= Profile
;
1009 WifiMgrUpdateConnectMessage (Nic
, FALSE
, NULL
);
1012 //Start Connecting ...
1014 Status
= Nic
->Wmp
->ConnectNetwork (Nic
->Wmp
, ConnectToken
);
1017 // Erase secrets after connection is triggered
1019 WifiMgrCleanProfileSecrets (Profile
);
1021 if (EFI_ERROR (Status
)) {
1022 if (Status
== EFI_ALREADY_STARTED
) {
1023 Nic
->ConnectState
= WifiMgrConnectedToAp
;
1024 WifiMgrUpdateConnectMessage (Nic
, TRUE
, NULL
);
1027 Nic
->ConnectState
= WifiMgrDisconnected
;
1028 Nic
->CurrentOperateNetwork
= NULL
;
1030 if (Nic
->OneTimeConnectRequest
) {
1031 if (Status
== EFI_NOT_FOUND
) {
1032 WifiMgrUpdateConnectMessage (Nic
, FALSE
, L
"Connect Failed: Not Available!");
1034 WifiMgrUpdateConnectMessage (Nic
, FALSE
, L
"Connect Failed: Unexpected Error!");
1043 if (EFI_ERROR (Status
)) {
1044 WifiMgrFreeToken (ConfigToken
);
1046 gBS
->RestoreTPL (OldTpl
);
1048 DEBUG ((DEBUG_INFO
, "[WiFi Connection Manager] WifiMgrConnectToNetwork: %r\n", Status
));
1053 The callback function for disconnect operation.
1055 ASSERT when errors occur in config token.
1057 @param[in] Event The Disconnect token receive event.
1058 @param[in] Context The context of the Disconnect token.
1063 WifiMgrOnDisconnectFinished (
1068 WIFI_MGR_MAC_CONFIG_TOKEN
*ConfigToken
;
1070 ASSERT (Context
!= NULL
);
1072 ConfigToken
= (WIFI_MGR_MAC_CONFIG_TOKEN
*) Context
;
1073 ASSERT (ConfigToken
->Nic
!= NULL
);
1074 ASSERT (ConfigToken
->Type
== TokenTypeDisconnectNetworkToken
);
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
;
1084 ConfigToken
->Nic
->ConnectState
= WifiMgrDisconnected
;
1085 ConfigToken
->Nic
->CurrentOperateNetwork
= NULL
;
1086 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, TRUE
, NULL
);
1087 ConfigToken
->Nic
->OneTimeDisconnectRequest
= FALSE
;
1090 // Disconnected network may not be in network list now, trigger a scan again!
1092 ConfigToken
->Nic
->OneTimeScanRequest
= TRUE
;
1095 WifiMgrFreeToken(ConfigToken
);
1100 Start disconnect operation, and send out a token to disconnect from current connected
1103 @param[in] Nic Pointer to the device data of the selected NIC.
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.
1112 WifiMgrDisconnectToNetwork (
1113 IN WIFI_MGR_DEVICE_DATA
*Nic
1118 WIFI_MGR_MAC_CONFIG_TOKEN
*ConfigToken
;
1119 EFI_80211_DISCONNECT_NETWORK_TOKEN
*DisconnectToken
;
1122 return EFI_INVALID_PARAMETER
;
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
;
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
;
1142 DisconnectToken
= ConfigToken
->Token
.DisconnectNetworkToken
;
1144 Status
= gBS
->CreateEvent (
1147 WifiMgrOnDisconnectFinished
,
1149 &DisconnectToken
->Event
1151 if (EFI_ERROR (Status
)) {
1152 WifiMgrFreeToken(ConfigToken
);
1153 gBS
->RestoreTPL (OldTpl
);
1157 Nic
->ConnectState
= WifiMgrDisconnectingToAp
;
1158 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, NULL
);
1160 Status
= Nic
->Wmp
->DisconnectNetwork (Nic
->Wmp
, DisconnectToken
);
1161 if (EFI_ERROR (Status
)) {
1162 if (Status
== EFI_NOT_FOUND
) {
1164 Nic
->ConnectState
= WifiMgrDisconnected
;
1165 Nic
->CurrentOperateNetwork
= NULL
;
1168 // This network is not in network list now, trigger a scan again!
1170 Nic
->OneTimeScanRequest
= TRUE
;
1173 // State has been changed from Connected to Disconnected
1175 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, TRUE
, NULL
);
1176 Status
= EFI_SUCCESS
;
1178 if (Nic
->OneTimeDisconnectRequest
) {
1180 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, L
"Disconnect Failed: Unexpected Error!");
1183 Nic
->ConnectState
= WifiMgrConnectedToAp
;
1184 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, NULL
);
1186 WifiMgrFreeToken(ConfigToken
);
1189 gBS
->RestoreTPL (OldTpl
);
1194 The state machine of the connection manager, periodically check the state and
1195 perform a corresponding operation.
1197 @param[in] Event The timer event to be triggered.
1198 @param[in] Context The context of the Nic device data.
1203 WifiMgrOnTimerTick (
1208 WIFI_MGR_DEVICE_DATA
*Nic
;
1210 EFI_ADAPTER_INFO_MEDIA_STATE LinkState
;
1211 WIFI_MGR_NETWORK_PROFILE
*Profile
;
1213 if (Context
== NULL
) {
1217 Nic
= (WIFI_MGR_DEVICE_DATA
*) Context
;
1218 NET_CHECK_SIGNATURE (Nic
, WIFI_MGR_DEVICE_DATA_SIGNATURE
);
1220 Status
= WifiMgrGetLinkState (Nic
, &LinkState
);
1221 if (EFI_ERROR (Status
)) {
1222 DEBUG ((DEBUG_INFO
, "[WiFi Connection Manager] Error: Failed to get link state!\n"));
1226 if (Nic
->LastLinkState
.MediaState
!= LinkState
.MediaState
) {
1227 if (Nic
->LastLinkState
.MediaState
== EFI_SUCCESS
&& LinkState
.MediaState
== EFI_NO_MEDIA
) {
1228 Nic
->HasDisconnectPendingNetwork
= TRUE
;
1230 Nic
->LastLinkState
.MediaState
= LinkState
.MediaState
;
1233 Nic
->ScanTickTime
++;
1234 if ((Nic
->ScanTickTime
> WIFI_SCAN_FREQUENCY
|| Nic
->OneTimeScanRequest
) &&
1235 Nic
->ScanState
== WifiMgrScanFinished
) {
1237 Nic
->OneTimeScanRequest
= FALSE
;
1238 Nic
->ScanTickTime
= 0;
1240 DEBUG ((DEBUG_INFO
, "[WiFi Connection Manager] Scan is triggered.\n"));
1241 WifiMgrStartScan (Nic
);
1244 if (Nic
->AvailableCount
> 0 && Nic
->ScanState
== WifiMgrScanFinished
) {
1246 switch (Nic
->ConnectState
) {
1247 case WifiMgrDisconnected
:
1249 if (Nic
->HasDisconnectPendingNetwork
) {
1250 Nic
->HasDisconnectPendingNetwork
= FALSE
;
1253 if (Nic
->ConnectPendingNetwork
!= NULL
) {
1255 Profile
= Nic
->ConnectPendingNetwork
;
1256 Status
= WifiMgrConnectToNetwork(Nic
, Profile
);
1257 Nic
->ConnectPendingNetwork
= NULL
;
1258 if (EFI_ERROR (Status
)) {
1260 // Some error happened, don't wait for a return connect token!
1262 Nic
->OneTimeConnectRequest
= FALSE
;
1267 case WifiMgrConnectingToAp
:
1270 case WifiMgrDisconnectingToAp
:
1273 case WifiMgrConnectedToAp
:
1275 if (Nic
->ConnectPendingNetwork
!= NULL
|| Nic
->HasDisconnectPendingNetwork
) {
1277 Status
= WifiMgrDisconnectToNetwork(Nic
);
1278 if (EFI_ERROR (Status
)) {
1280 // Some error happened, don't wait for a return disconnect token!
1282 Nic
->OneTimeDisconnectRequest
= FALSE
;