git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11505 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			434 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			434 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Functions to deal with Disk buffer.
 | 
						|
 | 
						|
  Copyright (c) 2005 - 2011, 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"
 | 
						|
#include <Protocol/BlockIo.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_DISK_IMAGE            HDiskImage;
 | 
						|
HEFI_EDITOR_DISK_IMAGE            HDiskImageBackupVar;
 | 
						|
 | 
						|
//
 | 
						|
// for basic initialization of HDiskImage
 | 
						|
//
 | 
						|
HEFI_EDITOR_DISK_IMAGE            HDiskImageConst = {
 | 
						|
  NULL,
 | 
						|
  0,
 | 
						|
  0,
 | 
						|
  0
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
  Initialization function for HDiskImage.
 | 
						|
 
 | 
						|
  @retval EFI_SUCCESS     The operation was successful.
 | 
						|
  @retval EFI_LOAD_ERROR  A load error occured.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
HDiskImageInit (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // basically initialize the HDiskImage
 | 
						|
  //
 | 
						|
  CopyMem (&HDiskImage, &HDiskImageConst, sizeof (HDiskImage));
 | 
						|
 | 
						|
  CopyMem (&HDiskImageBackupVar, &HDiskImageConst, sizeof (HDiskImageBackupVar));
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Backup function for HDiskImage. Only a few fields need to be backup.   
 | 
						|
  This is for making the Disk buffer refresh as few as possible.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The operation was successful.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  gST->ConOut of resources.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
HDiskImageBackup (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // backup the disk name, offset and size
 | 
						|
  //
 | 
						|
  //
 | 
						|
  SHELL_FREE_NON_NULL (HDiskImageBackupVar.Name);
 | 
						|
 | 
						|
  HDiskImageBackupVar.Name = CatSPrint(NULL, L"%s", HDiskImage.Name);
 | 
						|
  if (HDiskImageBackupVar.Name == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  HDiskImageBackupVar.Offset  = HDiskImage.Offset;
 | 
						|
  HDiskImageBackupVar.Size    = HDiskImage.Size;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Cleanup function for HDiskImage.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The operation was successful.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
HDiskImageCleanup (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  SHELL_FREE_NON_NULL (HDiskImage.Name);
 | 
						|
  SHELL_FREE_NON_NULL (HDiskImageBackupVar.Name);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Set FileName field in HFileImage.
 | 
						|
 | 
						|
  @param[in] Str      File name to set.
 | 
						|
  @param[in] Offset   The offset.
 | 
						|
  @param[in] Size     The size.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The operation was successful.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
HDiskImageSetDiskNameOffsetSize (
 | 
						|
  IN CONST CHAR16   *Str,
 | 
						|
  IN UINTN    Offset,
 | 
						|
  IN UINTN    Size
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN Len;
 | 
						|
  UINTN Index;
 | 
						|
 | 
						|
  //
 | 
						|
  // free the old file name
 | 
						|
  //
 | 
						|
  SHELL_FREE_NON_NULL (HDiskImage.Name);
 | 
						|
 | 
						|
  Len             = StrLen (Str);
 | 
						|
 | 
						|
  HDiskImage.Name = AllocateZeroPool (2 * (Len + 1));
 | 
						|
  if (HDiskImage.Name == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  for (Index = 0; Index < Len; Index++) {
 | 
						|
    HDiskImage.Name[Index] = Str[Index];
 | 
						|
  }
 | 
						|
 | 
						|
  HDiskImage.Name[Len]  = L'\0';
 | 
						|
 | 
						|
  HDiskImage.Offset     = Offset;
 | 
						|
  HDiskImage.Size       = Size;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Read a disk from disk into HBufferImage.
 | 
						|
 | 
						|
  @param[in] DeviceName   filename to read.
 | 
						|
  @param[in] Offset       The offset.
 | 
						|
  @param[in] Size         The size.
 | 
						|
  @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.
 | 
						|
  @retval EFI_INVALID_PARAMETER A parameter was invalid.  
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
HDiskImageRead (
 | 
						|
  IN CONST CHAR16   *DeviceName,
 | 
						|
  IN UINTN    Offset,
 | 
						|
  IN UINTN    Size,
 | 
						|
  IN BOOLEAN  Recover
 | 
						|
  )
 | 
						|
{
 | 
						|
  CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL        *DupDevicePath;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL        *DupDevicePathForFree;
 | 
						|
  EFI_HANDLE                      Handle;
 | 
						|
  EFI_BLOCK_IO_PROTOCOL           *BlkIo;
 | 
						|
  EFI_STATUS                      Status;
 | 
						|
 | 
						|
  VOID                            *Buffer;
 | 
						|
  CHAR16                          *Str;
 | 
						|
  UINTN                           Bytes;
 | 
						|
 | 
						|
  HEFI_EDITOR_LINE                *Line;
 | 
						|
  UINT64                          ByteOffset;
 | 
						|
 | 
						|
  EDIT_FILE_TYPE                  BufferTypeBackup;
 | 
						|
 | 
						|
  BufferTypeBackup        = HBufferImage.BufferType;
 | 
						|
  HBufferImage.BufferType = FileTypeDiskBuffer;
 | 
						|
 | 
						|
  DevicePath              = gEfiShellProtocol->GetDevicePathFromMap(DeviceName);
 | 
						|
  if (DevicePath == NULL) {
 | 
						|
    StatusBarSetStatusString (L"Cannot Find Device");
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  DupDevicePath = DuplicateDevicePath(DevicePath);
 | 
						|
  DupDevicePathForFree = DupDevicePath;
 | 
						|
  //
 | 
						|
  // get blkio interface
 | 
						|
  //
 | 
						|
  Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid,&DupDevicePath,&Handle);
 | 
						|
  FreePool(DupDevicePathForFree);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    StatusBarSetStatusString (L"Read Disk Failed");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  Status = gBS->OpenProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID**)&BlkIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    StatusBarSetStatusString (L"Read Disk Failed");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // if Offset exceeds LastBlock,
 | 
						|
  //   return error
 | 
						|
  //
 | 
						|
  if (Offset > BlkIo->Media->LastBlock || Offset + Size > BlkIo->Media->LastBlock) {
 | 
						|
    StatusBarSetStatusString (L"Invalid Offset + Size");
 | 
						|
    return EFI_LOAD_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  Bytes   = BlkIo->Media->BlockSize * Size;
 | 
						|
  Buffer  = AllocateZeroPool (Bytes);
 | 
						|
 | 
						|
  if (Buffer == NULL) {
 | 
						|
    StatusBarSetStatusString (L"Read Disk Failed");
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  ByteOffset = MultU64x32 (Offset, BlkIo->Media->BlockSize);
 | 
						|
 | 
						|
  //
 | 
						|
  // read from disk
 | 
						|
  //
 | 
						|
  Status = BlkIo->ReadBlocks (
 | 
						|
                    BlkIo,
 | 
						|
                    BlkIo->Media->MediaId,
 | 
						|
                    Offset,
 | 
						|
                    Bytes,
 | 
						|
                    Buffer
 | 
						|
                    );
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    FreePool (Buffer);
 | 
						|
    StatusBarSetStatusString (L"Read Disk Failed");
 | 
						|
    return EFI_LOAD_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  HBufferImageFree ();
 | 
						|
 | 
						|
  //
 | 
						|
  // convert buffer to line list
 | 
						|
  //
 | 
						|
  Status = HBufferImageBufferToList (Buffer, Bytes);
 | 
						|
  FreePool (Buffer);
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    StatusBarSetStatusString (L"Read Disk Failed");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = HDiskImageSetDiskNameOffsetSize (DeviceName, Offset, Size);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    StatusBarSetStatusString (L"Read Disk Failed");
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // initialize some variables
 | 
						|
  //
 | 
						|
  HDiskImage.BlockSize                = BlkIo->Media->BlockSize;
 | 
						|
 | 
						|
  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;
 | 
						|
 | 
						|
  if (!Recover) {
 | 
						|
    Str = CatSPrint(NULL, L"%d Lines Read", HBufferImage.NumLines);
 | 
						|
    if (Str == NULL) {
 | 
						|
      StatusBarSetStatusString (L"Read Disk Failed");
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
 | 
						|
    StatusBarSetStatusString (Str);
 | 
						|
    SHELL_FREE_NON_NULL (Str);
 | 
						|
 | 
						|
    HMainEditor.SelectStart = 0;
 | 
						|
    HMainEditor.SelectEnd   = 0;
 | 
						|
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // has line
 | 
						|
  //
 | 
						|
  if (HBufferImage.Lines != NULL) {
 | 
						|
    HBufferImage.CurrentLine = CR (
 | 
						|
                                HBufferImage.ListHead->ForwardLink,
 | 
						|
                                HEFI_EDITOR_LINE,
 | 
						|
                                Link,
 | 
						|
                                EFI_EDITOR_LINE_LIST
 | 
						|
                                );
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // create a dummy line
 | 
						|
    //
 | 
						|
    Line = HBufferImageCreateLine ();
 | 
						|
    if (Line == NULL) {
 | 
						|
      StatusBarSetStatusString (L"Read Disk Failed");
 | 
						|
      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.
 | 
						|
  NOT ALLOW TO WRITE TO ANOTHER DISK!!!!!!!!!
 | 
						|
 | 
						|
  @param[in] DeviceName   The device name.
 | 
						|
  @param[in] Offset       The offset.
 | 
						|
  @param[in] Size         The size.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The operation was successful.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.
 | 
						|
  @retval EFI_LOAD_ERROR        A load error occured.
 | 
						|
  @retval EFI_INVALID_PARAMETER A parameter was invalid.  
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
HDiskImageSave (
 | 
						|
  IN CHAR16 *DeviceName,
 | 
						|
  IN UINTN  Offset,
 | 
						|
  IN UINTN  Size
 | 
						|
  )
 | 
						|
{
 | 
						|
 | 
						|
  CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL        *DupDevicePath;
 | 
						|
  EFI_BLOCK_IO_PROTOCOL           *BlkIo;
 | 
						|
  EFI_STATUS                      Status;
 | 
						|
  EFI_HANDLE                      Handle;
 | 
						|
  VOID                            *Buffer;
 | 
						|
  UINTN                           Bytes;
 | 
						|
 | 
						|
  UINT64                          ByteOffset;
 | 
						|
 | 
						|
  EDIT_FILE_TYPE                  BufferTypeBackup;
 | 
						|
 | 
						|
  //
 | 
						|
  // if not modified, directly return
 | 
						|
  //
 | 
						|
  if (HBufferImage.Modified == FALSE) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  BufferTypeBackup        = HBufferImage.BufferType;
 | 
						|
  HBufferImage.BufferType = FileTypeDiskBuffer;
 | 
						|
 | 
						|
  DevicePath              = gEfiShellProtocol->GetDevicePathFromMap(DeviceName);
 | 
						|
  if (DevicePath == NULL) {
 | 
						|
//    StatusBarSetStatusString (L"Cannot Find Device");
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  DupDevicePath = DuplicateDevicePath(DevicePath);
 | 
						|
 | 
						|
  //
 | 
						|
  // get blkio interface
 | 
						|
  //
 | 
						|
  Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid,&DupDevicePath,&Handle);
 | 
						|
  FreePool(DupDevicePath);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
//    StatusBarSetStatusString (L"Read Disk Failed");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  Status = gBS->OpenProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID**)&BlkIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
//    StatusBarSetStatusString (L"Read Disk Failed");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Bytes   = BlkIo->Media->BlockSize * Size;
 | 
						|
  Buffer  = AllocateZeroPool (Bytes);
 | 
						|
 | 
						|
  if (Buffer == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // concatenate the line list to a buffer
 | 
						|
  //
 | 
						|
  Status = HBufferImageListToBuffer (Buffer, Bytes);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    FreePool (Buffer);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  ByteOffset = MultU64x32 (Offset, BlkIo->Media->BlockSize);
 | 
						|
 | 
						|
  //
 | 
						|
  // write the buffer to disk
 | 
						|
  //
 | 
						|
  Status = BlkIo->WriteBlocks (
 | 
						|
                    BlkIo,
 | 
						|
                    BlkIo->Media->MediaId,
 | 
						|
                    Offset,
 | 
						|
                    Bytes,
 | 
						|
                    Buffer
 | 
						|
                    );
 | 
						|
 | 
						|
  FreePool (Buffer);
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return EFI_LOAD_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // now not modified
 | 
						|
  //
 | 
						|
  HBufferImage.Modified = FALSE;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 |