]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrDriver.c
NetworkPkg: Fix Duplicate FreePool Error in WCM
[mirror_edk2.git] / NetworkPkg / WifiConnectionManagerDxe / WifiConnectionMgrDriver.c
1 /** @file
2 The driver binding protocol for the WiFi Connection Manager.
3
4 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
5
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "WifiConnectionMgrDxe.h"
17
18 ///
19 /// Driver Binding Protocol instance
20 ///
21 EFI_DRIVER_BINDING_PROTOCOL gWifiMgrDxeDriverBinding = {
22 WifiMgrDxeDriverBindingSupported,
23 WifiMgrDxeDriverBindingStart,
24 WifiMgrDxeDriverBindingStop,
25 WIFI_MGR_DXE_VERSION,
26 NULL,
27 NULL
28 };
29
30 //
31 //The private global data for WiFi Connection Manager
32 //
33 WIFI_MGR_PRIVATE_DATA *mPrivate = NULL;
34
35 //
36 //The private guid to identify WiFi Connection Manager
37 //
38 EFI_GUID mEfiWifiMgrPrivateGuid = EFI_WIFIMGR_PRIVATE_GUID;
39
40 //
41 //The Hii config guids
42 //
43 EFI_GUID gWifiConfigFormSetGuid = WIFI_CONNECTION_MANAGER_CONFIG_GUID;
44 EFI_GUID mWifiConfigNetworkListRefreshGuid = WIFI_CONFIG_NETWORK_LIST_REFRESH_GUID;
45 EFI_GUID mWifiConfigConnectFormRefreshGuid = WIFI_CONFIG_CONNECT_FORM_REFRESH_GUID;
46 EFI_GUID mWifiConfigMainFormRefreshGuid = WIFI_CONFIG_MAIN_FORM_REFRESH_GUID;
47
48 /**
49 Tests to see if this driver supports a given controller. If a child device is provided,
50 it further tests to see if this driver supports creating a handle for the specified child device.
51
52 This function checks to see if the driver specified by This supports the device specified by
53 ControllerHandle. Drivers will typically use the device path attached to
54 ControllerHandle and/or the services from the bus I/O abstraction attached to
55 ControllerHandle to determine if the driver supports ControllerHandle. This function
56 may be called many times during platform initialization. In order to reduce boot times, the tests
57 performed by this function must be very small, and take as little time as possible to execute. This
58 function must not change the state of any hardware devices, and this function must be aware that the
59 device specified by ControllerHandle may already be managed by the same driver or a
60 different driver. This function must match its calls to AllocatePages() with FreePages(),
61 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
62 Because ControllerHandle may have been previously started by the same driver, if a protocol is
63 already in the opened state, then it must not be closed with CloseProtocol(). This is required
64 to guarantee the state of ControllerHandle is not modified by this function.
65
66 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
67 @param[in] ControllerHandle The handle of the controller to test. This handle
68 must support a protocol interface that supplies
69 an I/O abstraction to the driver.
70 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
71 parameter is ignored by device drivers, and is optional for bus
72 drivers. For bus drivers, if this parameter is not NULL, then
73 the bus driver must determine if the bus controller specified
74 by ControllerHandle and the child controller specified
75 by RemainingDevicePath are both supported by this
76 bus driver.
77
78 @retval EFI_SUCCESS The device specified by ControllerHandle and
79 RemainingDevicePath is supported by the driver specified by This.
80 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
81 RemainingDevicePath is already being managed by the driver
82 specified by This.
83 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
84 RemainingDevicePath is already being managed by a different
85 driver or an application that requires exclusive access.
86 Currently not implemented.
87 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
88 RemainingDevicePath is not supported by the driver specified by This.
89
90 **/
91 EFI_STATUS
92 EFIAPI
93 WifiMgrDxeDriverBindingSupported (
94 IN EFI_DRIVER_BINDING_PROTOCOL *This,
95 IN EFI_HANDLE ControllerHandle,
96 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
97 )
98 {
99 EFI_STATUS Status;
100
101 Status = gBS->OpenProtocol (
102 ControllerHandle,
103 &mEfiWifiMgrPrivateGuid,
104 NULL,
105 This->DriverBindingHandle,
106 ControllerHandle,
107 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
108 );
109 if (!EFI_ERROR (Status)) {
110 return EFI_ALREADY_STARTED;
111 }
112
113 //
114 // Test for the wireless MAC connection 2 protocol
115 //
116 return gBS->OpenProtocol (
117 ControllerHandle,
118 &gEfiWiFi2ProtocolGuid,
119 NULL,
120 This->DriverBindingHandle,
121 ControllerHandle,
122 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
123 );
124 }
125
126 /**
127 Starts a device controller or a bus controller.
128
129 The Start() function is designed to be invoked from the EFI boot service ConnectController().
130 As a result, much of the error checking on the parameters to Start() has been moved into this
131 common boot service. It is legal to call Start() from other locations,
132 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
133 1. ControllerHandle must be a valid EFI_HANDLE.
134 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
135 EFI_DEVICE_PATH_PROTOCOL.
136 3. Prior to calling Start(), the Supported() function for the driver specified by This must
137 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
138
139 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
140 @param[in] ControllerHandle The handle of the controller to start. This handle
141 must support a protocol interface that supplies
142 an I/O abstraction to the driver.
143 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
144 parameter is ignored by device drivers, and is optional for bus
145 drivers. For a bus driver, if this parameter is NULL, then handles
146 for all the children of Controller are created by this driver.
147 If this parameter is not NULL and the first Device Path Node is
148 not the End of Device Path Node, then only the handle for the
149 child device specified by the first Device Path Node of
150 RemainingDevicePath is created by this driver.
151 If the first Device Path Node of RemainingDevicePath is
152 the End of Device Path Node, no child handle is created by this
153 driver.
154
155 @retval EFI_SUCCESS The device was started.
156 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
157 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
158 @retval Others The driver failded to start the device.
159
160 **/
161 EFI_STATUS
162 EFIAPI
163 WifiMgrDxeDriverBindingStart (
164 IN EFI_DRIVER_BINDING_PROTOCOL *This,
165 IN EFI_HANDLE ControllerHandle,
166 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
167 )
168 {
169 EFI_STATUS Status;
170 EFI_TPL OldTpl;
171 UINTN AddressSize;
172 WIFI_MGR_DEVICE_DATA *Nic;
173 EFI_WIRELESS_MAC_CONNECTION_II_PROTOCOL *Wmp;
174 EFI_SUPPLICANT_PROTOCOL *Supplicant;
175 EFI_EAP_CONFIGURATION_PROTOCOL *EapConfig;
176
177 Nic = NULL;
178
179 //
180 //Open Protocols
181 //
182 Status = gBS->OpenProtocol (
183 ControllerHandle,
184 &gEfiWiFi2ProtocolGuid,
185 (VOID**) &Wmp,
186 This->DriverBindingHandle,
187 ControllerHandle,
188 EFI_OPEN_PROTOCOL_BY_DRIVER
189 );
190 if (EFI_ERROR (Status)) {
191 return Status;
192 }
193
194 Status = gBS->OpenProtocol (
195 ControllerHandle,
196 &gEfiSupplicantProtocolGuid,
197 (VOID**) &Supplicant,
198 This->DriverBindingHandle,
199 ControllerHandle,
200 EFI_OPEN_PROTOCOL_BY_DRIVER
201 );
202 if (EFI_ERROR (Status)) {
203 Supplicant = NULL;
204 }
205
206 Status = gBS->OpenProtocol (
207 ControllerHandle,
208 &gEfiEapConfigurationProtocolGuid,
209 (VOID**) &EapConfig,
210 This->DriverBindingHandle,
211 ControllerHandle,
212 EFI_OPEN_PROTOCOL_BY_DRIVER
213 );
214 if (EFI_ERROR (Status)) {
215 EapConfig = NULL;
216 }
217
218 //
219 //Initialize Nic device data
220 //
221 Nic = AllocateZeroPool (sizeof (WIFI_MGR_DEVICE_DATA));
222 if (Nic == NULL) {
223 Status = EFI_OUT_OF_RESOURCES;
224 goto ERROR1;
225 }
226 Nic->Signature = WIFI_MGR_DEVICE_DATA_SIGNATURE;
227 Nic->DriverHandle = This->DriverBindingHandle;
228 Nic->ControllerHandle = ControllerHandle;
229 Nic->Private = mPrivate;
230 Nic->Wmp = Wmp;
231 Nic->Supplicant = Supplicant;
232 Nic->EapConfig = EapConfig;
233 Nic->UserSelectedProfile = NULL;
234 Nic->OneTimeScanRequest = FALSE;
235 Nic->ScanTickTime = WIFI_SCAN_FREQUENCY; //Initialize the first scan
236
237 if (Nic->Supplicant != NULL) {
238 WifiMgrGetSupportedSuites(Nic);
239 }
240
241 InitializeListHead (&Nic->ProfileList);
242
243 //
244 // Record the MAC address of the incoming NIC.
245 //
246 Status = NetLibGetMacAddress (
247 ControllerHandle,
248 (EFI_MAC_ADDRESS*) &Nic->MacAddress,
249 &AddressSize
250 );
251 if (EFI_ERROR (Status)) {
252 goto ERROR2;
253 }
254
255 //
256 // Create and start the timer for the status check
257 //
258 Status = gBS->CreateEvent (
259 EVT_NOTIFY_SIGNAL | EVT_TIMER,
260 TPL_CALLBACK,
261 WifiMgrOnTimerTick,
262 Nic,
263 &Nic->TickTimer
264 );
265 if (EFI_ERROR (Status)) {
266 goto ERROR2;
267 }
268
269 Status = gBS->SetTimer (Nic->TickTimer, TimerPeriodic, EFI_TIMER_PERIOD_MILLISECONDS(500));
270 if (EFI_ERROR (Status)) {
271 goto ERROR3;
272 }
273
274 Nic->ConnectState = WifiMgrDisconnected;
275 Nic->ScanState = WifiMgrScanFinished;
276
277 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
278 InsertTailList (&mPrivate->NicList, &Nic->Link);
279 Nic->NicIndex = mPrivate->NicCount ++;
280 if (mPrivate->CurrentNic == NULL) {
281 mPrivate->CurrentNic = Nic;
282 }
283 gBS->RestoreTPL (OldTpl);
284
285 Status = gBS->InstallProtocolInterface (
286 &ControllerHandle,
287 &mEfiWifiMgrPrivateGuid,
288 EFI_NATIVE_INTERFACE,
289 &Nic->WifiMgrIdentifier
290 );
291 if (EFI_ERROR (Status)) {
292 goto ERROR4;
293 }
294
295 return EFI_SUCCESS;
296
297 ERROR4:
298
299 gBS->SetTimer (Nic->TickTimer, TimerCancel, 0);
300 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
301 RemoveEntryList (&Nic->Link);
302 mPrivate->NicCount--;
303 gBS->RestoreTPL (OldTpl);
304
305 ERROR3:
306
307 gBS->CloseEvent (Nic->TickTimer);
308
309 ERROR2:
310
311 if (Nic->Supplicant != NULL) {
312 if (Nic->SupportedSuites.SupportedAKMSuites != NULL) {
313 FreePool (Nic->SupportedSuites.SupportedAKMSuites);
314 }
315 if (Nic->SupportedSuites.SupportedSwCipherSuites != NULL) {
316 FreePool (Nic->SupportedSuites.SupportedSwCipherSuites);
317 }
318 if (Nic->SupportedSuites.SupportedHwCipherSuites != NULL) {
319 FreePool (Nic->SupportedSuites.SupportedHwCipherSuites);
320 }
321 }
322 FreePool (Nic);
323
324 ERROR1:
325
326 if (Supplicant != NULL) {
327 gBS->CloseProtocol (
328 ControllerHandle,
329 &gEfiSupplicantProtocolGuid,
330 This->DriverBindingHandle,
331 ControllerHandle
332 );
333 }
334
335 if (EapConfig != NULL) {
336 gBS->CloseProtocol (
337 ControllerHandle,
338 &gEfiEapConfigurationProtocolGuid,
339 This->DriverBindingHandle,
340 ControllerHandle
341 );
342 }
343
344 gBS->CloseProtocol (
345 ControllerHandle,
346 &gEfiWiFi2ProtocolGuid,
347 This->DriverBindingHandle,
348 ControllerHandle
349 );
350
351 return Status;
352 }
353
354 /**
355 Stops a device controller or a bus controller.
356
357 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
358 As a result, much of the error checking on the parameters to Stop() has been moved
359 into this common boot service. It is legal to call Stop() from other locations,
360 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
361 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
362 same driver's Start() function.
363 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
364 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
365 Start() function, and the Start() function must have called OpenProtocol() on
366 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
367
368 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
369 @param[in] ControllerHandle A handle to the device being stopped. The handle must
370 support a bus specific I/O protocol for the driver
371 to use to stop the device.
372 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
373 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
374 if NumberOfChildren is 0.
375
376 @retval EFI_SUCCESS The device was stopped.
377 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
378
379 **/
380 EFI_STATUS
381 EFIAPI
382 WifiMgrDxeDriverBindingStop (
383 IN EFI_DRIVER_BINDING_PROTOCOL *This,
384 IN EFI_HANDLE ControllerHandle,
385 IN UINTN NumberOfChildren,
386 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
387 )
388 {
389 EFI_STATUS Status;
390 EFI_TPL OldTpl;
391 WIFI_MGR_PRIVATE_PROTOCOL *WifiMgrIdentifier;
392 WIFI_MGR_DEVICE_DATA *Nic;
393
394 Status = gBS->OpenProtocol (
395 ControllerHandle,
396 &mEfiWifiMgrPrivateGuid,
397 (VOID **) &WifiMgrIdentifier,
398 This->DriverBindingHandle,
399 ControllerHandle,
400 EFI_OPEN_PROTOCOL_GET_PROTOCOL
401 );
402 if (EFI_ERROR (Status)) {
403 return EFI_DEVICE_ERROR;
404 }
405
406 Nic = WIFI_MGR_DEVICE_DATA_FROM_IDENTIFIER (WifiMgrIdentifier);
407 if (Nic == NULL) {
408 return EFI_DEVICE_ERROR;
409 }
410
411 //
412 // Close Event
413 //
414 gBS->SetTimer (Nic->TickTimer, TimerCancel, 0);
415 gBS->CloseEvent (Nic->TickTimer);
416
417 //
418 // Clean Supported Suites
419 //
420 if (Nic->Supplicant != NULL) {
421 if (Nic->SupportedSuites.SupportedAKMSuites != NULL) {
422 FreePool (Nic->SupportedSuites.SupportedAKMSuites);
423 }
424 if (Nic->SupportedSuites.SupportedSwCipherSuites != NULL) {
425 FreePool (Nic->SupportedSuites.SupportedSwCipherSuites);
426 }
427 if (Nic->SupportedSuites.SupportedHwCipherSuites != NULL) {
428 FreePool (Nic->SupportedSuites.SupportedHwCipherSuites);
429 }
430 }
431
432 //
433 // Close Protocols
434 //
435 Status = gBS->UninstallProtocolInterface (
436 ControllerHandle,
437 &mEfiWifiMgrPrivateGuid,
438 &Nic->WifiMgrIdentifier
439 );
440 if (EFI_ERROR (Status)) {
441 return Status;
442 }
443
444 Status = gBS->CloseProtocol (
445 ControllerHandle,
446 &gEfiWiFi2ProtocolGuid,
447 Nic->DriverHandle,
448 Nic->ControllerHandle
449 );
450 if (EFI_ERROR (Status)) {
451 return Status;
452 }
453
454 if (Nic->Supplicant != NULL) {
455 Status = gBS->CloseProtocol (
456 ControllerHandle,
457 &gEfiSupplicantProtocolGuid,
458 Nic->DriverHandle,
459 Nic->ControllerHandle
460 );
461 if (EFI_ERROR (Status)) {
462 return Status;
463 }
464 }
465
466 if (Nic->EapConfig != NULL) {
467 Status = gBS->CloseProtocol (
468 ControllerHandle,
469 &gEfiEapConfigurationProtocolGuid,
470 Nic->DriverHandle,
471 Nic->ControllerHandle
472 );
473 if (EFI_ERROR (Status)) {
474 return Status;
475 }
476 }
477
478 //
479 // Remove this Nic from Nic list
480 //
481 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
482
483 RemoveEntryList (&Nic->Link);
484 mPrivate->NicCount--;
485 if (mPrivate->CurrentNic == Nic) {
486 mPrivate->CurrentNic = NULL;
487 }
488
489 gBS->RestoreTPL (OldTpl);
490
491 WifiMgrFreeProfileList (&Nic->ProfileList);
492 FreePool (Nic);
493
494 DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] Device Controller has been Disconnected!\n"));
495 return EFI_SUCCESS;
496 }
497
498 /**
499 This is the declaration of an EFI image entry point. This entry point is
500 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
501 both device drivers and bus drivers.
502
503 @param ImageHandle The firmware allocated handle for the UEFI image.
504 @param SystemTable A pointer to the EFI System Table.
505
506 @retval EFI_SUCCESS The operation completed successfully.
507 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
508 @retval Others An unexpected error occurred.
509
510 **/
511 EFI_STATUS
512 EFIAPI
513 WifiMgrDxeDriverEntryPoint (
514 IN EFI_HANDLE ImageHandle,
515 IN EFI_SYSTEM_TABLE *SystemTable
516 )
517 {
518 EFI_STATUS Status;
519
520 Status = EfiLibInstallDriverBindingComponentName2 (
521 ImageHandle,
522 SystemTable,
523 &gWifiMgrDxeDriverBinding,
524 ImageHandle,
525 &gWifiMgrDxeComponentName,
526 &gWifiMgrDxeComponentName2
527 );
528 if (EFI_ERROR (Status)) {
529 return Status;
530 }
531
532 //
533 // Initialize the global private data structure.
534 //
535 mPrivate = AllocateZeroPool (sizeof (WIFI_MGR_PRIVATE_DATA));
536 if (mPrivate == NULL) {
537 Status = EFI_OUT_OF_RESOURCES;
538 goto ERROR1;
539 }
540 mPrivate->Signature = WIFI_MGR_PRIVATE_DATA_SIGNATURE;
541 mPrivate->DriverHandle = ImageHandle;
542 InitializeListHead (&mPrivate->NicList);
543 mPrivate->NicCount = 0;
544 mPrivate->CurrentNic = NULL;
545 InitializeListHead (&mPrivate->HiddenNetworkList);
546 mPrivate->HiddenNetworkCount = 0;
547
548 //
549 //Create events for page refresh
550 //
551 Status = gBS->CreateEventEx (
552 EVT_NOTIFY_SIGNAL,
553 TPL_CALLBACK,
554 WifiMgrInternalEmptyFunction,
555 NULL,
556 &mWifiConfigNetworkListRefreshGuid,
557 &mPrivate->NetworkListRefreshEvent
558 );
559 if (EFI_ERROR (Status)) {
560 goto ERROR2;
561 }
562
563 Status = gBS->CreateEventEx (
564 EVT_NOTIFY_SIGNAL,
565 TPL_CALLBACK,
566 WifiMgrInternalEmptyFunction,
567 NULL,
568 &mWifiConfigConnectFormRefreshGuid,
569 &mPrivate->ConnectFormRefreshEvent
570 );
571 if (EFI_ERROR (Status)) {
572 goto ERROR3;
573 }
574
575 Status = gBS->CreateEventEx (
576 EVT_NOTIFY_SIGNAL,
577 TPL_CALLBACK,
578 WifiMgrInternalEmptyFunction,
579 NULL,
580 &mWifiConfigMainFormRefreshGuid,
581 &mPrivate->MainPageRefreshEvent
582 );
583 if (EFI_ERROR (Status)) {
584 goto ERROR4;
585 }
586
587 Status = WifiMgrDxeConfigFormInit (mPrivate);
588 if (EFI_ERROR (Status)) {
589 goto ERROR5;
590 }
591
592 return Status;
593
594 ERROR5:
595 gBS->CloseEvent (mPrivate->MainPageRefreshEvent);
596
597 ERROR4:
598 gBS->CloseEvent (mPrivate->ConnectFormRefreshEvent);
599
600 ERROR3:
601 gBS->CloseEvent (mPrivate->NetworkListRefreshEvent);
602
603 ERROR2:
604 if (mPrivate != NULL) {
605 FreePool (mPrivate);
606 mPrivate = NULL;
607 }
608
609 ERROR1:
610 gBS->UninstallMultipleProtocolInterfaces (
611 ImageHandle,
612 &gEfiDriverBindingProtocolGuid,
613 &gWifiMgrDxeDriverBinding,
614 &gEfiComponentNameProtocolGuid,
615 &gWifiMgrDxeComponentName,
616 &gEfiComponentName2ProtocolGuid,
617 &gWifiMgrDxeComponentName2,
618 NULL
619 );
620
621 return Status;
622 }