]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDriver.c
dfa4cdcd8f9911c5adfd1207d27a4d1c7b47319d
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4ConfigDxe / Ip4ConfigDriver.c
1 /** @file
2 The driver binding for IP4 CONFIG protocol.
3
4 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at<BR>
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15
16 #include "Ip4Config.h"
17 #include "Ip4ConfigNv.h"
18 #include "NicIp4Variable.h"
19
20 EFI_DRIVER_BINDING_PROTOCOL gIp4ConfigDriverBinding = {
21 Ip4ConfigDriverBindingSupported,
22 Ip4ConfigDriverBindingStart,
23 Ip4ConfigDriverBindingStop,
24 0xa,
25 NULL,
26 NULL
27 };
28
29 /**
30 The entry point for IP4 config driver which install the driver
31 binding and component name protocol on its image.
32
33 @param ImageHandle The image handle of the driver.
34 @param SystemTable The system table.
35
36 @retval EFI_SUCCES All the related protocols are installed on the driver.
37 @retval Others Failed to install protocols.
38
39 **/
40 EFI_STATUS
41 EFIAPI
42 Ip4ConfigDriverEntryPoint (
43 IN EFI_HANDLE ImageHandle,
44 IN EFI_SYSTEM_TABLE *SystemTable
45 )
46 {
47 return EfiLibInstallDriverBindingComponentName2 (
48 ImageHandle,
49 SystemTable,
50 &gIp4ConfigDriverBinding,
51 ImageHandle,
52 &gIp4ConfigComponentName,
53 &gIp4ConfigComponentName2
54 );
55 }
56
57
58 /**
59 Test to see if this driver supports ControllerHandle.
60
61 @param This Protocol instance pointer.
62 @param ControllerHandle Handle of device to test
63 @param RemainingDevicePath Optional parameter use to pick a specific child
64 device to start.
65
66 @retval EFI_SUCCES This driver supports this device
67 @retval EFI_ALREADY_STARTED This driver is already running on this device
68 @retval other This driver does not support this device
69
70 **/
71 EFI_STATUS
72 EFIAPI
73 Ip4ConfigDriverBindingSupported (
74 IN EFI_DRIVER_BINDING_PROTOCOL *This,
75 IN EFI_HANDLE ControllerHandle,
76 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
77 )
78 {
79 EFI_STATUS Status;
80
81 Status = gBS->OpenProtocol (
82 ControllerHandle,
83 &gEfiManagedNetworkServiceBindingProtocolGuid,
84 NULL,
85 This->DriverBindingHandle,
86 ControllerHandle,
87 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
88 );
89
90 return Status;
91 }
92
93
94 /**
95 Start this driver on ControllerHandle.
96
97 @param This Protocol instance pointer.
98 @param ControllerHandle Handle of device to bind driver to
99 @param RemainingDevicePath Optional parameter use to pick a specific child
100 device to start.
101
102 @retval EFI_SUCCES This driver is added to ControllerHandle
103 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
104 @retval other This driver does not support this device
105
106 **/
107 EFI_STATUS
108 EFIAPI
109 Ip4ConfigDriverBindingStart (
110 IN EFI_DRIVER_BINDING_PROTOCOL *This,
111 IN EFI_HANDLE ControllerHandle,
112 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
113 )
114 {
115 EFI_IP4_CONFIG_PROTOCOL *Ip4Config;
116 EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
117 EFI_HANDLE MnpHandle;
118 IP4_CONFIG_INSTANCE *Instance;
119 EFI_SIMPLE_NETWORK_MODE SnpMode;
120 NIC_IP4_CONFIG_INFO *NicConfig;
121 EFI_STATUS Status;
122 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
123
124 Status = gBS->HandleProtocol (
125 ControllerHandle,
126 &gEfiDevicePathProtocolGuid,
127 (VOID **) &ParentDevicePath
128 );
129 if (EFI_ERROR (Status)) {
130 return Status;
131 }
132
133 //
134 // Check for multiple start.
135 //
136 Status = gBS->OpenProtocol (
137 ControllerHandle,
138 &gEfiIp4ConfigProtocolGuid,
139 (VOID **) &Ip4Config,
140 This->DriverBindingHandle,
141 ControllerHandle,
142 EFI_OPEN_PROTOCOL_GET_PROTOCOL
143 );
144
145 if (!EFI_ERROR (Status)) {
146 return EFI_ALREADY_STARTED;
147 }
148
149 //
150 // Create a MNP child
151 //
152 Mnp = NULL;
153 MnpHandle = NULL;
154 Instance = NULL;
155
156 Status = NetLibCreateServiceChild (
157 ControllerHandle,
158 This->DriverBindingHandle,
159 &gEfiManagedNetworkServiceBindingProtocolGuid,
160 &MnpHandle
161 );
162
163 if (EFI_ERROR (Status)) {
164 return Status;
165 }
166
167 Status = gBS->OpenProtocol (
168 MnpHandle,
169 &gEfiManagedNetworkProtocolGuid,
170 (VOID **) &Mnp,
171 This->DriverBindingHandle,
172 ControllerHandle,
173 EFI_OPEN_PROTOCOL_BY_DRIVER
174 );
175
176 if (EFI_ERROR (Status)) {
177 goto ON_ERROR;
178 }
179
180 //
181 // Allocate an instance then initialize it
182 //
183 Instance = AllocateZeroPool (sizeof (IP4_CONFIG_INSTANCE));
184
185 if (Instance == NULL) {
186 Status = EFI_OUT_OF_RESOURCES;
187 goto ON_ERROR;
188 }
189
190 Instance->Signature = IP4_CONFIG_INSTANCE_SIGNATURE;
191 Instance->Controller = ControllerHandle;
192 Instance->Image = This->DriverBindingHandle;
193 Instance->ParentDevicePath = ParentDevicePath;
194
195 CopyMem (&Instance->Ip4ConfigProtocol, &mIp4ConfigProtocolTemplate, sizeof (mIp4ConfigProtocolTemplate));
196
197 Instance->State = IP4_CONFIG_STATE_IDLE;
198 Instance->Mnp = Mnp;
199 Instance->MnpHandle = MnpHandle;
200
201 Instance->DoneEvent = NULL;
202 Instance->ReconfigEvent = NULL;
203 Instance->Result = EFI_NOT_READY;
204 Instance->NicConfig = NULL;
205
206 Instance->Dhcp4 = NULL;
207 Instance->Dhcp4Handle = NULL;
208 Instance->Dhcp4Event = NULL;
209
210 Status = Mnp->GetModeData (Mnp, NULL, &SnpMode);
211
212 if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {
213 goto ON_ERROR;
214 }
215
216 Instance->NicAddr.Type = (UINT16) SnpMode.IfType;
217 Instance->NicAddr.Len = (UINT8) SnpMode.HwAddressSize;
218 CopyMem (&Instance->NicAddr.MacAddr, &SnpMode.CurrentAddress, Instance->NicAddr.Len);
219
220 //
221 // Add it to the global list, and compose the name
222 //
223 Status = NetLibGetMacString (Instance->Controller, Instance->Image, &Instance->MacString);
224 if (EFI_ERROR (Status)) {
225 goto ON_ERROR;
226 }
227
228 Status = Ip4ConfigDeviceInit (Instance);
229
230 //
231 // Install the IP4_CONFIG protocols
232 //
233 Status = gBS->InstallMultipleProtocolInterfaces (
234 &ControllerHandle,
235 &gEfiIp4ConfigProtocolGuid,
236 &Instance->Ip4ConfigProtocol,
237 NULL
238 );
239
240 if (EFI_ERROR (Status)) {
241 goto ON_ERROR;
242 }
243
244 //
245 // Get the previous configure parameters. If an error happend here,
246 // just ignore it because the driver should be able to operate.
247 //
248 NicConfig = Ip4ConfigReadVariable (Instance);
249 if (NicConfig != NULL) {
250 if (NicConfig->Perment) {
251 if (NicConfig->Source == IP4_CONFIG_SOURCE_STATIC) {
252 //
253 // Don't modify the permanent static configuration.
254 //
255 } else if (NicConfig->Source == IP4_CONFIG_SOURCE_DHCP) {
256 //
257 // Remove the previous acquired DHCP parameters.
258 //
259 ZeroMem (&NicConfig->Ip4Info, sizeof (EFI_IP4_IPCONFIG_DATA));
260 Ip4ConfigWriteVariable (Instance, NicConfig);
261 }
262 } else {
263 //
264 // Delete the non-permanent configuration.
265 //
266 Ip4ConfigWriteVariable (Instance, NULL);
267 }
268
269 FreePool (NicConfig);
270 }
271
272 return EFI_SUCCESS;
273
274 ON_ERROR:
275 if (Instance != NULL) {
276 FreePool (Instance);
277 }
278
279 if (Mnp != NULL) {
280 gBS->CloseProtocol (
281 MnpHandle,
282 &gEfiManagedNetworkProtocolGuid,
283 This->DriverBindingHandle,
284 ControllerHandle
285 );
286 }
287
288 NetLibDestroyServiceChild (
289 ControllerHandle,
290 This->DriverBindingHandle,
291 &gEfiManagedNetworkProtocolGuid,
292 MnpHandle
293 );
294
295 return Status;
296 }
297
298
299 /**
300 Stop this driver on ControllerHandle.
301
302 @param This Protocol instance pointer.
303 @param ControllerHandle Handle of device to stop driver on
304 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
305 children is zero stop the entire bus driver.
306 @param ChildHandleBuffer List of Child Handles to Stop.
307
308 @retval EFI_SUCCES This driver is removed ControllerHandle
309 @retval other This driver was not removed from this device
310
311 **/
312 EFI_STATUS
313 EFIAPI
314 Ip4ConfigDriverBindingStop (
315 IN EFI_DRIVER_BINDING_PROTOCOL *This,
316 IN EFI_HANDLE ControllerHandle,
317 IN UINTN NumberOfChildren,
318 IN EFI_HANDLE *ChildHandleBuffer
319 )
320 {
321 IP4_CONFIG_INSTANCE *Instance;
322 EFI_IP4_CONFIG_PROTOCOL *Ip4Config;
323 EFI_HANDLE NicHandle;
324 EFI_STATUS Status;
325
326 //
327 // IP4_CONFIG instance opens an MNP child. It may also create and open
328 // a DHCP child. If this is the DHCP handle, stop the DHCP process. If
329 // it is the MNP child, stop the whole driver.
330 //
331 //
332 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);
333
334 if (NicHandle != NULL) {
335 //
336 // Get our context back then clean the DHCP up. Notify the user if necessary.
337 //
338 Status = gBS->OpenProtocol (
339 NicHandle,
340 &gEfiIp4ConfigProtocolGuid,
341 (VOID **) &Ip4Config,
342 This->DriverBindingHandle,
343 ControllerHandle,
344 EFI_OPEN_PROTOCOL_GET_PROTOCOL
345 );
346
347 if (EFI_ERROR (Status)) {
348 return Status;
349 }
350
351 Instance = IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (Ip4Config);
352 ASSERT (ControllerHandle == Instance->Dhcp4Handle);
353
354 Ip4ConfigCleanDhcp4 (Instance);
355
356 Instance->State = IP4_CONFIG_STATE_CONFIGURED;
357 Instance->Result = EFI_DEVICE_ERROR;
358
359 if (Instance->DoneEvent != NULL) {
360 gBS->SignalEvent (Instance->DoneEvent);
361 }
362
363 return EFI_SUCCESS;
364 }
365
366 //
367 // This is a MNP handle, stop the whole driver
368 //
369 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);
370
371 if (NicHandle == NULL) {
372 return EFI_SUCCESS;
373 }
374
375 //
376 // Get our context back.
377 //
378 Status = gBS->OpenProtocol (
379 NicHandle,
380 &gEfiIp4ConfigProtocolGuid,
381 (VOID **) &Ip4Config,
382 This->DriverBindingHandle,
383 ControllerHandle,
384 EFI_OPEN_PROTOCOL_GET_PROTOCOL
385 );
386
387 if (EFI_ERROR (Status)) {
388 return Status;
389 }
390
391 Instance = IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (Ip4Config);
392
393 Ip4ConfigDeviceUnload (Instance);
394
395 //
396 // Unload the protocols first to inform the top drivers
397 //
398 Status = gBS->UninstallMultipleProtocolInterfaces (
399 NicHandle,
400 &gEfiIp4ConfigProtocolGuid,
401 &Instance->Ip4ConfigProtocol,
402 NULL
403 );
404
405 if (EFI_ERROR (Status)) {
406 return Status;
407 }
408
409 //
410 // Release all the resources
411 //
412 if (Instance->MnpHandle != NULL) {
413 gBS->CloseProtocol (
414 Instance->MnpHandle,
415 &gEfiManagedNetworkProtocolGuid,
416 This->DriverBindingHandle,
417 NicHandle
418 );
419
420 NetLibDestroyServiceChild (
421 NicHandle,
422 Instance->Image,
423 &gEfiManagedNetworkServiceBindingProtocolGuid,
424 Instance->MnpHandle
425 );
426
427 Instance->Mnp = NULL;
428 Instance->MnpHandle = NULL;
429 }
430
431 if (Instance->MacString != NULL) {
432 FreePool (Instance->MacString);
433 }
434
435 Ip4ConfigCleanConfig (Instance);
436 FreePool (Instance);
437
438 return EFI_SUCCESS;
439 }