| /** @file | |
| HII Config Access protocol implementation of VLAN configuration module. | |
| Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR> | |
| This program and the accompanying materials | |
| are licensed and made available under the terms and conditions | |
| of the BSD License which accompanies this distribution. The full | |
| text of the license may be found at<BR> | |
| http://opensource.org/licenses/bsd-license.php | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| **/ | |
| #include "VlanConfigImpl.h" | |
| CHAR16 mVlanStorageName[] = L"VlanNvData"; | |
| EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting = NULL; | |
| VLAN_CONFIG_PRIVATE_DATA mVlanConfigPrivateDateTemplate = { | |
| VLAN_CONFIG_PRIVATE_DATA_SIGNATURE, | |
| { | |
| VlanExtractConfig, | |
| VlanRouteConfig, | |
| VlanCallback | |
| } | |
| }; | |
| VENDOR_DEVICE_PATH mHiiVendorDevicePathNode = { | |
| { | |
| HARDWARE_DEVICE_PATH, | |
| HW_VENDOR_DP, | |
| { | |
| (UINT8) (sizeof (VENDOR_DEVICE_PATH)), | |
| (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) | |
| } | |
| }, | |
| VLAN_CONFIG_FORM_SET_GUID | |
| }; | |
| /** | |
| This function allows a caller to extract the current configuration for one | |
| or more named elements from the target driver. | |
| @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. | |
| @param[in] Request A null-terminated Unicode string in | |
| <ConfigRequest> format. | |
| @param[out] Progress On return, points to a character in the Request | |
| string. Points to the string's null terminator if | |
| request was successful. Points to the most recent | |
| '&' before the first failing name/value pair (or | |
| the beginning of the string if the failure is in | |
| the first name/value pair) if the request was not | |
| successful. | |
| @param[out] Results A null-terminated Unicode string in | |
| <ConfigAltResp> format which has all values filled | |
| in for the names in the Request string. String to | |
| be allocated by the called function. | |
| @retval EFI_SUCCESS The Results is filled with the requested values. | |
| @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. | |
| @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name. | |
| @retval EFI_NOT_FOUND Routing data doesn't match any storage in this | |
| driver. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| VlanExtractConfig ( | |
| IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, | |
| IN CONST EFI_STRING Request, | |
| OUT EFI_STRING *Progress, | |
| OUT EFI_STRING *Results | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| UINTN BufferSize; | |
| VLAN_CONFIGURATION Configuration; | |
| VLAN_CONFIG_PRIVATE_DATA *PrivateData; | |
| EFI_STRING ConfigRequestHdr; | |
| EFI_STRING ConfigRequest; | |
| BOOLEAN AllocatedRequest; | |
| UINTN Size; | |
| if (Progress == NULL || Results == NULL) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| *Progress = Request; | |
| if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gVlanConfigFormSetGuid, mVlanStorageName)) { | |
| return EFI_NOT_FOUND; | |
| } | |
| ConfigRequestHdr = NULL; | |
| ConfigRequest = NULL; | |
| AllocatedRequest = FALSE; | |
| Size = 0; | |
| // | |
| // Retrieve the pointer to the UEFI HII Config Routing Protocol | |
| // | |
| if (mHiiConfigRouting == NULL) { | |
| gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &mHiiConfigRouting); | |
| } | |
| ASSERT (mHiiConfigRouting != NULL); | |
| // | |
| // Convert buffer data to <ConfigResp> by helper function BlockToConfig() | |
| // | |
| PrivateData = VLAN_CONFIG_PRIVATE_DATA_FROM_THIS (This); | |
| ZeroMem (&Configuration, sizeof (VLAN_CONFIGURATION)); | |
| BufferSize = sizeof (Configuration); | |
| ConfigRequest = Request; | |
| if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) { | |
| // | |
| // Request has no request element, construct full request string. | |
| // Allocate and fill a buffer large enough to hold the <ConfigHdr> template | |
| // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator | |
| // | |
| ConfigRequestHdr = HiiConstructConfigHdr (&gVlanConfigFormSetGuid, mVlanStorageName, PrivateData->DriverHandle); | |
| Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16); | |
| ConfigRequest = AllocateZeroPool (Size); | |
| ASSERT (ConfigRequest != NULL); | |
| AllocatedRequest = TRUE; | |
| UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize); | |
| FreePool (ConfigRequestHdr); | |
| } | |
| Status = mHiiConfigRouting->BlockToConfig ( | |
| mHiiConfigRouting, | |
| ConfigRequest, | |
| (UINT8 *) &Configuration, | |
| BufferSize, | |
| Results, | |
| Progress | |
| ); | |
| // | |
| // Free the allocated config request string. | |
| // | |
| if (AllocatedRequest) { | |
| FreePool (ConfigRequest); | |
| ConfigRequest = NULL; | |
| } | |
| // | |
| // Set Progress string to the original request string. | |
| // | |
| if (Request == NULL) { | |
| *Progress = NULL; | |
| } else if (StrStr (Request, L"OFFSET") == NULL) { | |
| *Progress = Request + StrLen (Request); | |
| } | |
| return Status; | |
| } | |
| /** | |
| This function processes the results of changes in configuration. | |
| @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. | |
| @param[in] Configuration A null-terminated Unicode string in <ConfigResp> | |
| format. | |
| @param[out] Progress A pointer to a string filled in with the offset of | |
| the most recent '&' before the first failing | |
| name/value pair (or the beginning of the string if | |
| the failure is in the first name/value pair) or | |
| the terminating NULL if all was successful. | |
| @retval EFI_SUCCESS The Results is processed successfully. | |
| @retval EFI_INVALID_PARAMETER Configuration is NULL. | |
| @retval EFI_NOT_FOUND Routing data doesn't match any storage in this | |
| driver. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| VlanRouteConfig ( | |
| IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, | |
| IN CONST EFI_STRING Configuration, | |
| OUT EFI_STRING *Progress | |
| ) | |
| { | |
| if (Configuration == NULL || Progress == NULL) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| *Progress = Configuration; | |
| if (!HiiIsConfigHdrMatch (Configuration, &gVlanConfigFormSetGuid, mVlanStorageName)) { | |
| return EFI_NOT_FOUND; | |
| } | |
| *Progress = Configuration + StrLen (Configuration); | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| This function processes the results of changes in configuration. | |
| @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. | |
| @param[in] Action Specifies the type of action taken by the browser. | |
| @param[in] QuestionId A unique value which is sent to the original | |
| exporting driver so that it can identify the type | |
| of data to expect. | |
| @param[in] Type The type of value for the question. | |
| @param[in] Value A pointer to the data being sent to the original | |
| exporting driver. | |
| @param[out] ActionRequest On return, points to the action requested by the | |
| callback function. | |
| @retval EFI_SUCCESS The callback successfully handled the action. | |
| @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the | |
| variable and its data. | |
| @retval EFI_DEVICE_ERROR The variable could not be saved. | |
| @retval EFI_UNSUPPORTED The specified Action is not supported by the | |
| callback. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| VlanCallback ( | |
| IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, | |
| IN EFI_BROWSER_ACTION Action, | |
| IN EFI_QUESTION_ID QuestionId, | |
| IN UINT8 Type, | |
| IN EFI_IFR_TYPE_VALUE *Value, | |
| OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest | |
| ) | |
| { | |
| VLAN_CONFIG_PRIVATE_DATA *PrivateData; | |
| VLAN_CONFIGURATION *Configuration; | |
| EFI_VLAN_CONFIG_PROTOCOL *VlanConfig; | |
| UINTN Index; | |
| EFI_HANDLE VlanHandle; | |
| PrivateData = VLAN_CONFIG_PRIVATE_DATA_FROM_THIS (This); | |
| if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)) { | |
| return EFI_SUCCESS; | |
| } | |
| if ((Action != EFI_BROWSER_ACTION_CHANGED) && (Action != EFI_BROWSER_ACTION_CHANGING)) { | |
| // | |
| // All other action return unsupported. | |
| // | |
| return EFI_UNSUPPORTED; | |
| } | |
| // | |
| // Get Browser data | |
| // | |
| Configuration = AllocateZeroPool (sizeof (VLAN_CONFIGURATION)); | |
| ASSERT (Configuration != NULL); | |
| HiiGetBrowserData (&gVlanConfigFormSetGuid, mVlanStorageName, sizeof (VLAN_CONFIGURATION), (UINT8 *) Configuration); | |
| VlanConfig = PrivateData->VlanConfig; | |
| if (Action == EFI_BROWSER_ACTION_CHANGED) { | |
| switch (QuestionId) { | |
| case VLAN_ADD_QUESTION_ID: | |
| // | |
| // Add a VLAN | |
| // | |
| VlanConfig->Set (VlanConfig, Configuration->VlanId, Configuration->Priority); | |
| VlanUpdateForm (PrivateData); | |
| // | |
| // Connect the newly created VLAN device | |
| // | |
| VlanHandle = NetLibGetVlanHandle (PrivateData->ControllerHandle, Configuration->VlanId); | |
| if (VlanHandle == NULL) { | |
| // | |
| // There may be no child handle created for VLAN ID 0, connect the parent handle | |
| // | |
| VlanHandle = PrivateData->ControllerHandle; | |
| } | |
| gBS->ConnectController (VlanHandle, NULL, NULL, TRUE); | |
| // | |
| // Clear UI data | |
| // | |
| *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; | |
| Configuration->VlanId = 0; | |
| Configuration->Priority = 0; | |
| break; | |
| case VLAN_REMOVE_QUESTION_ID: | |
| // | |
| // Remove VLAN | |
| // | |
| ASSERT (PrivateData->NumberOfVlan <= MAX_VLAN_NUMBER); | |
| for (Index = 0; Index < PrivateData->NumberOfVlan; Index++) { | |
| if (Configuration->VlanList[Index] != 0) { | |
| // | |
| // Checkbox is selected, need remove this VLAN | |
| // | |
| VlanConfig->Remove (VlanConfig, PrivateData->VlanId[Index]); | |
| } | |
| } | |
| VlanUpdateForm (PrivateData); | |
| if (PrivateData->NumberOfVlan == 0) { | |
| // | |
| // No VLAN device now, connect the physical NIC handle. | |
| // Note: PrivateData->NumberOfVlan has been updated by VlanUpdateForm() | |
| // | |
| gBS->ConnectController (PrivateData->ControllerHandle, NULL, NULL, TRUE); | |
| } | |
| *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; | |
| ZeroMem (Configuration->VlanList, MAX_VLAN_NUMBER); | |
| break; | |
| default: | |
| break; | |
| } | |
| } else if (Action == EFI_BROWSER_ACTION_CHANGING) { | |
| switch (QuestionId) { | |
| case VLAN_UPDATE_QUESTION_ID: | |
| // | |
| // Update current VLAN list into Form. | |
| // | |
| VlanUpdateForm (PrivateData); | |
| break; | |
| default: | |
| break; | |
| } | |
| } | |
| HiiSetBrowserData (&gVlanConfigFormSetGuid, mVlanStorageName, sizeof (VLAN_CONFIGURATION), (UINT8 *) Configuration, NULL); | |
| FreePool (Configuration); | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| This function update VLAN list in the VLAN configuration Form. | |
| @param[in, out] PrivateData Points to VLAN configuration private data. | |
| **/ | |
| VOID | |
| VlanUpdateForm ( | |
| IN OUT VLAN_CONFIG_PRIVATE_DATA *PrivateData | |
| ) | |
| { | |
| EFI_VLAN_CONFIG_PROTOCOL *VlanConfig; | |
| UINT16 NumberOfVlan; | |
| UINTN Index; | |
| EFI_VLAN_FIND_DATA *VlanData; | |
| VOID *StartOpCodeHandle; | |
| EFI_IFR_GUID_LABEL *StartLabel; | |
| VOID *EndOpCodeHandle; | |
| EFI_IFR_GUID_LABEL *EndLabel; | |
| CHAR16 *String; | |
| CHAR16 VlanStr[30]; | |
| CHAR16 VlanIdStr[6]; | |
| UINTN DigitalCount; | |
| EFI_STRING_ID StringId; | |
| // | |
| // Find current VLAN configuration | |
| // | |
| VlanData = NULL; | |
| NumberOfVlan = 0; | |
| VlanConfig = PrivateData->VlanConfig; | |
| VlanConfig->Find (VlanConfig, NULL, &NumberOfVlan, &VlanData); | |
| // | |
| // Update VLAN configuration in PrivateData | |
| // | |
| if (NumberOfVlan > MAX_VLAN_NUMBER) { | |
| NumberOfVlan = MAX_VLAN_NUMBER; | |
| } | |
| PrivateData->NumberOfVlan = NumberOfVlan; | |
| // | |
| // Init OpCode Handle | |
| // | |
| StartOpCodeHandle = HiiAllocateOpCodeHandle (); | |
| ASSERT (StartOpCodeHandle != NULL); | |
| EndOpCodeHandle = HiiAllocateOpCodeHandle (); | |
| ASSERT (EndOpCodeHandle != NULL); | |
| // | |
| // Create Hii Extend Label OpCode as the start opcode | |
| // | |
| StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( | |
| StartOpCodeHandle, | |
| &gEfiIfrTianoGuid, | |
| NULL, | |
| sizeof (EFI_IFR_GUID_LABEL) | |
| ); | |
| StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; | |
| StartLabel->Number = LABEL_VLAN_LIST; | |
| // | |
| // Create Hii Extend Label OpCode as the end opcode | |
| // | |
| EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( | |
| EndOpCodeHandle, | |
| &gEfiIfrTianoGuid, | |
| NULL, | |
| sizeof (EFI_IFR_GUID_LABEL) | |
| ); | |
| EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; | |
| EndLabel->Number = LABEL_END; | |
| ZeroMem (PrivateData->VlanId, MAX_VLAN_NUMBER); | |
| for (Index = 0; Index < NumberOfVlan; Index++) { | |
| String = VlanStr; | |
| StrCpyS (String, (sizeof (VlanStr) /sizeof (CHAR16)), L" VLAN ID:"); | |
| String += 10; | |
| // | |
| // Pad VlanId string up to 4 characters with space | |
| // | |
| UnicodeValueToStringS (VlanIdStr, sizeof (VlanIdStr), 0, VlanData[Index].VlanId, 5); | |
| DigitalCount = StrnLenS (VlanIdStr, ARRAY_SIZE (VlanIdStr)); | |
| SetMem16 (String, (4 - DigitalCount) * sizeof (CHAR16), L' '); | |
| StrCpyS (String + 4 - DigitalCount, (sizeof (VlanStr) /sizeof (CHAR16)) - 10 - (4 - DigitalCount), VlanIdStr); | |
| String += 4; | |
| StrCpyS (String, (sizeof (VlanStr) /sizeof (CHAR16)) - 10 - (4 - DigitalCount) - 4, L", Priority:"); | |
| String += 11; | |
| UnicodeValueToStringS ( | |
| String, | |
| sizeof (VlanStr) - ((UINTN)String - (UINTN)VlanStr), | |
| 0, | |
| VlanData[Index].Priority, | |
| 4 | |
| ); | |
| String += StrnLenS (String, ARRAY_SIZE (VlanStr) - ((UINTN)String - (UINTN)VlanStr) / sizeof (CHAR16)); | |
| *String = 0; | |
| StringId = HiiSetString (PrivateData->HiiHandle, 0, VlanStr, NULL); | |
| ASSERT (StringId != 0); | |
| HiiCreateCheckBoxOpCode ( | |
| StartOpCodeHandle, | |
| (EFI_QUESTION_ID) (VLAN_LIST_VAR_OFFSET + Index), | |
| VLAN_CONFIGURATION_VARSTORE_ID, | |
| (UINT16) (VLAN_LIST_VAR_OFFSET + Index), | |
| StringId, | |
| STRING_TOKEN (STR_VLAN_VLAN_LIST_HELP), | |
| 0, | |
| 0, | |
| NULL | |
| ); | |
| // | |
| // Save VLAN id to private data | |
| // | |
| PrivateData->VlanId[Index] = VlanData[Index].VlanId; | |
| } | |
| HiiUpdateForm ( | |
| PrivateData->HiiHandle, // HII handle | |
| &gVlanConfigFormSetGuid, // Formset GUID | |
| VLAN_CONFIGURATION_FORM_ID, // Form ID | |
| StartOpCodeHandle, // Label for where to insert opcodes | |
| EndOpCodeHandle // Replace data | |
| ); | |
| HiiFreeOpCodeHandle (StartOpCodeHandle); | |
| HiiFreeOpCodeHandle (EndOpCodeHandle); | |
| if (VlanData != NULL) { | |
| FreePool (VlanData); | |
| } | |
| } | |
| /** | |
| This function publish the VLAN configuration Form for a network device. The | |
| HII Config Access protocol will be installed on a child handle of the network | |
| device. | |
| @param[in, out] PrivateData Points to VLAN configuration private data. | |
| @retval EFI_SUCCESS HII Form is installed for this network device. | |
| @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation. | |
| @retval Others Other errors as indicated. | |
| **/ | |
| EFI_STATUS | |
| InstallVlanConfigForm ( | |
| IN OUT VLAN_CONFIG_PRIVATE_DATA *PrivateData | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| EFI_HII_HANDLE HiiHandle; | |
| EFI_HANDLE DriverHandle; | |
| CHAR16 Str[26 + sizeof (EFI_MAC_ADDRESS) * 2 + 1]; | |
| CHAR16 *MacString; | |
| EFI_DEVICE_PATH_PROTOCOL *ChildDevicePath; | |
| EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; | |
| EFI_VLAN_CONFIG_PROTOCOL *VlanConfig; | |
| // | |
| // Create child handle and install HII Config Access Protocol | |
| // | |
| ChildDevicePath = AppendDevicePathNode ( | |
| PrivateData->ParentDevicePath, | |
| (CONST EFI_DEVICE_PATH_PROTOCOL *) &mHiiVendorDevicePathNode | |
| ); | |
| if (ChildDevicePath == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| PrivateData->ChildDevicePath = ChildDevicePath; | |
| DriverHandle = NULL; | |
| ConfigAccess = &PrivateData->ConfigAccess; | |
| Status = gBS->InstallMultipleProtocolInterfaces ( | |
| &DriverHandle, | |
| &gEfiDevicePathProtocolGuid, | |
| ChildDevicePath, | |
| &gEfiHiiConfigAccessProtocolGuid, | |
| ConfigAccess, | |
| NULL | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| PrivateData->DriverHandle = DriverHandle; | |
| // | |
| // Establish the parent-child relationship between the new created | |
| // child handle and the ControllerHandle. | |
| // | |
| Status = gBS->OpenProtocol ( | |
| PrivateData->ControllerHandle, | |
| &gEfiVlanConfigProtocolGuid, | |
| (VOID **)&VlanConfig, | |
| PrivateData->ImageHandle, | |
| PrivateData->DriverHandle, | |
| EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| // | |
| // Publish the HII package list | |
| // | |
| HiiHandle = HiiAddPackages ( | |
| &gVlanConfigFormSetGuid, | |
| DriverHandle, | |
| VlanConfigDxeStrings, | |
| VlanConfigBin, | |
| NULL | |
| ); | |
| if (HiiHandle == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| PrivateData->HiiHandle = HiiHandle; | |
| // | |
| // Update formset title help string. | |
| // | |
| MacString = NULL; | |
| Status = NetLibGetMacString (PrivateData->ControllerHandle, PrivateData->ImageHandle, &MacString); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| PrivateData->MacString = MacString; | |
| StrCpyS (Str, sizeof (Str) / sizeof (CHAR16), L"VLAN Configuration (MAC:"); | |
| StrCatS (Str, sizeof (Str) / sizeof (CHAR16), MacString); | |
| StrCatS (Str, sizeof (Str) / sizeof (CHAR16), L")"); | |
| HiiSetString ( | |
| HiiHandle, | |
| STRING_TOKEN (STR_VLAN_FORM_SET_TITLE_HELP), | |
| Str, | |
| NULL | |
| ); | |
| // | |
| // Update form title help string. | |
| // | |
| HiiSetString ( | |
| HiiHandle, | |
| STRING_TOKEN (STR_VLAN_FORM_HELP), | |
| Str, | |
| NULL | |
| ); | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| This function remove the VLAN configuration Form for a network device. The | |
| child handle for HII Config Access protocol will be destroyed. | |
| @param[in, out] PrivateData Points to VLAN configuration private data. | |
| @retval EFI_SUCCESS HII Form has been uninstalled successfully. | |
| @retval Others Other errors as indicated. | |
| **/ | |
| EFI_STATUS | |
| UninstallVlanConfigForm ( | |
| IN OUT VLAN_CONFIG_PRIVATE_DATA *PrivateData | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| EFI_VLAN_CONFIG_PROTOCOL *VlanConfig; | |
| // | |
| // End the parent-child relationship. | |
| // | |
| Status = gBS->CloseProtocol ( | |
| PrivateData->ControllerHandle, | |
| &gEfiVlanConfigProtocolGuid, | |
| PrivateData->ImageHandle, | |
| PrivateData->DriverHandle | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| // | |
| // Uninstall HII Config Access Protocol | |
| // | |
| if (PrivateData->DriverHandle != NULL) { | |
| Status = gBS->UninstallMultipleProtocolInterfaces ( | |
| PrivateData->DriverHandle, | |
| &gEfiDevicePathProtocolGuid, | |
| PrivateData->ChildDevicePath, | |
| &gEfiHiiConfigAccessProtocolGuid, | |
| &PrivateData->ConfigAccess, | |
| NULL | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| gBS->OpenProtocol ( | |
| PrivateData->ControllerHandle, | |
| &gEfiVlanConfigProtocolGuid, | |
| (VOID **)&VlanConfig, | |
| PrivateData->ImageHandle, | |
| PrivateData->DriverHandle, | |
| EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER | |
| ); | |
| return Status; | |
| } | |
| PrivateData->DriverHandle = NULL; | |
| if (PrivateData->ChildDevicePath != NULL) { | |
| FreePool (PrivateData->ChildDevicePath); | |
| PrivateData->ChildDevicePath = NULL; | |
| } | |
| } | |
| // | |
| // Free MAC string | |
| // | |
| if (PrivateData->MacString != NULL) { | |
| FreePool (PrivateData->MacString); | |
| PrivateData->MacString = NULL; | |
| } | |
| // | |
| // Uninstall HII package list | |
| // | |
| if (PrivateData->HiiHandle != NULL) { | |
| HiiRemovePackages (PrivateData->HiiHandle); | |
| PrivateData->HiiHandle = NULL; | |
| } | |
| return EFI_SUCCESS; | |
| } |