BaseTools:Change the path of the file that Binary Cache
[mirror_edk2.git] / MdeModulePkg / Universal / Network / MnpDxe / MnpDriver.c
1 /** @file\r
2   Implementation of driver entry point and driver binding protocol.\r
3 \r
4 Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
6 \r
7 **/\r
8 \r
9 #include "MnpDriver.h"\r
10 #include "MnpImpl.h"\r
11 #include "MnpVlan.h"\r
12 \r
13 EFI_DRIVER_BINDING_PROTOCOL gMnpDriverBinding = {\r
14   MnpDriverBindingSupported,\r
15   MnpDriverBindingStart,\r
16   MnpDriverBindingStop,\r
17   0xa,\r
18   NULL,\r
19   NULL\r
20 };\r
21 \r
22 /**\r
23   Callback function which provided by user to remove one node in NetDestroyLinkList process.\r
24 \r
25   @param[in]    Entry           The entry to be removed.\r
26   @param[in]    Context         Pointer to the callback context corresponds to the Context in NetDestroyLinkList.\r
27 \r
28   @retval EFI_SUCCESS           The entry has been removed successfully.\r
29   @retval Others                Fail to remove the entry.\r
30 \r
31 **/\r
32 EFI_STATUS\r
33 EFIAPI\r
34 MnpDestroyServiceDataEntry (\r
35   IN LIST_ENTRY         *Entry,\r
36   IN VOID               *Context\r
37   )\r
38 {\r
39   MNP_SERVICE_DATA              *MnpServiceData;\r
40 \r
41   MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (Entry);\r
42   return MnpDestroyServiceData (MnpServiceData);\r
43 }\r
44 \r
45 /**\r
46   Callback function which provided by user to remove one node in NetDestroyLinkList process.\r
47 \r
48   @param[in]    Entry           The entry to be removed.\r
49   @param[in]    Context         Pointer to the callback context corresponds to the Context in NetDestroyLinkList.\r
50 \r
51   @retval EFI_SUCCESS           The entry has been removed successfully.\r
52   @retval Others                Fail to remove the entry.\r
53 \r
54 **/\r
55 EFI_STATUS\r
56 EFIAPI\r
57 MnpDestroyServiceChildEntry (\r
58   IN LIST_ENTRY         *Entry,\r
59   IN VOID               *Context\r
60   )\r
61 {\r
62   MNP_SERVICE_DATA              *MnpServiceData;\r
63 \r
64   MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (Entry);\r
65   return MnpDestroyServiceChild (MnpServiceData);\r
66 }\r
67 \r
68 /**\r
69   Test to see if this driver supports ControllerHandle. This service\r
70   is called by the EFI boot service ConnectController(). In\r
71   order to make drivers as small as possible, there are a few calling\r
72   restrictions for this service. ConnectController() must\r
73   follow these calling restrictions. If any other agent wishes to call\r
74   Supported() it must also follow these calling restrictions.\r
75 \r
76   @param[in]  This                 Protocol instance pointer.\r
77   @param[in]  ControllerHandle     Handle of device to test.\r
78   @param[in]  RemainingDevicePath  Optional parameter use to pick a specific\r
79                                    child device to start.\r
80 \r
81   @retval EFI_SUCCESS              This driver supports this device.\r
82   @retval EFI_ALREADY_STARTED      This driver is already running on this device.\r
83   @retval Others                   This driver does not support this device.\r
84 \r
85 **/\r
86 EFI_STATUS\r
87 EFIAPI\r
88 MnpDriverBindingSupported (\r
89   IN EFI_DRIVER_BINDING_PROTOCOL     *This,\r
90   IN EFI_HANDLE                      ControllerHandle,\r
91   IN EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath OPTIONAL\r
92   )\r
93 {\r
94   EFI_STATUS                   Status;\r
95   EFI_SIMPLE_NETWORK_PROTOCOL  *Snp;\r
96 \r
97   //\r
98   // Test to open the Simple Network protocol BY_DRIVER.\r
99   //\r
100   Status = gBS->OpenProtocol (\r
101                   ControllerHandle,\r
102                   &gEfiSimpleNetworkProtocolGuid,\r
103                   (VOID **) &Snp,\r
104                   This->DriverBindingHandle,\r
105                   ControllerHandle,\r
106                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
107                   );\r
108   if (EFI_ERROR (Status)) {\r
109     return Status;\r
110   }\r
111 \r
112   //\r
113   // Close the openned SNP protocol.\r
114   //\r
115   gBS->CloseProtocol (\r
116          ControllerHandle,\r
117          &gEfiSimpleNetworkProtocolGuid,\r
118          This->DriverBindingHandle,\r
119          ControllerHandle\r
120          );\r
121 \r
122   return EFI_SUCCESS;\r
123 }\r
124 \r
125 \r
126 /**\r
127   Start this driver on ControllerHandle. This service is called by the\r
128   EFI boot service ConnectController(). In order to make drivers as small\r
129   as possible, there are a few calling restrictions for this service.\r
130   ConnectController() must follow these calling restrictions. If any other\r
131   agent wishes to call Start() it must also follow these calling restrictions.\r
132 \r
133   @param[in]       This                 Protocol instance pointer.\r
134   @param[in]       ControllerHandle     Handle of device to bind driver to.\r
135   @param[in]       RemainingDevicePath  Optional parameter use to pick a specific\r
136                                         child device to start.\r
137 \r
138   @retval EFI_SUCCESS           This driver is added to ControllerHandle.\r
139   @retval EFI_ALREADY_STARTED   This driver is already running on ControllerHandle.\r
140   @retval EFI_OUT_OF_RESOURCES  Failed to allocate memory for Mnp Service Data.\r
141   @retval Others                This driver does not support this device.\r
142 \r
143 **/\r
144 EFI_STATUS\r
145 EFIAPI\r
146 MnpDriverBindingStart (\r
147   IN EFI_DRIVER_BINDING_PROTOCOL     *This,\r
148   IN EFI_HANDLE                      ControllerHandle,\r
149   IN EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath OPTIONAL\r
150   )\r
151 {\r
152   EFI_STATUS        Status;\r
153   MNP_SERVICE_DATA  *MnpServiceData;\r
154   MNP_DEVICE_DATA   *MnpDeviceData;\r
155   LIST_ENTRY        *Entry;\r
156   VLAN_TCI          *VlanVariable;\r
157   UINTN             NumberOfVlan;\r
158   UINTN             Index;\r
159 \r
160   VlanVariable = NULL;\r
161 \r
162   //\r
163   // Initialize the Mnp Device Data\r
164   //\r
165   MnpDeviceData = AllocateZeroPool (sizeof (MNP_DEVICE_DATA));\r
166   if (MnpDeviceData == NULL) {\r
167     DEBUG ((EFI_D_ERROR, "MnpDriverBindingStart(): Failed to allocate the Mnp Device Data.\n"));\r
168 \r
169     return EFI_OUT_OF_RESOURCES;\r
170   }\r
171 \r
172   Status = MnpInitializeDeviceData (MnpDeviceData, This->DriverBindingHandle, ControllerHandle);\r
173   if (EFI_ERROR (Status)) {\r
174     DEBUG ((EFI_D_ERROR, "MnpDriverBindingStart: MnpInitializeDeviceData failed, %r.\n", Status));\r
175 \r
176     FreePool (MnpDeviceData);\r
177     return Status;\r
178   }\r
179 \r
180   //\r
181   // Check whether NIC driver has already produced VlanConfig protocol\r
182   //\r
183   Status = gBS->OpenProtocol (\r
184                   ControllerHandle,\r
185                   &gEfiVlanConfigProtocolGuid,\r
186                   NULL,\r
187                   This->DriverBindingHandle,\r
188                   ControllerHandle,\r
189                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
190                   );\r
191   if (!EFI_ERROR (Status)) {\r
192     //\r
193     // NIC hardware already implement VLAN,\r
194     // no need to provide software VLAN implementation in MNP driver\r
195     //\r
196     MnpDeviceData->NumberOfVlan = 0;\r
197     ZeroMem (&MnpDeviceData->VlanConfig, sizeof (EFI_VLAN_CONFIG_PROTOCOL));\r
198     MnpServiceData = MnpCreateServiceData (MnpDeviceData, 0, 0);\r
199     Status = (MnpServiceData != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;\r
200     goto Exit;\r
201   }\r
202 \r
203   //\r
204   // Install VLAN Config Protocol\r
205   //\r
206   Status = gBS->InstallMultipleProtocolInterfaces (\r
207                   &ControllerHandle,\r
208                   &gEfiVlanConfigProtocolGuid,\r
209                   &MnpDeviceData->VlanConfig,\r
210                   NULL\r
211                   );\r
212   if (EFI_ERROR (Status)) {\r
213     goto Exit;\r
214   }\r
215 \r
216   //\r
217   // Get current VLAN configuration from EFI Variable\r
218   //\r
219   NumberOfVlan = 0;\r
220   Status = MnpGetVlanVariable (MnpDeviceData, &NumberOfVlan, &VlanVariable);\r
221   if (EFI_ERROR (Status)) {\r
222     //\r
223     // No VLAN is set, create a default MNP service data for untagged frame\r
224     //\r
225     MnpDeviceData->NumberOfVlan = 0;\r
226     MnpServiceData = MnpCreateServiceData (MnpDeviceData, 0, 0);\r
227     Status = (MnpServiceData != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;\r
228     goto Exit;\r
229   }\r
230 \r
231   //\r
232   // Create MNP service data for each VLAN\r
233   //\r
234   MnpDeviceData->NumberOfVlan = NumberOfVlan;\r
235   for (Index = 0; Index < NumberOfVlan; Index++) {\r
236     MnpServiceData = MnpCreateServiceData (\r
237                        MnpDeviceData,\r
238                        VlanVariable[Index].Bits.Vid,\r
239                        (UINT8) VlanVariable[Index].Bits.Priority\r
240                        );\r
241 \r
242     if (MnpServiceData == NULL) {\r
243       Status = EFI_OUT_OF_RESOURCES;\r
244 \r
245       goto Exit;\r
246     }\r
247   }\r
248 \r
249 Exit:\r
250   if (VlanVariable != NULL) {\r
251     FreePool (VlanVariable);\r
252   }\r
253 \r
254   if (EFI_ERROR (Status)) {\r
255     //\r
256     // Destroy all MNP service data\r
257     //\r
258     while (!IsListEmpty (&MnpDeviceData->ServiceList)) {\r
259       Entry = GetFirstNode (&MnpDeviceData->ServiceList);\r
260       MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (Entry);\r
261       MnpDestroyServiceData (MnpServiceData);\r
262     }\r
263 \r
264     //\r
265     // Uninstall the VLAN Config Protocol if any\r
266     //\r
267     if (MnpDeviceData->VlanConfig.Set != NULL) {\r
268       gBS->UninstallMultipleProtocolInterfaces (\r
269              MnpDeviceData->ControllerHandle,\r
270              &gEfiVlanConfigProtocolGuid,\r
271              &MnpDeviceData->VlanConfig,\r
272              NULL\r
273              );\r
274     }\r
275 \r
276     //\r
277     // Destroy Mnp Device Data\r
278     //\r
279     MnpDestroyDeviceData (MnpDeviceData, This->DriverBindingHandle);\r
280     FreePool (MnpDeviceData);\r
281   }\r
282 \r
283   return Status;\r
284 }\r
285 \r
286 /**\r
287   Stop this driver on ControllerHandle. This service is called by the\r
288   EFI boot service DisconnectController(). In order to make drivers as\r
289   small as possible, there are a few calling restrictions for this service.\r
290   DisconnectController() must follow these calling restrictions. If any other\r
291   agent wishes to call Stop() it must also follow these calling restrictions.\r
292 \r
293   @param[in]  This               Protocol instance pointer.\r
294   @param[in]  ControllerHandle   Handle of device to stop driver on.\r
295   @param[in]  NumberOfChildren   Number of Handles in ChildHandleBuffer. If\r
296                                  number of children is zero stop the entire\r
297                                  bus driver.\r
298   @param[in]  ChildHandleBuffer  List of Child Handles to Stop.\r
299 \r
300   @retval EFI_SUCCESS            This driver is removed ControllerHandle.\r
301   @retval EFI_DEVICE_ERROR       The device could not be stopped due to a device error.\r
302 \r
303 **/\r
304 EFI_STATUS\r
305 EFIAPI\r
306 MnpDriverBindingStop (\r
307   IN EFI_DRIVER_BINDING_PROTOCOL     *This,\r
308   IN EFI_HANDLE                      ControllerHandle,\r
309   IN UINTN                           NumberOfChildren,\r
310   IN EFI_HANDLE                      *ChildHandleBuffer OPTIONAL\r
311   )\r
312 {\r
313   EFI_STATUS                    Status;\r
314   EFI_SERVICE_BINDING_PROTOCOL  *ServiceBinding;\r
315   EFI_VLAN_CONFIG_PROTOCOL      *VlanConfig;\r
316   MNP_DEVICE_DATA               *MnpDeviceData;\r
317   MNP_SERVICE_DATA              *MnpServiceData;\r
318   LIST_ENTRY                    *List;\r
319   UINTN                         ListLength;\r
320 \r
321   //\r
322   // Try to retrieve MNP service binding protocol from the ControllerHandle\r
323   //\r
324   Status = gBS->OpenProtocol (\r
325                   ControllerHandle,\r
326                   &gEfiManagedNetworkServiceBindingProtocolGuid,\r
327                   (VOID **) &ServiceBinding,\r
328                   This->DriverBindingHandle,\r
329                   ControllerHandle,\r
330                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
331                   );\r
332   if (EFI_ERROR (Status)) {\r
333     //\r
334     // Retrieve VLAN Config Protocol from the ControllerHandle\r
335     //\r
336     Status = gBS->OpenProtocol (\r
337                     ControllerHandle,\r
338                     &gEfiVlanConfigProtocolGuid,\r
339                     (VOID **) &VlanConfig,\r
340                     This->DriverBindingHandle,\r
341                     ControllerHandle,\r
342                     EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
343                     );\r
344     if (EFI_ERROR (Status)) {\r
345       DEBUG ((EFI_D_ERROR, "MnpDriverBindingStop: try to stop unknown Controller.\n"));\r
346       return EFI_DEVICE_ERROR;\r
347     }\r
348 \r
349     MnpDeviceData = MNP_DEVICE_DATA_FROM_THIS (VlanConfig);\r
350   } else {\r
351     MnpServiceData = MNP_SERVICE_DATA_FROM_THIS (ServiceBinding);\r
352     MnpDeviceData = MnpServiceData->MnpDeviceData;\r
353   }\r
354 \r
355   if (NumberOfChildren == 0) {\r
356     //\r
357     // Destroy all MNP service data\r
358     //\r
359     List = &MnpDeviceData->ServiceList;\r
360     Status = NetDestroyLinkList (\r
361                List,\r
362                MnpDestroyServiceDataEntry,\r
363                NULL,\r
364                &ListLength\r
365                );\r
366     if (EFI_ERROR (Status) || ListLength !=0) {\r
367       return EFI_DEVICE_ERROR;\r
368     }\r
369 \r
370     //\r
371     // Uninstall the VLAN Config Protocol if any\r
372     //\r
373     if (MnpDeviceData->VlanConfig.Set != NULL) {\r
374       gBS->UninstallMultipleProtocolInterfaces (\r
375              MnpDeviceData->ControllerHandle,\r
376              &gEfiVlanConfigProtocolGuid,\r
377              &MnpDeviceData->VlanConfig,\r
378              NULL\r
379              );\r
380     }\r
381 \r
382     //\r
383     // Destroy Mnp Device Data\r
384     //\r
385     MnpDestroyDeviceData (MnpDeviceData, This->DriverBindingHandle);\r
386     FreePool (MnpDeviceData);\r
387 \r
388     if (gMnpControllerNameTable != NULL) {\r
389       FreeUnicodeStringTable (gMnpControllerNameTable);\r
390       gMnpControllerNameTable = NULL;\r
391     }\r
392     return EFI_SUCCESS;\r
393   }\r
394 \r
395   //\r
396   // Stop all MNP child\r
397   //\r
398   List = &MnpDeviceData->ServiceList;\r
399   Status = NetDestroyLinkList (\r
400              List,\r
401              MnpDestroyServiceChildEntry,\r
402              NULL,\r
403              &ListLength\r
404              );\r
405   if (EFI_ERROR (Status)) {\r
406     return EFI_DEVICE_ERROR;\r
407   }\r
408 \r
409   return EFI_SUCCESS;\r
410 }\r
411 \r
412 \r
413 /**\r
414   Creates a child handle with a set of I/O services.\r
415 \r
416   @param[in]       This              Protocol instance pointer.\r
417   @param[in, out]  ChildHandle       Pointer to the handle of the child to create. If\r
418                                      it is NULL, then a new handle is created. If\r
419                                      it is not NULL, then the I/O services are added\r
420                                      to the existing child handle.\r
421 \r
422   @retval EFI_SUCCES                 The protocol was added to ChildHandle.\r
423   @retval EFI_INVALID_PARAMETER      ChildHandle is NULL.\r
424   @retval EFI_OUT_OF_RESOURCES       There are not enough resources available to\r
425                                      create the child.\r
426   @retval Others                     The child handle was not created.\r
427 \r
428 **/\r
429 EFI_STATUS\r
430 EFIAPI\r
431 MnpServiceBindingCreateChild (\r
432   IN     EFI_SERVICE_BINDING_PROTOCOL    *This,\r
433   IN OUT EFI_HANDLE                      *ChildHandle\r
434   )\r
435 {\r
436   EFI_STATUS         Status;\r
437   MNP_SERVICE_DATA   *MnpServiceData;\r
438   MNP_INSTANCE_DATA  *Instance;\r
439   VOID               *MnpSb;\r
440   EFI_TPL            OldTpl;\r
441 \r
442   if ((This == NULL) || (ChildHandle == NULL)) {\r
443     return EFI_INVALID_PARAMETER;\r
444   }\r
445 \r
446   MnpServiceData = MNP_SERVICE_DATA_FROM_THIS (This);\r
447 \r
448   //\r
449   // Allocate buffer for the new instance.\r
450   //\r
451   Instance = AllocateZeroPool (sizeof (MNP_INSTANCE_DATA));\r
452   if (Instance == NULL) {\r
453     DEBUG ((EFI_D_ERROR, "MnpServiceBindingCreateChild: Faild to allocate memory for the new instance.\n"));\r
454 \r
455     return EFI_OUT_OF_RESOURCES;\r
456   }\r
457 \r
458   //\r
459   // Init the instance data.\r
460   //\r
461   MnpInitializeInstanceData (MnpServiceData, Instance);\r
462 \r
463   Status = gBS->InstallMultipleProtocolInterfaces (\r
464                   ChildHandle,\r
465                   &gEfiManagedNetworkProtocolGuid,\r
466                   &Instance->ManagedNetwork,\r
467                   NULL\r
468                   );\r
469   if (EFI_ERROR (Status)) {\r
470     DEBUG (\r
471       (EFI_D_ERROR,\r
472       "MnpServiceBindingCreateChild: Failed to install the MNP protocol, %r.\n",\r
473       Status)\r
474       );\r
475 \r
476     goto ErrorExit;\r
477   }\r
478 \r
479   //\r
480   // Save the instance's childhandle.\r
481   //\r
482   Instance->Handle = *ChildHandle;\r
483 \r
484   Status = gBS->OpenProtocol (\r
485                   MnpServiceData->ServiceHandle,\r
486                   &gEfiManagedNetworkServiceBindingProtocolGuid,\r
487                   (VOID **) &MnpSb,\r
488                   gMnpDriverBinding.DriverBindingHandle,\r
489                   Instance->Handle,\r
490                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
491                   );\r
492   if (EFI_ERROR (Status)) {\r
493     goto ErrorExit;\r
494   }\r
495 \r
496   //\r
497   // Add the child instance into ChildrenList.\r
498   //\r
499   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
500 \r
501   InsertTailList (&MnpServiceData->ChildrenList, &Instance->InstEntry);\r
502   MnpServiceData->ChildrenNumber++;\r
503 \r
504   gBS->RestoreTPL (OldTpl);\r
505 \r
506 ErrorExit:\r
507 \r
508   if (EFI_ERROR (Status)) {\r
509 \r
510     if (Instance->Handle != NULL) {\r
511 \r
512       gBS->UninstallMultipleProtocolInterfaces (\r
513             Instance->Handle,\r
514             &gEfiManagedNetworkProtocolGuid,\r
515             &Instance->ManagedNetwork,\r
516             NULL\r
517             );\r
518     }\r
519 \r
520     FreePool (Instance);\r
521   }\r
522 \r
523   return Status;\r
524 }\r
525 \r
526 \r
527 /**\r
528   Destroys a child handle with a set of I/O services.\r
529 \r
530   The DestroyChild() function does the opposite of CreateChild(). It removes a\r
531   protocol that was installed by CreateChild() from ChildHandle. If the removed\r
532   protocol is the last protocol on ChildHandle, then ChildHandle is destroyed.\r
533 \r
534   @param[in]  This               Pointer to the EFI_SERVICE_BINDING_PROTOCOL\r
535                                  instance.\r
536   @param[in]  ChildHandle        Handle of the child to destroy.\r
537 \r
538   @retval EFI_SUCCES             The protocol was removed from ChildHandle.\r
539   @retval EFI_UNSUPPORTED        ChildHandle does not support the protocol that\r
540                                  is being removed.\r
541   @retval EFI_INVALID_PARAMETER  ChildHandle is NULL.\r
542   @retval EFI_ACCESS_DENIED      The protocol could not be removed from the\r
543                                  ChildHandle because its services are being\r
544                                  used.\r
545   @retval Others                 The child handle was not destroyed.\r
546 \r
547 **/\r
548 EFI_STATUS\r
549 EFIAPI\r
550 MnpServiceBindingDestroyChild (\r
551   IN EFI_SERVICE_BINDING_PROTOCOL    *This,\r
552   IN EFI_HANDLE                      ChildHandle\r
553   )\r
554 {\r
555   EFI_STATUS                    Status;\r
556   MNP_SERVICE_DATA              *MnpServiceData;\r
557   EFI_MANAGED_NETWORK_PROTOCOL  *ManagedNetwork;\r
558   MNP_INSTANCE_DATA             *Instance;\r
559   EFI_TPL                       OldTpl;\r
560 \r
561   if ((This == NULL) || (ChildHandle == NULL)) {\r
562     return EFI_INVALID_PARAMETER;\r
563   }\r
564 \r
565   MnpServiceData = MNP_SERVICE_DATA_FROM_THIS (This);\r
566 \r
567   //\r
568   // Try to retrieve ManagedNetwork Protocol from ChildHandle.\r
569   //\r
570   Status = gBS->OpenProtocol (\r
571                   ChildHandle,\r
572                   &gEfiManagedNetworkProtocolGuid,\r
573                   (VOID **) &ManagedNetwork,\r
574                   gMnpDriverBinding.DriverBindingHandle,\r
575                   ChildHandle,\r
576                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
577                   );\r
578   if (EFI_ERROR (Status)) {\r
579     return EFI_UNSUPPORTED;\r
580   }\r
581 \r
582   Instance = MNP_INSTANCE_DATA_FROM_THIS (ManagedNetwork);\r
583 \r
584   //\r
585   // MnpServiceBindingDestroyChild may be called twice: first called by\r
586   // MnpServiceBindingStop, second called by uninstalling the MNP protocol\r
587   // in this ChildHandle. Use destroyed to make sure the resource clean code\r
588   // will only excecute once.\r
589   //\r
590   if (Instance->Destroyed) {\r
591     return EFI_SUCCESS;\r
592   }\r
593 \r
594   Instance->Destroyed = TRUE;\r
595 \r
596   //\r
597   // Close the Simple Network protocol.\r
598   //\r
599   gBS->CloseProtocol (\r
600          MnpServiceData->ServiceHandle,\r
601          &gEfiManagedNetworkServiceBindingProtocolGuid,\r
602          MnpServiceData->MnpDeviceData->ImageHandle,\r
603          ChildHandle\r
604          );\r
605 \r
606   //\r
607   // Uninstall the ManagedNetwork protocol.\r
608   //\r
609   Status = gBS->UninstallMultipleProtocolInterfaces (\r
610                   ChildHandle,\r
611                   &gEfiManagedNetworkProtocolGuid,\r
612                   &Instance->ManagedNetwork,\r
613                   NULL\r
614                   );\r
615   if (EFI_ERROR (Status)) {\r
616     DEBUG (\r
617       (EFI_D_ERROR,\r
618       "MnpServiceBindingDestroyChild: Failed to uninstall the ManagedNetwork protocol, %r.\n",\r
619       Status)\r
620       );\r
621 \r
622     Instance->Destroyed = FALSE;\r
623     return Status;\r
624   }\r
625 \r
626   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
627 \r
628   //\r
629   // Reset the configuration.\r
630   //\r
631   ManagedNetwork->Configure (ManagedNetwork, NULL);\r
632 \r
633   //\r
634   // Try to flush the RcvdPacketQueue.\r
635   //\r
636   MnpFlushRcvdDataQueue (Instance);\r
637 \r
638   //\r
639   // Clean the RxTokenMap.\r
640   //\r
641   NetMapClean (&Instance->RxTokenMap);\r
642 \r
643   //\r
644   // Remove this instance from the ChildrenList.\r
645   //\r
646   RemoveEntryList (&Instance->InstEntry);\r
647   MnpServiceData->ChildrenNumber--;\r
648 \r
649   gBS->RestoreTPL (OldTpl);\r
650 \r
651   FreePool (Instance);\r
652 \r
653   return Status;\r
654 }\r
655 \r
656 /**\r
657   The entry point for Mnp driver which installs the driver binding and component\r
658   name protocol on its ImageHandle.\r
659 \r
660   @param[in]  ImageHandle  The image handle of the driver.\r
661   @param[in]  SystemTable  The system table.\r
662 \r
663   @retval EFI_SUCCES       The driver binding and component name protocols are\r
664                            successfully installed.\r
665   @retval Others           Other errors as indicated.\r
666 \r
667 **/\r
668 EFI_STATUS\r
669 EFIAPI\r
670 MnpDriverEntryPoint (\r
671   IN EFI_HANDLE          ImageHandle,\r
672   IN EFI_SYSTEM_TABLE    *SystemTable\r
673   )\r
674 {\r
675   return EfiLibInstallDriverBindingComponentName2 (\r
676            ImageHandle,\r
677            SystemTable,\r
678            &gMnpDriverBinding,\r
679            ImageHandle,\r
680            &gMnpComponentName,\r
681            &gMnpComponentName2\r
682            );\r
683 }\r