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