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