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