2 Provides interface to shell MAN file parser.
4 Copyright (c) 2009 - 2015, 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
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.
18 Verifies that the filename has .MAN on the end.
20 allocates a new buffer and copies the name (appending .MAN if necessary)
22 ASSERT if ManFileName is NULL
24 @param[in] ManFileName original filename
26 @return the new filename with .man as the extension.
31 IN CONST CHAR16
*ManFileName
35 if (ManFileName
== NULL
) {
41 if (StrnCmp(ManFileName
+StrLen(ManFileName
)-4, L
".man", 4)==0) {
42 Buffer
= AllocateCopyPool(StrSize(ManFileName
), ManFileName
);
44 Buffer
= AllocateZeroPool(StrSize(ManFileName
) + 4*sizeof(CHAR16
));
47 (StrSize(ManFileName
) + 4*sizeof(CHAR16
))/sizeof(CHAR16
),
52 (StrSize(ManFileName
) + 4*sizeof(CHAR16
))/sizeof(CHAR16
),
62 Search the path environment variable for possible locations and test for
63 which one contains a man file with the name specified. If a valid file is found
64 stop searching and return the (opened) SHELL_FILE_HANDLE for that file.
66 @param[in] FileName Name of the file to find and open.
67 @param[out] Handle Pointer to the handle of the found file. The
68 value of this is undefined for return values
71 @retval EFI_SUCCESS The file was found. Handle is a valid SHELL_FILE_HANDLE
72 @retval EFI_INVALID_PARAMETER A parameter had an invalid value.
73 @retval EFI_NOT_FOUND The file was not found.
78 IN CONST CHAR16
*FileName
,
79 OUT SHELL_FILE_HANDLE
*Handle
87 || StrLen(FileName
) == 0
89 return (EFI_INVALID_PARAMETER
);
92 FullFileName
= ShellFindFilePath(FileName
);
93 if (FullFileName
== NULL
) {
94 return (EFI_NOT_FOUND
);
100 Status
= EfiShellOpenFileByName(FullFileName
, Handle
, EFI_FILE_MODE_READ
);
101 FreePool(FullFileName
);
107 parses through Buffer (which is MAN file formatted) and returns the
108 detailed help for any sub section specified in the comma seperated list of
109 sections provided. If the end of the file or a .TH section is found then
112 Upon a sucessful return the caller is responsible to free the memory in *HelpText
114 @param[in] Buffer Buffer to read from
115 @param[in] Sections name of command's sub sections to find
116 @param[in] HelpText pointer to pointer to string where text goes.
117 @param[in] HelpSize pointer to size of allocated HelpText (may be updated)
119 @retval EFI_OUT_OF_RESOURCES a memory allocation failed.
120 @retval EFI_SUCCESS the section was found and its description sotred in
125 ManBufferFindSections(
126 IN CONST CHAR16
*Buffer
,
127 IN CONST CHAR16
*Sections
,
128 IN CHAR16
**HelpText
,
133 CONST CHAR16
*CurrentLocation
;
134 BOOLEAN CurrentlyReading
;
145 return (EFI_INVALID_PARAMETER
);
148 Status
= EFI_SUCCESS
;
149 CurrentlyReading
= FALSE
;
152 for (CurrentLocation
= Buffer
,TempString
= NULL
153 ; CurrentLocation
!= NULL
&& *CurrentLocation
!= CHAR_NULL
154 ; CurrentLocation
=StrStr(CurrentLocation
, L
"\r\n"),TempString
= NULL
156 while(CurrentLocation
[0] == L
'\r' || CurrentLocation
[0] == L
'\n') {
159 if (CurrentLocation
[0] == L
'#') {
161 // Skip comment lines
165 if (StrnCmp(CurrentLocation
, L
".TH", 3) == 0) {
167 // we hit the end of this commands section so stop.
171 if (StrnCmp(CurrentLocation
, L
".SH ", 4) == 0) {
172 if (Sections
== NULL
) {
173 CurrentlyReading
= TRUE
;
175 } else if (CurrentlyReading
) {
176 CurrentlyReading
= FALSE
;
178 CurrentLocation
+= 4;
180 // is this a section we want to read in?
182 if (StrLen(CurrentLocation
)!=0) {
183 TempString2
= StrStr(CurrentLocation
, L
" ");
184 TempString2
= MIN(TempString2
, StrStr(CurrentLocation
, L
"\r"));
185 TempString2
= MIN(TempString2
, StrStr(CurrentLocation
, L
"\n"));
186 ASSERT(TempString
== NULL
);
187 TempString
= StrnCatGrow(&TempString
, NULL
, CurrentLocation
, TempString2
==NULL
?0:TempString2
- CurrentLocation
);
188 if (TempString
== NULL
) {
189 Status
= EFI_OUT_OF_RESOURCES
;
192 SectionName
= TempString
;
193 SectionLen
= StrLen(SectionName
);
194 SectionName
= StrStr(Sections
, SectionName
);
195 if (SectionName
== NULL
) {
198 if (*(SectionName
+ SectionLen
) == CHAR_NULL
|| *(SectionName
+ SectionLen
) == L
',') {
199 CurrentlyReading
= TRUE
;
202 } else if (CurrentlyReading
) {
204 if (StrLen(CurrentLocation
)!=0) {
205 TempString2
= StrStr(CurrentLocation
, L
"\r");
206 TempString2
= MIN(TempString2
, StrStr(CurrentLocation
, L
"\n"));
207 ASSERT(TempString
== NULL
);
208 TempString
= StrnCatGrow(&TempString
, NULL
, CurrentLocation
, TempString2
==NULL
?0:TempString2
- CurrentLocation
);
209 if (TempString
== NULL
) {
210 Status
= EFI_OUT_OF_RESOURCES
;
214 // copy and save the current line.
216 ASSERT((*HelpText
== NULL
&& *HelpSize
== 0) || (*HelpText
!= NULL
));
217 StrnCatGrow (HelpText
, HelpSize
, TempString
, 0);
218 if (HelpText
== NULL
) {
219 Status
= EFI_OUT_OF_RESOURCES
;
222 StrnCatGrow (HelpText
, HelpSize
, L
"\r\n", 0);
223 if (HelpText
== NULL
) {
224 Status
= EFI_OUT_OF_RESOURCES
;
229 SHELL_FREE_NON_NULL(TempString
);
231 if (!Found
&& !EFI_ERROR(Status
)) {
232 return (EFI_NOT_FOUND
);
238 parses through the MAN file specified by SHELL_FILE_HANDLE and returns the
239 detailed help for any sub section specified in the comma seperated list of
240 sections provided. If the end of the file or a .TH section is found then
243 Upon a sucessful return the caller is responsible to free the memory in *HelpText
245 @param[in] Handle FileHandle to read from
246 @param[in] Sections name of command's sub sections to find
247 @param[out] HelpText pointer to pointer to string where text goes.
248 @param[out] HelpSize pointer to size of allocated HelpText (may be updated)
249 @param[in] Ascii TRUE if the file is ASCII, FALSE otherwise.
251 @retval EFI_OUT_OF_RESOURCES a memory allocation failed.
252 @retval EFI_SUCCESS the section was found and its description sotred in
258 IN SHELL_FILE_HANDLE Handle
,
259 IN CONST CHAR16
*Sections
,
260 OUT CHAR16
**HelpText
,
268 BOOLEAN CurrentlyReading
;
277 return (EFI_INVALID_PARAMETER
);
280 Status
= EFI_SUCCESS
;
281 CurrentlyReading
= FALSE
;
285 ReadLine
= AllocateZeroPool(Size
);
286 if (ReadLine
== NULL
) {
287 return (EFI_OUT_OF_RESOURCES
);
290 for (;!ShellFileHandleEof(Handle
);Size
= 1024) {
291 Status
= ShellFileHandleReadLine(Handle
, ReadLine
, &Size
, TRUE
, &Ascii
);
292 if (ReadLine
[0] == L
'#') {
294 // Skip comment lines
299 // ignore too small of buffer...
301 if (Status
== EFI_BUFFER_TOO_SMALL
) {
302 Status
= EFI_SUCCESS
;
304 if (EFI_ERROR(Status
)) {
306 } else if (StrnCmp(ReadLine
, L
".TH", 3) == 0) {
308 // we hit the end of this commands section so stop.
311 } else if (StrnCmp(ReadLine
, L
".SH", 3) == 0) {
312 if (Sections
== NULL
) {
313 CurrentlyReading
= TRUE
;
317 // we found a section
319 if (CurrentlyReading
) {
320 CurrentlyReading
= FALSE
;
323 // is this a section we want to read in?
325 for ( SectionName
= ReadLine
+ 3
326 ; *SectionName
== L
' '
328 SectionLen
= StrLen(SectionName
);
329 SectionName
= StrStr(Sections
, SectionName
);
330 if (SectionName
== NULL
) {
333 if (*(SectionName
+ SectionLen
) == CHAR_NULL
|| *(SectionName
+ SectionLen
) == L
',') {
334 CurrentlyReading
= TRUE
;
336 } else if (CurrentlyReading
) {
339 // copy and save the current line.
341 ASSERT((*HelpText
== NULL
&& *HelpSize
== 0) || (*HelpText
!= NULL
));
342 StrnCatGrow (HelpText
, HelpSize
, ReadLine
, 0);
343 StrnCatGrow (HelpText
, HelpSize
, L
"\r\n", 0);
347 if (!Found
&& !EFI_ERROR(Status
)) {
348 return (EFI_NOT_FOUND
);
354 parses through the MAN file formatted Buffer and returns the
355 "Brief Description" for the .TH section as specified by Command. If the
356 command section is not found return EFI_NOT_FOUND.
358 Upon a sucessful return the caller is responsible to free the memory in *BriefDesc
360 @param[in] Handle Buffer to read from
361 @param[in] Command name of command's section to find
362 @param[in] BriefDesc pointer to pointer to string where description goes.
363 @param[in] BriefSize pointer to size of allocated BriefDesc
365 @retval EFI_OUT_OF_RESOURCES a memory allocation failed.
366 @retval EFI_SUCCESS the section was found and its description sotred in
371 ManBufferFindTitleSection(
373 IN CONST CHAR16
*Command
,
374 IN CHAR16
**BriefDesc
,
381 CHAR16
*CurrentLocation
;
383 CONST CHAR16 StartString
[] = L
".TH ";
384 CONST CHAR16 EndString
[] = L
" 0 ";
388 || (BriefDesc
!= NULL
&& BriefSize
== NULL
)
390 return (EFI_INVALID_PARAMETER
);
393 Status
= EFI_SUCCESS
;
396 // more characters for StartString and EndString
398 TitleLength
= StrSize(Command
) + (StrLen(StartString
) + StrLen(EndString
)) * sizeof(CHAR16
);
399 TitleString
= AllocateZeroPool(TitleLength
);
400 if (TitleString
== NULL
) {
401 return (EFI_OUT_OF_RESOURCES
);
403 StrCpyS(TitleString
, TitleLength
/sizeof(CHAR16
), StartString
);
404 StrCatS(TitleString
, TitleLength
/sizeof(CHAR16
), Command
);
405 StrCatS(TitleString
, TitleLength
/sizeof(CHAR16
), EndString
);
407 CurrentLocation
= StrStr(*Buffer
, TitleString
);
408 if (CurrentLocation
== NULL
){
409 Status
= EFI_NOT_FOUND
;
412 // we found it so copy out the rest of the line into BriefDesc
413 // After skipping any spaces or zeroes
415 for (CurrentLocation
+= StrLen(TitleString
)
416 ; *CurrentLocation
== L
' ' || *CurrentLocation
== L
'0' || *CurrentLocation
== L
'1' || *CurrentLocation
== L
'\"'
417 ; CurrentLocation
++);
419 TitleEnd
= StrStr(CurrentLocation
, L
"\"");
420 if (TitleEnd
== NULL
) {
421 Status
= EFI_DEVICE_ERROR
;
423 if (BriefDesc
!= NULL
) {
424 *BriefSize
= StrSize(TitleEnd
);
425 *BriefDesc
= AllocateZeroPool(*BriefSize
);
426 if (*BriefDesc
== NULL
) {
427 Status
= EFI_OUT_OF_RESOURCES
;
429 StrnCpyS(*BriefDesc
, (*BriefSize
)/sizeof(CHAR16
), CurrentLocation
, TitleEnd
-CurrentLocation
);
433 for (CurrentLocation
= TitleEnd
434 ; *CurrentLocation
!= L
'\n'
435 ; CurrentLocation
++);
437 ; *CurrentLocation
== L
' ' || *CurrentLocation
== L
'\n' || *CurrentLocation
== L
'\r'
438 ; CurrentLocation
++);
439 *Buffer
= CurrentLocation
;
443 FreePool(TitleString
);
448 parses through the MAN file specified by SHELL_FILE_HANDLE and returns the
449 "Brief Description" for the .TH section as specified by Command. if the
450 command section is not found return EFI_NOT_FOUND.
452 Upon a sucessful return the caller is responsible to free the memory in *BriefDesc
454 @param[in] Handle FileHandle to read from
455 @param[in] Command name of command's section to find
456 @param[out] BriefDesc pointer to pointer to string where description goes.
457 @param[out] BriefSize pointer to size of allocated BriefDesc
458 @param[in, out] Ascii TRUE if the file is ASCII, FALSE otherwise, will be
459 set if the file handle is at the 0 position.
461 @retval EFI_OUT_OF_RESOURCES a memory allocation failed.
462 @retval EFI_SUCCESS the section was found and its description sotred in
467 ManFileFindTitleSection(
468 IN SHELL_FILE_HANDLE Handle
,
469 IN CONST CHAR16
*Command
,
470 OUT CHAR16
**BriefDesc OPTIONAL
,
471 OUT UINTN
*BriefSize OPTIONAL
,
472 IN OUT BOOLEAN
*Ascii
486 || (BriefDesc
!= NULL
&& BriefSize
== NULL
)
488 return (EFI_INVALID_PARAMETER
);
491 Status
= EFI_SUCCESS
;
495 ReadLine
= AllocateZeroPool(Size
);
496 if (ReadLine
== NULL
) {
497 return (EFI_OUT_OF_RESOURCES
);
500 TitleSize
= (4*sizeof(CHAR16
)) + StrSize(Command
);
501 TitleString
= AllocateZeroPool(TitleSize
);
502 if (TitleString
== NULL
) {
504 return (EFI_OUT_OF_RESOURCES
);
506 StrCpyS(TitleString
, TitleSize
/sizeof(CHAR16
), L
".TH ");
507 StrCatS(TitleString
, TitleSize
/sizeof(CHAR16
), Command
);
509 TitleLen
= StrLen(TitleString
);
510 for (;!ShellFileHandleEof(Handle
);Size
= 1024) {
511 Status
= ShellFileHandleReadLine(Handle
, ReadLine
, &Size
, TRUE
, Ascii
);
512 if (ReadLine
[0] == L
'#') {
514 // Skip comment lines
519 // ignore too small of buffer...
521 if (Status
== EFI_BUFFER_TOO_SMALL
) {
522 Status
= EFI_SUCCESS
;
524 if (EFI_ERROR(Status
)) {
527 if (StrnCmp(ReadLine
, TitleString
, TitleLen
) == 0) {
530 // we found it so copy out the rest of the line into BriefDesc
531 // After skipping any spaces or zeroes
533 for ( TitleEnd
= ReadLine
+TitleLen
534 ; *TitleEnd
== L
' ' || *TitleEnd
== L
'0' || *TitleEnd
== L
'1'
536 if (BriefDesc
!= NULL
) {
537 *BriefSize
= StrSize(TitleEnd
);
538 *BriefDesc
= AllocateZeroPool(*BriefSize
);
539 if (*BriefDesc
== NULL
) {
540 Status
= EFI_OUT_OF_RESOURCES
;
543 StrCpyS(*BriefDesc
, (*BriefSize
)/sizeof(CHAR16
), TitleEnd
);
549 FreePool(TitleString
);
550 if (!Found
&& !EFI_ERROR(Status
)) {
551 return (EFI_NOT_FOUND
);
557 This function returns the help information for the specified command. The help text
558 will be parsed from a UEFI Shell manual page. (see UEFI Shell 2.0 Appendix B)
560 If Sections is specified, then each section name listed will be compared in a casesensitive
561 manner, to the section names described in Appendix B. If the section exists,
562 it will be appended to the returned help text. If the section does not exist, no
563 information will be returned. If Sections is NULL, then all help text information
564 available will be returned.
566 if BriefDesc is NULL, then the breif description will not be savedd seperatly,
567 but placed first in the main HelpText.
569 @param[in] ManFileName Points to the NULL-terminated UEFI Shell MAN file name.
570 @param[in] Command Points to the NULL-terminated UEFI Shell command name.
571 @param[in] Sections Points to the NULL-terminated comma-delimited
572 section names to return. If NULL, then all
573 sections will be returned.
574 @param[out] BriefDesc On return, points to a callee-allocated buffer
575 containing brief description text.
576 @param[out] HelpText On return, points to a callee-allocated buffer
577 containing all specified help text.
579 @retval EFI_SUCCESS The help text was returned.
580 @retval EFI_OUT_OF_RESOURCES The necessary buffer could not be allocated to hold the
582 @retval EFI_INVALID_PARAMETER HelpText is NULL.
583 @retval EFI_INVALID_PARAMETER ManFileName is invalid.
584 @retval EFI_NOT_FOUND There is no help text available for Command.
589 IN CONST CHAR16
*ManFileName
,
590 IN CONST CHAR16
*Command
,
591 IN CONST CHAR16
*Sections OPTIONAL
,
592 OUT CHAR16
**BriefDesc OPTIONAL
,
593 OUT CHAR16
**HelpText
597 SHELL_FILE_HANDLE FileHandle
;
603 EFI_DEVICE_PATH_PROTOCOL
*FileDevPath
;
604 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
606 if ( ManFileName
== NULL
610 return (EFI_INVALID_PARAMETER
);
618 // See if it's in HII first
620 TempString
= ShellCommandGetCommandHelp(Command
);
621 if (TempString
!= NULL
) {
622 TempString2
= TempString
;
623 Status
= ManBufferFindTitleSection(&TempString2
, Command
, BriefDesc
, &BriefSize
);
624 if (!EFI_ERROR(Status
) && HelpText
!= NULL
){
625 Status
= ManBufferFindSections(TempString2
, Sections
, HelpText
, &HelpSize
);
629 TempString
= GetManFileName(ManFileName
);
630 if (TempString
== NULL
) {
631 return (EFI_INVALID_PARAMETER
);
634 Status
= SearchPathForFile(TempString
, &FileHandle
);
635 if (EFI_ERROR(Status
)) {
636 FileDevPath
= FileDevicePath(NULL
, TempString
);
637 DevPath
= AppendDevicePath (ShellInfoObject
.ImageDevPath
, FileDevPath
);
638 Status
= InternalOpenFileDevicePath(DevPath
, &FileHandle
, EFI_FILE_MODE_READ
, 0);
639 FreePool(FileDevPath
);
643 if (!EFI_ERROR(Status
)) {
646 Status
= ManFileFindTitleSection(FileHandle
, Command
, BriefDesc
, &BriefSize
, &Ascii
);
647 if (!EFI_ERROR(Status
) && HelpText
!= NULL
){
648 Status
= ManFileFindSections(FileHandle
, Sections
, HelpText
, &HelpSize
, Ascii
);
650 ShellInfoObject
.NewEfiShellProtocol
->CloseFile(FileHandle
);
655 if (TempString
!= NULL
) {
656 FreePool(TempString
);