Home | History | Annotate | Download | only in VConfig
      1 /** @file
      2   Shell application for VLAN configuration.
      3 
      4   Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>
      5 
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions of the BSD License
      8   which accompanies this distribution.  The full text of the license may be found at
      9   http://opensource.org/licenses/bsd-license.php.
     10 
     11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include <Uefi.h>
     17 
     18 #include <Protocol/VlanConfig.h>
     19 
     20 #include <Library/UefiApplicationEntryPoint.h>
     21 #include <Library/UefiLib.h>
     22 #include <Library/ShellLib.h>
     23 #include <Library/MemoryAllocationLib.h>
     24 #include <Library/HiiLib.h>
     25 #include <Library/UefiBootServicesTableLib.h>
     26 #include <Library/NetLib.h>
     27 
     28 #define INVALID_NIC_INDEX   0xffff
     29 #define INVALID_VLAN_ID     0xffff
     30 
     31 //
     32 // This is the generated String package data for all .UNI files.
     33 // This data array is ready to be used as input of HiiAddPackages() to
     34 // create a packagelist (which contains Form packages, String packages, etc).
     35 //
     36 extern UINT8      VConfigStrings[];
     37 
     38 EFI_HANDLE        mImageHandle  = NULL;
     39 EFI_HII_HANDLE    mHiiHandle    = NULL;
     40 
     41 SHELL_PARAM_ITEM  mParamList[] = {
     42   {
     43     L"-l",
     44     TypeValue
     45   },
     46   {
     47     L"-a",
     48     TypeMaxValue
     49   },
     50   {
     51     L"-d",
     52     TypeValue
     53   },
     54   {
     55     NULL,
     56     TypeMax
     57   }
     58 };
     59 
     60 /**
     61   Locate the network interface handle buffer.
     62 
     63   @param[out]  NumberOfHandles Pointer to the number of handles.
     64   @param[out]  HandleBuffer    Pointer to the buffer to store the returned handles.
     65 
     66 **/
     67 VOID
     68 LocateNicHandleBuffer (
     69   OUT UINTN                       *NumberOfHandles,
     70   OUT EFI_HANDLE                  **HandleBuffer
     71   )
     72 {
     73   EFI_STATUS  Status;
     74 
     75   *NumberOfHandles  = 0;
     76   *HandleBuffer     = NULL;
     77 
     78   Status = gBS->LocateHandleBuffer (
     79                   ByProtocol,
     80                   &gEfiVlanConfigProtocolGuid,
     81                   NULL,
     82                   NumberOfHandles,
     83                   HandleBuffer
     84                   );
     85   if (EFI_ERROR (Status)) {
     86     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_LOCATE_FAIL), mHiiHandle, Status);
     87   }
     88 }
     89 
     90 /**
     91   Extract the decimal index from the network interface name.
     92 
     93   @param[in]  Name           Name of the network interface.
     94 
     95   @retval INVALID_NIC_INDEX  Failed to extract the network interface index.
     96   @return others             The network interface index.
     97 
     98 **/
     99 UINTN
    100 NicNameToIndex (
    101   IN CHAR16                   *Name
    102   )
    103 {
    104   CHAR16  *Str;
    105 
    106   Str = Name + 3;
    107   if ((StrnCmp (Name, L"eth", 3) != 0) || (*Str == 0)) {
    108     return INVALID_NIC_INDEX;
    109   }
    110 
    111   while (*Str != 0) {
    112     if ((*Str < L'0') || (*Str > L'9')) {
    113       return INVALID_NIC_INDEX;
    114     }
    115 
    116     Str++;
    117   }
    118 
    119   return (UINT16) StrDecimalToUintn (Name + 3);
    120 }
    121 
    122 /**
    123   Find network interface device handle by its name.
    124 
    125   @param[in]  Name           Name of the network interface.
    126 
    127   @retval NULL               Cannot find the network interface.
    128   @return others             Handle of the network interface.
    129 
    130 **/
    131 EFI_HANDLE
    132 NicNameToHandle (
    133   IN CHAR16                   *Name
    134   )
    135 {
    136   UINTN       NumberOfHandles;
    137   EFI_HANDLE  *HandleBuffer;
    138   UINTN       Index;
    139   EFI_HANDLE  Handle;
    140 
    141   //
    142   // Find all NIC handles.
    143   //
    144   LocateNicHandleBuffer (&NumberOfHandles, &HandleBuffer);
    145   if (NumberOfHandles == 0) {
    146     return NULL;
    147   }
    148 
    149   Index = NicNameToIndex (Name);
    150   if (Index >= NumberOfHandles) {
    151     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_INVALID_IF), mHiiHandle, Name);
    152     Handle = NULL;
    153   } else {
    154     Handle = HandleBuffer[Index];
    155   }
    156 
    157   FreePool (HandleBuffer);
    158   return Handle;
    159 }
    160 
    161 /**
    162   Open VlanConfig protocol from a handle.
    163 
    164   @param[in]  Handle         The handle to open the VlanConfig protocol.
    165 
    166   @return The VlanConfig protocol interface.
    167 
    168 **/
    169 EFI_VLAN_CONFIG_PROTOCOL *
    170 OpenVlanConfigProtocol (
    171   IN EFI_HANDLE                 Handle
    172   )
    173 {
    174   EFI_VLAN_CONFIG_PROTOCOL  *VlanConfig;
    175 
    176   VlanConfig = NULL;
    177   gBS->OpenProtocol (
    178          Handle,
    179          &gEfiVlanConfigProtocolGuid,
    180          (VOID **) &VlanConfig,
    181          mImageHandle,
    182          Handle,
    183          EFI_OPEN_PROTOCOL_GET_PROTOCOL
    184          );
    185 
    186   return VlanConfig;
    187 }
    188 
    189 /**
    190   Close VlanConfig protocol of a handle.
    191 
    192   @param[in]  Handle         The handle to close the VlanConfig protocol.
    193 
    194 **/
    195 VOID
    196 CloseVlanConfigProtocol (
    197   IN EFI_HANDLE                 Handle
    198   )
    199 {
    200   gBS->CloseProtocol (
    201          Handle,
    202          &gEfiVlanConfigProtocolGuid,
    203          mImageHandle,
    204          Handle
    205          );
    206 }
    207 
    208 /**
    209   Display VLAN configuration of a network interface.
    210 
    211   @param[in]  Handle         Handle of the network interface.
    212   @param[in]  NicIndex       Index of the network interface.
    213 
    214 **/
    215 VOID
    216 ShowNicVlanInfo (
    217   IN EFI_HANDLE              Handle,
    218   IN UINTN                   NicIndex
    219   )
    220 {
    221   CHAR16                    *MacStr;
    222   EFI_STATUS                Status;
    223   UINTN                     Index;
    224   EFI_VLAN_CONFIG_PROTOCOL  *VlanConfig;
    225   UINT16                    NumberOfVlan;
    226   EFI_VLAN_FIND_DATA        *VlanData;
    227 
    228   VlanConfig = OpenVlanConfigProtocol (Handle);
    229   if (VlanConfig == NULL) {
    230     return ;
    231   }
    232 
    233   MacStr  = NULL;
    234   Status  = NetLibGetMacString (Handle, mImageHandle, &MacStr);
    235   if (EFI_ERROR (Status)) {
    236     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_MAC_FAIL), mHiiHandle, Status);
    237     goto Exit;
    238   }
    239 
    240   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_ETH_MAC), mHiiHandle, NicIndex, MacStr);
    241 
    242   Status = VlanConfig->Find (VlanConfig, NULL, &NumberOfVlan, &VlanData);
    243   if (EFI_ERROR (Status)) {
    244     if (Status == EFI_NOT_FOUND) {
    245       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_VLAN), mHiiHandle);
    246     } else {
    247       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_FIND_FAIL), mHiiHandle, Status);
    248     }
    249 
    250     goto Exit;
    251   }
    252 
    253   for (Index = 0; Index < NumberOfVlan; Index++) {
    254     ShellPrintHiiEx (
    255       -1,
    256       -1,
    257       NULL,
    258       STRING_TOKEN (STR_VCONFIG_VLAN_DISPLAY),
    259       mHiiHandle,
    260       VlanData[Index].VlanId,
    261       VlanData[Index].Priority
    262       );
    263   }
    264 
    265   FreePool (VlanData);
    266 
    267 Exit:
    268   CloseVlanConfigProtocol (Handle);
    269 
    270   if (MacStr != NULL) {
    271     FreePool (MacStr);
    272   }
    273 }
    274 
    275 /**
    276   Display the VLAN configuration of all, or a specified network interface.
    277 
    278   @param[in]  Name           Name of the network interface. If NULL, the VLAN
    279                              configuration of all network will be displayed.
    280 
    281 **/
    282 VOID
    283 DisplayVlan (
    284   IN CHAR16              *Name OPTIONAL
    285   )
    286 {
    287   UINTN       NumberOfHandles;
    288   EFI_HANDLE  *HandleBuffer;
    289   UINTN       Index;
    290   EFI_HANDLE  NicHandle;
    291 
    292   if (Name != NULL) {
    293     //
    294     // Display specified NIC
    295     //
    296     NicHandle = NicNameToHandle (Name);
    297     if (NicHandle == NULL) {
    298       return ;
    299     }
    300 
    301     ShowNicVlanInfo (NicHandle, 0);
    302     return ;
    303   }
    304 
    305   //
    306   // Find all NIC handles
    307   //
    308   LocateNicHandleBuffer (&NumberOfHandles, &HandleBuffer);
    309   if (NumberOfHandles == 0) {
    310     return ;
    311   }
    312 
    313   for (Index = 0; Index < NumberOfHandles; Index++) {
    314     ShowNicVlanInfo (HandleBuffer[Index], Index);
    315   }
    316 
    317   FreePool (HandleBuffer);
    318 }
    319 
    320 /**
    321   Convert a NULL-terminated unicode decimal VLAN ID string to VLAN ID.
    322 
    323   @param[in]  String       Pointer to VLAN ID string from user input.
    324 
    325   @retval Value translated from String, or INVALID_VLAN_ID is string is invalid.
    326 
    327 **/
    328 UINT16
    329 StrToVlanId (
    330   IN CHAR16             *String
    331   )
    332 {
    333   CHAR16  *Str;
    334 
    335   if (String == NULL) {
    336     return INVALID_VLAN_ID;
    337   }
    338 
    339   Str = String;
    340   while ((*Str >= '0') && (*Str <= '9')) {
    341     Str++;
    342   }
    343 
    344   if (*Str != 0) {
    345     return INVALID_VLAN_ID;
    346   }
    347 
    348   return (UINT16) StrDecimalToUintn (String);
    349 }
    350 
    351 /**
    352   Add a VLAN device.
    353 
    354   @param[in]  ParamStr       Parameter string from user input.
    355 
    356 **/
    357 VOID
    358 AddVlan (
    359   IN CHAR16             *ParamStr
    360   )
    361 {
    362   CHAR16                    *Name;
    363   CHAR16                    *VlanIdStr;
    364   CHAR16                    *PriorityStr;
    365   CHAR16                    *StrPtr;
    366   BOOLEAN                   IsSpace;
    367   UINTN                     VlanId;
    368   UINTN                     Priority;
    369   EFI_HANDLE                Handle;
    370   EFI_HANDLE                VlanHandle;
    371   EFI_VLAN_CONFIG_PROTOCOL  *VlanConfig;
    372   EFI_STATUS                Status;
    373 
    374   VlanConfig  = NULL;
    375   Priority    = 0;
    376 
    377   if (ParamStr == NULL) {
    378     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_IF), mHiiHandle);
    379     return ;
    380   }
    381 
    382   StrPtr = AllocateCopyPool (StrSize (ParamStr), ParamStr);
    383   if (StrPtr == NULL) {
    384     return ;
    385   }
    386 
    387   Name        = StrPtr;
    388   VlanIdStr   = NULL;
    389   PriorityStr = NULL;
    390   IsSpace     = FALSE;
    391   while (*StrPtr != 0) {
    392     if (*StrPtr == L' ') {
    393       *StrPtr = 0;
    394       IsSpace = TRUE;
    395     } else {
    396       if (IsSpace) {
    397         //
    398         // Start of a parameter.
    399         //
    400         if (VlanIdStr == NULL) {
    401           //
    402           // 2nd parameter is VLAN ID.
    403           //
    404           VlanIdStr = StrPtr;
    405         } else if (PriorityStr == NULL) {
    406           //
    407           // 3rd parameter is Priority.
    408           //
    409           PriorityStr = StrPtr;
    410         } else {
    411           //
    412           // Ignore else parameters.
    413           //
    414           break;
    415         }
    416       }
    417 
    418       IsSpace = FALSE;
    419     }
    420 
    421     StrPtr++;
    422   }
    423 
    424   Handle = NicNameToHandle (Name);
    425   if (Handle == NULL) {
    426     goto Exit;
    427   }
    428 
    429   VlanConfig = OpenVlanConfigProtocol (Handle);
    430   if (VlanConfig == NULL) {
    431     goto Exit;
    432   }
    433 
    434   //
    435   // Check VLAN ID.
    436   //
    437   if ((VlanIdStr == NULL) || (*VlanIdStr == 0)) {
    438     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_VID), mHiiHandle);
    439     goto Exit;
    440   }
    441 
    442   VlanId = StrToVlanId (VlanIdStr);
    443   if (VlanId > 4094) {
    444     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_INVALID_VID), mHiiHandle, VlanIdStr);
    445     goto Exit;
    446   }
    447 
    448   //
    449   // Check Priority.
    450   //
    451   if ((PriorityStr != NULL) && (*PriorityStr != 0)) {
    452     Priority = StrDecimalToUintn (PriorityStr);
    453     if (Priority > 7) {
    454       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_INVALID_PRIORITY), mHiiHandle, PriorityStr);
    455       goto Exit;
    456     }
    457   }
    458 
    459   //
    460   // Set VLAN
    461   //
    462   Status = VlanConfig->Set (VlanConfig, (UINT16) VlanId, (UINT8) Priority);
    463   if (EFI_ERROR (Status)) {
    464     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_SET_FAIL), mHiiHandle, Status);
    465     goto Exit;
    466   }
    467 
    468   //
    469   // Connect the VLAN device.
    470   //
    471   VlanHandle = NetLibGetVlanHandle (Handle, (UINT16) VlanId);
    472   if (VlanHandle != NULL) {
    473     gBS->ConnectController (VlanHandle, NULL, NULL, TRUE);
    474   }
    475 
    476   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_SET_SUCCESS), mHiiHandle);
    477 
    478 Exit:
    479   if (VlanConfig != NULL) {
    480     CloseVlanConfigProtocol (Handle);
    481   }
    482 
    483   FreePool (Name);
    484 }
    485 
    486 /**
    487   Remove a VLAN device.
    488 
    489   @param[in]  ParamStr       Parameter string from user input.
    490 
    491 **/
    492 VOID
    493 DeleteVlan (
    494   IN CHAR16 *ParamStr
    495   )
    496 {
    497   CHAR16                    *Name;
    498   CHAR16                    *VlanIdStr;
    499   CHAR16                    *StrPtr;
    500   UINTN                     VlanId;
    501   EFI_HANDLE                Handle;
    502   EFI_VLAN_CONFIG_PROTOCOL  *VlanConfig;
    503   EFI_STATUS                Status;
    504   UINT16                    NumberOfVlan;
    505   EFI_VLAN_FIND_DATA        *VlanData;
    506 
    507   VlanConfig = NULL;
    508 
    509   if (ParamStr == NULL) {
    510     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_IF), mHiiHandle);
    511     return ;
    512   }
    513 
    514   StrPtr = AllocateCopyPool (StrSize (ParamStr), ParamStr);
    515   if (StrPtr == NULL) {
    516     return ;
    517   }
    518 
    519   Name      = StrPtr;
    520   VlanIdStr = NULL;
    521   while (*StrPtr != 0) {
    522     if (*StrPtr == L'.') {
    523       *StrPtr   = 0;
    524       VlanIdStr = StrPtr + 1;
    525       break;
    526     }
    527 
    528     StrPtr++;
    529   }
    530 
    531   Handle = NicNameToHandle (Name);
    532   if (Handle == NULL) {
    533     goto Exit;
    534   }
    535 
    536   VlanConfig = OpenVlanConfigProtocol (Handle);
    537   if (VlanConfig == NULL) {
    538     goto Exit;
    539   }
    540 
    541   //
    542   // Check VLAN ID
    543   //
    544   if (VlanIdStr == NULL || *VlanIdStr == 0) {
    545     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_VID), mHiiHandle);
    546     goto Exit;
    547   }
    548 
    549   VlanId = StrToVlanId (VlanIdStr);
    550   if (VlanId > 4094) {
    551     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_INVALID_VID), mHiiHandle, VlanIdStr);
    552     goto Exit;
    553   }
    554 
    555   //
    556   // Delete VLAN.
    557   //
    558   Status = VlanConfig->Remove (VlanConfig, (UINT16) VlanId);
    559   if (EFI_ERROR (Status)) {
    560     if (Status == EFI_NOT_FOUND) {
    561       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NOT_FOUND), mHiiHandle);
    562     } else {
    563       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_REMOVE_FAIL), mHiiHandle, Status);
    564     }
    565 
    566     goto Exit;
    567   }
    568 
    569   //
    570   // Check whether this is the last VLAN to remove.
    571   //
    572   Status = VlanConfig->Find (VlanConfig, NULL, &NumberOfVlan, &VlanData);
    573   if (EFI_ERROR (Status)) {
    574     //
    575     // This is the last VLAN to remove, try to connect the controller handle.
    576     //
    577     gBS->ConnectController (Handle, NULL, NULL, TRUE);
    578   } else {
    579     FreePool (VlanData);
    580   }
    581 
    582   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_REMOVE_SUCCESS), mHiiHandle);
    583 
    584 Exit:
    585   if (VlanConfig != NULL) {
    586     CloseVlanConfigProtocol (Handle);
    587   }
    588 
    589   FreePool (Name);
    590 }
    591 
    592 /**
    593   The actual entry point for the application.
    594 
    595   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
    596   @param[in] SystemTable    A pointer to the EFI System Table.
    597 
    598   @retval EFI_SUCCESS       The entry point executed successfully.
    599   @retval other             Some error occur when executing this entry point.
    600 
    601 **/
    602 EFI_STATUS
    603 EFIAPI
    604 VlanConfigMain (
    605   IN EFI_HANDLE        ImageHandle,
    606   IN EFI_SYSTEM_TABLE  *SystemTable
    607   )
    608 {
    609   LIST_ENTRY    *List;
    610   CONST CHAR16  *Str;
    611 
    612   mImageHandle = ImageHandle;
    613 
    614   //
    615   // Register our string package to HII database.
    616   //
    617   mHiiHandle = HiiAddPackages (&gEfiCallerIdGuid, ImageHandle, VConfigStrings, NULL);
    618   if (mHiiHandle == NULL) {
    619     return EFI_SUCCESS;
    620   }
    621 
    622   List = NULL;
    623   ShellCommandLineParseEx (mParamList, &List, NULL, FALSE, FALSE);
    624   if (List == NULL) {
    625     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_ARG), mHiiHandle);
    626     goto Exit;
    627   }
    628 
    629   if (ShellCommandLineGetFlag (List, L"-?")) {
    630     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_HELP), mHiiHandle);
    631     goto Exit;
    632   }
    633 
    634   if (ShellCommandLineGetFlag (List, L"-l")) {
    635     Str = ShellCommandLineGetValue (List, L"-l");
    636     DisplayVlan ((CHAR16 *) Str);
    637     goto Exit;
    638   }
    639 
    640   if (ShellCommandLineGetFlag (List, L"-a")) {
    641     Str = ShellCommandLineGetValue (List, L"-a");
    642     AddVlan ((CHAR16 *) Str);
    643     goto Exit;
    644   }
    645 
    646   if (ShellCommandLineGetFlag (List, L"-d")) {
    647     Str = ShellCommandLineGetValue (List, L"-d");
    648     DeleteVlan ((CHAR16 *) Str);
    649     goto Exit;
    650   }
    651 
    652   //
    653   // No valid argument till now.
    654   //
    655   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_ARG), mHiiHandle);
    656 
    657 Exit:
    658   if (List != NULL) {
    659     ShellCommandLineFreeVarList (List);
    660   }
    661 
    662   //
    663   // Remove our string package from HII database.
    664   //
    665   HiiRemovePackages (mHiiHandle);
    666 
    667   return EFI_SUCCESS;
    668 }
    669