+ InsertTailList (&MnpDeviceData->ServiceList, &MnpServiceData->Link);\r
+\r
+ MnpServiceData->Signature = MNP_SERVICE_DATA_SIGNATURE;\r
+ MnpServiceData->MnpDeviceData = MnpDeviceData;\r
+\r
+ //\r
+ // Copy the ServiceBinding structure.\r
+ //\r
+ CopyMem (&MnpServiceData->ServiceBinding, &mMnpServiceBindingProtocol, sizeof (EFI_SERVICE_BINDING_PROTOCOL));\r
+\r
+ //\r
+ // Initialize the lists.\r
+ //\r
+ InitializeListHead (&MnpServiceData->ChildrenList);\r
+\r
+ SnpMode = MnpDeviceData->Snp->Mode;\r
+ if (VlanId != 0) {\r
+ //\r
+ // Create VLAN child handle\r
+ //\r
+ MnpServiceHandle = MnpCreateVlanChild (\r
+ MnpDeviceData->ImageHandle,\r
+ MnpDeviceData->ControllerHandle,\r
+ VlanId,\r
+ &MnpServiceData->DevicePath\r
+ );\r
+ if (MnpServiceHandle == NULL) {\r
+ DEBUG ((EFI_D_ERROR, "MnpCreateServiceData: Faild to create child handle.\n"));\r
+\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Open VLAN Config Protocol by child\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ MnpDeviceData->ControllerHandle,\r
+ &gEfiVlanConfigProtocolGuid,\r
+ (VOID **) &VlanConfig,\r
+ MnpDeviceData->ImageHandle,\r
+ MnpServiceHandle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // Reduce MTU for VLAN device\r
+ //\r
+ MnpServiceData->Mtu = SnpMode->MaxPacketSize - NET_VLAN_TAG_LEN;\r
+ } else {\r
+ //\r
+ // VlanId set to 0 means rx/tx untagged frame\r
+ //\r
+ MnpServiceHandle = MnpDeviceData->ControllerHandle;\r
+ MnpServiceData->Mtu = SnpMode->MaxPacketSize;\r
+ }\r
+\r
+ MnpServiceData->ServiceHandle = MnpServiceHandle;\r
+ MnpServiceData->VlanId = VlanId;\r
+ MnpServiceData->Priority = Priority;\r
+\r
+ //\r
+ // Install the MNP Service Binding Protocol\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &MnpServiceHandle,\r
+ &gEfiManagedNetworkServiceBindingProtocolGuid,\r
+ &MnpServiceData->ServiceBinding,\r
+ NULL\r
+ );\r
+\r
+Exit:\r
+ if (EFI_ERROR (Status)) {\r
+ MnpDestroyServiceData (MnpServiceData);\r
+ MnpServiceData = NULL;\r
+ }\r
+\r
+ return MnpServiceData;\r
+}\r
+\r
+/**\r
+ Destroy the MNP service context data.\r
+\r
+ @param[in, out] MnpServiceData Pointer to the mnp service context data.\r
+\r
+ @retval EFI_SUCCESS The mnp service context is destroyed.\r
+ @retval Others Errors as indicated.\r
+\r
+**/\r
+EFI_STATUS\r
+MnpDestroyServiceData (\r
+ IN OUT MNP_SERVICE_DATA *MnpServiceData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Uninstall the MNP Service Binding Protocol\r
+ //\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ MnpServiceData->ServiceHandle,\r
+ &gEfiManagedNetworkServiceBindingProtocolGuid,\r
+ &MnpServiceData->ServiceBinding,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (MnpServiceData->VlanId != 0) {\r
+ //\r
+ // Close VlanConfig Protocol opened by VLAN child handle\r
+ //\r
+ Status = gBS->CloseProtocol (\r
+ MnpServiceData->MnpDeviceData->ControllerHandle,\r
+ &gEfiVlanConfigProtocolGuid,\r
+ MnpServiceData->MnpDeviceData->ImageHandle,\r
+ MnpServiceData->ServiceHandle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Uninstall Device Path Protocol to destroy the VLAN child handle\r
+ //\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ MnpServiceData->ServiceHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ MnpServiceData->DevicePath,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (MnpServiceData->DevicePath != NULL) {\r
+ FreePool (MnpServiceData->DevicePath);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Remove from MnpDeviceData service list\r
+ //\r
+ RemoveEntryList (&MnpServiceData->Link);\r
+\r
+ FreePool (MnpServiceData);\r
+\r
+ return Status;\r