--- /dev/null
+/** @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