]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Driver.c
Update modules to show real dependencies on the BaseMemoryLib and MemoryAllocationLib
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Mtftp4Dxe / Mtftp4Driver.c
1 /** @file
2 Implementation of Mtftp drivers.
3
4 Copyright (c) 2006 - 2007, Intel Corporation<BR>
5 All rights reserved. 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
8 http://opensource.org/licenses/bsd-license.php<BR>
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 #include "Mtftp4Impl.h"
16
17 EFI_DRIVER_BINDING_PROTOCOL gMtftp4DriverBinding = {
18 Mtftp4DriverBindingSupported,
19 Mtftp4DriverBindingStart,
20 Mtftp4DriverBindingStop,
21 0xa,
22 NULL,
23 NULL
24 };
25
26 EFI_SERVICE_BINDING_PROTOCOL gMtftp4ServiceBindingTemplete = {
27 Mtftp4ServiceBindingCreateChild,
28 Mtftp4ServiceBindingDestroyChild
29 };
30
31
32 /**
33 The driver entry point which installs multiple protocols to the ImageHandle.
34
35 @param ImageHandle The MTFTP's image handle.
36 @param SystemTable The system table.
37
38 @retval EFI_SUCCESS The handles are successfully installed on the image.
39 @retval others some EFI_ERROR occured.
40
41 **/
42 EFI_STATUS
43 EFIAPI
44 Mtftp4DriverEntryPoint (
45 IN EFI_HANDLE ImageHandle,
46 IN EFI_SYSTEM_TABLE *SystemTable
47 )
48 {
49 return EfiLibInstallDriverBindingComponentName2 (
50 ImageHandle,
51 SystemTable,
52 &gMtftp4DriverBinding,
53 ImageHandle,
54 &gMtftp4ComponentName,
55 &gMtftp4ComponentName2
56 );
57 }
58
59
60 /**
61 Test whether MTFTP driver support this controller.
62
63 @param This The MTFTP driver binding instance
64 @param Controller The controller to test
65 @param RemainingDevicePath The remaining device path
66
67 @retval EFI_SUCCESS The controller has UDP service binding protocol
68 installed, MTFTP can support it.
69 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
70 RemainingDevicePath is already being managed by
71 the driver specified by This.
72 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
73 RemainingDevicePath is already being managed by a
74 different driver or an application that requires
75 exclusive access.
76 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
77 RemainingDevicePath is not supported by the driver
78 specified by This.
79
80 **/
81 EFI_STATUS
82 EFIAPI
83 Mtftp4DriverBindingSupported (
84 IN EFI_DRIVER_BINDING_PROTOCOL *This,
85 IN EFI_HANDLE Controller,
86 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
87 )
88 {
89 EFI_STATUS Status;
90
91 Status = gBS->OpenProtocol (
92 Controller,
93 &gEfiUdp4ServiceBindingProtocolGuid,
94 NULL,
95 This->DriverBindingHandle,
96 Controller,
97 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
98 );
99
100 return Status;
101 }
102
103
104 /**
105 Config a NULL UDP that is used to keep the connection between UDP and MTFTP.
106
107 Just leave the Udp child unconfigured. When UDP is unloaded,
108 MTFTP will be informed with DriverBinding Stop.
109
110 @param UdpIo The UDP port to configure
111 @param Context The opaque parameter to the callback
112
113 @retval EFI_SUCCESS It always return EFI_SUCCESS directly.
114
115 **/
116 EFI_STATUS
117 Mtftp4ConfigNullUdp (
118 IN UDP_IO_PORT *UdpIo,
119 IN VOID *Context
120 )
121 {
122 return EFI_SUCCESS;
123 }
124
125
126 /**
127 Create then initialize a MTFTP service binding instance.
128
129 @param Controller The controller to install the MTFTP service
130 binding on
131 @param Image The driver binding image of the MTFTP driver
132 @param Service The variable to receive the created service
133 binding instance.
134
135 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance
136 @retval EFI_DEVICE_ERROR Failed to create a NULL UDP port to keep
137 connection with UDP.
138 @retval EFI_SUCCESS The service instance is created for the
139 controller.
140
141 **/
142 EFI_STATUS
143 Mtftp4CreateService (
144 IN EFI_HANDLE Controller,
145 IN EFI_HANDLE Image,
146 OUT MTFTP4_SERVICE **Service
147 )
148 {
149 MTFTP4_SERVICE *MtftpSb;
150 EFI_STATUS Status;
151
152 *Service = NULL;
153 MtftpSb = AllocatePool (sizeof (MTFTP4_SERVICE));
154
155 if (MtftpSb == NULL) {
156 return EFI_OUT_OF_RESOURCES;
157 }
158
159 MtftpSb->Signature = MTFTP4_SERVICE_SIGNATURE;
160 MtftpSb->ServiceBinding = gMtftp4ServiceBindingTemplete;
161 MtftpSb->InDestory = FALSE;
162 MtftpSb->ChildrenNum = 0;
163 InitializeListHead (&MtftpSb->Children);
164
165 MtftpSb->Timer = NULL;
166 MtftpSb->TimerToGetMap = NULL;
167 MtftpSb->Controller = Controller;
168 MtftpSb->Image = Image;
169 MtftpSb->ConnectUdp = NULL;
170
171 //
172 // Create the timer and a udp to be notified when UDP is uninstalled
173 //
174 Status = gBS->CreateEvent (
175 EVT_NOTIFY_SIGNAL | EVT_TIMER,
176 TPL_CALLBACK,
177 Mtftp4OnTimerTick,
178 MtftpSb,
179 &MtftpSb->Timer
180 );
181
182 if (EFI_ERROR (Status)) {
183 gBS->FreePool (MtftpSb);
184 return Status;
185 }
186
187 //
188 // Create the timer used to time out the procedure which is used to
189 // get the default IP address.
190 //
191 Status = gBS->CreateEvent (
192 EVT_TIMER,
193 TPL_CALLBACK,
194 NULL,
195 NULL,
196 &MtftpSb->TimerToGetMap
197 );
198 if (EFI_ERROR (Status)) {
199 gBS->CloseEvent (MtftpSb->Timer);
200 gBS->FreePool (MtftpSb);
201 return Status;
202 }
203
204 MtftpSb->ConnectUdp = UdpIoCreatePort (Controller, Image, Mtftp4ConfigNullUdp, NULL);
205
206 if (MtftpSb->ConnectUdp == NULL) {
207 gBS->CloseEvent (MtftpSb->TimerToGetMap);
208 gBS->CloseEvent (MtftpSb->Timer);
209 gBS->FreePool (MtftpSb);
210 return EFI_DEVICE_ERROR;
211 }
212
213 *Service = MtftpSb;
214 return EFI_SUCCESS;
215 }
216
217
218 /**
219 Release all the resource used the MTFTP service binding instance.
220
221 @param MtftpSb The MTFTP service binding instance.
222
223 **/
224 VOID
225 Mtftp4CleanService (
226 IN MTFTP4_SERVICE *MtftpSb
227 )
228 {
229 UdpIoFreePort (MtftpSb->ConnectUdp);
230 gBS->CloseEvent (MtftpSb->TimerToGetMap);
231 gBS->CloseEvent (MtftpSb->Timer);
232 }
233
234
235 /**
236 Start the MTFTP driver on this controller.
237
238 MTFTP driver will install a MTFTP SERVICE BINDING protocol on the supported
239 controller, which can be used to create/destroy MTFTP children.
240
241 @param This The MTFTP driver binding protocol.
242 @param Controller The controller to manage.
243 @param RemainingDevicePath Remaining device path.
244
245 @retval EFI_ALREADY_STARTED The MTFTP service binding protocol has been
246 started on the controller.
247 @retval EFI_SUCCESS The MTFTP service binding is installed on the
248 controller.
249
250 **/
251 EFI_STATUS
252 EFIAPI
253 Mtftp4DriverBindingStart (
254 IN EFI_DRIVER_BINDING_PROTOCOL *This,
255 IN EFI_HANDLE Controller,
256 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
257 )
258 {
259 MTFTP4_SERVICE *MtftpSb;
260 EFI_STATUS Status;
261
262 //
263 // Directly return if driver is already running.
264 //
265 Status = gBS->OpenProtocol (
266 Controller,
267 &gEfiMtftp4ServiceBindingProtocolGuid,
268 NULL,
269 This->DriverBindingHandle,
270 Controller,
271 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
272 );
273
274 if (Status == EFI_SUCCESS) {
275 return EFI_ALREADY_STARTED;
276 }
277
278 Status = Mtftp4CreateService (Controller, This->DriverBindingHandle, &MtftpSb);
279
280 if (EFI_ERROR (Status)) {
281 return Status;
282 }
283
284 Status = gBS->SetTimer (MtftpSb->Timer, TimerPeriodic, TICKS_PER_SECOND);
285
286 if (EFI_ERROR (Status)) {
287 goto ON_ERROR;
288 }
289
290 //
291 // Install the Mtftp4ServiceBinding Protocol onto Controller
292 //
293 Status = gBS->InstallMultipleProtocolInterfaces (
294 &Controller,
295 &gEfiMtftp4ServiceBindingProtocolGuid,
296 &MtftpSb->ServiceBinding,
297 NULL
298 );
299
300 if (EFI_ERROR (Status)) {
301 goto ON_ERROR;
302 }
303
304 return EFI_SUCCESS;
305
306 ON_ERROR:
307 Mtftp4CleanService (MtftpSb);
308 gBS->FreePool (MtftpSb);
309
310 return Status;
311 }
312
313
314 /**
315 Stop the MTFTP driver on controller. The controller is a UDP
316 child handle.
317
318 @param This The MTFTP driver binding protocol
319 @param Controller The controller to stop
320 @param NumberOfChildren The number of children
321 @param ChildHandleBuffer The array of the child handle.
322
323 @retval EFI_SUCCESS The driver is stopped on the controller.
324 @retval EFI_DEVICE_ERROR Failed to stop the driver on the controller.
325
326 **/
327 EFI_STATUS
328 EFIAPI
329 Mtftp4DriverBindingStop (
330 IN EFI_DRIVER_BINDING_PROTOCOL *This,
331 IN EFI_HANDLE Controller,
332 IN UINTN NumberOfChildren,
333 IN EFI_HANDLE *ChildHandleBuffer
334 )
335 {
336 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
337 MTFTP4_SERVICE *MtftpSb;
338 MTFTP4_PROTOCOL *Instance;
339 EFI_HANDLE NicHandle;
340 EFI_STATUS Status;
341 EFI_TPL OldTpl;
342
343 //
344 // MTFTP driver opens UDP child, So, Controller is a UDP
345 // child handle. Locate the Nic handle first. Then get the
346 // MTFTP private data back.
347 //
348 NicHandle = NetLibGetNicHandle (Controller, &gEfiUdp4ProtocolGuid);
349
350 if (NicHandle == NULL) {
351 return EFI_DEVICE_ERROR;
352 }
353
354 Status = gBS->OpenProtocol (
355 NicHandle,
356 &gEfiMtftp4ServiceBindingProtocolGuid,
357 (VOID **) &ServiceBinding,
358 This->DriverBindingHandle,
359 NicHandle,
360 EFI_OPEN_PROTOCOL_GET_PROTOCOL
361 );
362
363 if (EFI_ERROR (Status)) {
364 return EFI_DEVICE_ERROR;
365 }
366
367 MtftpSb = MTFTP4_SERVICE_FROM_THIS (ServiceBinding);
368
369 if (MtftpSb->InDestory) {
370 return EFI_SUCCESS;
371 }
372
373 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
374
375 if (NumberOfChildren == 0) {
376
377 MtftpSb->InDestory = TRUE;
378
379 gBS->UninstallProtocolInterface (
380 NicHandle,
381 &gEfiMtftp4ServiceBindingProtocolGuid,
382 ServiceBinding
383 );
384
385 Mtftp4CleanService (MtftpSb);
386
387 gBS->FreePool (MtftpSb);
388 } else {
389
390 while (!IsListEmpty (&MtftpSb->Children)) {
391 Instance = NET_LIST_HEAD (&MtftpSb->Children, MTFTP4_PROTOCOL, Link);
392 Mtftp4ServiceBindingDestroyChild (ServiceBinding, Instance->Handle);
393 }
394
395 if (MtftpSb->ChildrenNum != 0) {
396 Status = EFI_DEVICE_ERROR;
397 }
398 }
399
400 gBS->RestoreTPL (OldTpl);
401 return Status;
402 }
403
404
405 /**
406 Initialize a MTFTP protocol instance which is the child of MtftpSb.
407
408 @param MtftpSb The MTFTP service binding protocol.
409 @param Instance The MTFTP instance to initialize.
410
411 **/
412 VOID
413 Mtftp4InitProtocol (
414 IN MTFTP4_SERVICE *MtftpSb,
415 OUT MTFTP4_PROTOCOL *Instance
416 )
417 {
418 ZeroMem (Instance, sizeof (MTFTP4_PROTOCOL));
419
420 Instance->Signature = MTFTP4_PROTOCOL_SIGNATURE;
421 InitializeListHead (&Instance->Link);
422 CopyMem (&Instance->Mtftp4, &gMtftp4ProtocolTemplate, sizeof (Instance->Mtftp4));
423 Instance->State = MTFTP4_STATE_UNCONFIGED;
424 Instance->InDestory = FALSE;
425 Instance->Service = MtftpSb;
426
427 InitializeListHead (&Instance->Blocks);
428 }
429
430
431 /**
432 Create a MTFTP child for the service binding instance, then
433 install the MTFTP protocol to the ChildHandle.
434
435 @param This The MTFTP service binding instance.
436 @param ChildHandle The Child handle to install the MTFTP protocol.
437
438 @retval EFI_INVALID_PARAMETER The parameter is invalid.
439 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the new child.
440 @retval EFI_SUCCESS The child is successfully create.
441
442 **/
443 EFI_STATUS
444 EFIAPI
445 Mtftp4ServiceBindingCreateChild (
446 IN EFI_SERVICE_BINDING_PROTOCOL *This,
447 IN EFI_HANDLE *ChildHandle
448 )
449 {
450 MTFTP4_SERVICE *MtftpSb;
451 MTFTP4_PROTOCOL *Instance;
452 EFI_STATUS Status;
453 EFI_TPL OldTpl;
454 VOID *Udp4;
455
456 if ((This == NULL) || (ChildHandle == NULL)) {
457 return EFI_INVALID_PARAMETER;
458 }
459
460 Instance = AllocatePool (sizeof (*Instance));
461
462 if (Instance == NULL) {
463 return EFI_OUT_OF_RESOURCES;
464 }
465
466 MtftpSb = MTFTP4_SERVICE_FROM_THIS (This);
467
468 Mtftp4InitProtocol (MtftpSb, Instance);
469
470 Instance->UnicastPort = UdpIoCreatePort (
471 MtftpSb->Controller,
472 MtftpSb->Image,
473 Mtftp4ConfigNullUdp,
474 Instance
475 );
476
477 if (Instance->UnicastPort == NULL) {
478 gBS->FreePool (Instance);
479 return EFI_OUT_OF_RESOURCES;
480 }
481
482 //
483 // Install the MTFTP protocol onto ChildHandle
484 //
485 Status = gBS->InstallMultipleProtocolInterfaces (
486 ChildHandle,
487 &gEfiMtftp4ProtocolGuid,
488 &Instance->Mtftp4,
489 NULL
490 );
491
492 if (EFI_ERROR (Status)) {
493 goto ON_ERROR;
494 }
495
496 Instance->Handle = *ChildHandle;
497
498 //
499 // Open the Udp4 protocol BY_CHILD.
500 //
501 Status = gBS->OpenProtocol (
502 MtftpSb->ConnectUdp->UdpHandle,
503 &gEfiUdp4ProtocolGuid,
504 (VOID **) &Udp4,
505 gMtftp4DriverBinding.DriverBindingHandle,
506 Instance->Handle,
507 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
508 );
509 if (EFI_ERROR (Status)) {
510 gBS->UninstallMultipleProtocolInterfaces (
511 Instance->Handle,
512 &gEfiMtftp4ProtocolGuid,
513 &Instance->Mtftp4,
514 NULL
515 );
516
517 goto ON_ERROR;
518 }
519
520 //
521 // Add it to the parent's child list.
522 //
523 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
524
525 InsertTailList (&MtftpSb->Children, &Instance->Link);
526 MtftpSb->ChildrenNum++;
527
528 gBS->RestoreTPL (OldTpl);
529
530 ON_ERROR:
531
532 if (EFI_ERROR (Status)) {
533 UdpIoFreePort (Instance->UnicastPort);
534 gBS->FreePool (Instance);
535 }
536
537 return Status;
538 }
539
540
541 /**
542 Destory one of the service binding's child.
543
544 @param This The service binding instance
545 @param ChildHandle The child handle to destory
546
547 @retval EFI_INVALID_PARAMETER The parameter is invaid.
548 @retval EFI_UNSUPPORTED The child may have already been destoried.
549 @retval EFI_SUCCESS The child is destoried and removed from the
550 parent's child list.
551
552 **/
553 EFI_STATUS
554 EFIAPI
555 Mtftp4ServiceBindingDestroyChild (
556 IN EFI_SERVICE_BINDING_PROTOCOL *This,
557 IN EFI_HANDLE ChildHandle
558 )
559 {
560 MTFTP4_SERVICE *MtftpSb;
561 MTFTP4_PROTOCOL *Instance;
562 EFI_MTFTP4_PROTOCOL *Mtftp4;
563 EFI_STATUS Status;
564 EFI_TPL OldTpl;
565
566 if ((This == NULL) || (ChildHandle == NULL)) {
567 return EFI_INVALID_PARAMETER;
568 }
569
570 //
571 // Retrieve the private context data structures
572 //
573 Status = gBS->OpenProtocol (
574 ChildHandle,
575 &gEfiMtftp4ProtocolGuid,
576 (VOID **) &Mtftp4,
577 gMtftp4DriverBinding.DriverBindingHandle,
578 ChildHandle,
579 EFI_OPEN_PROTOCOL_GET_PROTOCOL
580 );
581
582 if (EFI_ERROR (Status)) {
583 return EFI_UNSUPPORTED;
584 }
585
586 Instance = MTFTP4_PROTOCOL_FROM_THIS (Mtftp4);
587 MtftpSb = MTFTP4_SERVICE_FROM_THIS (This);
588
589 if (Instance->Service != MtftpSb) {
590 return EFI_INVALID_PARAMETER;
591 }
592
593 if (Instance->InDestory) {
594 return EFI_SUCCESS;
595 }
596
597 Instance->InDestory = TRUE;
598
599 //
600 // Close the Udp4 protocol.
601 //
602 gBS->CloseProtocol (
603 MtftpSb->ConnectUdp->UdpHandle,
604 &gEfiUdp4ProtocolGuid,
605 gMtftp4DriverBinding.DriverBindingHandle,
606 ChildHandle
607 );
608
609 //
610 // Uninstall the MTFTP4 protocol first to enable a top down destruction.
611 //
612 Status = gBS->UninstallProtocolInterface (
613 ChildHandle,
614 &gEfiMtftp4ProtocolGuid,
615 Mtftp4
616 );
617
618 if (EFI_ERROR (Status)) {
619 Instance->InDestory = FALSE;
620 return Status;
621 }
622
623 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
624
625 Mtftp4CleanOperation (Instance, EFI_DEVICE_ERROR);
626 UdpIoFreePort (Instance->UnicastPort);
627
628 RemoveEntryList (&Instance->Link);
629 MtftpSb->ChildrenNum--;
630
631 gBS->RestoreTPL (OldTpl);
632
633 gBS->FreePool (Instance);
634 return EFI_SUCCESS;
635 }