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