You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
418 lines
10 KiB
418 lines
10 KiB
4 years ago
|
/** @file
|
||
|
Functions to deal with Disk buffer.
|
||
|
|
||
|
Copyright (c) 2005 - 2018, 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
|
||
|
HDiskImageSetDiskNameOffsetSize (
|
||
|
IN CONST CHAR16 *Str,
|
||
|
IN UINTN Offset,
|
||
|
IN UINTN Size
|
||
|
)
|
||
|
{
|
||
|
if (Str == HDiskImage.Name) {
|
||
|
//
|
||
|
// This function might be called using HDiskImage.FileName as Str.
|
||
|
// Directly return without updating HDiskImage.FileName.
|
||
|
//
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// free the old file name
|
||
|
//
|
||
|
SHELL_FREE_NON_NULL (HDiskImage.Name);
|
||
|
HDiskImage.Name = AllocateCopyPool (StrSize (Str), Str);
|
||
|
if (HDiskImage.Name == NULL) {
|
||
|
return EFI_OUT_OF_RESOURCES;
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// 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_DEVICE_PATH_PROTOCOL *DupDevicePathForFree;
|
||
|
EFI_BLOCK_IO_PROTOCOL *BlkIo;
|
||
|
EFI_STATUS Status;
|
||
|
EFI_HANDLE Handle;
|
||
|
VOID *Buffer;
|
||
|
UINTN Bytes;
|
||
|
|
||
|
//
|
||
|
// if not modified, directly return
|
||
|
//
|
||
|
if (HBufferImage.Modified == FALSE) {
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// 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;
|
||
|
}
|