Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Qiu Shumin <shumin.qiu@intel.com> Reviewed-by: Jaben Carsey <Jaben.carsey@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16683 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			404 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			404 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Functions to deal with file buffer.
 | |
| 
 | |
|   Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved. <BR>
 | |
|   This program and the accompanying materials
 | |
|   are licensed and made available under the terms and conditions of the BSD License
 | |
|   which accompanies this distribution.  The full text of the license may be found at
 | |
|   http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
|   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
|   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "HexEditor.h"
 | |
| 
 | |
| extern EFI_HANDLE                 HImageHandleBackup;
 | |
| extern HEFI_EDITOR_BUFFER_IMAGE   HBufferImage;
 | |
| 
 | |
| extern BOOLEAN                    HBufferImageNeedRefresh;
 | |
| extern BOOLEAN                    HBufferImageOnlyLineNeedRefresh;
 | |
| extern BOOLEAN                    HBufferImageMouseNeedRefresh;
 | |
| 
 | |
| extern HEFI_EDITOR_GLOBAL_EDITOR  HMainEditor;
 | |
| 
 | |
| HEFI_EDITOR_FILE_IMAGE            HFileImage;
 | |
| HEFI_EDITOR_FILE_IMAGE            HFileImageBackupVar;
 | |
| 
 | |
| //
 | |
| // for basic initialization of HFileImage
 | |
| //
 | |
| HEFI_EDITOR_BUFFER_IMAGE          HFileImageConst = {
 | |
|   NULL,
 | |
|   0,
 | |
|   FALSE
 | |
| };
 | |
| 
 | |
| /**
 | |
|   Initialization function for HFileImage
 | |
|  
 | |
|   @retval EFI_SUCCESS     The operation was successful.
 | |
| **/
 | |
| EFI_STATUS
 | |
