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