]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.c
1c93cd8958412fddd6db76dae63cb3c84f3592bb
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / HexEdit / DiskImage.c
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 EFIAPI
118 HDiskImageSetDiskNameOffsetSize (
119 IN CONST CHAR16 *Str,
120 IN UINTN Offset,
121 IN UINTN Size
122 )
123 {
124 UINTN Len;
125 UINTN Index;
126
127 //
128 // free the old file name
129 //
130 SHELL_FREE_NON_NULL (HDiskImage.Name);
131
132 Len = StrLen (Str);
133
134 HDiskImage.Name = AllocateZeroPool (2 * (Len + 1));
135 if (HDiskImage.Name == NULL) {
136 return EFI_OUT_OF_RESOURCES;
137 }
138
139 for (Index = 0; Index < Len; Index++) {
140 HDiskImage.Name[Index] = Str[Index];
141 }
142
143 HDiskImage.Name[Len] = L'\0';
144
145 HDiskImage.Offset = Offset;
146 HDiskImage.Size = Size;
147
148 return EFI_SUCCESS;
149 }
150
151 /**
152 Read a disk from disk into HBufferImage.
153
154 @param[in] DeviceName filename to read.
155 @param[in] Offset The offset.
156 @param[in] Size The size.
157 @param[in] Recover if is for recover, no information print.
158
159 @retval EFI_SUCCESS The operation was successful.
160 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
161 @retval EFI_LOAD_ERROR A load error occured.
162 @retval EFI_INVALID_PARAMETER A parameter was invalid.
163 **/
164 EFI_STATUS
165 HDiskImageRead (
166 IN CONST CHAR16 *DeviceName,
167 IN UINTN Offset,
168 IN UINTN Size,
169 IN BOOLEAN Recover
170 )
171 {
172 CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath;
173 EFI_DEVICE_PATH_PROTOCOL *DupDevicePath;
174 EFI_DEVICE_PATH_PROTOCOL *DupDevicePathForFree;
175 EFI_HANDLE Handle;
176 EFI_BLOCK_IO_PROTOCOL *BlkIo;
177 EFI_STATUS Status;
178
179 VOID *Buffer;
180 CHAR16 *Str;
181 UINTN Bytes;
182
183 HEFI_EDITOR_LINE *Line;
184
185 HBufferImage.BufferType = FileTypeDiskBuffer;
186
187 DevicePath = gEfiShellProtocol->GetDevicePathFromMap(DeviceName);
188 if (DevicePath == NULL) {
189 StatusBarSetStatusString (L"Cannot Find Device");
190 return EFI_INVALID_PARAMETER;
191 }
192 DupDevicePath = DuplicateDevicePath(DevicePath);
193 DupDevicePathForFree = DupDevicePath;
194 //
195 // get blkio interface
196 //
197 Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid,&DupDevicePath,&Handle);
198 FreePool(DupDevicePathForFree);
199 if (EFI_ERROR (Status)) {
200 StatusBarSetStatusString (L"Read Disk Failed");
201 return Status;
202 }
203 Status = gBS->OpenProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID**)&BlkIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
204 if (EFI_ERROR (Status)) {
205 StatusBarSetStatusString (L"Read Disk Failed");
206 return Status;
207 }
208 //
209 // if Offset exceeds LastBlock,
210 // return error
211 //
212 if (Offset > BlkIo->Media->LastBlock || Offset + Size > BlkIo->Media->LastBlock) {
213 StatusBarSetStatusString (L"Invalid Offset + Size");
214 return EFI_LOAD_ERROR;
215 }
216
217 Bytes = BlkIo->Media->BlockSize * Size;
218 Buffer = AllocateZeroPool (Bytes);
219
220 if (Buffer == NULL) {
221 StatusBarSetStatusString (L"Read Disk Failed");
222 return EFI_OUT_OF_RESOURCES;
223 }
224
225 //
226 // read from disk
227 //
228 Status = BlkIo->ReadBlocks (
229 BlkIo,
230 BlkIo->Media->MediaId,
231 Offset,
232 Bytes,
233 Buffer
234 );
235
236 if (EFI_ERROR (Status)) {
237 FreePool (Buffer);
238 StatusBarSetStatusString (L"Read Disk Failed");
239 return EFI_LOAD_ERROR;
240 }
241
242 HBufferImageFree ();
243
244 //
245 // convert buffer to line list
246 //
247 Status = HBufferImageBufferToList (Buffer, Bytes);
248 FreePool (Buffer);
249
250 if (EFI_ERROR (Status)) {
251 StatusBarSetStatusString (L"Read Disk Failed");
252 return Status;
253 }
254
255 Status = HDiskImageSetDiskNameOffsetSize (DeviceName, Offset, Size);
256 if (EFI_ERROR (Status)) {
257 StatusBarSetStatusString (L"Read Disk Failed");
258 return EFI_OUT_OF_RESOURCES;
259 }
260 //
261 // initialize some variables
262 //
263 HDiskImage.BlockSize = BlkIo->Media->BlockSize;
264
265 HBufferImage.DisplayPosition.Row = 2;
266 HBufferImage.DisplayPosition.Column = 10;
267
268 HBufferImage.MousePosition.Row = 2;
269 HBufferImage.MousePosition.Column = 10;
270
271 HBufferImage.LowVisibleRow = 1;
272 HBufferImage.HighBits = TRUE;
273
274 HBufferImage.BufferPosition.Row = 1;
275 HBufferImage.BufferPosition.Column = 1;
276
277 if (!Recover) {
278 Str = CatSPrint(NULL, L"%d Lines Read", HBufferImage.NumLines);
279 if (Str == NULL) {
280 StatusBarSetStatusString (L"Read Disk Failed");
281 return EFI_OUT_OF_RESOURCES;
282 }
283
284 StatusBarSetStatusString (Str);
285 SHELL_FREE_NON_NULL (Str);
286
287 HMainEditor.SelectStart = 0;
288 HMainEditor.SelectEnd = 0;
289
290 }
291
292 //
293 // has line
294 //
295 if (HBufferImage.Lines != NULL) {
296 HBufferImage.CurrentLine = CR (
297 HBufferImage.ListHead->ForwardLink,
298 HEFI_EDITOR_LINE,
299 Link,
300 EFI_EDITOR_LINE_LIST
301 );
302 } else {
303 //
304 // create a dummy line
305 //
306 Line = HBufferImageCreateLine ();
307 if (Line == NULL) {
308 StatusBarSetStatusString (L"Read Disk Failed");
309 return EFI_OUT_OF_RESOURCES;
310 }
311
312 HBufferImage.CurrentLine = Line;
313 }
314
315 HBufferImage.Modified = FALSE;
316 HBufferImageNeedRefresh = TRUE;
317 HBufferImageOnlyLineNeedRefresh = FALSE;
318 HBufferImageMouseNeedRefresh = TRUE;
319
320 return EFI_SUCCESS;
321 }
322
323 /**
324 Save lines in HBufferImage to disk.
325 NOT ALLOW TO WRITE TO ANOTHER DISK!!!!!!!!!
326
327 @param[in] DeviceName The device name.
328 @param[in] Offset The offset.
329 @param[in] Size The size.
330
331 @retval EFI_SUCCESS The operation was successful.
332 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
333 @retval EFI_LOAD_ERROR A load error occured.
334 @retval EFI_INVALID_PARAMETER A parameter was invalid.
335 **/
336 EFI_STATUS
337 HDiskImageSave (
338 IN CHAR16 *DeviceName,
339 IN UINTN Offset,
340 IN UINTN Size
341 )
342 {
343
344 CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath;
345 EFI_DEVICE_PATH_PROTOCOL *DupDevicePath;
346 EFI_DEVICE_PATH_PROTOCOL *DupDevicePathForFree;
347 EFI_BLOCK_IO_PROTOCOL *BlkIo;
348 EFI_STATUS Status;
349 EFI_HANDLE Handle;
350 VOID *Buffer;
351 UINTN Bytes;
352
353 //
354 // if not modified, directly return
355 //
356 if (HBufferImage.Modified == FALSE) {
357 return EFI_SUCCESS;
358 }
359
360 HBufferImage.BufferType = FileTypeDiskBuffer;
361
362 DevicePath = gEfiShellProtocol->GetDevicePathFromMap(DeviceName);
363 if (DevicePath == NULL) {
364 // StatusBarSetStatusString (L"Cannot Find Device");
365 return EFI_INVALID_PARAMETER;
366 }
367 DupDevicePath = DuplicateDevicePath(DevicePath);
368 DupDevicePathForFree = DupDevicePath;
369
370 //
371 // get blkio interface
372 //
373 Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid,&DupDevicePath,&Handle);
374 FreePool(DupDevicePathForFree);
375 if (EFI_ERROR (Status)) {
376 // StatusBarSetStatusString (L"Read Disk Failed");
377 return Status;
378 }
379 Status = gBS->OpenProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID**)&BlkIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
380 if (EFI_ERROR (Status)) {
381 // StatusBarSetStatusString (L"Read Disk Failed");
382 return Status;
383 }
384
385 Bytes = BlkIo->Media->BlockSize * Size;
386 Buffer = AllocateZeroPool (Bytes);
387
388 if (Buffer == NULL) {
389 return EFI_OUT_OF_RESOURCES;
390 }
391 //
392 // concatenate the line list to a buffer
393 //
394 Status = HBufferImageListToBuffer (Buffer, Bytes);
395 if (EFI_ERROR (Status)) {
396 FreePool (Buffer);
397 return Status;
398 }
399
400 //
401 // write the buffer to disk
402 //
403 Status = BlkIo->WriteBlocks (
404 BlkIo,
405 BlkIo->Media->MediaId,
406 Offset,
407 Bytes,
408 Buffer
409 );
410
411 FreePool (Buffer);
412
413 if (EFI_ERROR (Status)) {
414 return EFI_LOAD_ERROR;
415 }
416 //
417 // now not modified
418 //
419 HBufferImage.Modified = FALSE;
420
421 return EFI_SUCCESS;
422 }