]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Application/Shell/ShellManParser.c
NetworkPkg:Fix a bug the 2nd httpboot fail issue.
[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 default:
568 break;
569 }
570
571 } while (State < Final);
572
573 *Found = ReturnFound;
574 return ReturnValue;
575 }
576
577 /**
578 parses through the MAN file specified by SHELL_FILE_HANDLE and returns the
579 "Brief Description" for the .TH section as specified by Command. If the
580 command section is not found return EFI_NOT_FOUND.
581
582 Upon a sucessful return the caller is responsible to free the memory in *BriefDesc
583
584 @param[in] Handle FileHandle to read from
585 @param[in] Command name of command's section to find as entered on the
586 command line (may be a relative or absolute path or
587 be in any case: upper, lower, or mixed in numerous ways!).
588 @param[out] BriefDesc pointer to pointer to string where description goes.
589 @param[out] BriefSize pointer to size of allocated BriefDesc
590 @param[in, out] Ascii TRUE if the file is ASCII, FALSE otherwise, will be
591 set if the file handle is at the 0 position.
592
593 @retval EFI_OUT_OF_RESOURCES a memory allocation failed.
594 @retval EFI_SUCCESS the section was found and its description stored in
595 an allocated buffer if requested.
596 **/
597 EFI_STATUS
598 EFIAPI
599 ManFileFindTitleSection(
600 IN SHELL_FILE_HANDLE Handle,
601 IN CONST CHAR16 *Command,
602 OUT CHAR16 **BriefDesc OPTIONAL,
603 OUT UINTN *BriefSize OPTIONAL,
604 IN OUT BOOLEAN *Ascii
605 )
606 {
607 EFI_STATUS Status;
608 CHAR16 *ReadLine;
609 UINTN Size;
610 BOOLEAN Found;
611 UINTN Start;
612
613 if ( Handle == NULL
614 || Command == NULL
615 || (BriefDesc != NULL && BriefSize == NULL)
616 ){
617 return (EFI_INVALID_PARAMETER);
618 }
619
620 Status = EFI_SUCCESS;
621 Size = 1024;
622 Found = FALSE;
623
624 ReadLine = AllocateZeroPool(Size);
625 if (ReadLine == NULL) {
626 return (EFI_OUT_OF_RESOURCES);
627 }
628
629 //
630 // Do not pass any leading path information that may be present to IsTitleHeader().
631 //
632 Start = StrLen(Command);
633 while (Start
634 && (*(Command + Start - 1) != L'\\')
635 && (*(Command + Start - 1) != L'/')
636 && (*(Command + Start - 1) != L':')) {
637 --Start;
638 }
639
640 for (;!ShellFileHandleEof(Handle);Size = 1024) {
641 Status = ShellFileHandleReadLine(Handle, ReadLine, &Size, TRUE, Ascii);
642 //
643 // ignore too small of buffer...
644 //
645 if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {
646 break;
647 }
648
649 Status = EFI_NOT_FOUND;
650 if (IsTitleHeader (Command+Start, ReadLine, BriefDesc, BriefSize, &Found)) {
651 Status = Found ? EFI_SUCCESS : EFI_NOT_FOUND;
652 break;
653 }
654 }
655
656 FreePool(ReadLine);
657 return (Status);
658 }
659
660 /**
661 This function returns the help information for the specified command. The help text
662 will be parsed from a UEFI Shell manual page. (see UEFI Shell 2.0 Appendix B)
663
664 If Sections is specified, then each section name listed will be compared in a casesensitive
665 manner, to the section names described in Appendix B. If the section exists,
666 it will be appended to the returned help text. If the section does not exist, no
667 information will be returned. If Sections is NULL, then all help text information
668 available will be returned.
669
670 if BriefDesc is NULL, then the breif description will not be savedd seperatly,
671 but placed first in the main HelpText.
672
673 @param[in] ManFileName Points to the NULL-terminated UEFI Shell MAN file name.
674 @param[in] Command Points to the NULL-terminated UEFI Shell command name.
675 @param[in] Sections Points to the NULL-terminated comma-delimited
676 section names to return. If NULL, then all
677 sections will be returned.
678 @param[out] BriefDesc On return, points to a callee-allocated buffer
679 containing brief description text.
680 @param[out] HelpText On return, points to a callee-allocated buffer
681 containing all specified help text.
682
683 @retval EFI_SUCCESS The help text was returned.
684 @retval EFI_OUT_OF_RESOURCES The necessary buffer could not be allocated to hold the
685 returned help text.
686 @retval EFI_INVALID_PARAMETER HelpText is NULL.
687 @retval EFI_INVALID_PARAMETER ManFileName is invalid.
688 @retval EFI_NOT_FOUND There is no help text available for Command.
689 **/
690 EFI_STATUS
691 EFIAPI
692 ProcessManFile(
693 IN CONST CHAR16 *ManFileName,
694 IN CONST CHAR16 *Command,
695 IN CONST CHAR16 *Sections OPTIONAL,
696 OUT CHAR16 **BriefDesc OPTIONAL,
697 OUT CHAR16 **HelpText
698 )
699 {
700 CHAR16 *TempString;
701 SHELL_FILE_HANDLE FileHandle;
702 EFI_STATUS Status;
703 UINTN HelpSize;
704 UINTN BriefSize;
705 BOOLEAN Ascii;
706 CHAR16 *TempString2;
707 EFI_DEVICE_PATH_PROTOCOL *FileDevPath;
708 EFI_DEVICE_PATH_PROTOCOL *DevPath;
709
710 if ( ManFileName == NULL
711 || Command == NULL
712 || HelpText == NULL
713 ){
714 return (EFI_INVALID_PARAMETER);
715 }
716
717 HelpSize = 0;
718 BriefSize = 0;
719 TempString = NULL;
720 Ascii = FALSE;
721 //
722 // See if it's in HII first
723 //
724 TempString = ShellCommandGetCommandHelp(Command);
725 if (TempString != NULL) {
726 TempString2 = TempString;
727 Status = ManBufferFindTitleSection(&TempString2, Command, BriefDesc, &BriefSize);
728 if (!EFI_ERROR(Status) && HelpText != NULL){
729 Status = ManBufferFindSections(TempString2, Sections, HelpText, &HelpSize);
730 }
731 } else {
732 FileHandle = NULL;
733 TempString = GetManFileName(ManFileName);
734 if (TempString == NULL) {
735 return (EFI_INVALID_PARAMETER);
736 }
737
738 Status = SearchPathForFile(TempString, &FileHandle);
739 if (EFI_ERROR(Status)) {
740 FileDevPath = FileDevicePath(NULL, TempString);
741 DevPath = AppendDevicePath (ShellInfoObject.ImageDevPath, FileDevPath);
742 Status = InternalOpenFileDevicePath(DevPath, &FileHandle, EFI_FILE_MODE_READ, 0);
743 FreePool(FileDevPath);
744 FreePool(DevPath);
745 }
746
747 if (!EFI_ERROR(Status)) {
748 HelpSize = 0;
749 BriefSize = 0;
750 Status = ManFileFindTitleSection(FileHandle, Command, BriefDesc, &BriefSize, &Ascii);
751 if (!EFI_ERROR(Status) && HelpText != NULL){
752 Status = ManFileFindSections(FileHandle, Sections, HelpText, &HelpSize, Ascii);
753 }
754 ShellInfoObject.NewEfiShellProtocol->CloseFile(FileHandle);
755 } else {
756 *HelpText = NULL;
757 }
758 }
759 if (TempString != NULL) {
760 FreePool(TempString);
761 }
762
763 return (Status);
764 }