Home | History | Annotate | Download | only in HexEdit
      1 /** @file
      2   Functions to deal with Disk buffer.
      3 
      4   Copyright (c) 2005 - 2016, 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 #include <Protocol/BlockIo.h>
     17 
     18 extern EFI_HANDLE                 HImageHandleBackup;
     19 extern HEFI_EDITOR_BUFFER_IMAGE   HBufferImage;
     20 
     21 extern BOOLEAN                    HBufferImageNeedRefresh;
     22 extern BOOLEAN                    HBufferImageOnlyLineNeedRefresh;
     23 extern BOOLEAN                    HBufferImageMouseNeedRefresh;
     24 
     25 extern HEFI_EDITOR_GLOBAL_EDITOR  HMainEditor;
     26 
     27 HEFI_EDITOR_DISK_IMAGE            HDiskImage;
     28 HEFI_EDITOR_DISK_IMAGE            HDiskImageBackupVar;
     29 
     30 //
     31 // for basic initialization of HDiskImage
     32 //
     33 HEFI_EDITOR_DISK_IMAGE            HDiskImageConst = {
     34   NULL,
     35   0,
     36   0,
     37   0
     38 };
     39 
     40 /**
     41   Initialization function for HDiskImage.
     42 
     43   @retval EFI_SUCCESS     The operation was successful.
     44   @retval EFI_LOAD_ERROR  A load error occured.
     45 **/
     46 EFI_STATUS
     47 HDiskImageInit (
     48   VOID
     49   )
     50 {
     51   //
     52   // basically initialize the HDiskImage
     53   //
     54   CopyMem (&HDiskImage, &HDiskImageConst, sizeof (HDiskImage));
     55 
     56   CopyMem (&HDiskImageBackupVar, &HDiskImageConst, sizeof (HDiskImageBackupVar));
     57 
     58   return EFI_SUCCESS;
     59 }
     60 
     61 /**
     62   Backup function for HDiskImage. Only a few fields need to be backup.
     63   This is for making the Disk buffer refresh as few as possible.
     64 
     65   @retval EFI_SUCCESS           The operation was successful.
     66   @retval EFI_OUT_OF_RESOURCES  gST->ConOut of resources.
     67 **/
     68 EFI_STATUS
     69 HDiskImageBackup (
     70   VOID
     71   )
     72 {
     73   //
     74   // backup the disk name, offset and size
     75   //
     76   //
     77   SHELL_FREE_NON_NULL (HDiskImageBackupVar.Name);
     78 
     79   HDiskImageBackupVar.Name = CatSPrint(NULL, L"%s", HDiskImage.Name);
     80   if (HDiskImageBackupVar.Name == NULL) {
     81     return EFI_OUT_OF_RESOURCES;
     82   }
     83 
     84   HDiskImageBackupVar.Offset  = HDiskImage.Offset;
     85   HDiskImageBackupVar.Size    = HDiskImage.Size;
     86 
     87   return EFI_SUCCESS;
     88 }
     89 
     90 /**
     91   Cleanup function for HDiskImage.
     92 
     93   @retval EFI_SUCCESS           The operation was successful.
     94 **/
     95 EFI_STATUS
     96 HDiskImageCleanup (
     97   VOID
     98   )
     99 {
    100   SHELL_FREE_NON_NULL (HDiskImage.Name);
    101   SHELL_FREE_NON_NULL (HDiskImageBackupVar.Name);
    102 
    103   return EFI_SUCCESS;
    104 }
    105 
    106 /**
    107   Set FileName field in HFileImage.
    108 
    109   @param[in] Str      File name to set.
    110   @param[in] Offset   The offset.
    111   @param[in] Size     The size.
    112 
    113   @retval EFI_SUCCESS           The operation was successful.
    114   @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.
    115 **/
    116 EFI_STATUS
    117 HDiskImageSetDiskNameOffsetSize (
    118   IN CONST CHAR16   *Str,
    119   IN UINTN    Offset,
    120   IN UINTN    Size
    121   )
    122 {
    123   UINTN Len;
    124   UINTN Index;
    125 
    126   //
    127   // free the old file name
    128   //
    129   SHELL_FREE_NON_NULL (HDiskImage.Name);
    130 
    131   Len             = StrLen (Str);
    132 
    133   HDiskImage.Name = AllocateZeroPool (2 * (Len + 1));
    134   if (HDiskImage.Name == NULL) {
    135     return EFI_OUT_OF_RESOURCES;
    136   }
    137 
    138   for (Index = 0; Index < Len; Index++) {
    139     HDiskImage.Name[Index] = Str[Index];
    140   }
    141 
    142   HDiskImage.Name[Len]  = L'\0';
    143 
    144   HDiskImage.Offset     = Offset;
    145   HDiskImage.Size       = Size;
    146 
    147   return EFI_SUCCESS;
    148 }
    149 
    150 /**
    151   Read a disk from disk into HBufferImage.
    152 
    153   @param[in] DeviceName   filename to read.
    154   @param[in] Offset       The offset.
    155   @param[in] Size         The size.
    156   @param[in] Recover      if is for recover, no information print.
    157 
    158   @retval EFI_SUCCESS           The operation was successful.
    159   @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.
    160   @retval EFI_LOAD_ERROR        A load error occured.
    161   @retval EFI_INVALID_PARAMETER A parameter was invalid.
    162 **/
    163 EFI_STATUS
    164 HDiskImageRead (
    165   IN CONST CHAR16   *DeviceName,
    166   IN UINTN    Offset,
    167   IN UINTN    Size,
    168   IN BOOLEAN  Recover
    169   )
    170 {
    171   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
    172   EFI_DEVICE_PATH_PROTOCOL        *DupDevicePath;
    173   EFI_DEVICE_PATH_PROTOCOL        *DupDevicePathForFree;
    174   EFI_HANDLE                      Handle;
    175   EFI_BLOCK_IO_PROTOCOL           *BlkIo;
    176   EFI_STATUS                      Status;
    177 
    178   VOID                            *Buffer;
    179   CHAR16                          *Str;
    180   UINTN                           Bytes;
    181 
    182   HEFI_EDITOR_LINE                *Line;
    183 
    184   HBufferImage.BufferType = FileTypeDiskBuffer;
    185 
    186   DevicePath              = gEfiShellProtocol->GetDevicePathFromMap(DeviceName);
    187   if (DevicePath == NULL) {
    188     StatusBarSetStatusString (L"Cannot Find Device");
    189     return EFI_INVALID_PARAMETER;
    190   }
    191   DupDevicePath = DuplicateDevicePath(DevicePath);
    192   DupDevicePathForFree = DupDevicePath;
    193   //
    194   // get blkio interface
    195   //
    196   Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid,&DupDevicePath,&Handle);
    197   FreePool(DupDevicePathForFree);
    198   if (EFI_ERROR (Status)) {
    199     StatusBarSetStatusString (L"Read Disk Failed");
    200     return Status;
    201   }
    202   Status = gBS->OpenProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID**)&BlkIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
    203   if (EFI_ERROR (Status)) {
    204     StatusBarSetStatusString (L"Read Disk Failed");
    205     return Status;
    206   }
    207   //
    208   // if Offset exceeds LastBlock,
    209   //   return error
    210   //
    211   if (Offset > BlkIo->Media->LastBlock || Offset + Size > BlkIo->Media->LastBlock) {
    212     StatusBarSetStatusString (L"Invalid Offset + Size");
    213     return EFI_LOAD_ERROR;
    214   }
    215 
    216   Bytes   = BlkIo->Media->BlockSize * Size;
    217   Buffer  = AllocateZeroPool (Bytes);
    218 
    219   if (Buffer == NULL) {
    220     StatusBarSetStatusString (L"Read Disk Failed");
    221     return EFI_OUT_OF_RESOURCES;
    222   }
    223 
    224   //
    225   // read from disk
    226   //
    227   Status = BlkIo->ReadBlocks (
    228                     BlkIo,
    229                     BlkIo->Media->MediaId,
    230                     Offset,
    231                     Bytes,
    232                     Buffer
    233                     );
    234 
    235   if (EFI_ERROR (Status)) {
    236     FreePool (Buffer);
    237     StatusBarSetStatusString (L"Read Disk Failed");
    238     return EFI_LOAD_ERROR;
    239   }
    240 
    241   HBufferImageFree ();
    242 
    243   //
    244   // convert buffer to line list
    245   //
    246   Status = HBufferImageBufferToList (Buffer, Bytes);
    247   FreePool (Buffer);
    248 
    249   if (EFI_ERROR (Status)) {
    250     StatusBarSetStatusString (L"Read Disk Failed");
    251     return Status;
    252   }
    253 
    254   Status = HDiskImageSetDiskNameOffsetSize (DeviceName, Offset, Size);
    255   if (EFI_ERROR (Status)) {
    256     StatusBarSetStatusString (L"Read Disk Failed");
    257     return EFI_OUT_OF_RESOURCES;
    258   }
    259   //
    260   // initialize some variables
    261   //
    262   HDiskImage.BlockSize                = BlkIo->Media->BlockSize;
    263 
    264   HBufferImage.DisplayPosition.Row    = 2;
    265   HBufferImage.DisplayPosition.Column = 10;
    266 
    267   HBufferImage.MousePosition.Row      = 2;
    268   HBufferImage.MousePosition.Column   = 10;
    269 
    270   HBufferImage.LowVisibleRow          = 1;
    271   HBufferImage.HighBits               = TRUE;
    272 
    273   HBufferImage.BufferPosition.Row     = 1;
    274   HBufferImage.BufferPosition.Column  = 1;
    275 
    276   if (!Recover) {
    277     Str = CatSPrint(NULL, L"%d Lines Read", HBufferImage.NumLines);
    278     if (Str == NULL) {
    279       StatusBarSetStatusString (L"Read Disk Failed");
    280       return EFI_OUT_OF_RESOURCES;
    281     }
    282 
    283     StatusBarSetStatusString (Str);
    284     SHELL_FREE_NON_NULL (Str);
    285 
    286     HMainEditor.SelectStart = 0;
    287     HMainEditor.SelectEnd   = 0;
    288 
    289   }
    290 
    291   //
    292   // has line
    293   //
    294   if (HBufferImage.Lines != NULL) {
    295     HBufferImage.CurrentLine = CR (
    296                                 HBufferImage.ListHead->ForwardLink,
    297                                 HEFI_EDITOR_LINE,
    298                                 Link,
    299                                 EFI_EDITOR_LINE_LIST
    300                                 );
    301   } else {
    302     //
    303     // create a dummy line
    304     //
    305     Line = HBufferImageCreateLine ();
    306     if (Line == NULL) {
    307       StatusBarSetStatusString (L"Read Disk Failed");
    308       return EFI_OUT_OF_RESOURCES;
    309     }
    310 
    311     HBufferImage.CurrentLine = Line;
    312   }
    313 
    314   HBufferImage.Modified           = FALSE;
    315   HBufferImageNeedRefresh         = TRUE;
    316   HBufferImageOnlyLineNeedRefresh = FALSE;
    317   HBufferImageMouseNeedRefresh    = TRUE;
    318 
    319   return EFI_SUCCESS;
    320 }
    321 
    322 /**
    323   Save lines in HBufferImage to disk.
    324   NOT ALLOW TO WRITE TO ANOTHER DISK!!!!!!!!!
    325 
    326   @param[in] DeviceName   The device name.
    327   @param[in] Offset       The offset.
    328   @param[in] Size         The size.
    329 
    330   @retval EFI_SUCCESS           The operation was successful.
    331   @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.
    332   @retval EFI_LOAD_ERROR        A load error occured.
    333   @retval EFI_INVALID_PARAMETER A parameter was invalid.
    334 **/
    335 EFI_STATUS
    336 HDiskImageSave (
    337   IN CHAR16 *DeviceName,
    338   IN UINTN  Offset,
    339   IN UINTN  Size
    340   )
    341 {
    342 
    343   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
    344   EFI_DEVICE_PATH_PROTOCOL        *DupDevicePath;
    345   EFI_DEVICE_PATH_PROTOCOL        *DupDevicePathForFree;
    346   EFI_BLOCK_IO_PROTOCOL           *BlkIo;
    347   EFI_STATUS                      Status;
    348   EFI_HANDLE                      Handle;
    349   VOID                            *Buffer;
    350   UINTN                           Bytes;
    351 
    352   //
    353   // if not modified, directly return
    354   //
    355   if (HBufferImage.Modified == FALSE) {
    356     return EFI_SUCCESS;
    357   }
    358 
    359   HBufferImage.BufferType = FileTypeDiskBuffer;
    360 
    361   DevicePath              = gEfiShellProtocol->GetDevicePathFromMap(DeviceName);
    362   if (DevicePath == NULL) {
    363 //    StatusBarSetStatusString (L"Cannot Find Device");
    364     return EFI_INVALID_PARAMETER;
    365   }
    366   DupDevicePath = DuplicateDevicePath(DevicePath);
    367   DupDevicePathForFree = DupDevicePath;
    368 
    369   //
    370   // get blkio interface
    371   //
    372   Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid,&DupDevicePath,&Handle);
    373   FreePool(DupDevicePathForFree);
    374   if (EFI_ERROR (Status)) {
    375 //    StatusBarSetStatusString (L"Read Disk Failed");
    376     return Status;
    377   }
    378   Status = gBS->OpenProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID**)&BlkIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
    379   if (EFI_ERROR (Status)) {
    380 //    StatusBarSetStatusString (L"Read Disk Failed");
    381     return Status;
    382   }
    383 
    384   Bytes   = BlkIo->Media->BlockSize * Size;
    385   Buffer  = AllocateZeroPool (Bytes);
    386 
    387   if (Buffer == NULL) {
    388     return EFI_OUT_OF_RESOURCES;
    389   }
    390   //
    391   // concatenate the line list to a buffer
    392   //
    393   Status = HBufferImageListToBuffer (Buffer, Bytes);
    394   if (EFI_ERROR (Status)) {
    395     FreePool (Buffer);
    396     return Status;
    397   }
    398 
    399   //
    400   // write the buffer to disk
    401   //
    402   Status = BlkIo->WriteBlocks (
    403                     BlkIo,
    404                     BlkIo->Media->MediaId,
    405                     Offset,
    406                     Bytes,
    407                     Buffer
    408                     );
    409 
    410   FreePool (Buffer);
    411 
    412   if (EFI_ERROR (Status)) {
    413     return EFI_LOAD_ERROR;
    414   }
    415   //
    416   // now not modified
    417   //
    418   HBufferImage.Modified = FALSE;
    419 
    420   return EFI_SUCCESS;
    421 }
    422