| /** @file | |
| Functions to deal with Disk buffer. | |
| Copyright (c) 2005 - 2016, 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 | |
| ) | |
| { | |
| 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; | |
| 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; | |
| } |