]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.c
add Edit and HexEdit commands.
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / HexEdit / FileImage.c
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.c b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.c
new file mode 100644 (file)
index 0000000..adf7928
--- /dev/null
@@ -0,0 +1,504 @@
+/** @file\r
+  Functions to deal with file buffer.\r
+\r
+  Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "HexEditor.h"\r
+\r
+extern EFI_HANDLE                 HImageHandleBackup;\r
+extern HEFI_EDITOR_BUFFER_IMAGE   HBufferImage;\r
+\r
+extern BOOLEAN                    HBufferImageNeedRefresh;\r
+extern BOOLEAN                    HBufferImageOnlyLineNeedRefresh;\r
+extern BOOLEAN                    HBufferImageMouseNeedRefresh;\r
+\r
+extern HEFI_EDITOR_GLOBAL_EDITOR  HMainEditor;\r
+\r
+HEFI_EDITOR_FILE_IMAGE            HFileImage;\r
+HEFI_EDITOR_FILE_IMAGE            HFileImageBackupVar;\r
+\r
+//\r
+// for basic initialization of HFileImage\r
+//\r
+HEFI_EDITOR_BUFFER_IMAGE          HFileImageConst = {\r
+  NULL,\r
+  0,\r
+  FALSE\r
+};\r
+\r
+EFI_STATUS\r
+HFileImageInit (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+  Initialization function for HFileImage\r
+\r
+Arguments:  \r
+\r
+  None\r
+\r
+Returns:  \r
+\r
+  EFI_SUCCESS\r
+  EFI_LOAD_ERROR\r
+\r
+--*/\r
+{\r
+  //\r
+  // basically initialize the HFileImage\r
+  //\r
+  CopyMem (&HFileImage, &HFileImageConst, sizeof (HFileImage));\r
+\r
+  CopyMem (\r
+    &HFileImageBackupVar,\r
+    &HFileImageConst,\r
+    sizeof (HFileImageBackupVar)\r
+    );\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HFileImageBackup (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+  Backup function for HFileImage\r
+  Only a few fields need to be backup. \r
+  This is for making the file buffer refresh \r
+  as few as possible.\r
+\r
+Arguments:  \r
+\r
+  None\r
+\r
+Returns:  \r
+\r
+  EFI_SUCCESS\r
+  EFI_OUT_OF_RESOURCES\r
+\r
+--*/\r
+{\r
+  SHELL_FREE_NON_NULL (HFileImageBackupVar.FileName);\r
+  HFileImageBackupVar.FileName = CatSPrint(NULL, L"%s", HFileImage.FileName);\r
+  if (HFileImageBackupVar.FileName == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HFileImageCleanup (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+  Cleanup function for HFileImage\r
+\r
+Arguments:  \r
+\r
+  None\r
+\r
+Returns:  \r
+\r
+  EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+\r
+  SHELL_FREE_NON_NULL (HFileImage.FileName);\r
+  SHELL_FREE_NON_NULL (HFileImageBackupVar.FileName);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HFileImageSetFileName (\r
+  IN CONST CHAR16 *Str\r
+  )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+  Set FileName field in HFileImage\r
+\r
+Arguments:  \r
+\r
+  Str -- File name to set\r
+\r
+Returns:  \r
+\r
+  EFI_SUCCESS\r
+  EFI_OUT_OF_RESOURCES\r
+\r
+--*/\r
+{\r
+  UINTN Size;\r
+  UINTN Index;\r
+\r
+  //\r
+  // free the old file name\r
+  //\r
+  SHELL_FREE_NON_NULL (HFileImage.FileName);\r
+\r
+  Size                = StrLen (Str);\r
+\r
+  HFileImage.FileName = AllocateZeroPool (2 * (Size + 1));\r
+  if (HFileImage.FileName == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  for (Index = 0; Index < Size; Index++) {\r
+    HFileImage.FileName[Index] = Str[Index];\r
+  }\r
+\r
+  HFileImage.FileName[Size] = L'\0';\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HFileImageGetFileInfo (\r
+  IN  EFI_FILE_HANDLE Handle,\r
+  IN  CHAR16          *FileName,\r
+  OUT EFI_FILE_INFO   **InfoOut\r
+  )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+  Get this file's information\r
+\r
+Arguments:  \r
+\r
+  Handle   - in NT32 mode Directory handle, in other mode File Handle\r
+  FileName - The file name\r
+  InfoOut  - parameter to pass file information out\r
+\r
+Returns:  \r
+\r
+  EFI_SUCCESS\r
+  EFI_OUT_OF_RESOURCES\r
+  EFI_LOAD_ERROR\r
+\r
+--*/\r
+{\r
+\r
+  VOID        *Info;\r
+  UINTN       Size;\r
+  EFI_STATUS  Status;\r
+\r
+  Size  = SIZE_OF_EFI_FILE_INFO + 1024;\r
+  Info  = AllocateZeroPool (Size);\r
+  if (!Info) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  //\r
+  // get file information\r
+  //\r
+  Status = Handle->GetInfo (Handle, &gEfiFileInfoGuid, &Size, Info);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_LOAD_ERROR;\r
+  }\r
+\r
+  *InfoOut = (EFI_FILE_INFO *) Info;\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+HFileImageRead (\r
+  IN CONST CHAR16  *FileName,\r
+  IN BOOLEAN Recover\r
+  )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+  Read a file from disk into HBufferImage\r
+\r
+Arguments:  \r
+\r
+  FileName -- filename to read\r
+  Recover -- if is for recover, no information print\r
+\r
+Returns:  \r
+\r
+  EFI_SUCCESS\r
+  EFI_LOAD_ERROR\r
+  EFI_OUT_OF_RESOURCES\r
+  \r
+--*/\r
+{\r
+  HEFI_EDITOR_LINE                *Line;\r
+  UINT8                           *Buffer;\r
+  CHAR16                          *UnicodeBuffer;\r
+  EFI_STATUS                      Status;\r
+\r
+  //\r
+  // variable initialization\r
+  //\r
+  Line                    = NULL;\r
+\r
+  //\r
+  // in this function, when you return error ( except EFI_OUT_OF_RESOURCES )\r
+  // you should set status string\r
+  // since this function maybe called before the editorhandleinput loop\r
+  // so any error will cause editor return\r
+  // so if you want to print the error status\r
+  // you should set the status string\r
+  //\r
+  Status = ReadFileIntoBuffer (FileName, (VOID**)&Buffer, &HFileImage.Size, &HFileImage.ReadOnly);\r
+  if (EFI_ERROR(Status)) {\r
+    UnicodeBuffer = CatSPrint(NULL, L"Read error on file &s: %r", FileName, Status);\r
+    if (UnicodeBuffer == NULL) {\r
+      SHELL_FREE_NON_NULL(Buffer);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    StatusBarSetStatusString (UnicodeBuffer);\r
+    FreePool (UnicodeBuffer);\r
+  }\r
+\r
+  HFileImageSetFileName (FileName);\r
+\r
+  //\r
+  // free the old lines\r
+  //\r
+  HBufferImageFree ();\r
+\r
+  Status = HBufferImageBufferToList (Buffer, HFileImage.Size);\r
+  SHELL_FREE_NON_NULL (Buffer);\r
+  if (EFI_ERROR (Status)) {\r
+    StatusBarSetStatusString (L"Error parsing file.");\r
+    return Status;\r
+  }\r
+\r
+  HBufferImage.DisplayPosition.Row    = 2;\r
+  HBufferImage.DisplayPosition.Column = 10;\r
+  HBufferImage.MousePosition.Row      = 2;\r
+  HBufferImage.MousePosition.Column   = 10;\r
+  HBufferImage.LowVisibleRow          = 1;\r
+  HBufferImage.HighBits               = TRUE;\r
+  HBufferImage.BufferPosition.Row     = 1;\r
+  HBufferImage.BufferPosition.Column  = 1;\r
+\r
+  if (!Recover) {\r
+    UnicodeBuffer = CatSPrint(NULL, L"%d Lines Read", HBufferImage.NumLines);\r
+    if (UnicodeBuffer == NULL) {\r
+      SHELL_FREE_NON_NULL(Buffer);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    StatusBarSetStatusString (UnicodeBuffer);\r
+    FreePool (UnicodeBuffer);\r
+\r
+    HMainEditor.SelectStart = 0;\r
+    HMainEditor.SelectEnd   = 0;\r
+  }\r
+\r
+  //\r
+  // has line\r
+  //\r
+  if (HBufferImage.Lines != 0) {\r
+    HBufferImage.CurrentLine = CR (HBufferImage.ListHead->ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
+  } else {\r
+    //\r
+    // create a dummy line\r
+    //\r
+    Line = HBufferImageCreateLine ();\r
+    if (Line == NULL) {\r
+      SHELL_FREE_NON_NULL(Buffer);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    HBufferImage.CurrentLine = Line;\r
+  }\r
+\r
+  HBufferImage.Modified           = FALSE;\r
+  HBufferImageNeedRefresh         = TRUE;\r
+  HBufferImageOnlyLineNeedRefresh = FALSE;\r
+  HBufferImageMouseNeedRefresh    = TRUE;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HFileImageSave (\r
+  IN CHAR16 *FileName\r
+  )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+  Save lines in HBufferImage to disk\r
+\r
+Arguments:  \r
+\r
+  FileName - The file name\r
+\r
+Returns:  \r
+\r
+  EFI_SUCCESS\r
+  EFI_LOAD_ERROR\r
+  EFI_OUT_OF_RESOURCES\r
+\r
+--*/\r
+{\r
+\r
+  LIST_ENTRY                      *Link;\r
+  HEFI_EDITOR_LINE                *Line;\r
+  CHAR16                          *Str;\r
+  EFI_STATUS                      Status;\r
+  UINTN                           NumLines;\r
+  SHELL_FILE_HANDLE                 FileHandle;\r
+  UINTN                           TotalSize;\r
+  UINT8                           *Buffer;\r
+  UINT8                           *Ptr;\r
+  EDIT_FILE_TYPE                  BufferTypeBackup;\r
+\r
+  BufferTypeBackup        = HBufferImage.BufferType;\r
+  HBufferImage.BufferType = FileTypeFileBuffer;\r
+\r
+  //\r
+  // if is the old file\r
+  //\r
+  if (StrCmp (FileName, HFileImage.FileName) == 0) {\r
+    //\r
+    // check whether file exists on disk\r
+    //\r
+    if (ShellIsFile(FileName) == EFI_SUCCESS) {\r
+      //\r
+      // current file exists on disk\r
+      // so if not modified, then not save\r
+      //\r
+      if (HBufferImage.Modified == FALSE) {\r
+        return EFI_SUCCESS;\r
+      }\r
+      //\r
+      // if file is read-only, set error\r
+      //\r
+      if (HFileImage.ReadOnly == TRUE) {\r
+        StatusBarSetStatusString (L"Read Only File Can Not Be Saved");\r
+        return EFI_SUCCESS;\r
+      }\r
+    }\r
+  }\r
+\r
+   if (ShellIsDirectory(FileName) == EFI_SUCCESS) {\r
+    StatusBarSetStatusString (L"Directory Can Not Be Saved");\r
+    return EFI_LOAD_ERROR;\r
+  }\r
+\r
+  Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0);\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // the file exits, delete it\r
+    //\r
+    Status = ShellDeleteFile (&FileHandle);\r
+    if (EFI_ERROR (Status) || Status == EFI_WARN_DELETE_FAILURE) {\r
+      StatusBarSetStatusString (L"Write File Failed");\r
+      return EFI_LOAD_ERROR;\r
+    }\r
+ }\r
+\r
+  //\r
+  // write all the lines back to disk\r
+  //\r
+  NumLines  = 0;\r
+  TotalSize = 0;\r
+  for (Link = HBufferImage.ListHead->ForwardLink; Link != HBufferImage.ListHead; Link = Link->ForwardLink) {\r
+    Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
+\r
+    if (Line->Size != 0) {\r
+      TotalSize += Line->Size;\r
+    }\r
+    //\r
+    // end of if Line -> Size != 0\r
+    //\r
+    NumLines++;\r
+  }\r
+  //\r
+  // end of for Link\r
+  //\r
+  Buffer = AllocateZeroPool (TotalSize);\r
+  if (Buffer == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Ptr = Buffer;\r
+  for (Link = HBufferImage.ListHead->ForwardLink; Link != HBufferImage.ListHead; Link = Link->ForwardLink) {\r
+    Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
+\r
+    if (Line->Size != 0) {\r
+      CopyMem (Ptr, Line->Buffer, Line->Size);\r
+      Ptr += Line->Size;\r
+    }\r
+    //\r
+    // end of if Line -> Size != 0\r
+    //\r
+  }\r
+\r
+\r
+  Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    StatusBarSetStatusString (L"Create File Failed");\r
+    return EFI_LOAD_ERROR;\r
+  }\r
+\r
+  Status = ShellWriteFile (FileHandle, &TotalSize, Buffer);\r
+  FreePool (Buffer);\r
+  if (EFI_ERROR (Status)) {\r
+    ShellDeleteFile (&FileHandle);\r
+    return EFI_LOAD_ERROR;\r
+  }\r
+\r
+  ShellCloseFile(&FileHandle);\r
+\r
+  HBufferImage.Modified = FALSE;\r
+\r
+  //\r
+  // set status string\r
+  //\r
+  Str = CatSPrint(NULL, L"%d Lines Wrote", NumLines);\r
+  StatusBarSetStatusString (Str);\r
+  FreePool (Str);\r
+\r
+  //\r
+  // now everything is ready , you can set the new file name to filebuffer\r
+  //\r
+  if (BufferTypeBackup != FileTypeFileBuffer || StringNoCaseCompare (&FileName, &HFileImage.FileName) != 0) {\r
+    //\r
+    // not the same\r
+    //\r
+    HFileImageSetFileName (FileName);\r
+    if (HFileImage.FileName == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+  }\r
+\r
+  HFileImage.ReadOnly = FALSE;\r
+\r
+  return EFI_SUCCESS;\r
+}\r