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