WifiConnectionMgrImpl.c 48 KB

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