| /** @file | |
| Shell application for VLAN configuration. | |
| Copyright (c) 2009 - 2016, 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 | |
| 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 <Uefi.h> | |
| #include <Protocol/VlanConfig.h> | |
| #include <Library/UefiApplicationEntryPoint.h> | |
| #include <Library/UefiLib.h> | |
| #include <Library/ShellLib.h> | |
| #include <Library/MemoryAllocationLib.h> | |
| #include <Library/HiiLib.h> | |
| #include <Library/UefiBootServicesTableLib.h> | |
| #include <Library/UefiHiiServicesLib.h> | |
| #include <Library/NetLib.h> | |
| // | |
| // String token ID of VConfig command help message text. | |
| // | |
| GLOBAL_REMOVE_IF_UNREFERENCED EFI_STRING_ID mStringVConfigHelpTokenId = STRING_TOKEN (STR_VCONFIG_HELP); | |
| #define INVALID_NIC_INDEX 0xffff | |
| #define INVALID_VLAN_ID 0xffff | |
| // | |
| // This is the generated String package data for all .UNI files. | |
| // This data array is ready to be used as input of HiiAddPackages() to | |
| // create a packagelist (which contains Form packages, String packages, etc). | |
| // | |
| extern UINT8 VConfigStrings[]; | |
| EFI_HANDLE mImageHandle = NULL; | |
| EFI_HII_HANDLE mHiiHandle = NULL; | |
| SHELL_PARAM_ITEM mParamList[] = { | |
| { | |
| L"-l", | |
| TypeValue | |
| }, | |
| { | |
| L"-a", | |
| TypeMaxValue | |
| }, | |
| { | |
| L"-d", | |
| TypeValue | |
| }, | |
| { | |
| NULL, | |
| TypeMax | |
| } | |
| }; | |
| /** | |
| Locate the network interface handle buffer. | |
| @param[out] NumberOfHandles Pointer to the number of handles. | |
| @param[out] HandleBuffer Pointer to the buffer to store the returned handles. | |
| **/ | |
| VOID | |
| LocateNicHandleBuffer ( | |
| OUT UINTN *NumberOfHandles, | |
| OUT EFI_HANDLE **HandleBuffer | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| *NumberOfHandles = 0; | |
| *HandleBuffer = NULL; | |
| Status = gBS->LocateHandleBuffer ( | |
| ByProtocol, | |
| &gEfiVlanConfigProtocolGuid, | |
| NULL, | |
| NumberOfHandles, | |
| HandleBuffer | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_LOCATE_FAIL), mHiiHandle, Status); | |
| } | |
| } | |
| /** | |
| Extract the decimal index from the network interface name. | |
| @param[in] Name Name of the network interface. | |
| @retval INVALID_NIC_INDEX Failed to extract the network interface index. | |
| @return others The network interface index. | |
| **/ | |
| UINTN | |
| NicNameToIndex ( | |
| IN CHAR16 *Name | |
| ) | |
| { | |
| CHAR16 *Str; | |
| Str = Name + 3; | |
| if ((StrnCmp (Name, L"eth", 3) != 0) || (*Str == 0)) { | |
| return INVALID_NIC_INDEX; | |
| } | |
| while (*Str != 0) { | |
| if ((*Str < L'0') || (*Str > L'9')) { | |
| return INVALID_NIC_INDEX; | |
| } | |
| Str++; | |
| } | |
| return (UINT16) StrDecimalToUintn (Name + 3); | |
| } | |
| /** | |
| Find network interface device handle by its name. | |
| @param[in] Name Name of the network interface. | |
| @retval NULL Cannot find the network interface. | |
| @return others Handle of the network interface. | |
| **/ | |
| EFI_HANDLE | |
| NicNameToHandle ( | |
| IN CHAR16 *Name | |
| ) | |
| { | |
| UINTN NumberOfHandles; | |
| EFI_HANDLE *HandleBuffer; | |
| UINTN Index; | |
| EFI_HANDLE Handle; | |
| // | |
| // Find all NIC handles. | |
| // | |
| LocateNicHandleBuffer (&NumberOfHandles, &HandleBuffer); | |
| if (NumberOfHandles == 0) { | |
| return NULL; | |
| } | |
| Index = NicNameToIndex (Name); | |
| if (Index >= NumberOfHandles) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_INVALID_IF), mHiiHandle, Name); | |
| Handle = NULL; | |
| } else { | |
| Handle = HandleBuffer[Index]; | |
| } | |
| FreePool (HandleBuffer); | |
| return Handle; | |
| } | |
| /** | |
| Open VlanConfig protocol from a handle. | |
| @param[in] Handle The handle to open the VlanConfig protocol. | |
| @return The VlanConfig protocol interface. | |
| **/ | |
| EFI_VLAN_CONFIG_PROTOCOL * | |
| OpenVlanConfigProtocol ( | |
| IN EFI_HANDLE Handle | |
| ) | |
| { | |
| EFI_VLAN_CONFIG_PROTOCOL *VlanConfig; | |
| VlanConfig = NULL; | |
| gBS->OpenProtocol ( | |
| Handle, | |
| &gEfiVlanConfigProtocolGuid, | |
| (VOID **) &VlanConfig, | |
| mImageHandle, | |
| Handle, | |
| EFI_OPEN_PROTOCOL_GET_PROTOCOL | |
| ); | |
| return VlanConfig; | |
| } | |
| /** | |
| Close VlanConfig protocol of a handle. | |
| @param[in] Handle The handle to close the VlanConfig protocol. | |
| **/ | |
| VOID | |
| CloseVlanConfigProtocol ( | |
| IN EFI_HANDLE Handle | |
| ) | |
| { | |
| gBS->CloseProtocol ( | |
| Handle, | |
| &gEfiVlanConfigProtocolGuid, | |
| mImageHandle, | |
| Handle | |
| ); | |
| } | |
| /** | |
| Display VLAN configuration of a network interface. | |
| @param[in] Handle Handle of the network interface. | |
| @param[in] NicIndex Index of the network interface. | |
| **/ | |
| VOID | |
| ShowNicVlanInfo ( | |
| IN EFI_HANDLE Handle, | |
| IN UINTN NicIndex | |
| ) | |
| { | |
| CHAR16 *MacStr; | |
| EFI_STATUS Status; | |
| UINTN Index; | |
| EFI_VLAN_CONFIG_PROTOCOL *VlanConfig; | |
| UINT16 NumberOfVlan; | |
| EFI_VLAN_FIND_DATA *VlanData; | |
| VlanConfig = OpenVlanConfigProtocol (Handle); | |
| if (VlanConfig == NULL) { | |
| return ; | |
| } | |
| MacStr = NULL; | |
| Status = NetLibGetMacString (Handle, mImageHandle, &MacStr); | |
| if (EFI_ERROR (Status)) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_MAC_FAIL), mHiiHandle, Status); | |
| goto Exit; | |
| } | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_ETH_MAC), mHiiHandle, NicIndex, MacStr); | |
| Status = VlanConfig->Find (VlanConfig, NULL, &NumberOfVlan, &VlanData); | |
| if (EFI_ERROR (Status)) { | |
| if (Status == EFI_NOT_FOUND) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_VLAN), mHiiHandle); | |
| } else { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_FIND_FAIL), mHiiHandle, Status); | |
| } | |
| goto Exit; | |
| } | |
| for (Index = 0; Index < NumberOfVlan; Index++) { | |
| ShellPrintHiiEx ( | |
| -1, | |
| -1, | |
| NULL, | |
| STRING_TOKEN (STR_VCONFIG_VLAN_DISPLAY), | |
| mHiiHandle, | |
| VlanData[Index].VlanId, | |
| VlanData[Index].Priority | |
| ); | |
| } | |
| FreePool (VlanData); | |
| Exit: | |
| CloseVlanConfigProtocol (Handle); | |
| if (MacStr != NULL) { | |
| FreePool (MacStr); | |
| } | |
| } | |
| /** | |
| Display the VLAN configuration of all, or a specified network interface. | |
| @param[in] Name Name of the network interface. If NULL, the VLAN | |
| configuration of all network will be displayed. | |
| **/ | |
| VOID | |
| DisplayVlan ( | |
| IN CHAR16 *Name OPTIONAL | |
| ) | |
| { | |
| UINTN NumberOfHandles; | |
| EFI_HANDLE *HandleBuffer; | |
| UINTN Index; | |
| EFI_HANDLE NicHandle; | |
| if (Name != NULL) { | |
| // | |
| // Display specified NIC | |
| // | |
| NicHandle = NicNameToHandle (Name); | |
| if (NicHandle == NULL) { | |
| return ; | |
| } | |
| ShowNicVlanInfo (NicHandle, 0); | |
| return ; | |
| } | |
| // | |
| // Find all NIC handles | |
| // | |
| LocateNicHandleBuffer (&NumberOfHandles, &HandleBuffer); | |
| if (NumberOfHandles == 0) { | |
| return ; | |
| } | |
| for (Index = 0; Index < NumberOfHandles; Index++) { | |
| ShowNicVlanInfo (HandleBuffer[Index], Index); | |
| } | |
| FreePool (HandleBuffer); | |
| } | |
| /** | |
| Convert a NULL-terminated unicode decimal VLAN ID string to VLAN ID. | |
| @param[in] String Pointer to VLAN ID string from user input. | |
| @retval Value translated from String, or INVALID_VLAN_ID is string is invalid. | |
| **/ | |
| UINT16 | |
| StrToVlanId ( | |
| IN CHAR16 *String | |
| ) | |
| { | |
| CHAR16 *Str; | |
| if (String == NULL) { | |
| return INVALID_VLAN_ID; | |
| } | |
| Str = String; | |
| while ((*Str >= '0') && (*Str <= '9')) { | |
| Str++; | |
| } | |
| if (*Str != 0) { | |
| return INVALID_VLAN_ID; | |
| } | |
| return (UINT16) StrDecimalToUintn (String); | |
| } | |
| /** | |
| Add a VLAN device. | |
| @param[in] ParamStr Parameter string from user input. | |
| **/ | |
| VOID | |
| AddVlan ( | |
| IN CHAR16 *ParamStr | |
| ) | |
| { | |
| CHAR16 *Name; | |
| CHAR16 *VlanIdStr; | |
| CHAR16 *PriorityStr; | |
| CHAR16 *StrPtr; | |
| BOOLEAN IsSpace; | |
| UINTN VlanId; | |
| UINTN Priority; | |
| EFI_HANDLE Handle; | |
| EFI_HANDLE VlanHandle; | |
| EFI_VLAN_CONFIG_PROTOCOL *VlanConfig; | |
| EFI_STATUS Status; | |
| VlanConfig = NULL; | |
| Priority = 0; | |
| if (ParamStr == NULL) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_IF), mHiiHandle); | |
| return ; | |
| } | |
| StrPtr = AllocateCopyPool (StrSize (ParamStr), ParamStr); | |
| if (StrPtr == NULL) { | |
| return ; | |
| } | |
| Name = StrPtr; | |
| VlanIdStr = NULL; | |
| PriorityStr = NULL; | |
| IsSpace = FALSE; | |
| while (*StrPtr != 0) { | |
| if (*StrPtr == L' ') { | |
| *StrPtr = 0; | |
| IsSpace = TRUE; | |
| } else { | |
| if (IsSpace) { | |
| // | |
| // Start of a parameter. | |
| // | |
| if (VlanIdStr == NULL) { | |
| // | |
| // 2nd parameter is VLAN ID. | |
| // | |
| VlanIdStr = StrPtr; | |
| } else if (PriorityStr == NULL) { | |
| // | |
| // 3rd parameter is Priority. | |
| // | |
| PriorityStr = StrPtr; | |
| } else { | |
| // | |
| // Ignore else parameters. | |
| // | |
| break; | |
| } | |
| } | |
| IsSpace = FALSE; | |
| } | |
| StrPtr++; | |
| } | |
| Handle = NicNameToHandle (Name); | |
| if (Handle == NULL) { | |
| goto Exit; | |
| } | |
| VlanConfig = OpenVlanConfigProtocol (Handle); | |
| if (VlanConfig == NULL) { | |
| goto Exit; | |
| } | |
| // | |
| // Check VLAN ID. | |
| // | |
| if ((VlanIdStr == NULL) || (*VlanIdStr == 0)) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_VID), mHiiHandle); | |
| goto Exit; | |
| } | |
| VlanId = StrToVlanId (VlanIdStr); | |
| if (VlanId > 4094) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_INVALID_VID), mHiiHandle, VlanIdStr); | |
| goto Exit; | |
| } | |
| // | |
| // Check Priority. | |
| // | |
| if ((PriorityStr != NULL) && (*PriorityStr != 0)) { | |
| Priority = StrDecimalToUintn (PriorityStr); | |
| if (Priority > 7) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_INVALID_PRIORITY), mHiiHandle, PriorityStr); | |
| goto Exit; | |
| } | |
| } | |
| // | |
| // Set VLAN | |
| // | |
| Status = VlanConfig->Set (VlanConfig, (UINT16) VlanId, (UINT8) Priority); | |
| if (EFI_ERROR (Status)) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_SET_FAIL), mHiiHandle, Status); | |
| goto Exit; | |
| } | |
| // | |
| // Connect the VLAN device. | |
| // | |
| VlanHandle = NetLibGetVlanHandle (Handle, (UINT16) VlanId); | |
| if (VlanHandle != NULL) { | |
| gBS->ConnectController (VlanHandle, NULL, NULL, TRUE); | |
| } | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_SET_SUCCESS), mHiiHandle); | |
| Exit: | |
| if (VlanConfig != NULL) { | |
| CloseVlanConfigProtocol (Handle); | |
| } | |
| FreePool (Name); | |
| } | |
| /** | |
| Remove a VLAN device. | |
| @param[in] ParamStr Parameter string from user input. | |
| **/ | |
| VOID | |
| DeleteVlan ( | |
| IN CHAR16 *ParamStr | |
| ) | |
| { | |
| CHAR16 *Name; | |
| CHAR16 *VlanIdStr; | |
| CHAR16 *StrPtr; | |
| UINTN VlanId; | |
| EFI_HANDLE Handle; | |
| EFI_VLAN_CONFIG_PROTOCOL *VlanConfig; | |
| EFI_STATUS Status; | |
| UINT16 NumberOfVlan; | |
| EFI_VLAN_FIND_DATA *VlanData; | |
| VlanConfig = NULL; | |
| if (ParamStr == NULL) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_IF), mHiiHandle); | |
| return ; | |
| } | |
| StrPtr = AllocateCopyPool (StrSize (ParamStr), ParamStr); | |
| if (StrPtr == NULL) { | |
| return ; | |
| } | |
| Name = StrPtr; | |
| VlanIdStr = NULL; | |
| while (*StrPtr != 0) { | |
| if (*StrPtr == L'.') { | |
| *StrPtr = 0; | |
| VlanIdStr = StrPtr + 1; | |
| break; | |
| } | |
| StrPtr++; | |
| } | |
| Handle = NicNameToHandle (Name); | |
| if (Handle == NULL) { | |
| goto Exit; | |
| } | |
| VlanConfig = OpenVlanConfigProtocol (Handle); | |
| if (VlanConfig == NULL) { | |
| goto Exit; | |
| } | |
| // | |
| // Check VLAN ID | |
| // | |
| if (VlanIdStr == NULL || *VlanIdStr == 0) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_VID), mHiiHandle); | |
| goto Exit; | |
| } | |
| VlanId = StrToVlanId (VlanIdStr); | |
| if (VlanId > 4094) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_INVALID_VID), mHiiHandle, VlanIdStr); | |
| goto Exit; | |
| } | |
| // | |
| // Delete VLAN. | |
| // | |
| Status = VlanConfig->Remove (VlanConfig, (UINT16) VlanId); | |
| if (EFI_ERROR (Status)) { | |
| if (Status == EFI_NOT_FOUND) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NOT_FOUND), mHiiHandle); | |
| } else { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_REMOVE_FAIL), mHiiHandle, Status); | |
| } | |
| goto Exit; | |
| } | |
| // | |
| // Check whether this is the last VLAN to remove. | |
| // | |
| Status = VlanConfig->Find (VlanConfig, NULL, &NumberOfVlan, &VlanData); | |
| if (EFI_ERROR (Status)) { | |
| // | |
| // This is the last VLAN to remove, try to connect the controller handle. | |
| // | |
| gBS->ConnectController (Handle, NULL, NULL, TRUE); | |
| } else { | |
| FreePool (VlanData); | |
| } | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_REMOVE_SUCCESS), mHiiHandle); | |
| Exit: | |
| if (VlanConfig != NULL) { | |
| CloseVlanConfigProtocol (Handle); | |
| } | |
| FreePool (Name); | |
| } | |
| /** | |
| The actual entry point for the application. | |
| @param[in] ImageHandle The firmware allocated handle for the EFI image. | |
| @param[in] SystemTable A pointer to the EFI System Table. | |
| @retval EFI_SUCCESS The entry point executed successfully. | |
| @retval other Some error occur when executing this entry point. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| VlanConfigMain ( | |
| IN EFI_HANDLE ImageHandle, | |
| IN EFI_SYSTEM_TABLE *SystemTable | |
| ) | |
| { | |
| LIST_ENTRY *List; | |
| CONST CHAR16 *Str; | |
| EFI_HII_PACKAGE_LIST_HEADER *PackageList; | |
| EFI_STATUS Status; | |
| mImageHandle = ImageHandle; | |
| // | |
| // Retrieve HII package list from ImageHandle | |
| // | |
| Status = gBS->OpenProtocol ( | |
| ImageHandle, | |
| &gEfiHiiPackageListProtocolGuid, | |
| (VOID **) &PackageList, | |
| ImageHandle, | |
| NULL, | |
| EFI_OPEN_PROTOCOL_GET_PROTOCOL | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| // | |
| // Publish HII package list to HII Database. | |
| // | |
| Status = gHiiDatabase->NewPackageList ( | |
| gHiiDatabase, | |
| PackageList, | |
| NULL, | |
| &mHiiHandle | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| if (mHiiHandle == NULL) { | |
| return EFI_SUCCESS; | |
| } | |
| List = NULL; | |
| ShellCommandLineParseEx (mParamList, &List, NULL, FALSE, FALSE); | |
| if (List == NULL) { | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_ARG), mHiiHandle); | |
| goto Exit; | |
| } | |
| if (ShellCommandLineGetFlag (List, L"-l")) { | |
| Str = ShellCommandLineGetValue (List, L"-l"); | |
| DisplayVlan ((CHAR16 *) Str); | |
| goto Exit; | |
| } | |
| if (ShellCommandLineGetFlag (List, L"-a")) { | |
| Str = ShellCommandLineGetValue (List, L"-a"); | |
| AddVlan ((CHAR16 *) Str); | |
| goto Exit; | |
| } | |
| if (ShellCommandLineGetFlag (List, L"-d")) { | |
| Str = ShellCommandLineGetValue (List, L"-d"); | |
| DeleteVlan ((CHAR16 *) Str); | |
| goto Exit; | |
| } | |
| // | |
| // No valid argument till now. | |
| // | |
| ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_ARG), mHiiHandle); | |
| Exit: | |
| if (List != NULL) { | |
| ShellCommandLineFreeVarList (List); | |
| } | |
| // | |
| // Remove our string package from HII database. | |
| // | |
| HiiRemovePackages (mHiiHandle); | |
| return EFI_SUCCESS; | |
| } |