]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/IpSecDxe/IpSecDriver.c
Update the relevant drivers to use the correct GUID for EFI_IPSEC2_PROTOCOL.
[mirror_edk2.git] / NetworkPkg / IpSecDxe / IpSecDriver.c
1 /** @file
2 Driver Binding Protocol for IPsec Driver.
3
4 Copyright (c) 2009 - 2010, 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 <Library/BaseCryptLib.h>
17
18 #include "IpSecConfigImpl.h"
19 #include "IkeService.h"
20 #include "IpSecDebug.h"
21
22 /**
23 Test to see if this driver supports ControllerHandle.
24
25 @param[in] This Protocol instance pointer.
26 @param[in] ControllerHandle Handle of device to test.
27 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
28 device to start.
29
30 @retval EFI_SUCCES This driver supports this device.
31 @retval EFI_ALREADY_STARTED This driver is already running on this device.
32 @retval other This driver does not support this device.
33
34 **/
35 EFI_STATUS
36 EFIAPI
37 IpSecDriverBindingSupported (
38 IN EFI_DRIVER_BINDING_PROTOCOL *This,
39 IN EFI_HANDLE ControllerHandle,
40 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
41 )
42 {
43 EFI_STATUS Udp4Status;
44 EFI_STATUS Udp6Status;
45
46 Udp4Status = gBS->OpenProtocol (
47 ControllerHandle,
48 &gEfiUdp4ServiceBindingProtocolGuid,
49 NULL,
50 This->DriverBindingHandle,
51 ControllerHandle,
52 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
53 );
54
55 Udp6Status = gBS->OpenProtocol (
56 ControllerHandle,
57 &gEfiUdp6ServiceBindingProtocolGuid,
58 NULL,
59 This->DriverBindingHandle,
60 ControllerHandle,
61 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
62 );
63
64 //
65 // The controller with either Udp4Sb or Udp6Sb is supported.
66 //
67 if (!EFI_ERROR (Udp4Status) || !EFI_ERROR (Udp6Status)) {
68 return EFI_SUCCESS;
69 }
70
71 return EFI_UNSUPPORTED;
72 }
73
74 /**
75 Start this driver on ControllerHandle.
76
77 @param[in] This Protocol instance pointer.
78 @param[in] ControllerHandle Handle of device to bind driver to.
79 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
80 device to start.
81
82 @retval EFI_SUCCES This driver is added to ControllerHandle
83 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
84 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.
85 Currently not implemented.
86 @retval other This driver does not support this device
87
88 **/
89 EFI_STATUS
90 EFIAPI
91 IpSecDriverBindingStart (
92 IN EFI_DRIVER_BINDING_PROTOCOL *This,
93 IN EFI_HANDLE ControllerHandle,
94 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
95 )
96 {
97 EFI_IPSEC2_PROTOCOL *IpSec;
98 EFI_STATUS Status;
99 EFI_STATUS Udp4Status;
100 EFI_STATUS Udp6Status;
101 IPSEC_PRIVATE_DATA *Private;
102
103 //
104 // Ipsec protocol should be installed when load image.
105 //
106 Status = gBS->LocateProtocol (&gEfiIpSec2ProtocolGuid, NULL, (VOID **) &IpSec);
107
108 if (EFI_ERROR (Status)) {
109 return Status;
110 }
111
112 Private = IPSEC_PRIVATE_DATA_FROM_IPSEC (IpSec);
113
114 //
115 // If udp4 sb is on the controller, try to open a udp4 io for input.
116 //
117 Udp4Status = gBS->OpenProtocol (
118 ControllerHandle,
119 &gEfiUdp4ServiceBindingProtocolGuid,
120 NULL,
121 This->DriverBindingHandle,
122 ControllerHandle,
123 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
124 );
125
126 if (!EFI_ERROR (Udp4Status)) {
127 Udp4Status = IkeOpenInputUdp4 (Private, ControllerHandle);
128 }
129 //
130 // If udp6 sb is on the controller, try to open a udp6 io for input.
131 //
132 Udp6Status = gBS->OpenProtocol (
133 ControllerHandle,
134 &gEfiUdp6ServiceBindingProtocolGuid,
135 NULL,
136 This->DriverBindingHandle,
137 ControllerHandle,
138 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
139 );
140
141 if (!EFI_ERROR (Udp6Status)) {
142 Udp6Status = IkeOpenInputUdp6 (Private, ControllerHandle);
143 }
144
145 if (!EFI_ERROR (Udp4Status) || !EFI_ERROR (Udp6Status)) {
146 return EFI_SUCCESS;
147 }
148
149 return EFI_DEVICE_ERROR;
150 }
151
152 /**
153 Stop this driver on ControllerHandle.
154
155 @param[in] This Protocol instance pointer.
156 @param[in] ControllerHandle Handle of a device to stop the driver on.
157 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If the number of
158 children is zero, stop the entire bus driver.
159 @param[in] ChildHandleBuffer List of Child Handles to Stop.
160
161 @retval EFI_SUCCES This driver removed ControllerHandle.
162 @retval other This driver was not removed from this device.
163
164 **/
165 EFI_STATUS
166 EFIAPI
167 IpSecDriverBindingStop (
168 IN EFI_DRIVER_BINDING_PROTOCOL *This,
169 IN EFI_HANDLE ControllerHandle,
170 IN UINTN NumberOfChildren,
171 IN EFI_HANDLE *ChildHandleBuffer
172 )
173 {
174 EFI_IPSEC2_PROTOCOL *IpSec;
175 EFI_STATUS Status;
176 IPSEC_PRIVATE_DATA *Private;
177 IKE_UDP_SERVICE *UdpSrv;
178 LIST_ENTRY *Entry;
179 LIST_ENTRY *Next;
180
181 //
182 // Locate ipsec protocol to get private data.
183 //
184 Status = gBS->LocateProtocol (&gEfiIpSec2ProtocolGuid, NULL, (VOID **) &IpSec);
185
186 if (EFI_ERROR (Status)) {
187 return Status;
188 }
189
190 Private = IPSEC_PRIVATE_DATA_FROM_IPSEC (IpSec);
191
192 //
193 // If has udp4 io opened on the controller, close and free it.
194 //
195 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Private->Udp4List) {
196
197 UdpSrv = IPSEC_UDP_SERVICE_FROM_LIST (Entry);
198 //
199 // Find the right udp service which installed on the appointed nic handle.
200 //
201 if (UdpSrv->Input != NULL && ControllerHandle == UdpSrv->Input->UdpHandle) {
202 UdpIoFreeIo (UdpSrv->Input);
203 UdpSrv->Input = NULL;
204 }
205
206 if (UdpSrv->Output != NULL && ControllerHandle == UdpSrv->Output->UdpHandle) {
207 UdpIoFreeIo (UdpSrv->Output);
208 UdpSrv->Output = NULL;
209 }
210
211 if (UdpSrv->Input == NULL && UdpSrv->Output == NULL) {
212 RemoveEntryList (&UdpSrv->List);
213 FreePool (UdpSrv);
214 ASSERT (Private->Udp4Num > 0);
215 Private->Udp4Num--;
216 }
217 }
218 //
219 // If has udp6 io opened on the controller, close and free it.
220 //
221 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Private->Udp6List) {
222
223 UdpSrv = IPSEC_UDP_SERVICE_FROM_LIST (Entry);
224 //
225 // Find the right udp service which installed on the appointed nic handle.
226 //
227 if (UdpSrv->Input != NULL && ControllerHandle == UdpSrv->Input->UdpHandle) {
228 UdpIoFreeIo (UdpSrv->Input);
229 UdpSrv->Input = NULL;
230 }
231
232 if (UdpSrv->Output != NULL && ControllerHandle == UdpSrv->Output->UdpHandle) {
233 UdpIoFreeIo (UdpSrv->Output);
234 UdpSrv->Output = NULL;
235 }
236
237 if (UdpSrv->Input == NULL && UdpSrv->Output == NULL) {
238 RemoveEntryList (&UdpSrv->List);
239 FreePool (UdpSrv);
240 ASSERT (Private->Udp6Num > 0);
241 Private->Udp6Num--;
242 }
243 }
244
245 return EFI_SUCCESS;
246 }
247
248 EFI_DRIVER_BINDING_PROTOCOL gIpSecDriverBinding = {
249 IpSecDriverBindingSupported,
250 IpSecDriverBindingStart,
251 IpSecDriverBindingStop,
252 0xa,
253 NULL,
254 NULL
255 };
256
257 /**
258 This is a callback function when the mIpSecInstance.DisabledEvent is signaled.
259
260 @param[in] Event Event whose notification function is being invoked.
261 @param[in] Context Pointer to the notification function's context.
262
263 **/
264 VOID
265 EFIAPI
266 IpSecCleanupAllSa (
267 IN EFI_EVENT Event,
268 IN VOID *Context
269 )
270 {
271 IPSEC_PRIVATE_DATA *Private;
272 Private = (IPSEC_PRIVATE_DATA *) Context;
273 Private->IsIPsecDisabling = TRUE;
274 IkeDeleteAllSas (Private);
275 }
276
277 /**
278 This is the declaration of an EFI image entry point. This entry point is
279 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers, including
280 both device drivers and bus drivers.
281
282 The entry point for IPsec driver which installs the driver binding,
283 component name protocol, IPsec Config protcolon, and IPsec protocol in
284 its ImageHandle.
285
286 @param[in] ImageHandle The firmware allocated handle for the UEFI image.
287 @param[in] SystemTable A pointer to the EFI System Table.
288
289 @retval EFI_SUCCESS The operation completed successfully.
290 @retval EFI_ALREADY_STARTED The IPsec driver has been already loaded.
291 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
292 @retval Others The operation is failed.
293
294 **/
295 EFI_STATUS
296 EFIAPI
297 IpSecDriverEntryPoint (
298 IN EFI_HANDLE ImageHandle,
299 IN EFI_SYSTEM_TABLE *SystemTable
300 )
301 {
302 EFI_STATUS Status;
303 IPSEC_PRIVATE_DATA *Private;
304 EFI_IPSEC2_PROTOCOL *IpSec;
305
306 //
307 // Check whether ipsec protocol has already been installed.
308 //
309 Status = gBS->LocateProtocol (&gEfiIpSec2ProtocolGuid, NULL, (VOID **) &IpSec);
310
311 if (!EFI_ERROR (Status)) {
312 DEBUG ((DEBUG_WARN, "_ModuleEntryPoint: IpSec has been already loaded\n"));
313 Status = EFI_ALREADY_STARTED;
314 goto ON_EXIT;
315 }
316
317 Status = gBS->LocateProtocol (&gEfiDpcProtocolGuid, NULL, (VOID **) &mDpc);
318
319 if (EFI_ERROR (Status)) {
320 DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to locate EfiDpcProtocol\n"));
321 goto ON_EXIT;
322 }
323
324 Private = AllocateZeroPool (sizeof (IPSEC_PRIVATE_DATA));
325
326 if (Private == NULL) {
327 DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to allocate private data\n"));
328 Status = EFI_OUT_OF_RESOURCES;
329 goto ON_EXIT;
330 }
331 //
332 // Create disable event to cleanup all SA when ipsec disabled by user.
333 //
334 Status = gBS->CreateEvent (
335 EVT_NOTIFY_SIGNAL,
336 TPL_CALLBACK,
337 IpSecCleanupAllSa,
338 Private,
339 &mIpSecInstance.DisabledEvent
340 );
341 if (EFI_ERROR (Status)) {
342 DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to create disable event\n"));
343 goto ON_FREE_PRIVATE;
344 }
345
346 Private->Signature = IPSEC_PRIVATE_DATA_SIGNATURE;
347 Private->ImageHandle = ImageHandle;
348 CopyMem (&Private->IpSec, &mIpSecInstance, sizeof (EFI_IPSEC2_PROTOCOL));
349
350 //
351 // Initilize Private's members. Thess members is used for IKE.
352 //
353 InitializeListHead (&Private->Udp4List);
354 InitializeListHead (&Private->Udp6List);
355 InitializeListHead (&Private->Ikev1SessionList);
356 InitializeListHead (&Private->Ikev1EstablishedList);
357 InitializeListHead (&Private->Ikev2SessionList);
358 InitializeListHead (&Private->Ikev2EstablishedList);
359
360 RandomSeed (NULL, 0);
361 //
362 // Initialize the ipsec config data and restore it from variable.
363 //
364 Status = IpSecConfigInitialize (Private);
365 if (EFI_ERROR (Status)) {
366 DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to initialize IpSecConfig\n"));
367 goto ON_CLOSE_EVENT;
368 }
369 //
370 // Install ipsec protocol which is used by ip driver to process ipsec header.
371 //
372 Status = gBS->InstallMultipleProtocolInterfaces (
373 &Private->Handle,
374 &gEfiIpSec2ProtocolGuid,
375 &Private->IpSec,
376 NULL
377 );
378 if (EFI_ERROR (Status)) {
379 goto ON_UNINSTALL_CONFIG;
380 }
381
382 Status = EfiLibInstallDriverBindingComponentName2 (
383 ImageHandle,
384 SystemTable,
385 &gIpSecDriverBinding,
386 ImageHandle,
387 &gIpSecComponentName,
388 &gIpSecComponentName2
389 );
390 if (EFI_ERROR (Status)) {
391 goto ON_UNINSTALL_IPSEC;
392 }
393
394 return Status;
395
396 ON_UNINSTALL_IPSEC:
397 gBS->UninstallProtocolInterface (
398 Private->Handle,
399 &gEfiIpSec2ProtocolGuid,
400 &Private->IpSec
401 );
402 ON_UNINSTALL_CONFIG:
403 gBS->UninstallProtocolInterface (
404 Private->Handle,
405 &gEfiIpSecConfigProtocolGuid,
406 &Private->IpSecConfig
407 );
408 ON_CLOSE_EVENT:
409 gBS->CloseEvent (mIpSecInstance.DisabledEvent);
410 mIpSecInstance.DisabledEvent = NULL;
411 ON_FREE_PRIVATE:
412 FreePool (Private);
413 ON_EXIT:
414 return Status;
415 }
416