| HFileImageInit (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // basically initialize the HFileImage
 | |
|   //
 | |
|   CopyMem (&HFileImage, &HFileImageConst, sizeof (HFileImage));
 | |
| 
 | |
|   CopyMem (
 | |
|     &HFileImageBackupVar,
 | |
|     &HFileImageConst,
 | |
|     sizeof (HFileImageBackupVar)
 | |
|     );
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Backup function for HFileImage. Only a few fields need to be backup. 
 | |
|   This is for making the file buffer refresh as few as possible.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The operation was successful.
 | |
|   @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.
 | |
| **/
 | |
| EFI_STATUS
 | |
| HFileImageBackup (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   SHELL_FREE_NON_NULL (HFileImageBackupVar.FileName);
 | |
|   HFileImageBackupVar.FileName = CatSPrint(NULL, L"%s", HFileImage.FileName);
 | |
|   if (HFileImageBackupVar.FileName == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Cleanup function for HFileImage.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The operation was successful.
 | |
| **/
 | |
| EFI_STATUS
 | |
| HFileImageCleanup (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
| 
 | |
|   SHELL_FREE_NON_NULL (HFileImage.FileName);
 | |
|   SHELL_FREE_NON_NULL (HFileImageBackupVar.FileName);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Set FileName field in HFileImage
 | |
| 
 | |
|   @param[in] Str  File name to set.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The operation was successful.
 | |
|   @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.
 | |
| **/
 | |
| EFI_STATUS
 | |
| HFileImageSetFileName (
 | |
|   IN CONST CHAR16 *Str
 | |
|   )
 | |
| {
 | |
|   UINTN Size;
 | |
|   UINTN Index;
 | |
| 
 | |
|   //
 | |
|   // free the old file name
 | |
|   //
 | |
|   SHELL_FREE_NON_NULL (HFileImage.FileName);
 | |
| 
 | |
|   Size                = StrLen (Str);
 | |
| 
 | |
|   HFileImage.FileName = AllocateZeroPool (2 * (Size + 1));
 | |
|   if (HFileImage.FileName == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   for (Index = 0; Index < Size; Index++) {
 | |
|     HFileImage.FileName[Index] = Str[Index];
 | |
|   }
 | |
| 
 | |
|   HFileImage.FileName[Size] = L'\0';
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Read a file from disk into HBufferImage.
 | |
| 
 | |
|   @param[in] FileName     filename to read.
 | |
|   @param[in] Recover      if is for recover, no information print.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The operation was successful.
 | |
|   @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.
 | |
|   @retval EFI_LOAD_ERROR        A load error occured.
 | |
| **/
 | |
| EFI_STATUS
 | |
| HFileImageRead (
 | |
|   IN CONST CHAR16  *FileName,
 | |
|   IN BOOLEAN Recover
 | |
|   )
 | |
| {
 | |
|   HEFI_EDITOR_LINE                *Line;
 | |
|   UINT8                           *Buffer;
 | |
|   CHAR16                          *UnicodeBuffer;
 | |
|   EFI_STATUS                      Status;
 | |
| 
 | |
|   //
 | |
|   // variable initialization
 | |
|   //
 | |
|   Line                    = NULL;
 | |
| 
 | |
|   //
 | |
|   // in this function, when you return error ( except EFI_OUT_OF_RESOURCES )
 | |
|   // you should set status string
 | |
|   // since this function maybe called before the editorhandleinput loop
 | |
|   // so any error will cause editor return
 | |
|   // so if you want to print the error status
 | |
|   // you should set the status string
 | |
|   //
 | |
|   Status = ReadFileIntoBuffer (FileName, (VOID**)&Buffer, &HFileImage.Size, &HFileImage.ReadOnly);
 | |
|   //
 | |
|   // NULL pointer is only also a failure for a non-zero file size.
 | |
|   //
 | |
|   if ((EFI_ERROR(Status)) || (Buffer == NULL && HFileImage.Size != 0)) {
 | |
|     UnicodeBuffer = CatSPrint(NULL, L"Read error on file %s: %r", FileName, Status);
 | |
|     if (UnicodeBuffer == NULL) {
 | |
|       SHELL_FREE_NON_NULL(Buffer);
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
| 
 | |
|     StatusBarSetStatusString (UnicodeBuffer);
 | |
|     FreePool (UnicodeBuffer);
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   HFileImageSetFileName (FileName);
 | |
| 
 | |
|   //
 | |
|   // free the old lines
 | |
|   //
 | |
|   HBufferImageFree ();
 | |
| 
 | |
|   Status = HBufferImageBufferToList (Buffer, HFileImage.Size);
 | |
|   SHELL_FREE_NON_NULL (Buffer);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     StatusBarSetStatusString (L"Error parsing file.");
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   HBufferImage.DisplayPosition.Row    = 2;
 | |
|   HBufferImage.DisplayPosition.Column = 10;
 | |
|   HBufferImage.MousePosition.Row      = 2;
 | |
|   HBufferImage.MousePosition.Column   = 10;
 | |
|   HBufferImage.LowVisibleRow          = 1;
 | |
|   HBufferImage.HighBits               = TRUE;
 | |
|   HBufferImage.BufferPosition.Row     = 1;
 | |
|   HBufferImage.BufferPosition.Column  = 1;
 | |
|   HBufferImage.BufferType = FileTypeFileBuffer;
 | |
| 
 | |
|   if (!Recover) {
 | |
|     UnicodeBuffer = CatSPrint(NULL, L"%d Lines Read", HBufferImage.NumLines);
 | |
|     if (UnicodeBuffer == NULL) {
 | |
|       SHELL_FREE_NON_NULL(Buffer);
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
| 
 | |
|     StatusBarSetStatusString (UnicodeBuffer);
 | |
|     FreePool (UnicodeBuffer);
 | |
| 
 | |
|     HMainEditor.SelectStart = 0;
 | |
|     HMainEditor.SelectEnd   = 0;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // has line
 | |
|   //
 | |
|   if (HBufferImage.Lines != 0) {
 | |
|     HBufferImage.CurrentLine = CR (HBufferImage.ListHead->ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
 | |
|   } else {
 | |
|     //
 | |
|     // create a dummy line
 | |
|     //
 | |
|     Line = HBufferImageCreateLine ();
 | |
|     if (Line == NULL) {
 | |
|       SHELL_FREE_NON_NULL(Buffer);
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
| 
 | |
|     HBufferImage.CurrentLine = Line;
 | |
|   }
 | |
| 
 | |
|   HBufferImage.Modified           = FALSE;
 | |
|   HBufferImageNeedRefresh         = TRUE;
 | |
|   HBufferImageOnlyLineNeedRefresh = FALSE;
 | |
|   HBufferImageMouseNeedRefresh    = TRUE;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Save lines in HBufferImage to disk.
 | |
| 
 | |
|   @param[in] FileName     The file name.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The operation was successful.
 | |
|   @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.
 | |
|   @retval EFI_LOAD_ERROR        A load error occured.
 | |
| **/
 | |
| EFI_STATUS
 | |
| HFileImageSave (
 | |
|   IN CHAR16 *FileName
 | |
|   )
 | |
| {
 | |
| 
 | |
|   LIST_ENTRY                      *Link;
 | |
|   HEFI_EDITOR_LINE                *Line;
 | |
|   CHAR16                          *Str;
 | |
|   EFI_STATUS                      Status;
 | |
|   UINTN                           NumLines;
 | |
|   SHELL_FILE_HANDLE                 FileHandle;
 | |
|   UINTN                           TotalSize;
 | |
|   UINT8                           *Buffer;
 | |
|   UINT8                           *Ptr;
 | |
|   EDIT_FILE_TYPE                  BufferTypeBackup;
 | |
| 
 | |
|   BufferTypeBackup        = HBufferImage.BufferType;
 | |
|   HBufferImage.BufferType = FileTypeFileBuffer;
 | |
| 
 | |
|   //
 | |
|   // if is the old file
 | |
|   //
 | |
|   if (HFileImage.FileName != NULL && FileName != NULL && StrCmp (FileName, HFileImage.FileName) == 0) {
 | |
|     //
 | |
|     // check whether file exists on disk
 | |
|     //
 | |
|     if (ShellIsFile(FileName) == EFI_SUCCESS) {
 | |
|       //
 | |
|       // current file exists on disk
 | |
|       // so if not modified, then not save
 | |
|       //
 | |
|       if (HBufferImage.Modified == FALSE) {
 | |
|         return EFI_SUCCESS;
 | |
|       }
 | |
|       //
 | |
|       // if file is read-only, set error
 | |
|       //
 | |
|       if (HFileImage.ReadOnly == TRUE) {
 | |
|         StatusBarSetStatusString (L"Read Only File Can Not Be Saved");
 | |
|         return EFI_SUCCESS;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|    if (ShellIsDirectory(FileName) == EFI_SUCCESS) {
 | |
|     StatusBarSetStatusString (L"Directory Can Not Be Saved");
 | |
|     return EFI_LOAD_ERROR;
 | |
|   }
 | |
| 
 | |
|   Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0);
 | |
| 
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     //
 | |
|     // the file exits, delete it
 | |
|     //
 | |
|     Status = ShellDeleteFile (&FileHandle);
 | |
|     if (EFI_ERROR (Status) || Status == EFI_WARN_DELETE_FAILURE) {
 | |
|       StatusBarSetStatusString (L"Write File Failed");
 | |
|       return EFI_LOAD_ERROR;
 | |
|     }
 | |
|  }
 | |
| 
 | |
|   //
 | |
|   // write all the lines back to disk
 | |
|   //
 | |
|   NumLines  = 0;
 | |
|   TotalSize = 0;
 | |
|   for (Link = HBufferImage.ListHead->ForwardLink; Link != HBufferImage.ListHead; Link = Link->ForwardLink) {
 | |
|     Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
 | |
| 
 | |
|     if (Line->Size != 0) {
 | |
|       TotalSize += Line->Size;
 | |
|     }
 | |
|     //
 | |
|     // end of if Line -> Size != 0
 | |
|     //
 | |
|     NumLines++;
 | |
|   }
 | |
|   //
 | |
|   // end of for Link
 | |
|   //
 | |
|   Buffer = AllocateZeroPool (TotalSize);
 | |
|   if (Buffer == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   Ptr = Buffer;
 | |
|   for (Link = HBufferImage.ListHead->ForwardLink; Link != HBufferImage.ListHead; Link = Link->ForwardLink) {
 | |
|     Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
 | |
| 
 | |
|     if (Line->Size != 0) {
 | |
|       CopyMem (Ptr, Line->Buffer, Line->Size);
 | |
|       Ptr += Line->Size;
 | |
|     }
 | |
|     //
 | |
|     // end of if Line -> Size != 0
 | |
|     //
 | |
|   }
 | |
| 
 | |
| 
 | |
|   Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     StatusBarSetStatusString (L"Create File Failed");
 | |
|     return EFI_LOAD_ERROR;
 | |
|   }
 | |
| 
 | |
|   Status = ShellWriteFile (FileHandle, &TotalSize, Buffer);
 | |
|   FreePool (Buffer);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     ShellDeleteFile (&FileHandle);
 | |
|     return EFI_LOAD_ERROR;
 | |
|   }
 | |
| 
 | |
|   ShellCloseFile(&FileHandle);
 | |
| 
 | |
|   HBufferImage.Modified = FALSE;
 | |
| 
 | |
|   //
 | |
|   // set status string
 | |
|   //
 | |
|   Str = CatSPrint(NULL, L"%d Lines Wrote", NumLines);
 | |
|   StatusBarSetStatusString (Str);
 | |
|   FreePool (Str);
 | |
| 
 | |
|   //
 | |
|   // now everything is ready , you can set the new file name to filebuffer
 | |
|   //
 | |
|   if ((BufferTypeBackup != FileTypeFileBuffer && FileName != NULL) ||
 | |
|      (FileName != NULL && HFileImage.FileName != NULL && StringNoCaseCompare (&FileName, &HFileImage.FileName) != 0)){
 | |
|     //
 | |
|     // not the same
 | |
|     //
 | |
|     HFileImageSetFileName (FileName);
 | |
|     if (HFileImage.FileName == NULL) {
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   HFileImage.ReadOnly = FALSE;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 |