/** parses through the MAN file specified by SHELL_FILE_HANDLE and returns the detailed help for any sub section specified in the comma seperated list of sections provided. If the end of the file or a .TH section is found then return. Upon a sucessful return the caller is responsible to free the memory in *HelpText @param[in] Handle FileHandle to read from @param[in] Sections name of command's sub sections to find @param[out] HelpText pointer to pointer to string where text goes. @param[out] HelpSize pointer to size of allocated HelpText (may be updated) @param[in] Ascii TRUE if the file is ASCII, FALSE otherwise. @retval EFI_OUT_OF_RESOURCES a memory allocation failed. @retval EFI_SUCCESS the section was found and its description sotred in an alloceted buffer. **/ EFI_STATUS EFIAPI ManFileFindSections( IN SHELL_FILE_HANDLE Handle, IN CONST CHAR16 *Sections, OUT CHAR16 **HelpText, OUT UINTN *HelpSize, IN BOOLEAN Ascii ) { EFI_STATUS Status; CHAR16 *ReadLine; UINTN Size; BOOLEAN CurrentlyReading; CHAR16 *SectionName; UINTN SectionLen; BOOLEAN Found; if ( Handle == NULL || HelpText == NULL || HelpSize == NULL ){ return (EFI_INVALID_PARAMETER); } Status = EFI_SUCCESS; CurrentlyReading = FALSE; Size = 1024; Found = FALSE; ReadLine = AllocateZeroPool(Size); if (ReadLine == NULL) { return (EFI_OUT_OF_RESOURCES); } for (;!ShellFileHandleEof(Handle);Size = 1024) { Status = ShellFileHandleReadLine(Handle, ReadLine, &Size, TRUE, &Ascii); if (ReadLine[0] == L'#') { // // Skip comment lines // continue; } // // ignore too small of buffer... // if (Status == EFI_BUFFER_TOO_SMALL) { Status = EFI_SUCCESS; } if (EFI_ERROR(Status)) { break; } else if (StrnCmp(ReadLine, L".TH", 3) == 0) { // // we hit the end of this commands section so stop. // break; } else if (StrnCmp(ReadLine, L".SH", 3) == 0) { if (Sections == NULL) { CurrentlyReading = TRUE; continue; } // // we found a section // if (CurrentlyReading) { CurrentlyReading = FALSE; } // // is this a section we want to read in? // for ( SectionName = ReadLine + 3 ; *SectionName == L' ' ; SectionName++); SectionLen = StrLen(SectionName); SectionName = StrStr(Sections, SectionName); if (SectionName == NULL) { continue; } if (*(SectionName + SectionLen) == CHAR_NULL || *(SectionName + SectionLen) == L',') { CurrentlyReading = TRUE; } } else if (CurrentlyReading) { Found = TRUE; // // copy and save the current line. // ASSERT((*HelpText == NULL && *HelpSize == 0) || (*HelpText != NULL)); StrnCatGrow (HelpText, HelpSize, ReadLine, 0); StrnCatGrow (HelpText, HelpSize, L"\r\n", 0); } } FreePool(ReadLine); if (!Found && !EFI_ERROR(Status)) { return (EFI_NOT_FOUND); } return (Status); }
/** Do the actual parsing of the file. the file should be SFO output from a shell command or a similar format. @param[in] FileName The filename to open. @param[in] TableName The name of the table to find. @param[in] ColumnIndex The column number to get. @param[in] TableNameInstance Which instance of the table to get (row). @param[in] ShellCommandInstance Which instance of the command to get. @retval SHELL_NOT_FOUND The requested instance was not found. @retval SHELL_SUCCESS The operation was successful. **/ SHELL_STATUS EFIAPI PerformParsing( IN CONST CHAR16 *FileName, IN CONST CHAR16 *TableName, IN CONST UINTN ColumnIndex, IN CONST UINTN TableNameInstance, IN CONST UINTN ShellCommandInstance ) { SHELL_FILE_HANDLE FileHandle; EFI_STATUS Status; BOOLEAN Ascii; UINTN LoopVariable; UINTN ColumnLoop; CHAR16 *TempLine; CHAR16 *ColumnPointer; SHELL_STATUS ShellStatus; CHAR16 *TempSpot; ASSERT(FileName != NULL); ASSERT(TableName != NULL); ShellStatus = SHELL_SUCCESS; Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_READ, 0); if (EFI_ERROR(Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel2HiiHandle, FileName); ShellStatus = SHELL_NOT_FOUND; } else if (!EFI_ERROR (FileHandleIsDirectory (FileHandle))) { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_FILE), gShellLevel2HiiHandle, FileName); ShellStatus = SHELL_NOT_FOUND; } else { for (LoopVariable = 0 ; LoopVariable < ShellCommandInstance && !ShellFileHandleEof(FileHandle);) { TempLine = ShellFileHandleReturnLine(FileHandle, &Ascii); if (TempLine == NULL) { break; } // // Search for "ShellCommand," in the file to start the SFO table // for a given ShellCommand. The UEFI Shell spec does not specify // a space after the comma. // if (StrStr (TempLine, L"ShellCommand,") == TempLine) { LoopVariable++; } SHELL_FREE_NON_NULL(TempLine); } if (LoopVariable == ShellCommandInstance) { LoopVariable = 0; while(1) { TempLine = ShellFileHandleReturnLine(FileHandle, &Ascii); if (TempLine == NULL || *TempLine == CHAR_NULL || StrStr (TempLine, L"ShellCommand,") == TempLine) { SHELL_FREE_NON_NULL(TempLine); break; } if (StrStr (TempLine, TableName) == TempLine) { LoopVariable++; if (LoopVariable == TableNameInstance || (TableNameInstance == (UINTN)-1)) { for (ColumnLoop = 1, ColumnPointer = TempLine; ColumnLoop < ColumnIndex && ColumnPointer != NULL && *ColumnPointer != CHAR_NULL; ColumnLoop++) { ColumnPointer = StrStr (ColumnPointer, L",\""); if (ColumnPointer != NULL && *ColumnPointer != CHAR_NULL){ ColumnPointer++; } } if (ColumnLoop == ColumnIndex) { if (ColumnPointer == NULL) { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellLevel2HiiHandle, L"Column Index"); ShellStatus = SHELL_INVALID_PARAMETER; } else { TempSpot = StrStr (ColumnPointer, L",\""); if (TempSpot != NULL) { *TempSpot = CHAR_NULL; } while (ColumnPointer != NULL && *ColumnPointer != CHAR_NULL && ColumnPointer[0] == L' '){ ColumnPointer++; } if (ColumnPointer != NULL && *ColumnPointer != CHAR_NULL && ColumnPointer[0] == L'\"'){ ColumnPointer++; } if (ColumnPointer != NULL && *ColumnPointer != CHAR_NULL && ColumnPointer[StrLen (ColumnPointer) - 1] == L'\"'){ ColumnPointer[StrLen (ColumnPointer) - 1] = CHAR_NULL; } ShellPrintEx (-1, -1, L"%s\r\n", ColumnPointer); } } } } SHELL_FREE_NON_NULL(TempLine); } } } return (ShellStatus); }