]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellLevel3CommandsLib/Help.c
Updates the logic to allow help to ouput help information from a dynamic shell command
[mirror_edk2.git] / ShellPkg / Library / UefiShellLevel3CommandsLib / Help.c
1 /** @file
2 Main file for Help shell level 3 function.
3
4 Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved. <BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "UefiShellLevel3CommandsLib.h"
16
17 #include <Library/ShellLib.h>
18 #include <Library/HandleParsingLib.h>
19
20 #include <Protocol/EfiShellDynamicCommand.h>
21
22 /**
23 Attempt to print help from a dynamically added command.
24
25 @param[in] CommandToGetHelpOn The unicode name of the command that help is requested on.
26
27 @retval EFI_SUCCESS The help was displayed
28 @retval FI_NOT_FOUND The command name could not be found
29 **/
30 STATIC
31 EFI_STATUS
32 EFIAPI
33 PrintDynamicCommandHelp(
34 IN CHAR16 *CommandToGetHelpOn
35 )
36 {
37 EFI_STATUS Status;
38 BOOLEAN Found = FALSE;
39 EFI_HANDLE *CommandHandleList = NULL;
40 EFI_HANDLE *NextCommand;
41 EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *DynamicCommand;
42 CHAR16 *OutText = NULL;
43
44 CommandHandleList = GetHandleListByProtocol(&gEfiShellDynamicCommandProtocolGuid);
45
46 if (CommandHandleList == NULL) {
47 //
48 // not found or out of resources
49 //
50 return FALSE;
51 }
52
53 for (NextCommand = CommandHandleList; *NextCommand != NULL; NextCommand++) {
54 Status = gBS->HandleProtocol(
55 *NextCommand,
56 &gEfiShellDynamicCommandProtocolGuid,
57 (VOID **)&DynamicCommand
58 );
59
60 if (EFI_ERROR(Status)) {
61 continue;
62 }
63
64 if ((gUnicodeCollation->MetaiMatch(gUnicodeCollation, (CHAR16 *)DynamicCommand->CommandName, CommandToGetHelpOn)) ||
65 (gEfiShellProtocol->GetAlias(CommandToGetHelpOn, NULL) != NULL && (gUnicodeCollation->MetaiMatch(gUnicodeCollation, (CHAR16 *)DynamicCommand->CommandName, (CHAR16*)(gEfiShellProtocol->GetAlias(CommandToGetHelpOn, NULL)))))) {
66 //
67 // TODO: how to get proper language?
68 //
69 OutText = DynamicCommand->GetHelp(DynamicCommand, "en");
70
71 if (OutText == NULL) {
72 continue;
73 }
74
75 //
76 // Trim extra characters from the end the the string before printing
77 //
78 while (StrLen(OutText) > 0
79 && (OutText[StrLen(OutText) - 1] == L'\r' || OutText[StrLen(OutText) - 1] == L'\n' || OutText[StrLen(OutText) - 1] == L' ')) {
80 OutText[StrLen(OutText) - 1] = CHAR_NULL;
81 }
82
83 //
84 // Make sure we have something to print still.
85 //
86 if (StrLen(OutText) == 0) {
87 FreePool(OutText);
88 OutText = NULL;
89 continue;
90 }
91
92 //
93 // Print and move on.
94 //
95 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_HELP_COMMAND), gShellLevel3HiiHandle, DynamicCommand->CommandName, OutText);
96 FreePool(OutText);
97 OutText = NULL;
98 Found = TRUE;
99 break;
100 }
101
102 }
103
104 FreePool(CommandHandleList);
105
106 return Found ? EFI_SUCCESS : EFI_NOT_FOUND;
107 }
108
109 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
110 {L"-usage", TypeFlag},
111 {L"-section", TypeMaxValue},
112 {L"-verbose", TypeFlag},
113 {L"-v", TypeFlag},
114 {NULL, TypeMax}
115 };
116
117 /**
118 Function for 'help' command.
119
120 @param[in] ImageHandle Handle to the Image (NULL if Internal).
121 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
122 **/
123 SHELL_STATUS
124 EFIAPI
125 ShellCommandRunHelp (
126 IN EFI_HANDLE ImageHandle,
127 IN EFI_SYSTEM_TABLE *SystemTable
128 )
129 {
130 EFI_STATUS Status;
131 LIST_ENTRY *Package;
132 CHAR16 *ProblemParam;
133 SHELL_STATUS ShellStatus;
134 CONST COMMAND_LIST *CommandList;
135 CONST COMMAND_LIST *Node;
136 CHAR16 *CommandToGetHelpOn;
137 CHAR16 *SectionToGetHelpOn;
138 CHAR16 *HiiString;
139 BOOLEAN Found;
140 BOOLEAN PrintCommandText;
141
142 PrintCommandText = TRUE;
143 ProblemParam = NULL;
144 ShellStatus = SHELL_SUCCESS;
145 CommandToGetHelpOn = NULL;
146 SectionToGetHelpOn = NULL;
147 Found = FALSE;
148
149 //
150 // initialize the shell lib (we must be in non-auto-init...)
151 //
152 Status = ShellInitialize();
153 ASSERT_EFI_ERROR(Status);
154
155 Status = CommandInit();
156 ASSERT_EFI_ERROR(Status);
157
158 //
159 // parse the command line
160 //
161 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
162 if (EFI_ERROR(Status)) {
163 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
164 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, ProblemParam);
165 FreePool(ProblemParam);
166 ShellStatus = SHELL_INVALID_PARAMETER;
167 } else {
168 ASSERT(FALSE);
169 }
170 } else {
171 //
172 // Check for conflicting parameters.
173 //
174 if (ShellCommandLineGetFlag(Package, L"-usage")
175 &&ShellCommandLineGetFlag(Package, L"-section")
176 &&(ShellCommandLineGetFlag(Package, L"-verbose") || ShellCommandLineGetFlag(Package, L"-v"))
177 ){
178 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellLevel3HiiHandle);
179 ShellStatus = SHELL_INVALID_PARAMETER;
180 } else if (ShellCommandLineGetRawValue(Package, 2) != NULL) {
181 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle);
182 ShellStatus = SHELL_INVALID_PARAMETER;
183 } else {
184 //
185 // Get the command name we are getting help on
186 //
187 ASSERT(CommandToGetHelpOn == NULL);
188 StrnCatGrow(&CommandToGetHelpOn, NULL, ShellCommandLineGetRawValue(Package, 1), 0);
189 if (CommandToGetHelpOn == NULL && ShellCommandLineGetFlag(Package, L"-?")) {
190 //
191 // If we dont have a command and we got a simple -?
192 // we are looking for help on help command.
193 //
194 StrnCatGrow(&CommandToGetHelpOn, NULL, L"help", 0);
195 }
196
197 if (CommandToGetHelpOn == NULL) {
198 StrnCatGrow(&CommandToGetHelpOn, NULL, L"*", 0);
199 ASSERT(SectionToGetHelpOn == NULL);
200 StrnCatGrow(&SectionToGetHelpOn, NULL, L"NAME", 0);
201 } else {
202 PrintCommandText = FALSE;
203 ASSERT(SectionToGetHelpOn == NULL);
204 //
205 // Get the section name for the given command name
206 //
207 if (ShellCommandLineGetFlag(Package, L"-section")) {
208 StrnCatGrow(&SectionToGetHelpOn, NULL, ShellCommandLineGetValue(Package, L"-section"), 0);
209 } else if (ShellCommandLineGetFlag(Package, L"-usage")) {
210 StrnCatGrow(&SectionToGetHelpOn, NULL, L"NAME,SYNOPSIS", 0);
211 } else if (ShellCommandLineGetFlag(Package, L"-verbose") || ShellCommandLineGetFlag(Package, L"-v")) {
212 } else {
213 //
214 // The output of help <command> will display NAME, SYNOPSIS, OPTIONS, DESCRIPTION, and EXAMPLES sections.
215 //
216 StrnCatGrow (&SectionToGetHelpOn, NULL, L"NAME,SYNOPSIS,OPTIONS,DESCRIPTION,EXAMPLES", 0);
217 }
218 }
219
220 if (gUnicodeCollation->StriColl(gUnicodeCollation, CommandToGetHelpOn, L"special") == 0) {
221 //
222 // we need info on the special characters
223 //
224 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_SC_HEADER), gShellLevel3HiiHandle);
225 HiiString = HiiGetString(gShellLevel3HiiHandle, STRING_TOKEN(STR_HELP_SC_DATA), NULL);
226 ShellPrintEx(-1, -1, L"%s", HiiString);
227 FreePool(HiiString);
228 Found = TRUE;
229 } else {
230 CommandList = ShellCommandGetCommandList(TRUE);
231 ASSERT(CommandList != NULL);
232 for ( Node = (COMMAND_LIST*)GetFirstNode(&CommandList->Link)
233 ; CommandList != NULL && !IsListEmpty(&CommandList->Link) && !IsNull(&CommandList->Link, &Node->Link)
234 ; Node = (COMMAND_LIST*)GetNextNode(&CommandList->Link, &Node->Link)
235 ){
236 //
237 // Checking execution break flag when print multiple command help information.
238 //
239 if (ShellGetExecutionBreakFlag ()) {
240 break;
241 }
242 if ((gUnicodeCollation->MetaiMatch(gUnicodeCollation, Node->CommandString, CommandToGetHelpOn)) ||
243 (gEfiShellProtocol->GetAlias(CommandToGetHelpOn, NULL) != NULL && (gUnicodeCollation->MetaiMatch(gUnicodeCollation, Node->CommandString, (CHAR16*)(gEfiShellProtocol->GetAlias(CommandToGetHelpOn, NULL)))))) {
244 //
245 // We have a command to look for help on.
246 //
247 Status = ShellPrintHelp(Node->CommandString, SectionToGetHelpOn, PrintCommandText);
248 if (Status == EFI_DEVICE_ERROR) {
249 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_INV), gShellLevel3HiiHandle, Node->CommandString);
250 } else if (EFI_ERROR(Status)) {
251 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_NF), gShellLevel3HiiHandle, Node->CommandString);
252 } else {
253 Found = TRUE;
254 }
255 }
256 }
257 //
258 // Search the .man file for Shell applications (Shell external commands).
259 //
260 if (!Found) {
261 Status = ShellPrintHelp(CommandToGetHelpOn, SectionToGetHelpOn, FALSE);
262 if (Status == EFI_DEVICE_ERROR) {
263 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_INV), gShellLevel3HiiHandle, CommandToGetHelpOn);
264 } else if (EFI_ERROR(Status)) {
265 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_NF), gShellLevel3HiiHandle, CommandToGetHelpOn);
266 } else {
267 Found = TRUE;
268 }
269 }
270
271 //
272 // now try to match against the dynamic command list and print help
273 //
274 Status = PrintDynamicCommandHelp(CommandToGetHelpOn);
275 if (Status == EFI_SUCCESS) {
276 Found = TRUE;
277 }
278
279 }
280
281 if (!Found) {
282 ShellStatus = SHELL_NOT_FOUND;
283 }
284
285 //
286 // free the command line package
287 //
288 ShellCommandLineFreeVarList (Package);
289 }
290 }
291
292 if (CommandToGetHelpOn != NULL && StrCmp(CommandToGetHelpOn, L"*") == 0){
293 //
294 // If '*' then the command entered was 'Help' without qualifiers, This footer
295 // provides additional info on help switches
296 //
297 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_FOOTER), gShellLevel3HiiHandle);
298 }
299 if (CommandToGetHelpOn != NULL) {
300 FreePool(CommandToGetHelpOn);
301 }
302 if (SectionToGetHelpOn != NULL) {
303 FreePool(SectionToGetHelpOn);
304 }
305
306 return (ShellStatus);
307 }