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