VConfig.c 16 KB

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