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