/** @file Functions to deal with Disk buffer. Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "HexEditor.h" #include 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 occurred. **/ 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 occurred. @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 occurred. @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; }