--- /dev/null
+/** @file\r
+ Shell application for VLAN configuration.\r
+\r
+ Copyright (C) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Uefi.h>\r
+\r
+#include <Protocol/VlanConfig.h>\r
+\r
+#include <Library/UefiApplicationEntryPoint.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/ShellLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/NetLib.h>\r
+\r
+#define INVALID_NIC_INDEX 0xffff\r
+#define INVALID_VLAN_ID 0xffff\r
+\r
+//\r
+// This is the generated String package data for all .UNI files.\r
+// This data array is ready to be used as input of HiiAddPackages() to\r
+// create a packagelist (which contains Form packages, String packages, etc).\r
+//\r
+extern UINT8 VConfigStrings[];\r
+\r
+EFI_HANDLE mImageHandle = NULL;\r
+EFI_HII_HANDLE mHiiHandle = NULL;\r
+\r
+SHELL_PARAM_ITEM mParamList[] = {\r
+ {\r
+ L"-l",\r
+ TypeValue\r
+ },\r
+ {\r
+ L"-a",\r
+ TypeMaxValue\r
+ },\r
+ {\r
+ L"-d",\r
+ TypeValue\r
+ },\r
+ {\r
+ NULL,\r
+ TypeMax\r
+ }\r
+};\r
+\r
+/**\r
+ Locate the network interface handle buffer.\r
+\r
+ @param[out] NumberOfHandles Pointer to the number of handles.\r
+ @param[out] HandleBuffer Pointer to the buffer to store the returned handles.\r
+\r
+**/\r
+VOID\r
+LocateNicHandleBuffer (\r
+ OUT UINTN *NumberOfHandles,\r
+ OUT EFI_HANDLE **HandleBuffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ *NumberOfHandles = 0;\r
+ *HandleBuffer = NULL;\r
+\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiVlanConfigProtocolGuid,\r
+ NULL,\r
+ NumberOfHandles,\r
+ HandleBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_LOCATE_FAIL), mHiiHandle, Status);\r
+ }\r
+}\r
+\r
+/**\r
+ Extract the decimal index from the network interface name.\r
+\r
+ @param[in] Name Name of the network interface.\r
+\r
+ @retval INVALID_NIC_INDEX Failed to extract the network interface index.\r
+ @return others The network interface index.\r
+\r
+**/\r
+UINTN\r
+NicNameToIndex (\r
+ IN CHAR16 *Name\r
+ )\r
+{\r
+ CHAR16 *Str;\r
+\r
+ Str = Name + 3;\r
+ if ((StrnCmp (Name, L"eth", 3) != 0) || (*Str == 0)) {\r
+ return INVALID_NIC_INDEX;\r
+ }\r
+\r
+ while (*Str != 0) {\r
+ if ((*Str < L'0') || (*Str > L'9')) {\r
+ return INVALID_NIC_INDEX;\r
+ }\r
+\r
+ Str++;\r
+ }\r
+\r
+ return (UINT16) StrDecimalToUintn (Name + 3);\r
+}\r
+\r
+/**\r
+ Find network interface device handle by its name.\r
+\r
+ @param[in] Name Name of the network interface.\r
+\r
+ @retval NULL Cannot find the network interface.\r
+ @return others Handle of the network interface.\r
+\r
+**/\r
+EFI_HANDLE\r
+NicNameToHandle (\r
+ IN CHAR16 *Name\r
+ )\r
+{\r
+ UINTN NumberOfHandles;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN Index;\r
+ EFI_HANDLE Handle;\r
+\r
+ //\r
+ // Find all NIC handles.\r
+ //\r
+ LocateNicHandleBuffer (&NumberOfHandles, &HandleBuffer);\r
+ if (NumberOfHandles == 0) {\r
+ return NULL;\r
+ }\r
+\r
+ Index = NicNameToIndex (Name);\r
+ if (Index >= NumberOfHandles) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_INVALID_IF), mHiiHandle, Name);\r
+ Handle = NULL;\r
+ } else {\r
+ Handle = HandleBuffer[Index];\r
+ }\r
+\r
+ FreePool (HandleBuffer);\r
+ return Handle;\r
+}\r
+\r
+/**\r
+ Open VlanConfig protocol from a handle.\r
+\r
+ @param[in] Handle The handle to open the VlanConfig protocol.\r
+\r
+ @return The VlanConfig protocol interface.\r
+\r
+**/\r
+EFI_VLAN_CONFIG_PROTOCOL *\r
+OpenVlanConfigProtocol (\r
+ IN EFI_HANDLE Handle\r
+ )\r
+{\r
+ EFI_VLAN_CONFIG_PROTOCOL *VlanConfig;\r
+\r
+ VlanConfig = NULL;\r
+ gBS->OpenProtocol (\r
+ Handle,\r
+ &gEfiVlanConfigProtocolGuid,\r
+ (VOID **) &VlanConfig,\r
+ mImageHandle,\r
+ Handle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+\r
+ return VlanConfig;\r
+}\r
+\r
+/**\r
+ Close VlanConfig protocol of a handle.\r
+\r
+ @param[in] Handle The handle to close the VlanConfig protocol.\r
+\r
+**/\r
+VOID\r
+CloseVlanConfigProtocol (\r
+ IN EFI_HANDLE Handle\r
+ )\r
+{\r
+ gBS->CloseProtocol (\r
+ Handle,\r
+ &gEfiVlanConfigProtocolGuid,\r
+ mImageHandle,\r
+ Handle\r
+ );\r
+}\r
+\r
+/**\r
+ Display VLAN configuration of a network interface.\r
+\r
+ @param[in] Handle Handle of the network interface.\r
+ @param[in] NicIndex Index of the network interface.\r
+\r
+**/\r
+VOID\r
+ShowNicVlanInfo (\r
+ IN EFI_HANDLE Handle,\r
+ IN UINTN NicIndex\r
+ )\r
+{\r
+ CHAR16 *MacStr;\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ EFI_VLAN_CONFIG_PROTOCOL *VlanConfig;\r
+ UINT16 NumberOfVlan;\r
+ EFI_VLAN_FIND_DATA *VlanData;\r
+\r
+ VlanConfig = OpenVlanConfigProtocol (Handle);\r
+ if (VlanConfig == NULL) {\r
+ return ;\r
+ }\r
+\r
+ MacStr = NULL;\r
+ Status = NetLibGetMacString (Handle, mImageHandle, &MacStr);\r
+ if (EFI_ERROR (Status)) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_MAC_FAIL), mHiiHandle, Status);\r
+ goto Exit;\r
+ }\r
+\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_ETH_MAC), mHiiHandle, NicIndex, MacStr);\r
+\r
+ Status = VlanConfig->Find (VlanConfig, NULL, &NumberOfVlan, &VlanData);\r
+ if (EFI_ERROR (Status)) {\r
+ if (Status == EFI_NOT_FOUND) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_VLAN), mHiiHandle);\r
+ } else {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_FIND_FAIL), mHiiHandle, Status);\r
+ }\r
+\r
+ goto Exit;\r
+ }\r
+\r
+ for (Index = 0; Index < NumberOfVlan; Index++) {\r
+ ShellPrintHiiEx (\r
+ -1,\r
+ -1,\r
+ NULL,\r
+ STRING_TOKEN (STR_VCONFIG_VLAN_DISPLAY),\r
+ mHiiHandle,\r
+ VlanData[Index].VlanId,\r
+ VlanData[Index].Priority\r
+ );\r
+ }\r
+\r
+ FreePool (VlanData);\r
+\r
+Exit:\r
+ CloseVlanConfigProtocol (Handle);\r
+\r
+ if (MacStr != NULL) {\r
+ FreePool (MacStr);\r
+ }\r
+}\r
+\r
+/**\r
+ Display the VLAN configuration of all, or a specified network interface.\r
+\r
+ @param[in] Name Name of the network interface. If NULL, the VLAN\r
+ configuration of all network will be displayed.\r
+\r
+**/\r
+VOID\r
+DisplayVlan (\r
+ IN CHAR16 *Name OPTIONAL\r
+ )\r
+{\r
+ UINTN NumberOfHandles;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN Index;\r
+ EFI_HANDLE NicHandle;\r
+\r
+ if (Name != NULL) {\r
+ //\r
+ // Display specified NIC\r
+ //\r
+ NicHandle = NicNameToHandle (Name);\r
+ if (NicHandle == NULL) {\r
+ return ;\r
+ }\r
+\r
+ ShowNicVlanInfo (NicHandle, 0);\r
+ return ;\r
+ }\r
+\r
+ //\r
+ // Find all NIC handles\r
+ //\r
+ LocateNicHandleBuffer (&NumberOfHandles, &HandleBuffer);\r
+ if (NumberOfHandles == 0) {\r
+ return ;\r
+ }\r
+\r
+ for (Index = 0; Index < NumberOfHandles; Index++) {\r
+ ShowNicVlanInfo (HandleBuffer[Index], Index);\r
+ }\r
+\r
+ FreePool (HandleBuffer);\r
+}\r
+\r
+/**\r
+ Convert a NULL-terminated unicode decimal VLAN ID string to VLAN ID.\r
+\r
+ @param[in] String Pointer to VLAN ID string from user input.\r
+\r
+ @retval Value translated from String, or INVALID_VLAN_ID is string is invalid.\r
+\r
+**/\r
+UINT16\r
+StrToVlanId (\r
+ IN CHAR16 *String\r
+ )\r
+{\r
+ CHAR16 *Str;\r
+\r
+ if (String == NULL) {\r
+ return INVALID_VLAN_ID;\r
+ }\r
+\r
+ Str = String;\r
+ while ((*Str >= '0') && (*Str <= '9')) {\r
+ Str++;\r
+ }\r
+\r
+ if (*Str != 0) {\r
+ return INVALID_VLAN_ID;\r
+ }\r
+\r
+ return (UINT16) StrDecimalToUintn (String);\r
+}\r
+\r
+/**\r
+ Add a VLAN device.\r
+\r
+ @param[in] ParamStr Parameter string from user input.\r
+\r
+**/\r
+VOID\r
+AddVlan (\r
+ IN CHAR16 *ParamStr\r
+ )\r
+{\r
+ CHAR16 *Name;\r
+ CHAR16 *VlanIdStr;\r
+ CHAR16 *PriorityStr;\r
+ CHAR16 *StrPtr;\r
+ BOOLEAN IsSpace;\r
+ UINTN VlanId;\r
+ UINTN Priority;\r
+ EFI_HANDLE Handle;\r
+ EFI_HANDLE VlanHandle;\r
+ EFI_VLAN_CONFIG_PROTOCOL *VlanConfig;\r
+ EFI_STATUS Status;\r
+\r
+ VlanConfig = NULL;\r
+ Priority = 0;\r
+\r
+ if (ParamStr == NULL) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_IF), mHiiHandle);\r
+ return ;\r
+ }\r
+\r
+ StrPtr = AllocateCopyPool (StrSize (ParamStr), ParamStr);\r
+ if (StrPtr == NULL) {\r
+ return ;\r
+ }\r
+\r
+ Name = StrPtr;\r
+ VlanIdStr = NULL;\r
+ PriorityStr = NULL;\r
+ IsSpace = FALSE;\r
+ while (*StrPtr != 0) {\r
+ if (*StrPtr == L' ') {\r
+ *StrPtr = 0;\r
+ IsSpace = TRUE;\r
+ } else {\r
+ if (IsSpace) {\r
+ //\r
+ // Start of a parameter.\r
+ //\r
+ if (VlanIdStr == NULL) {\r
+ //\r
+ // 2nd parameter is VLAN ID.\r
+ //\r
+ VlanIdStr = StrPtr;\r
+ } else if (PriorityStr == NULL) {\r
+ //\r
+ // 3rd parameter is Priority.\r
+ //\r
+ PriorityStr = StrPtr;\r
+ } else {\r
+ //\r
+ // Ignore else parameters.\r
+ //\r
+ break;\r
+ }\r
+ }\r
+\r
+ IsSpace = FALSE;\r
+ }\r
+\r
+ StrPtr++;\r
+ }\r
+\r
+ Handle = NicNameToHandle (Name);\r
+ if (Handle == NULL) {\r
+ goto Exit;\r
+ }\r
+\r
+ VlanConfig = OpenVlanConfigProtocol (Handle);\r
+ if (VlanConfig == NULL) {\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // Check VLAN ID.\r
+ //\r
+ if ((VlanIdStr == NULL) || (*VlanIdStr == 0)) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_VID), mHiiHandle);\r
+ goto Exit;\r
+ }\r
+\r
+ VlanId = StrToVlanId (VlanIdStr);\r
+ if (VlanId > 4094) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_INVALID_VID), mHiiHandle, VlanIdStr);\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // Check Priority.\r
+ //\r
+ if ((PriorityStr != NULL) && (*PriorityStr != 0)) {\r
+ Priority = StrDecimalToUintn (PriorityStr);\r
+ if (Priority > 7) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_INVALID_PRIORITY), mHiiHandle, PriorityStr);\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Set VLAN\r
+ //\r
+ Status = VlanConfig->Set (VlanConfig, (UINT16) VlanId, (UINT8) Priority);\r
+ if (EFI_ERROR (Status)) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_SET_FAIL), mHiiHandle, Status);\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // Connect the VLAN device.\r
+ //\r
+ VlanHandle = NetLibGetVlanHandle (Handle, (UINT16) VlanId);\r
+ if (VlanHandle != NULL) {\r
+ gBS->ConnectController (VlanHandle, NULL, NULL, TRUE);\r
+ }\r
+\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_SET_SUCCESS), mHiiHandle);\r
+\r
+Exit:\r
+ if (VlanConfig != NULL) {\r
+ CloseVlanConfigProtocol (Handle);\r
+ }\r
+\r
+ FreePool (Name);\r
+}\r
+\r
+/**\r
+ Remove a VLAN device.\r
+\r
+ @param[in] ParamStr Parameter string from user input.\r
+\r
+**/\r
+VOID\r
+DeleteVlan (\r
+ CHAR16 *ParamStr\r
+ )\r
+{\r
+ CHAR16 *Name;\r
+ CHAR16 *VlanIdStr;\r
+ CHAR16 *StrPtr;\r
+ UINTN VlanId;\r
+ EFI_HANDLE Handle;\r
+ EFI_VLAN_CONFIG_PROTOCOL *VlanConfig;\r
+ EFI_STATUS Status;\r
+ UINT16 NumberOfVlan;\r
+ EFI_VLAN_FIND_DATA *VlanData;\r
+\r
+ VlanConfig = NULL;\r
+\r
+ if (ParamStr == NULL) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_IF), mHiiHandle);\r
+ return ;\r
+ }\r
+\r
+ StrPtr = AllocateCopyPool (StrSize (ParamStr), ParamStr);\r
+ if (StrPtr == NULL) {\r
+ return ;\r
+ }\r
+\r
+ Name = StrPtr;\r
+ VlanIdStr = NULL;\r
+ while (*StrPtr != 0) {\r
+ if (*StrPtr == L'.') {\r
+ *StrPtr = 0;\r
+ VlanIdStr = StrPtr + 1;\r
+ break;\r
+ }\r
+\r
+ StrPtr++;\r
+ }\r
+\r
+ Handle = NicNameToHandle (Name);\r
+ if (Handle == NULL) {\r
+ goto Exit;\r
+ }\r
+\r
+ VlanConfig = OpenVlanConfigProtocol (Handle);\r
+ if (VlanConfig == NULL) {\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // Check VLAN ID\r
+ //\r
+ if (VlanIdStr == NULL || *VlanIdStr == 0) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_VID), mHiiHandle);\r
+ goto Exit;\r
+ }\r
+\r
+ VlanId = StrToVlanId (VlanIdStr);\r
+ if (VlanId > 4094) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_INVALID_VID), mHiiHandle, VlanIdStr);\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // Delete VLAN.\r
+ //\r
+ Status = VlanConfig->Remove (VlanConfig, (UINT16) VlanId);\r
+ if (EFI_ERROR (Status)) {\r
+ if (Status == EFI_NOT_FOUND) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NOT_FOUND), mHiiHandle);\r
+ } else {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_REMOVE_FAIL), mHiiHandle, Status);\r
+ }\r
+\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // Check whether this is the last VLAN to remove.\r
+ //\r
+ Status = VlanConfig->Find (VlanConfig, NULL, &NumberOfVlan, &VlanData);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // This is the last VLAN to remove, try to connect the controller handle.\r
+ //\r
+ gBS->ConnectController (Handle, NULL, NULL, TRUE);\r
+ } else {\r
+ FreePool (VlanData);\r
+ }\r
+\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_REMOVE_SUCCESS), mHiiHandle);\r
+\r
+Exit:\r
+ if (VlanConfig != NULL) {\r
+ CloseVlanConfigProtocol (Handle);\r
+ }\r
+\r
+ FreePool (Name);\r
+}\r
+\r
+/**\r
+ The actual entry point for the application.\r
+\r
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
+ @param[in] SystemTable A pointer to the EFI System Table.\r
+\r
+ @retval EFI_SUCCESS The entry point executed successfully.\r
+ @retval other Some error occur when executing this entry point.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VlanConfigMain (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ LIST_ENTRY *List;\r
+ CONST CHAR16 *Str;\r
+\r
+ mImageHandle = ImageHandle;\r
+\r
+ //\r
+ // Register our string package to HII database.\r
+ //\r
+ mHiiHandle = HiiAddPackages (&gEfiCallerIdGuid, ImageHandle, VConfigStrings, NULL);\r
+ if (mHiiHandle == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ List = NULL;\r
+ ShellCommandLineParseEx (mParamList, &List, NULL, FALSE, FALSE);\r
+ if (List == NULL) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_ARG), mHiiHandle);\r
+ goto Exit;\r
+ }\r
+\r
+ if (ShellCommandLineGetFlag (List, L"-?")) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_HELP), mHiiHandle);\r
+ goto Exit;\r
+ }\r
+\r
+ if (ShellCommandLineGetFlag (List, L"-l")) {\r
+ Str = ShellCommandLineGetValue (List, L"-l");\r
+ DisplayVlan ((CHAR16 *) Str);\r
+ goto Exit;\r
+ }\r
+\r
+ if (ShellCommandLineGetFlag (List, L"-a")) {\r
+ Str = ShellCommandLineGetValue (List, L"-a");\r
+ AddVlan ((CHAR16 *) Str);\r
+ goto Exit;\r
+ }\r
+\r
+ if (ShellCommandLineGetFlag (List, L"-d")) {\r
+ Str = ShellCommandLineGetValue (List, L"-d");\r
+ DeleteVlan ((CHAR16 *) Str);\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // No valid argument till now.\r
+ //\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_ARG), mHiiHandle);\r
+\r
+Exit:\r
+ if (List != NULL) {\r
+ ShellCommandLineFreeVarList (List);\r
+ }\r
+\r
+ //\r
+ // Remove our string package from HII database.\r
+ //\r
+ HiiRemovePackages (mHiiHandle);\r
+\r
+ return EFI_SUCCESS;\r
+}\r