Home | History | Annotate | Download | only in HexEdit
      1 /** @file
      2   Functions to deal with file buffer.
      3 
      4   Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved. <BR>
      5   This program and the accompanying materials
      6   are licensed and made available under the terms and conditions of the BSD License
      7   which accompanies this distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "HexEditor.h"
     16 
     17 extern EFI_HANDLE                 HImageHandleBackup;
     18 extern HEFI_EDITOR_BUFFER_IMAGE   HBufferImage;
     19 
     20 extern BOOLEAN                    HBufferImageNeedRefresh;
     21 extern BOOLEAN                    HBufferImageOnlyLineNeedRefresh;
     22 extern BOOLEAN                    HBufferImageMouseNeedRefresh;
     23 
     24 extern HEFI_EDITOR_GLOBAL_EDITOR  HMainEditor;
     25 
     26 HEFI_EDITOR_FILE_IMAGE            HFileImage;
     27 HEFI_EDITOR_FILE_IMAGE            HFileImageBackupVar;
     28 
     29 //
     30 // for basic initialization of HFileImage
     31 //
     32 HEFI_EDITOR_BUFFER_IMAGE          HFileImageConst = {
     33   NULL,
     34   0,
     35   FALSE
     36 };
     37 
     38 /**
     39   Initialization function for HFileImage
     40 
     41   @retval EFI_SUCCESS     The operation was successful.
     42 **/
     43 EFI_STATUS
     44 HFileImageInit (
     45   VOID
     46   )
     47 {
     48   //
     49   // basically initialize the HFileImage
     50   //
     51   CopyMem (&HFileImage, &HFileImageConst, sizeof (HFileImage));
     52 
     53   CopyMem (
     54     &HFileImageBackupVar,
     55     &HFileImageConst,
     56     sizeof (HFileImageBackupVar)
     57     );
     58 
     59   return EFI_SUCCESS;
     60 }
     61 
     62 /**
     63   Backup function for HFileImage. Only a few fields need to be backup.
     64   This is for making the file buffer refresh as few as possible.
     65 
     66   @retval EFI_SUCCESS           The operation was successful.
     67   @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.
     68 **/
     69 EFI_STATUS
     70 HFileImageBackup (
     71   VOID
     72   )
     73 {
     74   SHELL_FREE_NON_NULL (HFileImageBackupVar.FileName);
     75   HFileImageBackupVar.FileName = CatSPrint(NULL, L"%s", HFileImage.FileName);
     76   if (HFileImageBackupVar.FileName == NULL) {
     77     return EFI_OUT_OF_RESOURCES;
     78   }
     79 
     80   return EFI_SUCCESS;
     81 }
     82 
     83 /**
     84   Cleanup function for HFileImage.
     85 
     86   @retval EFI_SUCCESS           The operation was successful.
     87 **/
     88 EFI_STATUS
     89 HFileImageCleanup (
     90   VOID
     91   )
     92 {
     93 
     94   SHELL_FREE_NON_NULL (HFileImage.FileName);
     95   SHELL_FREE_NON_NULL (HFileImageBackupVar.FileName);
     96 
     97   return EFI_SUCCESS;
     98 }
     99 
    100 /**
    101   Set FileName field in HFileImage
    102 
    103   @param[in] Str  File name to set.
    104 
    105   @retval EFI_SUCCESS           The operation was successful.
    106   @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.
    107 **/
    108 EFI_STATUS
    109 HFileImageSetFileName (
    110   IN CONST CHAR16 *Str
    111   )
    112 {
    113   UINTN Size;
    114   UINTN Index;
    115 
    116   //
    117   // free the old file name
    118   //
    119   SHELL_FREE_NON_NULL (HFileImage.FileName);
    120 
    121   Size                = StrLen (Str);
    122 
    123   HFileImage.FileName = AllocateZeroPool (2 * (Size + 1));
    124   if (HFileImage.FileName == NULL) {
    125     return EFI_OUT_OF_RESOURCES;
    126   }
    127 
    128   for (Index = 0; Index < Size; Index++) {
    129     HFileImage.FileName[Index] = Str[Index];
    130   }
    131 
    132   HFileImage.FileName[Size] = L'\0';
    133 
    134   return EFI_SUCCESS;
    135 }
    136 
    137 /**
    138   Read a file from disk into HBufferImage.
    139 
    140   @param[in] FileName     filename to read.
    141   @param[in] Recover      if is for recover, no information print.
    142 
    143   @retval EFI_SUCCESS           The operation was successful.
    144   @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.
    145   @retval EFI_LOAD_ERROR        A load error occured.
    146 **/
    147 EFI_STATUS
    148 HFileImageRead (
    149   IN CONST CHAR16  *FileName,
    150   IN BOOLEAN Recover
    151   )
    152 {
    153   HEFI_EDITOR_LINE                *Line;
    154   UINT8                           *Buffer;
    155   CHAR16                          *UnicodeBuffer;
    156   EFI_STATUS                      Status;
    157 
    158   //
    159   // variable initialization
    160   //
    161   Line                    = NULL;
    162 
    163   //
    164   // in this function, when you return error ( except EFI_OUT_OF_RESOURCES )
    165   // you should set status string
    166   // since this function maybe called before the editorhandleinput loop
    167   // so any error will cause editor return
    168   // so if you want to print the error status
    169   // you should set the status string
    170   //
    171   Status = ReadFileIntoBuffer (FileName, (VOID**)&Buffer, &HFileImage.Size, &HFileImage.ReadOnly);
    172   //
    173   // NULL pointer is only also a failure for a non-zero file size.
    174   //
    175   if ((EFI_ERROR(Status)) || (Buffer == NULL && HFileImage.Size != 0)) {
    176     UnicodeBuffer = CatSPrint(NULL, L"Read error on file %s: %r", FileName, Status);
    177     if (UnicodeBuffer == NULL) {
    178       SHELL_FREE_NON_NULL(Buffer);
    179       return EFI_OUT_OF_RESOURCES;
    180     }
    181 
    182     StatusBarSetStatusString (UnicodeBuffer);
    183     FreePool (UnicodeBuffer);
    184     return EFI_OUT_OF_RESOURCES;
    185   }
    186 
    187   HFileImageSetFileName (FileName);
    188 
    189   //
    190   // free the old lines
    191   //
    192   HBufferImageFree ();
    193 
    194   Status = HBufferImageBufferToList (Buffer, HFileImage.Size);
    195   SHELL_FREE_NON_NULL (Buffer);
    196   if (EFI_ERROR (Status)) {
    197     StatusBarSetStatusString (L"Error parsing file.");
    198     return Status;
    199   }
    200 
    201   HBufferImage.DisplayPosition.Row    = 2;
    202   HBufferImage.DisplayPosition.Column = 10;
    203   HBufferImage.MousePosition.Row      = 2;
    204   HBufferImage.MousePosition.Column   = 10;
    205   HBufferImage.LowVisibleRow          = 1;
    206   HBufferImage.HighBits               = TRUE;
    207   HBufferImage.BufferPosition.Row     = 1;
    208   HBufferImage.BufferPosition.Column  = 1;
    209   HBufferImage.BufferType = FileTypeFileBuffer;
    210 
    211   if (!Recover) {
    212     UnicodeBuffer = CatSPrint(NULL, L"%d Lines Read", HBufferImage.NumLines);
    213     if (UnicodeBuffer == NULL) {
    214       SHELL_FREE_NON_NULL(Buffer);
    215       return EFI_OUT_OF_RESOURCES;
    216     }
    217 
    218     StatusBarSetStatusString (UnicodeBuffer);
    219     FreePool (UnicodeBuffer);
    220 
    221     HMainEditor.SelectStart = 0;
    222     HMainEditor.SelectEnd   = 0;
    223   }
    224 
    225   //
    226   // has line
    227   //
    228   if (HBufferImage.Lines != 0) {
    229     HBufferImage.CurrentLine = CR (HBufferImage.ListHead->ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
    230   } else {
    231     //
    232     // create a dummy line
    233     //
    234     Line = HBufferImageCreateLine ();
    235     if (Line == NULL) {
    236       SHELL_FREE_NON_NULL(Buffer);
    237       return EFI_OUT_OF_RESOURCES;
    238     }
    239 
    240     HBufferImage.CurrentLine = Line;
    241   }
    242 
    243   HBufferImage.Modified           = FALSE;
    244   HBufferImageNeedRefresh         = TRUE;
    245   HBufferImageOnlyLineNeedRefresh = FALSE;
    246   HBufferImageMouseNeedRefresh    = TRUE;
    247 
    248   return EFI_SUCCESS;
    249 }
    250 
    251 /**
    252   Save lines in HBufferImage to disk.
    253 
    254   @param[in] FileName     The file name.
    255 
    256   @retval EFI_SUCCESS           The operation was successful.
    257   @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.
    258   @retval EFI_LOAD_ERROR        A load error occured.
    259 **/
    260 EFI_STATUS
    261 HFileImageSave (
    262   IN CHAR16 *FileName
    263   )
    264 {
    265 
    266   LIST_ENTRY                      *Link;
    267   HEFI_EDITOR_LINE                *Line;
    268   CHAR16                          *Str;
    269   EFI_STATUS                      Status;
    270   UINTN                           NumLines;
    271   SHELL_FILE_HANDLE                 FileHandle;
    272   UINTN                           TotalSize;
    273   UINT8                           *Buffer;
    274   UINT8                           *Ptr;
    275   EDIT_FILE_TYPE                  BufferTypeBackup;
    276 
    277   BufferTypeBackup        = HBufferImage.BufferType;
    278   HBufferImage.BufferType = FileTypeFileBuffer;
    279 
    280   //
    281   // if is the old file
    282   //
    283   if (HFileImage.FileName != NULL && FileName != NULL && StrCmp (FileName, HFileImage.FileName) == 0) {
    284     //
    285     // check whether file exists on disk
    286     //
    287     if (ShellIsFile(FileName) == EFI_SUCCESS) {
    288       //
    289       // current file exists on disk
    290       // so if not modified, then not save
    291       //
    292       if (HBufferImage.Modified == FALSE) {
    293         return EFI_SUCCESS;
    294       }
    295       //
    296       // if file is read-only, set error
    297       //
    298       if (HFileImage.ReadOnly == TRUE) {
    299         StatusBarSetStatusString (L"Read Only File Can Not Be Saved");
    300         return EFI_SUCCESS;
    301       }
    302     }
    303   }
    304 
    305    if (ShellIsDirectory(FileName) == EFI_SUCCESS) {
    306     StatusBarSetStatusString (L"Directory Can Not Be Saved");
    307     return EFI_LOAD_ERROR;
    308   }
    309 
    310   Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0);
    311 
    312   if (!EFI_ERROR (Status)) {
    313     //
    314     // the file exits, delete it
    315     //
    316     Status = ShellDeleteFile (&FileHandle);
    317     if (EFI_ERROR (Status) || Status == EFI_WARN_DELETE_FAILURE) {
    318       StatusBarSetStatusString (L"Write File Failed");
    319       return EFI_LOAD_ERROR;
    320     }
    321  }
    322 
    323   //
    324   // write all the lines back to disk
    325   //
    326   NumLines  = 0;
    327   TotalSize = 0;
    328   for (Link = HBufferImage.ListHead->ForwardLink; Link != HBufferImage.ListHead; Link = Link->ForwardLink) {
    329     Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
    330 
    331     if (Line->Size != 0) {
    332       TotalSize += Line->Size;
    333     }
    334     //
    335     // end of if Line -> Size != 0
    336     //
    337     NumLines++;
    338   }
    339   //
    340   // end of for Link
    341   //
    342   Buffer = AllocateZeroPool (TotalSize);
    343   if (Buffer == NULL) {
    344     return EFI_OUT_OF_RESOURCES;
    345   }
    346 
    347   Ptr = Buffer;
    348   for (Link = HBufferImage.ListHead->ForwardLink; Link != HBufferImage.ListHead; Link = Link->ForwardLink) {
    349     Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
    350 
    351     if (Line->Size != 0) {
    352       CopyMem (Ptr, Line->Buffer, Line->Size);
    353       Ptr += Line->Size;
    354     }
    355     //
    356     // end of if Line -> Size != 0
    357     //
    358   }
    359 
    360 
    361   Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
    362 
    363   if (EFI_ERROR (Status)) {
    364     StatusBarSetStatusString (L"Create File Failed");
    365     return EFI_LOAD_ERROR;
    366   }
    367 
    368   Status = ShellWriteFile (FileHandle, &TotalSize, Buffer);
    369   FreePool (Buffer);
    370   if (EFI_ERROR (Status)) {
    371     ShellDeleteFile (&FileHandle);
    372     return EFI_LOAD_ERROR;
    373   }
    374 
    375   ShellCloseFile(&FileHandle);
    376 
    377   HBufferImage.Modified = FALSE;
    378 
    379   //
    380   // set status string
    381   //
    382   Str = CatSPrint(NULL, L"%d Lines Wrote", NumLines);
    383   StatusBarSetStatusString (Str);
    384   FreePool (Str);
    385 
    386   //
    387   // now everything is ready , you can set the new file name to filebuffer
    388   //
    389   if ((BufferTypeBackup != FileTypeFileBuffer && FileName != NULL) ||
    390      (FileName != NULL && HFileImage.FileName != NULL && StringNoCaseCompare (&FileName, &HFileImage.FileName) != 0)){
    391     //
    392     // not the same
    393     //
    394     HFileImageSetFileName (FileName);
    395     if (HFileImage.FileName == NULL) {
    396       return EFI_OUT_OF_RESOURCES;
    397     }
    398   }
    399 
    400   HFileImage.ReadOnly = FALSE;
    401 
    402   return EFI_SUCCESS;
    403 }
    404