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