]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ShellPkg/help: Fix "-?" may not show manual sometimes
authorRuiyu Ni <ruiyu.ni@intel.com>
Sun, 11 Feb 2018 15:17:22 +0000 (23:17 +0800)
committerRuiyu Ni <ruiyu.ni@intel.com>
Tue, 13 Feb 2018 02:54:44 +0000 (10:54 +0800)
Shell core was enhanced to find the manual string in PE resource
section. But the finding algorithm is too strict: If the manual is
written beginning with:
.TH command 0 "descripton of command"

but user types "COMMAND.efi -?". The finding algorithm uses
case-sensitive compare between "command" and "COMMAND" resulting
in the manual cannot be found.

The patch fixes this issue by using existing ManFileFindTitleSection
and ManFileFindSections which compare command case-insensitive.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Reviewed-by: Jaben Carsey <jaben.carsey@intel.com>
ShellPkg/Application/Shell/FileHandleWrappers.c
ShellPkg/Application/Shell/ShellManParser.c

index 0a7a60294dc79d7171d17eb85c2748d45be043c2..63aad69fe89799e038791059d51a07eccbffe4b5 100644 (file)
@@ -3,7 +3,7 @@
   StdIn, StdOut, StdErr, etc...).\r
 \r
   Copyright 2016 Dell Inc.\r
   StdIn, StdOut, StdErr, etc...).\r
 \r
   Copyright 2016 Dell Inc.\r
-  Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
   (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -1554,6 +1554,54 @@ FileInterfaceMemGetPosition(
   return (EFI_SUCCESS);\r
 }\r
 \r
   return (EFI_SUCCESS);\r
 }\r
 \r
