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
HDiskImageInit(VOID)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
HDiskImageBackup(VOID)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
HDiskImageCleanup(VOID)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
HDiskImageSetDiskNameOffsetSize(IN CONST CHAR16 * Str,IN UINTN Offset,IN UINTN Size)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
HDiskImageRead(IN CONST CHAR16 * DeviceName,IN UINTN Offset,IN UINTN Size,IN BOOLEAN Recover)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
HDiskImageSave(IN CHAR16 * DeviceName,IN UINTN Offset,IN UINTN Size)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