]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Application/Shell/ShellManParser.c
NetworkPkg:Fix a bug the 2nd httpboot fail issue.
[mirror_edk2.git] / ShellPkg / Application / Shell / ShellManParser.c
CommitLineData
a405b86d 1/** @file\r
2 Provides interface to shell MAN file parser.\r
3\r
e75390f0 4 Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>\r
52d1f930 5 Copyright 2015 Dell Inc.\r
a405b86d 6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "Shell.h"\r
17\r
52d1f930
JD
18CHAR16 EFIAPI InternalShellCharToUpper (IN CHAR16 Char);\r
19\r
a405b86d 20/**\r
21 Verifies that the filename has .MAN on the end.\r
22\r
23 allocates a new buffer and copies the name (appending .MAN if necessary)\r
24\r
25 ASSERT if ManFileName is NULL\r
26\r
27 @param[in] ManFileName original filename\r
28\r
29 @return the new filename with .man as the extension.\r
30**/\r
31CHAR16 *\r
32EFIAPI\r
33GetManFileName(\r
34 IN CONST CHAR16 *ManFileName\r
35 )\r
36{\r
37 CHAR16 *Buffer;\r
3c865f20 38 if (ManFileName == NULL) {\r
39 return (NULL);\r
40 }\r
a405b86d 41 //\r
42 // Fix the file name\r
43 //\r
44 if (StrnCmp(ManFileName+StrLen(ManFileName)-4, L".man", 4)==0) {\r
7f79b01e 45 Buffer = AllocateCopyPool(StrSize(ManFileName), ManFileName);\r
a405b86d 46 } else {\r
47 Buffer = AllocateZeroPool(StrSize(ManFileName) + 4*sizeof(CHAR16));\r
3c865f20 48 if (Buffer != NULL) {\r
e75390f0
QS
49 StrnCpyS( Buffer, \r
50 (StrSize(ManFileName) + 4*sizeof(CHAR16))/sizeof(CHAR16), \r
51 ManFileName, \r
52 StrLen(ManFileName)\r
53 );\r
54 StrnCatS( Buffer, \r
55 (StrSize(ManFileName) + 4*sizeof(CHAR16))/sizeof(CHAR16),\r
56 L".man", \r
57 4\r
58 );\r
3c865f20 59 }\r
a405b86d 60 }\r
61 return (Buffer);\r
62}\r
63\r
64/**\r
65 Search the path environment variable for possible locations and test for\r
66 which one contains a man file with the name specified. If a valid file is found\r
67 stop searching and return the (opened) SHELL_FILE_HANDLE for that file.\r
68\r
69 @param[in] FileName Name of the file to find and open.\r
70 @param[out] Handle Pointer to the handle of the found file. The\r
71 value of this is undefined for return values\r
72 except EFI_SUCCESS.\r
73\r
74 @retval EFI_SUCCESS The file was found. Handle is a valid SHELL_FILE_HANDLE\r
75 @retval EFI_INVALID_PARAMETER A parameter had an invalid value.\r
76 @retval EFI_NOT_FOUND The file was not found.\r
77**/\r
78EFI_STATUS\r
79EFIAPI\r
80SearchPathForFile(\r
81 IN CONST CHAR16 *FileName,\r
82 OUT SHELL_FILE_HANDLE *Handle\r
83 )\r
84{\r
85 CHAR16 *FullFileName;\r
86 EFI_STATUS Status;\r
87\r
88 if ( FileName == NULL\r
89 || Handle == NULL\r
90 || StrLen(FileName) == 0\r
91 ){\r
92 return (EFI_INVALID_PARAMETER);\r
93 }\r
94\r
95 FullFileName = ShellFindFilePath(FileName);\r
96 if (FullFileName == NULL) {\r
97 return (EFI_NOT_FOUND);\r
98 }\r
99\r
100 //\r
101 // now open that file\r
102 //\r
103 Status = EfiShellOpenFileByName(FullFileName, Handle, EFI_FILE_MODE_READ);\r
104 FreePool(FullFileName);\r
105\r
106 return (Status);\r
107}\r
108\r
109/**\r
110 parses through Buffer (which is MAN file formatted) and returns the\r
111 detailed help for any sub section specified in the comma seperated list of\r
112 sections provided. If the end of the file or a .TH section is found then\r
113 return.\r
114\r
115 Upon a sucessful return the caller is responsible to free the memory in *HelpText\r
116\r
117 @param[in] Buffer Buffer to read from\r
118 @param[in] Sections name of command's sub sections to find\r
119 @param[in] HelpText pointer to pointer to string where text goes.\r
120 @param[in] HelpSize pointer to size of allocated HelpText (may be updated)\r
121\r
122 @retval EFI_OUT_OF_RESOURCES a memory allocation failed.\r
123 @retval EFI_SUCCESS the section was found and its description sotred in\r
124 an alloceted buffer.\r
125**/\r
126EFI_STATUS\r
127EFIAPI\r
128ManBufferFindSections(\r
129 IN CONST CHAR16 *Buffer,\r
130 IN CONST CHAR16 *Sections,\r
131 IN CHAR16 **HelpText,\r
132 IN UINTN *HelpSize\r
133 )\r
134{\r
135 EFI_STATUS Status;\r
136 CONST CHAR16 *CurrentLocation;\r
137 BOOLEAN CurrentlyReading;\r
138 CHAR16 *SectionName;\r
139 UINTN SectionLen;\r
140 BOOLEAN Found;\r
141 CHAR16 *TempString;\r
142 CHAR16 *TempString2;\r
143\r
144 if ( Buffer == NULL\r
145 || HelpText == NULL\r
146 || HelpSize == NULL\r
147 ){\r
148 return (EFI_INVALID_PARAMETER);\r
149 }\r
150\r
151 Status = EFI_SUCCESS;\r
152 CurrentlyReading = FALSE;\r
153 Found = FALSE;\r
154\r
155 for (CurrentLocation = Buffer,TempString = NULL\r
156 ; CurrentLocation != NULL && *CurrentLocation != CHAR_NULL\r
157 ; CurrentLocation=StrStr(CurrentLocation, L"\r\n"),TempString = NULL\r
158 ){\r
159 while(CurrentLocation[0] == L'\r' || CurrentLocation[0] == L'\n') {\r
160 CurrentLocation++;\r
161 }\r
162 if (CurrentLocation[0] == L'#') {\r
163 //\r
164 // Skip comment lines\r
165 //\r
166 continue;\r
167 }\r
168 if (StrnCmp(CurrentLocation, L".TH", 3) == 0) {\r
169 //\r
170 // we hit the end of this commands section so stop.\r
171 //\r
172 break;\r
173 }\r
174 if (StrnCmp(CurrentLocation, L".SH ", 4) == 0) {\r
175 if (Sections == NULL) {\r
176 CurrentlyReading = TRUE;\r
177 continue;\r
178 } else if (CurrentlyReading) {\r
179 CurrentlyReading = FALSE;\r
180 }\r
181 CurrentLocation += 4;\r
182 //\r
183 // is this a section we want to read in?\r
184 //\r
185 if (StrLen(CurrentLocation)!=0) {\r
186 TempString2 = StrStr(CurrentLocation, L" ");\r
187 TempString2 = MIN(TempString2, StrStr(CurrentLocation, L"\r"));\r
188 TempString2 = MIN(TempString2, StrStr(CurrentLocation, L"\n"));\r
189 ASSERT(TempString == NULL);\r
190 TempString = StrnCatGrow(&TempString, NULL, CurrentLocation, TempString2==NULL?0:TempString2 - CurrentLocation);\r
532691c8 191 if (TempString == NULL) {\r
192 Status = EFI_OUT_OF_RESOURCES;\r
193 break;\r
194 }\r
a405b86d 195 SectionName = TempString;\r
196 SectionLen = StrLen(SectionName);\r
197 SectionName = StrStr(Sections, SectionName);\r
198 if (SectionName == NULL) {\r
199 continue;\r
200 }\r
201 if (*(SectionName + SectionLen) == CHAR_NULL || *(SectionName + SectionLen) == L',') {\r
202 CurrentlyReading = TRUE;\r
203 }\r
204 }\r
205 } else if (CurrentlyReading) {\r
206 Found = TRUE;\r
207 if (StrLen(CurrentLocation)!=0) {\r
208 TempString2 = StrStr(CurrentLocation, L"\r");\r
209 TempString2 = MIN(TempString2, StrStr(CurrentLocation, L"\n"));\r
210 ASSERT(TempString == NULL);\r
211 TempString = StrnCatGrow(&TempString, NULL, CurrentLocation, TempString2==NULL?0:TempString2 - CurrentLocation);\r
532691c8 212 if (TempString == NULL) {\r
213 Status = EFI_OUT_OF_RESOURCES;\r
214 break;\r
215 }\r
a405b86d 216 //\r
217 // copy and save the current line.\r
218 //\r
219 ASSERT((*HelpText == NULL && *HelpSize == 0) || (*HelpText != NULL));\r
220 StrnCatGrow (HelpText, HelpSize, TempString, 0);\r
532691c8 221 if (HelpText == NULL) {\r
222 Status = EFI_OUT_OF_RESOURCES;\r
223 break;\r
224 }\r
a405b86d 225 StrnCatGrow (HelpText, HelpSize, L"\r\n", 0);\r
532691c8 226 if (HelpText == NULL) {\r
227 Status = EFI_OUT_OF_RESOURCES;\r
228 break;\r
229 }\r
a405b86d 230 }\r
231 }\r
232 SHELL_FREE_NON_NULL(TempString);\r
233 }\r
234 if (!Found && !EFI_ERROR(Status)) {\r
235 return (EFI_NOT_FOUND);\r
236 }\r
237 return (Status);\r
238}\r
239\r
240/**\r
241 parses through the MAN file specified by SHELL_FILE_HANDLE and returns the\r
242 detailed help for any sub section specified in the comma seperated list of\r
243 sections provided. If the end of the file or a .TH section is found then\r
244 return.\r
245\r
246 Upon a sucessful return the caller is responsible to free the memory in *HelpText\r
247\r
248 @param[in] Handle FileHandle to read from\r
249 @param[in] Sections name of command's sub sections to find\r
250 @param[out] HelpText pointer to pointer to string where text goes.\r
251 @param[out] HelpSize pointer to size of allocated HelpText (may be updated)\r
252 @param[in] Ascii TRUE if the file is ASCII, FALSE otherwise.\r
253\r
254 @retval EFI_OUT_OF_RESOURCES a memory allocation failed.\r
255 @retval EFI_SUCCESS the section was found and its description sotred in\r
256 an alloceted buffer.\r
257**/\r
258EFI_STATUS\r
259EFIAPI\r
260ManFileFindSections(\r
261 IN SHELL_FILE_HANDLE Handle,\r
262 IN CONST CHAR16 *Sections,\r
263 OUT CHAR16 **HelpText,\r
264 OUT UINTN *HelpSize,\r
265 IN BOOLEAN Ascii\r
266 )\r
267{\r
268 EFI_STATUS Status;\r
269 CHAR16 *ReadLine;\r
270 UINTN Size;\r
271 BOOLEAN CurrentlyReading;\r
272 CHAR16 *SectionName;\r
273 UINTN SectionLen;\r
274 BOOLEAN Found;\r
275\r
276 if ( Handle == NULL\r
277 || HelpText == NULL\r
278 || HelpSize == NULL\r
279 ){\r
280 return (EFI_INVALID_PARAMETER);\r
281 }\r
282\r
283 Status = EFI_SUCCESS;\r
284 CurrentlyReading = FALSE;\r
285 Size = 1024;\r
286 Found = FALSE;\r
287\r
288 ReadLine = AllocateZeroPool(Size);\r
289 if (ReadLine == NULL) {\r
290 return (EFI_OUT_OF_RESOURCES);\r
291 }\r
292\r
293 for (;!ShellFileHandleEof(Handle);Size = 1024) {\r
294 Status = ShellFileHandleReadLine(Handle, ReadLine, &Size, TRUE, &Ascii);\r
295 if (ReadLine[0] == L'#') {\r
296 //\r
297 // Skip comment lines\r
298 //\r
299 continue;\r
300 }\r
301 //\r
302 // ignore too small of buffer...\r
303 //\r
304 if (Status == EFI_BUFFER_TOO_SMALL) {\r
305 Status = EFI_SUCCESS;\r
306 }\r
307 if (EFI_ERROR(Status)) {\r
308 break;\r
309 } else if (StrnCmp(ReadLine, L".TH", 3) == 0) {\r
310 //\r
311 // we hit the end of this commands section so stop.\r
312 //\r
313 break;\r
314 } else if (StrnCmp(ReadLine, L".SH", 3) == 0) {\r
315 if (Sections == NULL) {\r
316 CurrentlyReading = TRUE;\r
317 continue;\r
318 }\r
319 //\r
320 // we found a section\r
321 //\r
322 if (CurrentlyReading) {\r
323 CurrentlyReading = FALSE;\r
324 }\r
325 //\r
326 // is this a section we want to read in?\r
327 //\r
328 for ( SectionName = ReadLine + 3\r
329 ; *SectionName == L' '\r
330 ; SectionName++);\r
331 SectionLen = StrLen(SectionName);\r
332 SectionName = StrStr(Sections, SectionName);\r
333 if (SectionName == NULL) {\r
334 continue;\r
335 }\r
336 if (*(SectionName + SectionLen) == CHAR_NULL || *(SectionName + SectionLen) == L',') {\r
337 CurrentlyReading = TRUE;\r
338 }\r
339 } else if (CurrentlyReading) {\r
340 Found = TRUE;\r
341 //\r
342 // copy and save the current line.\r
343 //\r
344 ASSERT((*HelpText == NULL && *HelpSize == 0) || (*HelpText != NULL));\r
345 StrnCatGrow (HelpText, HelpSize, ReadLine, 0);\r
346 StrnCatGrow (HelpText, HelpSize, L"\r\n", 0);\r
347 }\r
348 }\r
349 FreePool(ReadLine);\r
350 if (!Found && !EFI_ERROR(Status)) {\r
351 return (EFI_NOT_FOUND);\r
352 }\r
353 return (Status);\r
354}\r
355\r
356/**\r
357 parses through the MAN file formatted Buffer and returns the\r
358 "Brief Description" for the .TH section as specified by Command. If the\r
359 command section is not found return EFI_NOT_FOUND.\r
360\r
361 Upon a sucessful return the caller is responsible to free the memory in *BriefDesc\r
362\r
363 @param[in] Handle Buffer to read from\r
364 @param[in] Command name of command's section to find\r
365 @param[in] BriefDesc pointer to pointer to string where description goes.\r
366 @param[in] BriefSize pointer to size of allocated BriefDesc\r
367\r
368 @retval EFI_OUT_OF_RESOURCES a memory allocation failed.\r
369 @retval EFI_SUCCESS the section was found and its description sotred in\r
370 an alloceted buffer.\r
371**/\r
372EFI_STATUS\r
373EFIAPI\r
374ManBufferFindTitleSection(\r
375 IN CHAR16 **Buffer,\r
376 IN CONST CHAR16 *Command,\r
377 IN CHAR16 **BriefDesc,\r
378 IN UINTN *BriefSize\r
379 )\r
380{\r
381 EFI_STATUS Status;\r
382 CHAR16 *TitleString;\r
383 CHAR16 *TitleEnd;\r
384 CHAR16 *CurrentLocation;\r
7f79b01e
JC
385 UINTN TitleLength;\r
386 CONST CHAR16 StartString[] = L".TH ";\r
387 CONST CHAR16 EndString[] = L" 0 ";\r
a405b86d 388\r
389 if ( Buffer == NULL\r
390 || Command == NULL\r
391 || (BriefDesc != NULL && BriefSize == NULL)\r
392 ){\r
393 return (EFI_INVALID_PARAMETER);\r
394 }\r
395\r
396 Status = EFI_SUCCESS;\r
397\r
7f79b01e
JC
398 //\r
399 // more characters for StartString and EndString\r
400 //\r
401 TitleLength = StrSize(Command) + (StrLen(StartString) + StrLen(EndString)) * sizeof(CHAR16);\r
402 TitleString = AllocateZeroPool(TitleLength);\r
a405b86d 403 if (TitleString == NULL) {\r
404 return (EFI_OUT_OF_RESOURCES);\r
405 }\r
e75390f0
QS
406 StrCpyS(TitleString, TitleLength/sizeof(CHAR16), StartString);\r
407 StrCatS(TitleString, TitleLength/sizeof(CHAR16), Command);\r
408 StrCatS(TitleString, TitleLength/sizeof(CHAR16), EndString);\r
a405b86d 409\r
410 CurrentLocation = StrStr(*Buffer, TitleString);\r
411 if (CurrentLocation == NULL){\r
412 Status = EFI_NOT_FOUND;\r
413 } else {\r
414 //\r
415 // we found it so copy out the rest of the line into BriefDesc\r
416 // After skipping any spaces or zeroes\r
417 //\r
418 for (CurrentLocation += StrLen(TitleString)\r
419 ; *CurrentLocation == L' ' || *CurrentLocation == L'0' || *CurrentLocation == L'1' || *CurrentLocation == L'\"'\r
420 ; CurrentLocation++);\r
421\r
422 TitleEnd = StrStr(CurrentLocation, L"\"");\r
733f138d 423 if (TitleEnd == NULL) {\r
424 Status = EFI_DEVICE_ERROR;\r
425 } else {\r
426 if (BriefDesc != NULL) {\r
427 *BriefSize = StrSize(TitleEnd);\r
428 *BriefDesc = AllocateZeroPool(*BriefSize);\r
429 if (*BriefDesc == NULL) {\r
430 Status = EFI_OUT_OF_RESOURCES;\r
431 } else {\r
e75390f0 432 StrnCpyS(*BriefDesc, (*BriefSize)/sizeof(CHAR16), CurrentLocation, TitleEnd-CurrentLocation);\r
733f138d 433 }\r
a405b86d 434 }\r
a405b86d 435\r
733f138d 436 for (CurrentLocation = TitleEnd\r
437 ; *CurrentLocation != L'\n'\r
438 ; CurrentLocation++);\r
439 for (\r
440 ; *CurrentLocation == L' ' || *CurrentLocation == L'\n' || *CurrentLocation == L'\r'\r
441 ; CurrentLocation++);\r
442 *Buffer = CurrentLocation;\r
443 }\r
a405b86d 444 }\r
445\r
446 FreePool(TitleString);\r
447 return (Status);\r
448}\r
449\r
52d1f930
JD
450/**\r
451 Parses a line from a MAN file to see if it is the Title Header. If it is, then\r
452 if the "Brief Description" is desired, allocate a buffer for it and return a\r
453 copy. Upon a sucessful return the caller is responsible to free the memory in\r
454 *BriefDesc\r
455\r
456 Uses a simple state machine that allows "unlimited" whitespace before and after the\r
457 ".TH", compares Command and the MAN file commnd name without respect to case, and\r
458 allows "unlimited" whitespace and '0' and '1' characters before the Short Description.\r
459 The PCRE regex describing this functionality is: ^\s*\.TH\s+(\S)\s[\s01]*(.*)$\r
460 where group 1 is the Command Name and group 2 is the Short Description.\r
461\r
462 @param[in] Command name of command whose MAN file we think Line came from\r
463 @param[in] Line Pointer to a line from the MAN file\r
464 @param[out] BriefDesc pointer to pointer to string where description goes.\r
465 @param[out] BriefSize pointer to size of allocated BriefDesc\r
466 @param[out] Found TRUE if the Title Header was found and it belongs to Command\r
467\r
468 @retval TRUE Line contained the Title Header\r
469 @retval FALSE Line did not contain the Title Header\r
470**/\r
471BOOLEAN\r
472IsTitleHeader(\r
473 IN CONST CHAR16 *Command,\r
474 IN CHAR16 *Line,\r
475 OUT CHAR16 **BriefDesc OPTIONAL,\r
476 OUT UINTN *BriefSize OPTIONAL,\r
477 OUT BOOLEAN *Found\r
478 )\r
479{\r
480 // The states of a simple state machine used to recognize a title header line\r
481 // and to extract the Short Description, if desired.\r
482 typedef enum {\r
483 LookForThMacro, LookForCommandName, CompareCommands, GetBriefDescription, Final\r
484 } STATEVALUES;\r
485\r
486 STATEVALUES State;\r
487 UINTN CommandIndex; // Indexes Command as we compare its chars to the MAN file.\r
488 BOOLEAN ReturnValue; // TRUE if this the Title Header line of *some* MAN file.\r
489 BOOLEAN ReturnFound; // TRUE if this the Title Header line of *the desired* MAN file.\r
490\r
491 ReturnValue = FALSE;\r
492 ReturnFound = FALSE;\r
493 CommandIndex = 0;\r
494 State = LookForThMacro;\r
495\r
496 do {\r
497\r
498 if (*Line == L'\0') {\r
499 break;\r
500 }\r
501\r
502 switch (State) {\r
503\r
504 // Handle "^\s*.TH\s"\r
505 // Go to state LookForCommandName if the title header macro is present; otherwise,\r
506 // eat white space. If we see something other than white space, this is not a\r
507 // title header line.\r
508 case LookForThMacro:\r
509 if (StrnCmp (L".TH ", Line, 4) == 0 || StrnCmp (L".TH\t", Line, 4) == 0) {\r
510 Line += 4;\r
511 State = LookForCommandName;\r
512 }\r
513 else if (*Line == L' ' || *Line == L'\t') {\r
514 Line++;\r
515 }\r
516 else {\r
517 State = Final;\r
518 }\r
519 break;\r
520\r
521 // Handle "\s*"\r
522 // Eat any "extra" whitespace after the title header macro (we have already seen\r
523 // at least one white space character). Go to state CompareCommands when a\r
524 // non-white space is seen.\r
525 case LookForCommandName:\r
526 if (*Line == L' ' || *Line == L'\t') {\r
527 Line++;\r
528 }\r
529 else {\r
530 ReturnValue = TRUE; // This is *some* command's title header line.\r
531 State = CompareCommands;\r
532 // Do not increment Line; it points to the first character of the command\r
533 // name on the title header line.\r
534 }\r
535 break;\r
536\r
537 // Handle "(\S)\s"\r
538 // Compare Command to the title header command name, ignoring case. When we\r
539 // reach the end of the command (i.e. we see white space), the next state\r
540 // depends on whether the caller wants a copy of the Brief Description.\r
541 case CompareCommands:\r
542 if (*Line == L' ' || *Line == L'\t') {\r
543 ReturnFound = TRUE; // This is the desired command's title header line.\r
544 State = (BriefDesc == NULL) ? Final : GetBriefDescription;\r
545 }\r
546 else if (InternalShellCharToUpper (*Line) != InternalShellCharToUpper (*(Command + CommandIndex++))) {\r
547 State = Final;\r
548 }\r
549 Line++;\r
550 break;\r
551\r
552 // Handle "[\s01]*(.*)$"\r
553 // Skip whitespace, '0', and '1' characters, if any, prior to the brief description.\r
554 // Return the description to the caller.\r
555 case GetBriefDescription:\r
556 if (*Line != L' ' && *Line != L'\t' && *Line != L'0' && *Line != L'1') {\r
557 *BriefSize = StrSize(Line);\r
558 *BriefDesc = AllocateZeroPool(*BriefSize);\r
559 if (*BriefDesc != NULL) {\r
560 StrCpyS(*BriefDesc, (*BriefSize)/sizeof(CHAR16), Line);\r
561 }\r
562 State = Final;\r
563 }\r
564 Line++;\r
565 break;\r
566\r
d8ed4dec
PA
567 default:\r
568 break;\r
52d1f930
JD
569 }\r
570\r
571 } while (State < Final);\r
572\r
573 *Found = ReturnFound;\r
574 return ReturnValue;\r
575}\r
576\r
a405b86d 577/**\r
578 parses through the MAN file specified by SHELL_FILE_HANDLE and returns the\r
52d1f930 579 "Brief Description" for the .TH section as specified by Command. If the\r
a405b86d 580 command section is not found return EFI_NOT_FOUND.\r
581\r
582 Upon a sucessful return the caller is responsible to free the memory in *BriefDesc\r
583\r
4ff7e37b 584 @param[in] Handle FileHandle to read from\r
52d1f930
JD
585 @param[in] Command name of command's section to find as entered on the\r
586 command line (may be a relative or absolute path or\r
587 be in any case: upper, lower, or mixed in numerous ways!).\r
4ff7e37b
ED
588 @param[out] BriefDesc pointer to pointer to string where description goes.\r
589 @param[out] BriefSize pointer to size of allocated BriefDesc\r
590 @param[in, out] Ascii TRUE if the file is ASCII, FALSE otherwise, will be\r
591 set if the file handle is at the 0 position.\r
a405b86d 592\r
593 @retval EFI_OUT_OF_RESOURCES a memory allocation failed.\r
52d1f930
JD
594 @retval EFI_SUCCESS the section was found and its description stored in\r
595 an allocated buffer if requested.\r
a405b86d 596**/\r
597EFI_STATUS\r
598EFIAPI\r
599ManFileFindTitleSection(\r
600 IN SHELL_FILE_HANDLE Handle,\r
601 IN CONST CHAR16 *Command,\r
602 OUT CHAR16 **BriefDesc OPTIONAL,\r
603 OUT UINTN *BriefSize OPTIONAL,\r
604 IN OUT BOOLEAN *Ascii\r
605 )\r
606{\r
607 EFI_STATUS Status;\r
a405b86d 608 CHAR16 *ReadLine;\r
609 UINTN Size;\r
a405b86d 610 BOOLEAN Found;\r
52d1f930 611 UINTN Start;\r
a405b86d 612\r
613 if ( Handle == NULL\r
614 || Command == NULL\r
615 || (BriefDesc != NULL && BriefSize == NULL)\r
616 ){\r
617 return (EFI_INVALID_PARAMETER);\r
618 }\r
619\r
620 Status = EFI_SUCCESS;\r
621 Size = 1024;\r
622 Found = FALSE;\r
623\r
624 ReadLine = AllocateZeroPool(Size);\r
625 if (ReadLine == NULL) {\r
626 return (EFI_OUT_OF_RESOURCES);\r
627 }\r
628\r
52d1f930
JD
629 //\r
630 // Do not pass any leading path information that may be present to IsTitleHeader().\r
631 //\r
632 Start = StrLen(Command);\r
633 while (Start\r
634 && (*(Command + Start - 1) != L'\\')\r
635 && (*(Command + Start - 1) != L'/')\r
636 && (*(Command + Start - 1) != L':')) {\r
637 --Start;\r
a405b86d 638 }\r
d233c122 639\r
a405b86d 640 for (;!ShellFileHandleEof(Handle);Size = 1024) {\r
641 Status = ShellFileHandleReadLine(Handle, ReadLine, &Size, TRUE, Ascii);\r
a405b86d 642 //\r
643 // ignore too small of buffer...\r
644 //\r
52d1f930 645 if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
a405b86d 646 break;\r
647 }\r
52d1f930
JD
648\r
649 Status = EFI_NOT_FOUND;\r
650 if (IsTitleHeader (Command+Start, ReadLine, BriefDesc, BriefSize, &Found)) {\r
651 Status = Found ? EFI_SUCCESS : EFI_NOT_FOUND;\r
a405b86d 652 break;\r
653 }\r
654 }\r
52d1f930 655\r
a405b86d 656 FreePool(ReadLine);\r
a405b86d 657 return (Status);\r
658}\r
659\r
660/**\r
661 This function returns the help information for the specified command. The help text\r
662 will be parsed from a UEFI Shell manual page. (see UEFI Shell 2.0 Appendix B)\r
663\r
664 If Sections is specified, then each section name listed will be compared in a casesensitive\r
665 manner, to the section names described in Appendix B. If the section exists,\r
666 it will be appended to the returned help text. If the section does not exist, no\r
667 information will be returned. If Sections is NULL, then all help text information\r
668 available will be returned.\r
669\r
670 if BriefDesc is NULL, then the breif description will not be savedd seperatly,\r
671 but placed first in the main HelpText.\r
672\r
673 @param[in] ManFileName Points to the NULL-terminated UEFI Shell MAN file name.\r
674 @param[in] Command Points to the NULL-terminated UEFI Shell command name.\r
675 @param[in] Sections Points to the NULL-terminated comma-delimited\r
676 section names to return. If NULL, then all\r
677 sections will be returned.\r
678 @param[out] BriefDesc On return, points to a callee-allocated buffer\r
679 containing brief description text.\r
680 @param[out] HelpText On return, points to a callee-allocated buffer\r
681 containing all specified help text.\r
682\r
683 @retval EFI_SUCCESS The help text was returned.\r
684 @retval EFI_OUT_OF_RESOURCES The necessary buffer could not be allocated to hold the\r
685 returned help text.\r
ecae5117 686 @retval EFI_INVALID_PARAMETER HelpText is NULL.\r
687 @retval EFI_INVALID_PARAMETER ManFileName is invalid.\r
a405b86d 688 @retval EFI_NOT_FOUND There is no help text available for Command.\r
689**/\r
690EFI_STATUS\r
691EFIAPI\r
692ProcessManFile(\r
693 IN CONST CHAR16 *ManFileName,\r
694 IN CONST CHAR16 *Command,\r
695 IN CONST CHAR16 *Sections OPTIONAL,\r
696 OUT CHAR16 **BriefDesc OPTIONAL,\r
697 OUT CHAR16 **HelpText\r
698 )\r
699{\r
700 CHAR16 *TempString;\r
701 SHELL_FILE_HANDLE FileHandle;\r
702 EFI_STATUS Status;\r
703 UINTN HelpSize;\r
704 UINTN BriefSize;\r
705 BOOLEAN Ascii;\r
706 CHAR16 *TempString2;\r
707 EFI_DEVICE_PATH_PROTOCOL *FileDevPath;\r
708 EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
709\r
710 if ( ManFileName == NULL\r
711 || Command == NULL\r
712 || HelpText == NULL\r
713 ){\r
714 return (EFI_INVALID_PARAMETER);\r
715 }\r
716\r
717 HelpSize = 0;\r
718 BriefSize = 0;\r
719 TempString = NULL;\r
33fe8308 720 Ascii = FALSE;\r
a405b86d 721 //\r
722 // See if it's in HII first\r
723 //\r
724 TempString = ShellCommandGetCommandHelp(Command);\r
725 if (TempString != NULL) {\r
726 TempString2 = TempString;\r
727 Status = ManBufferFindTitleSection(&TempString2, Command, BriefDesc, &BriefSize);\r
728 if (!EFI_ERROR(Status) && HelpText != NULL){\r
729 Status = ManBufferFindSections(TempString2, Sections, HelpText, &HelpSize);\r
730 }\r
731 } else {\r
732 FileHandle = NULL;\r
733 TempString = GetManFileName(ManFileName);\r
ecae5117 734 if (TempString == NULL) {\r
735 return (EFI_INVALID_PARAMETER);\r
736 }\r
a405b86d 737\r
738 Status = SearchPathForFile(TempString, &FileHandle);\r
739 if (EFI_ERROR(Status)) {\r
740 FileDevPath = FileDevicePath(NULL, TempString);\r
741 DevPath = AppendDevicePath (ShellInfoObject.ImageDevPath, FileDevPath);\r
742 Status = InternalOpenFileDevicePath(DevPath, &FileHandle, EFI_FILE_MODE_READ, 0);\r
743 FreePool(FileDevPath);\r
744 FreePool(DevPath);\r
745 }\r
746\r
747 if (!EFI_ERROR(Status)) {\r
748 HelpSize = 0;\r
749 BriefSize = 0;\r
750 Status = ManFileFindTitleSection(FileHandle, Command, BriefDesc, &BriefSize, &Ascii);\r
751 if (!EFI_ERROR(Status) && HelpText != NULL){\r
752 Status = ManFileFindSections(FileHandle, Sections, HelpText, &HelpSize, Ascii);\r
753 }\r
754 ShellInfoObject.NewEfiShellProtocol->CloseFile(FileHandle);\r
755 } else {\r
756 *HelpText = NULL;\r
757 }\r
758 }\r
759 if (TempString != NULL) {\r
760 FreePool(TempString);\r
761 }\r
762\r
763 return (Status);\r
764}\r