+/**\r
+  File style interface for Mem (GetInfo).\r
+\r
+  @param  This            Protocol instance pointer.\r
+  @param  InformationType Type of information to return in Buffer.\r
+  @param  BufferSize      On input size of buffer, on output amount of data in buffer.\r
+  @param  Buffer          The buffer to return data.\r
+\r
+  @retval EFI_SUCCESS          Data was returned.\r
+  @retval EFI_UNSUPPORT        InformationType is not supported.\r
+  @retval EFI_NO_MEDIA         The device has no media.\r
+  @retval EFI_DEVICE_ERROR     The device reported an error.\r
+  @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+  @retval EFI_WRITE_PROTECTED  The device is write protected.\r
+  @retval EFI_ACCESS_DENIED    The file was open for read only.\r
+  @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceMemGetInfo(\r
+  IN EFI_FILE_PROTOCOL        *This,\r
+  IN EFI_GUID                 *InformationType,\r
+  IN OUT UINTN                *BufferSize,\r
+  OUT VOID                    *Buffer\r
+  )\r
+{\r
+  EFI_FILE_INFO               *FileInfo;\r
+\r
+  if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
+    if (*BufferSize < sizeof (EFI_FILE_INFO)) {\r
+      *BufferSize = sizeof (EFI_FILE_INFO);\r
+      return EFI_BUFFER_TOO_SMALL;\r
+    }\r
+    if (Buffer == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    FileInfo = (EFI_FILE_INFO *)Buffer;\r
+    FileInfo->Size = sizeof (*FileInfo);\r
+    ZeroMem (FileInfo, sizeof (*FileInfo));\r
+    FileInfo->FileSize = ((EFI_FILE_PROTOCOL_MEM*)This)->FileSize;\r
+    FileInfo->PhysicalSize = FileInfo->FileSize;\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
 /**\r
   File style interface for Mem (Write).\r
   \r
 /**\r
   File style interface for Mem (Write).\r
   \r
@@ -1689,7 +1737,7 @@ CreateFileInterfaceMem(
   FileInterface->Close       = FileInterfaceMemClose;\r
   FileInterface->GetPosition = FileInterfaceMemGetPosition;\r
   FileInterface->SetPosition = FileInterfaceMemSetPosition;\r
   FileInterface->Close       = FileInterfaceMemClose;\r
   FileInterface->GetPosition = FileInterfaceMemGetPosition;\r
   FileInterface->SetPosition = FileInterfaceMemSetPosition;\r
-  FileInterface->GetInfo     = FileInterfaceNopGetInfo;\r
+  FileInterface->GetInfo     = FileInterfaceMemGetInfo;\r
   FileInterface->SetInfo     = FileInterfaceNopSetInfo;\r
   FileInterface->Flush       = FileInterfaceNopGeneric;\r
   FileInterface->Delete      = FileInterfaceNopGeneric;\r
   FileInterface->SetInfo     = FileInterfaceNopSetInfo;\r
   FileInterface->Flush       = FileInterfaceNopGeneric;\r
   FileInterface->Delete      = FileInterfaceNopGeneric;\r
index 7a290e16f670828a58fc61fe902d1e948d09d0f8..975f3c22da878de77fb3f74ebabf1d3dcd7b40df 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Provides interface to shell MAN file parser.\r
 \r
 /** @file\r
   Provides interface to shell MAN file parser.\r
 \r
-  Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
   Copyright 2015 Dell Inc.\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   Copyright 2015 Dell Inc.\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -205,138 +205,6 @@ SearchPathForFile(
   return (Status);\r
 }\r
 \r
   return (Status);\r
 }\r
 \r
-/**\r
-  parses through Buffer (which is MAN file formatted) and returns the\r
-  detailed help for any sub section specified in the comma seperated list of\r
-  sections provided.  If the end of the file or a .TH section is found then\r
-  return.\r
-\r
-  Upon a sucessful return the caller is responsible to free the memory in *HelpText\r
-\r
-  @param[in] Buffer             Buffer to read from\r
-  @param[in] Sections           name of command's sub sections to find\r
-  @param[in] HelpText           pointer to pointer to string where text goes.\r
-  @param[in] HelpSize           pointer to size of allocated HelpText (may be updated)\r
-\r
-  @retval EFI_OUT_OF_RESOURCES  a memory allocation failed.\r
-  @retval EFI_SUCCESS           the section was found and its description sotred in\r
-                                an alloceted buffer.\r
-**/\r
-EFI_STATUS\r
-ManBufferFindSections(\r
-  IN CONST CHAR16 *Buffer,\r
-  IN CONST CHAR16 *Sections,\r
-  IN CHAR16       **HelpText,\r
-  IN UINTN        *HelpSize\r
-  )\r
-{\r
-  EFI_STATUS          Status;\r
-  CONST CHAR16        *CurrentLocation;\r
-  BOOLEAN             CurrentlyReading;\r
-  CHAR16              *SectionName;\r
-  UINTN               SectionLen;\r
-  BOOLEAN             Found;\r
-  CHAR16              *TempString;\r
-  CHAR16              *TempString2;\r
-\r
-  if ( Buffer     == NULL\r
-    || HelpText   == NULL\r
-    || HelpSize   == NULL\r
-   ){\r
-    return (EFI_INVALID_PARAMETER);\r
-  }\r
-\r
-  Status            = EFI_SUCCESS;\r
-  CurrentlyReading  = FALSE;\r
-  Found             = FALSE;\r
-\r
-  for (CurrentLocation = Buffer,TempString = NULL\r
-    ;  CurrentLocation != NULL && *CurrentLocation != CHAR_NULL\r
-    ;  CurrentLocation=StrStr(CurrentLocation, L"\r\n"),TempString = NULL\r
-   ){\r
-    while(CurrentLocation[0] == L'\r' || CurrentLocation[0] == L'\n') {\r
-      CurrentLocation++;\r
-    }\r
-    if (CurrentLocation[0] == L'#') {\r
-      //\r
-      // Skip comment lines\r
-      //\r
-      continue;\r
-    }\r
-    if (StrnCmp(CurrentLocation, L".TH", 3) == 0) {\r
-      //\r
-      // we hit the end of this commands section so stop.\r
-      //\r
-      break;\r
-    }\r
-    if (StrnCmp(CurrentLocation, L".SH ", 4) == 0) {\r
-      if (Sections == NULL) {\r
-        CurrentlyReading = TRUE;\r
-        continue;\r
-      } else if (CurrentlyReading) {\r
-        CurrentlyReading = FALSE;\r
-      }\r
-      CurrentLocation += 4;\r
-      //\r
-      // is this a section we want to read in?\r
-      //\r
-      if (StrLen(CurrentLocation)!=0) {\r
-        TempString2 = StrStr(CurrentLocation, L" ");\r
-        TempString2 = MIN(TempString2, StrStr(CurrentLocation, L"\r"));\r
-        TempString2 = MIN(TempString2, StrStr(CurrentLocation, L"\n"));\r
-        ASSERT(TempString == NULL);\r
-        TempString = StrnCatGrow(&TempString, NULL, CurrentLocation, TempString2==NULL?0:TempString2 - CurrentLocation);\r
-        if (TempString == NULL) {\r
-          Status = EFI_OUT_OF_RESOURCES;\r
-          break;\r
-        }\r
-        SectionName = TempString;\r
-        SectionLen = StrLen(SectionName);\r
-        SectionName = StrStr(Sections, SectionName);\r
-        if (SectionName == NULL) {\r
-          SHELL_FREE_NON_NULL(TempString);\r
-          continue;\r
-        }\r
-        if (*(SectionName + SectionLen) == CHAR_NULL || *(SectionName + SectionLen) == L',') {\r
-          CurrentlyReading = TRUE;\r
-        }\r
-      }\r
-    } else if (CurrentlyReading) {\r
-      Found = TRUE;\r
-      if (StrLen(CurrentLocation)!=0) {\r
-        TempString2 = StrStr(CurrentLocation, L"\r");\r
-        TempString2 = MIN(TempString2, StrStr(CurrentLocation, L"\n"));\r
-        ASSERT(TempString == NULL);\r
-        TempString = StrnCatGrow(&TempString, NULL, CurrentLocation, TempString2==NULL?0:TempString2 - CurrentLocation);\r
-        if (TempString == NULL) {\r
-          Status = EFI_OUT_OF_RESOURCES;\r
-          break;\r
-        }\r
-        //\r
-        // copy and save the current line.\r
-        //\r
-        ASSERT((*HelpText == NULL && *HelpSize == 0) || (*HelpText != NULL));\r
-        StrnCatGrow (HelpText, HelpSize, TempString, 0);\r
-        if (HelpText == NULL) {\r
-          Status = EFI_OUT_OF_RESOURCES;\r
-          break;\r
-        }\r
-        StrnCatGrow (HelpText, HelpSize, L"\r\n", 0);\r
-        if (HelpText == NULL) {\r
-          Status = EFI_OUT_OF_RESOURCES;\r
-          break;\r
-        }\r
-      }\r
-    }\r
-    SHELL_FREE_NON_NULL(TempString);\r
-  }\r
-  SHELL_FREE_NON_NULL(TempString);\r
-  if (!Found && !EFI_ERROR(Status)) {\r
-    return (EFI_NOT_FOUND);\r
-  }\r
-  return (Status);\r
-}\r
-\r
 /**\r
   parses through the MAN file specified by SHELL_FILE_HANDLE and returns the\r
   detailed help for any sub section specified in the comma seperated list of\r
 /**\r
   parses through the MAN file specified by SHELL_FILE_HANDLE and returns the\r
   detailed help for any sub section specified in the comma seperated list of\r
@@ -452,111 +320,6 @@ ManFileFindSections(
   return (Status);\r
 }\r
 \r
   return (Status);\r
 }\r
 \r
-/**\r
-  parses through the MAN file formatted Buffer and returns the\r
-  "Brief Description" for the .TH section as specified by Command.  If the\r
-  command section is not found return EFI_NOT_FOUND.\r
-\r
-  Upon a sucessful return the caller is responsible to free the memory in *BriefDesc\r
-\r
-  @param[in] Buffer             Buffer to read from\r
-  @param[in] Command            name of command's section to find\r
-  @param[in] BriefDesc          pointer to pointer to string where description goes.\r
-  @param[in] BriefSize          pointer to size of allocated BriefDesc\r
-\r
-  @retval EFI_OUT_OF_RESOURCES  a memory allocation failed.\r
-  @retval EFI_SUCCESS           the section was found and its description sotred in\r
-                                an alloceted buffer.\r
-**/\r
-EFI_STATUS\r
-ManBufferFindTitleSection(\r
-  IN CHAR16         **Buffer,\r
-  IN CONST CHAR16   *Command,\r
-  IN CHAR16         **BriefDesc,\r
-  IN UINTN          *BriefSize\r
-  )\r
-{\r
-  EFI_STATUS    Status;\r
-  CHAR16        *TitleString;\r
-  CHAR16        *TitleEnd;\r
-  CHAR16        *CurrentLocation;\r
-  UINTN         TitleLength;\r
-  UINTN         Start;\r
-  CONST CHAR16  StartString[] = L".TH ";\r
-  CONST CHAR16  EndString[]   = L" 0 ";\r
-\r
-  if ( Buffer     == NULL\r
-    || Command    == NULL\r
-    || (BriefDesc != NULL && BriefSize == NULL)\r
-   ){\r
-    return (EFI_INVALID_PARAMETER);\r
-  }\r
-\r
-  Status    = EFI_SUCCESS;\r
-\r
-  //\r
-  // Do not pass any leading path information that may be present to IsTitleHeader().\r
-  //\r
-  Start = StrLen(Command);\r
-  while ((Start != 0)\r
-         && (*(Command + Start - 1) != L'\\')\r
-         && (*(Command + Start - 1) != L'/')\r
-         && (*(Command + Start - 1) != L':')) {\r
-    --Start;\r
-  }\r
-\r
-  //\r
-  // more characters for StartString and EndString\r
-  //\r
-  TitleLength = StrSize(Command + Start) + (StrLen(StartString) + StrLen(EndString)) * sizeof(CHAR16);\r
-  TitleString = AllocateZeroPool(TitleLength);\r
-  if (TitleString == NULL) {\r
-    return (EFI_OUT_OF_RESOURCES);\r
-  }\r
-  StrCpyS(TitleString, TitleLength/sizeof(CHAR16), StartString);\r
-  StrCatS(TitleString, TitleLength/sizeof(CHAR16), Command + Start);\r
-  StrCatS(TitleString, TitleLength/sizeof(CHAR16), EndString);\r
-\r
-  CurrentLocation = StrStr(*Buffer, TitleString);\r
-  if (CurrentLocation == NULL){\r
-    Status = EFI_NOT_FOUND;\r
-  } else {\r
-    //\r
-    // we found it so copy out the rest of the line into BriefDesc\r
-    // After skipping any spaces or zeroes\r
-    //\r
-    for (CurrentLocation += StrLen(TitleString)\r
-      ;  *CurrentLocation == L' ' || *CurrentLocation == L'0' || *CurrentLocation == L'1' || *CurrentLocation == L'\"'\r
-      ;  CurrentLocation++);\r
-\r
-    TitleEnd = StrStr(CurrentLocation, L"\"");\r
-    if (TitleEnd == NULL) {\r
-      Status = EFI_DEVICE_ERROR;\r
-    } else {\r
-      if (BriefDesc != NULL) {\r
-        *BriefSize = StrSize(TitleEnd);\r
-        *BriefDesc = AllocateZeroPool(*BriefSize);\r
-        if (*BriefDesc == NULL) {\r
-          Status = EFI_OUT_OF_RESOURCES;\r
-        } else {\r
-          StrnCpyS(*BriefDesc, (*BriefSize)/sizeof(CHAR16), CurrentLocation, TitleEnd-CurrentLocation);\r
-        }\r
-      }\r
-\r
-      for (CurrentLocation = TitleEnd\r
-        ;  *CurrentLocation != L'\n'\r
-        ;  CurrentLocation++);\r
-      for (\r
-        ;  *CurrentLocation == L' ' || *CurrentLocation == L'\n' || *CurrentLocation == L'\r'\r
-        ;  CurrentLocation++);\r
-      *Buffer = CurrentLocation;\r
-    }\r
-  }\r
-\r
-  FreePool(TitleString);\r
-  return (Status);\r
-}\r
-\r
 /**\r
   Parses a line from a MAN file to see if it is the Title Header. If it is, then\r
   if the "Brief Description" is desired, allocate a buffer for it and return a\r
 /**\r
   Parses a line from a MAN file to see if it is the Title Header. If it is, then\r
   if the "Brief Description" is desired, allocate a buffer for it and return a\r
@@ -813,10 +576,8 @@ ProcessManFile(
   UINTN             BriefSize;\r
   UINTN             StringIdWalker;\r
   BOOLEAN           Ascii;\r
   UINTN             BriefSize;\r
   UINTN             StringIdWalker;\r
   BOOLEAN           Ascii;\r
-  CHAR16            *TempString2;\r
   CHAR16            *CmdFileName;\r
   CHAR16            *CmdFilePathName;\r
   CHAR16            *CmdFileName;\r
   CHAR16            *CmdFilePathName;\r
-  CHAR16            *StringBuff;\r
   EFI_DEVICE_PATH_PROTOCOL      *FileDevPath;\r
   EFI_DEVICE_PATH_PROTOCOL      *DevPath;\r
   EFI_HII_PACKAGE_LIST_HEADER   *PackageListHeader;\r
   EFI_DEVICE_PATH_PROTOCOL      *FileDevPath;\r
   EFI_DEVICE_PATH_PROTOCOL      *DevPath;\r
   EFI_HII_PACKAGE_LIST_HEADER   *PackageListHeader;\r
@@ -836,7 +597,6 @@ ProcessManFile(
   CmdFileName       = NULL;\r
   CmdFilePathName   = NULL;\r
   CmdFileImgHandle  = NULL;\r
   CmdFileName       = NULL;\r
   CmdFilePathName   = NULL;\r
   CmdFileImgHandle  = NULL;\r
-  StringBuff        = NULL;\r
   PackageListHeader = NULL;\r
   FileDevPath       = NULL;\r
   DevPath           = NULL;\r
   PackageListHeader = NULL;\r
   FileDevPath       = NULL;\r
   DevPath           = NULL;\r
@@ -846,11 +606,17 @@ ProcessManFile(
   //\r
   TempString = ShellCommandGetCommandHelp(Command);\r
   if (TempString != NULL) {\r
   //\r
   TempString = ShellCommandGetCommandHelp(Command);\r
   if (TempString != NULL) {\r
-    TempString2 = TempString;\r
-    Status = ManBufferFindTitleSection(&TempString2, Command, BriefDesc, &BriefSize);\r
+    FileHandle = ConvertEfiFileProtocolToShellHandle (CreateFileInterfaceMem (TRUE), NULL);\r
+    HelpSize = StrLen (TempString) * sizeof (CHAR16);\r
+    ShellWriteFile (FileHandle, &HelpSize, TempString);\r
+    ShellSetFilePosition (FileHandle, 0);\r
+    HelpSize  = 0;\r
+    BriefSize = 0;\r
+    Status = ManFileFindTitleSection(FileHandle, Command, BriefDesc, &BriefSize, &Ascii);\r
     if (!EFI_ERROR(Status) && HelpText != NULL){\r
     if (!EFI_ERROR(Status) && HelpText != NULL){\r
-      Status = ManBufferFindSections(TempString2, Sections, HelpText, &HelpSize);\r
+      Status = ManFileFindSections(FileHandle, Sections, HelpText, &HelpSize, Ascii);\r
     }\r
     }\r
+    ShellCloseFile (&FileHandle);\r
   } else {\r
     //\r
     // If the image is a external app, check .MAN file first.\r
   } else {\r
     //\r
     // If the image is a external app, check .MAN file first.\r
@@ -947,20 +713,26 @@ ProcessManFile(
 \r
     StringIdWalker = 1;\r
     do {\r
 \r
     StringIdWalker = 1;\r
     do {\r
-        SHELL_FREE_NON_NULL(StringBuff);\r
+        SHELL_FREE_NON_NULL(TempString);\r
         if (BriefDesc != NULL) {\r
           SHELL_FREE_NON_NULL(*BriefDesc);\r
         }\r
         if (BriefDesc != NULL) {\r
           SHELL_FREE_NON_NULL(*BriefDesc);\r
         }\r
-        StringBuff = HiiGetString (mShellManHiiHandle, (EFI_STRING_ID)StringIdWalker, NULL);\r
-        if (StringBuff == NULL) {\r
+        TempString = HiiGetString (mShellManHiiHandle, (EFI_STRING_ID)StringIdWalker, NULL);\r
+        if (TempString == NULL) {\r
           Status = EFI_NOT_FOUND;\r
           goto Done;\r
         }\r
           Status = EFI_NOT_FOUND;\r
           goto Done;\r
         }\r
-        TempString2 = StringBuff;\r
-        Status = ManBufferFindTitleSection(&TempString2, Command, BriefDesc, &BriefSize);\r
+        FileHandle = ConvertEfiFileProtocolToShellHandle (CreateFileInterfaceMem (TRUE), NULL);\r
+        HelpSize = StrLen (TempString) * sizeof (CHAR16);\r
+        ShellWriteFile (FileHandle, &HelpSize, TempString);\r
+        ShellSetFilePosition (FileHandle, 0);\r
+        HelpSize  = 0;\r
+        BriefSize = 0;\r
+        Status = ManFileFindTitleSection(FileHandle, Command, BriefDesc, &BriefSize, &Ascii);\r
         if (!EFI_ERROR(Status) && HelpText != NULL){\r
         if (!EFI_ERROR(Status) && HelpText != NULL){\r
-          Status = ManBufferFindSections(TempString2, Sections, HelpText, &HelpSize);\r
+          Status = ManFileFindSections(FileHandle, Sections, HelpText, &HelpSize, Ascii);\r
         }\r
         }\r
+        ShellCloseFile (&FileHandle);\r
         if (!EFI_ERROR(Status)){\r
           //\r
           // Found what we need and return\r
         if (!EFI_ERROR(Status)){\r
           //\r
           // Found what we need and return\r
@@ -969,7 +741,7 @@ ProcessManFile(
         }\r
 \r
         StringIdWalker += 1;\r
         }\r
 \r
         StringIdWalker += 1;\r
-    } while (StringIdWalker < 0xFFFF && StringBuff != NULL);\r
+    } while (StringIdWalker < 0xFFFF && TempString != NULL);\r
 \r
   }\r
 \r
 \r
   }\r
 \r
@@ -992,7 +764,6 @@ Done:
     Status = gBS->UnloadImage (CmdFileImgHandle);\r
   }\r
 \r
     Status = gBS->UnloadImage (CmdFileImgHandle);\r
   }\r
 \r
-  SHELL_FREE_NON_NULL(StringBuff);\r
   SHELL_FREE_NON_NULL(TempString);\r
   SHELL_FREE_NON_NULL(CmdFileName);\r
   SHELL_FREE_NON_NULL(CmdFilePathName);\r
   SHELL_FREE_NON_NULL(TempString);\r
   SHELL_FREE_NON_NULL(CmdFileName);\r
   SHELL_FREE_NON_NULL(CmdFilePathName);\r