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