From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001 From: Angelos Mouzakitis Date: Tue, 10 Oct 2023 14:33:42 +0000 Subject: Add submodule dependency files Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec --- .../edk2/NetworkPkg/VlanConfigDxe/VlanConfigImpl.c | 664 +++++++++++++++++++++ 1 file changed, 664 insertions(+) create mode 100644 roms/edk2/NetworkPkg/VlanConfigDxe/VlanConfigImpl.c (limited to 'roms/edk2/NetworkPkg/VlanConfigDxe/VlanConfigImpl.c') diff --git a/roms/edk2/NetworkPkg/VlanConfigDxe/VlanConfigImpl.c b/roms/edk2/NetworkPkg/VlanConfigDxe/VlanConfigImpl.c new file mode 100644 index 000000000..24d844cbf --- /dev/null +++ b/roms/edk2/NetworkPkg/VlanConfigDxe/VlanConfigImpl.c @@ -0,0 +1,664 @@ +/** @file + HII Config Access protocol implementation of VLAN configuration module. + +Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#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 + 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 + 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 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 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 + 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; +} -- cgit