fixed one bug in stop(), adding get NicHandle by gEfiArpProtocolGuid.
[people/mcb30/edk2.git] / edk2 / MdeModulePkg / Universal / Network / UefiPxeBcDxe / PxeBcDriver.c
1 /** @file\r
2 \r
3 Copyright (c) 2007 - 2008, Intel Corporation\r
4 All rights reserved. This program and the accompanying materials\r
5 are licensed and made available under the terms and conditions of the BSD License\r
6 which accompanies this distribution.  The full text of the license may be found at\r
7 http://opensource.org/licenses/bsd-license.php\r
8 \r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11 \r
12 Module Name:\r
13 \r
14   PxeBcDriver.c\r
15 \r
16 Abstract:\r
17 \r
18   The driver binding for IP4 CONFIG protocol.\r
19 \r
20 \r
21 **/\r
22 \r
23 \r
24 #include "PxeBcImpl.h"\r
25 \r
26 \r
27 /**\r
28   The entry point for PxeBc driver which install the driver\r
29   binding and component name protocol on its image.\r
30 \r
31   @param  ImageHandle          The Image handle of the driver\r
32   @param  SystemTable          The system table\r
33 \r
34   @return EFI_SUCCESS\r
35   @return Others\r
36 \r
37 **/\r
38 EFI_STATUS\r
39 PxeBcDriverEntryPoint (\r
40   IN EFI_HANDLE             ImageHandle,\r
41   IN EFI_SYSTEM_TABLE       *SystemTable\r
42   )\r
43 {\r
44   return EfiLibInstallDriverBindingComponentName2 (\r
45           ImageHandle,\r
46           SystemTable,\r
47           &gPxeBcDriverBinding,\r
48           ImageHandle,\r
49           &gPxeBcComponentName,\r
50           &gPxeBcComponentName2\r
51           );\r
52 }\r
53 \r
54 \r
55 /**\r
56   Test to see if this driver supports ControllerHandle.\r
57 \r
58   @param  This                 Protocol instance pointer.\r
59   @param  ControllerHandle     Handle of device to test\r
60   @param  RemainingDevicePath  Optional parameter use to pick a specific child\r
61                                device to start.\r
62 \r
63   @return EFI_SUCCES\r
64   @return EFI_ALREADY_STARTED\r
65   @return Others\r
66 \r
67 **/\r
68 EFI_STATUS\r
69 EFIAPI\r
70 PxeBcDriverBindingSupported (\r
71   IN EFI_DRIVER_BINDING_PROTOCOL  * This,\r
72   IN EFI_HANDLE                   ControllerHandle,\r
73   IN EFI_DEVICE_PATH_PROTOCOL     * RemainingDevicePath OPTIONAL\r
74   )\r
75 {\r
76   EFI_PXE_BASE_CODE_PROTOCOL  *PxeBc;\r
77   EFI_STATUS                  Status;\r
78 \r
79   Status = gBS->OpenProtocol (\r
80                   ControllerHandle,\r
81                   &gEfiPxeBaseCodeProtocolGuid,\r
82                   (VOID **) &PxeBc,\r
83                   This->DriverBindingHandle,\r
84                   ControllerHandle,\r
85                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
86                   );\r
87 \r
88   if (!EFI_ERROR (Status)) {\r
89     return EFI_ALREADY_STARTED;\r
90   }\r
91 \r
92   Status = gBS->OpenProtocol (\r
93                   ControllerHandle,\r
94                   &gEfiDhcp4ServiceBindingProtocolGuid,\r
95                   NULL,\r
96                   This->DriverBindingHandle,\r
97                   ControllerHandle,\r
98                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
99                   );\r
100 \r
101   if (!EFI_ERROR (Status)) {\r
102 \r
103     Status = gBS->OpenProtocol (\r
104                     ControllerHandle,\r
105                     &gEfiMtftp4ServiceBindingProtocolGuid,\r
106                     NULL,\r
107                     This->DriverBindingHandle,\r
108                     ControllerHandle,\r
109                     EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
110                     );\r
111 \r
112   }\r
113 \r
114   return Status;\r
115 }\r
116 \r
117 \r
118 /**\r
119   Start this driver on ControllerHandle.\r
120 \r
121   @param  This                 Protocol instance pointer.\r
122   @param  ControllerHandle     Handle of device to bind driver to\r
123   @param  RemainingDevicePath  Optional parameter use to pick a specific child\r
124                                device to start.\r
125 \r
126   @return EFI_SUCCES\r
127   @return EFI_ALREADY_STARTED\r
128   @return EFI_OUT_OF_RESOURCES\r
129   @return Others\r
130 \r
131 **/\r
132 EFI_STATUS\r
133 EFIAPI\r
134 PxeBcDriverBindingStart (\r
135   IN EFI_DRIVER_BINDING_PROTOCOL  * This,\r
136   IN EFI_HANDLE                   ControllerHandle,\r
137   IN EFI_DEVICE_PATH_PROTOCOL     * RemainingDevicePath OPTIONAL\r
138   )\r
139 {\r
140   PXEBC_PRIVATE_DATA  *Private;\r
141   UINTN               Index;\r
142   EFI_STATUS          Status;\r
143 \r
144   Private = AllocateZeroPool (sizeof (PXEBC_PRIVATE_DATA));\r
145   if (Private == NULL) {\r
146     return EFI_OUT_OF_RESOURCES;\r
147   }\r
148 \r
149   Private->Signature                    = PXEBC_PRIVATE_DATA_SIGNATURE;\r
150   Private->Controller                   = ControllerHandle;\r
151   Private->Image                        = This->DriverBindingHandle;\r
152   CopyMem (&Private->PxeBc, &mPxeBcProtocolTemplate, sizeof (Private->PxeBc));\r
153   Private->PxeBc.Mode                   = &Private->Mode;\r
154   CopyMem (&Private->LoadFile, &mLoadFileProtocolTemplate, sizeof (Private->LoadFile));\r
155 \r
156   Private->ProxyOffer.Packet.Offer.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;\r
157   Private->Dhcp4Ack.Packet.Ack.Size     = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;\r
158   Private->PxeReply.Packet.Ack.Size     = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;\r
159 \r
160   for (Index = 0; Index < PXEBC_MAX_OFFER_NUM; Index++) {\r
161     Private->Dhcp4Offers[Index].Packet.Offer.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;\r
162   }\r
163 \r
164   //\r
165   // Get the NII interface\r
166   //\r
167   Status = gBS->OpenProtocol (\r
168                   ControllerHandle,\r
169                   &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
170                   (VOID **) &Private->Nii,\r
171                   This->DriverBindingHandle,\r
172                   ControllerHandle,\r
173                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
174                   );\r
175   if (EFI_ERROR (Status)) {\r
176     goto ON_ERROR;\r
177   }\r
178 \r
179   Status = NetLibCreateServiceChild (\r
180             ControllerHandle,\r
181             This->DriverBindingHandle,\r
182             &gEfiArpServiceBindingProtocolGuid,\r
183             &Private->ArpChild\r
184             );\r
185   if (EFI_ERROR (Status)) {\r
186     goto ON_ERROR;\r
187   }\r
188 \r
189   Status = gBS->OpenProtocol (\r
190                   Private->ArpChild,\r
191                   &gEfiArpProtocolGuid,\r
192                   (VOID **) &Private->Arp,\r
193                   This->DriverBindingHandle,\r
194                   ControllerHandle,\r
195                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
196                   );\r
197   if (EFI_ERROR (Status)) {\r
198     goto ON_ERROR;\r
199   }\r
200 \r
201   Status = NetLibCreateServiceChild (\r
202             ControllerHandle,\r
203             This->DriverBindingHandle,\r
204             &gEfiDhcp4ServiceBindingProtocolGuid,\r
205             &Private->Dhcp4Child\r
206             );\r
207   if (EFI_ERROR (Status)) {\r
208     goto ON_ERROR;\r
209   }\r
210 \r
211   Status = gBS->OpenProtocol (\r
212                   Private->Dhcp4Child,\r
213                   &gEfiDhcp4ProtocolGuid,\r
214                   (VOID **) &Private->Dhcp4,\r
215                   This->DriverBindingHandle,\r
216                   ControllerHandle,\r
217                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
218                   );\r
219   if (EFI_ERROR (Status)) {\r
220     goto ON_ERROR;\r
221   }\r
222 \r
223   Status = NetLibCreateServiceChild (\r
224              ControllerHandle,\r
225              This->DriverBindingHandle,\r
226              &gEfiMtftp4ServiceBindingProtocolGuid,\r
227              &Private->Mtftp4Child\r
228              );\r
229 \r
230   if (EFI_ERROR (Status)) {\r
231     goto ON_ERROR;\r
232   }\r
233 \r
234   Status = gBS->OpenProtocol (\r
235                   Private->Mtftp4Child,\r
236                   &gEfiMtftp4ProtocolGuid,\r
237                   (VOID **) &Private->Mtftp4,\r
238                   This->DriverBindingHandle,\r
239                   ControllerHandle,\r
240                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
241                   );\r
242 \r
243   if (EFI_ERROR (Status)) {\r
244     goto ON_ERROR;\r
245   }\r
246 \r
247   Status = NetLibCreateServiceChild (\r
248              ControllerHandle,\r
249              This->DriverBindingHandle,\r
250              &gEfiUdp4ServiceBindingProtocolGuid,\r
251              &Private->Udp4Child\r
252              );\r
253 \r
254   if (EFI_ERROR (Status)) {\r
255     goto ON_ERROR;\r
256   }\r
257 \r
258   Status = gBS->OpenProtocol (\r
259                   Private->Udp4Child,\r
260                   &gEfiUdp4ProtocolGuid,\r
261                   (VOID **) &Private->Udp4,\r
262                   This->DriverBindingHandle,\r
263                   ControllerHandle,\r
264                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
265                   );\r
266 \r
267   if (EFI_ERROR (Status)) {\r
268     goto ON_ERROR;\r
269   }\r
270 \r
271   ZeroMem (&Private->Udp4CfgData, sizeof (EFI_UDP4_CONFIG_DATA));\r
272   Private->Udp4CfgData.AcceptBroadcast    = FALSE;\r
273   Private->Udp4CfgData.AcceptPromiscuous  = FALSE;\r
274   Private->Udp4CfgData.AcceptAnyPort      = FALSE;\r
275   Private->Udp4CfgData.AllowDuplicatePort = TRUE;\r
276   Private->Udp4CfgData.TypeOfService      = DEFAULT_ToS;\r
277   Private->Udp4CfgData.TimeToLive         = DEFAULT_TTL;\r
278   Private->Udp4CfgData.DoNotFragment      = FALSE;\r
279   Private->Udp4CfgData.ReceiveTimeout     = 10000;  // 10 milliseconds\r
280   Private->Udp4CfgData.UseDefaultAddress  = FALSE;\r
281 \r
282   PxeBcInitSeedPacket (&Private->SeedPacket, Private->Udp4);\r
283 \r
284   Status = gBS->InstallMultipleProtocolInterfaces (\r
285                   &ControllerHandle,\r
286                   &gEfiPxeBaseCodeProtocolGuid,\r
287                   &Private->PxeBc,\r
288                   &gEfiLoadFileProtocolGuid,\r
289                   &Private->LoadFile,\r
290                   NULL\r
291                   );\r
292   if (EFI_ERROR (Status)) {\r
293     goto ON_ERROR;\r
294   }\r
295 \r
296   return EFI_SUCCESS;\r
297 \r
298 ON_ERROR:\r
299 \r
300   if (Private->Udp4Child != NULL) {\r
301     gBS->CloseProtocol (\r
302           Private->Udp4Child,\r
303           &gEfiUdp4ProtocolGuid,\r
304           This->DriverBindingHandle,\r
305           ControllerHandle\r
306           );\r
307     NetLibDestroyServiceChild (\r
308       ControllerHandle,\r
309       This->DriverBindingHandle,\r
310       &gEfiUdp4ServiceBindingProtocolGuid,\r
311       Private->Udp4Child\r
312       );\r
313   }\r
314 \r
315   if (Private->Mtftp4Child != NULL) {\r
316     gBS->CloseProtocol (\r
317           Private->Mtftp4Child,\r
318           &gEfiMtftp4ProtocolGuid,\r
319           This->DriverBindingHandle,\r
320           ControllerHandle\r
321           );\r
322 \r
323     NetLibDestroyServiceChild (\r
324       ControllerHandle,\r
325       This->DriverBindingHandle,\r
326       &gEfiMtftp4ServiceBindingProtocolGuid,\r
327       Private->Mtftp4Child\r
328       );\r
329   }\r
330 \r
331   if (Private->Dhcp4Child != NULL) {\r
332     gBS->CloseProtocol (\r
333           Private->Dhcp4Child,\r
334           &gEfiDhcp4ProtocolGuid,\r
335           This->DriverBindingHandle,\r
336           ControllerHandle\r
337           );\r
338 \r
339     NetLibDestroyServiceChild (\r
340       ControllerHandle,\r
341       This->DriverBindingHandle,\r
342       &gEfiDhcp4ServiceBindingProtocolGuid,\r
343       Private->Dhcp4Child\r
344       );\r
345   }\r
346 \r
347   if (Private->ArpChild != NULL) {\r
348     gBS->CloseProtocol (\r
349           Private->ArpChild,\r
350           &gEfiArpProtocolGuid,\r
351           This->DriverBindingHandle,\r
352           ControllerHandle\r
353           );\r
354 \r
355     NetLibDestroyServiceChild (\r
356       ControllerHandle,\r
357       This->DriverBindingHandle,\r
358       &gEfiArpServiceBindingProtocolGuid,\r
359       Private->ArpChild\r
360       );\r
361   }\r
362 \r
363   gBS->FreePool (Private);\r
364 \r
365   return Status;\r
366 }\r
367 \r
368 \r
369 /**\r
370   Stop this driver on ControllerHandle.\r
371 \r
372   @param  This                 Protocol instance pointer.\r
373   @param  ControllerHandle     Handle of device to stop driver on\r
374   @param  NumberOfChildren     Number of Handles in ChildHandleBuffer. If number of\r
375                                 children is zero stop the entire bus driver.\r
376   @param  ChildHandleBuffer    List of Child Handles to Stop.\r
377 \r
378   @return EFI_SUCCESS\r
379   @return EFI_DEVICE_ERROR\r
380   @return Others\r
381 \r
382 **/\r
383 EFI_STATUS\r
384 EFIAPI\r
385 PxeBcDriverBindingStop (\r
386   IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
387   IN EFI_HANDLE                   ControllerHandle,\r
388   IN UINTN                        NumberOfChildren,\r
389   IN EFI_HANDLE                   *ChildHandleBuffer\r
390   )\r
391 {\r
392   PXEBC_PRIVATE_DATA          *Private;\r
393   EFI_PXE_BASE_CODE_PROTOCOL  *PxeBc;\r
394   EFI_HANDLE                  NicHandle;\r
395   EFI_STATUS                  Status;\r
396 \r
397   NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);\r
398 \r
399   if (NicHandle == NULL) {\r
400 \r
401     NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);\r
402 \r
403     if (NicHandle == NULL) {\r
404 \r
405       NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiMtftp4ProtocolGuid);\r
406 \r
407       if (NicHandle == NULL) {\r
408 \r
409         return EFI_DEVICE_ERROR;\r
410 \r
411       }\r
412     }\r
413   }\r
414 \r
415   Status = gBS->OpenProtocol (\r
416                   NicHandle,\r
417                   &gEfiPxeBaseCodeProtocolGuid,\r
418                   (VOID **) &PxeBc,\r
419                   This->DriverBindingHandle,\r
420                   ControllerHandle,\r
421                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
422                   );\r
423 \r
424   if (EFI_ERROR (Status)) {\r
425     return Status;\r
426   }\r
427 \r
428   Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (PxeBc);\r
429 \r
430   Status = gBS->UninstallMultipleProtocolInterfaces (\r
431                   NicHandle,\r
432                   &gEfiPxeBaseCodeProtocolGuid,\r
433                   &Private->PxeBc,\r
434                   &gEfiLoadFileProtocolGuid,\r
435                   &Private->LoadFile,\r
436                   NULL\r
437                   );\r
438 \r
439   if (!EFI_ERROR (Status)) {\r
440 \r
441     gBS->CloseProtocol (\r
442           Private->Udp4Child,\r
443           &gEfiUdp4ProtocolGuid,\r
444           This->DriverBindingHandle,\r
445           NicHandle\r
446           );\r
447     NetLibDestroyServiceChild (\r
448       NicHandle,\r
449       This->DriverBindingHandle,\r
450       &gEfiUdp4ServiceBindingProtocolGuid,\r
451       Private->Udp4Child\r
452       );\r
453 \r
454     gBS->CloseProtocol (\r
455           Private->Dhcp4Child,\r
456           &gEfiDhcp4ProtocolGuid,\r
457           This->DriverBindingHandle,\r
458           NicHandle\r
459           );\r
460     NetLibDestroyServiceChild (\r
461       NicHandle,\r
462       This->DriverBindingHandle,\r
463       &gEfiDhcp4ServiceBindingProtocolGuid,\r
464       Private->Dhcp4Child\r
465       );\r
466 \r
467     gBS->CloseProtocol (\r
468           Private->Mtftp4Child,\r
469           &gEfiMtftp4ProtocolGuid,\r
470           This->DriverBindingHandle,\r
471           NicHandle\r
472           );\r
473     NetLibDestroyServiceChild (\r
474       NicHandle,\r
475       This->DriverBindingHandle,\r
476       &gEfiMtftp4ServiceBindingProtocolGuid,\r
477       Private->Mtftp4Child\r
478       );\r
479 \r
480     gBS->CloseProtocol (\r
481           Private->ArpChild,\r
482           &gEfiArpProtocolGuid,\r
483           This->DriverBindingHandle,\r
484           NicHandle\r
485           );\r
486     NetLibDestroyServiceChild (\r
487       NicHandle,\r
488       This->DriverBindingHandle,\r
489       &gEfiArpServiceBindingProtocolGuid,\r
490       Private->ArpChild\r
491       );\r
492 \r
493     gBS->FreePool (Private);\r
494   }\r
495 \r
496   return Status;\r
497 }\r
498 \r
499 EFI_DRIVER_BINDING_PROTOCOL gPxeBcDriverBinding = {\r
500   PxeBcDriverBindingSupported,\r
501   PxeBcDriverBindingStart,\r
502   PxeBcDriverBindingStop,\r
503   0xa,\r
504   NULL,\r
505   NULL\r
506 };\r
507 \r
508 \r