]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.c
771a5c6840254740fb9b2688d9164549227aa3be
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / HexEdit / DiskImage.c
1 /** @file
2 Functions to deal with Disk buffer.
3
4 Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved. <BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "HexEditor.h"
10 #include <Protocol/BlockIo.h>
11
12 extern EFI_HANDLE HImageHandleBackup;
13 extern HEFI_EDITOR_BUFFER_IMAGE HBufferImage;
14
15 extern BOOLEAN HBufferImageNeedRefresh;
16 extern BOOLEAN HBufferImageOnlyLineNeedRefresh;
17 extern BOOLEAN HBufferImageMouseNeedRefresh;
18
19 extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;
20
21 HEFI_EDITOR_DISK_IMAGE HDiskImage;
22 HEFI_EDITOR_DISK_IMAGE HDiskImageBackupVar;
23
24 //
25 // for basic initialization of HDiskImage
26 //
27 HEFI_EDITOR_DISK_IMAGE HDiskImageConst = {
28 NULL,
29 0,
30 0,
31 0
32 };
33
34 /**
35 Initialization function for HDiskImage.
36
37 @retval EFI_SUCCESS The operation was successful.
38 @retval EFI_LOAD_ERROR A load error occurred.
39 **/
40 EFI_STATUS
41 HDiskImageInit (
42 VOID
43 )
44 {
45 //
46 // basically initialize the HDiskImage
47 //
48 CopyMem (&HDiskImage, &HDiskImageConst, sizeof (HDiskImage));
49
50 CopyMem (&HDiskImageBackupVar, &HDiskImageConst, sizeof (HDiskImageBackupVar));
51
52 return EFI_SUCCESS;
53 }
54
55 /**
56 Backup function for HDiskImage. Only a few fields need to be backup.
57 This is for making the Disk buffer refresh as few as possible.
58
59 @retval EFI_SUCCESS The operation was successful.
60 @retval EFI_OUT_OF_RESOURCES gST->ConOut of resources.
61 **/
62 EFI_STATUS
63 HDiskImageBackup (
64 VOID
65 )
66 {
67 //
68 // backup the disk name, offset and size
69 //
70 //
71 SHELL_FREE_NON_NULL (HDiskImageBackupVar.Name);
72
73 HDiskImageBackupVar.Name = CatSPrint(NULL, L"%s", HDiskImage.Name);
74 if (HDiskImageBackupVar.Name == NULL) {
75 return EFI_OUT_OF_RESOURCES;
76 }
77
78 HDiskImageBackupVar.Offset = HDiskImage.Offset;
79 HDiskImageBackupVar.Size = HDiskImage.Size;
80
81 return EFI_SUCCESS;
82 }
83
84 /**
85 Cleanup function for HDiskImage.
86
87 @retval EFI_SUCCESS The operation was successful.
88 **/
89 EFI_STATUS
90 HDiskImageCleanup (
91 VOID
92 )
93 {
94 SHELL_FREE_NON_NULL (HDiskImage.Name);
95 SHELL_FREE_NON_NULL (HDiskImageBackupVar.Name);
96
97 return EFI_SUCCESS;
98 }
99
100 /**
101 Set FileName field in HFileImage.
102
103 @param[in] Str File name to set.
104 @param[in] Offset The offset.
105 @param[in] Size The size.
106
107 @retval EFI_SUCCESS The operation was successful.
108 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
109 **/
110 EFI_STATUS
111 HDiskImageSetDiskNameOffsetSize (
112 IN CONST CHAR16 *Str,
113 IN UINTN Offset,
114 IN UINTN Size
115 )
116 {
117 if (Str == HDiskImage.Name) {
118 //
119 // This function might be called using HDiskImage.FileName as Str.
120 // Directly return without updating HDiskImage.FileName.
121 //
122 return EFI_SUCCESS;
123 }
124
125 //
126 // free the old file name
127 //
128 SHELL_FREE_NON_NULL (HDiskImage.Name);
129 HDiskImage.Name = AllocateCopyPool (StrSize (Str), Str);
130 if (HDiskImage.Name == NULL) {
131 return EFI_OUT_OF_RESOURCES;
132 }
133
134 HDiskImage.Offset = Offset;
135 HDiskImage.Size = Size;
136
137 return EFI_SUCCESS;
138 }
139
140 /**
141 Read a disk from disk into HBufferImage.
142
143 @param[in] DeviceName filename to read.
144 @param[in] Offset The offset.
145 @param[in] Size The size.
146 @param[in] Recover if is for recover, no information print.
147
148 @retval EFI_SUCCESS The operation was successful.
149 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
150 @retval EFI_LOAD_ERROR A load error occurred.
151 @retval EFI_INVALID_PARAMETER A parameter was invalid.
152 **/
153 EFI_STATUS
154 HDiskImageRead (
155 IN CONST CHAR16 *DeviceName,
156 IN UINTN Offset,
157 IN UINTN Size,
158 IN BOOLEAN Recover
159 )
160 {
161 CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath;
162 EFI_DEVICE_PATH_PROTOCOL *DupDevicePath;
163 EFI_DEVICE_PATH_PROTOCOL *DupDevicePathForFree;
164 EFI_HANDLE Handle;
165 EFI_BLOCK_IO_PROTOCOL *BlkIo;
166 EFI_STATUS Status;
167
168 VOID *Buffer;
169 CHAR16 *Str;
170 UINTN Bytes;
171
172 HEFI_EDITOR_LINE *Line;
173
174 HBufferImage.BufferType = FileTypeDiskBuffer;
175
176 DevicePath = gEfiShellProtocol->GetDevicePathFromMap(DeviceName);
177 if (DevicePath == NULL) {
178 StatusBarSetStatusString (L"Cannot Find Device");
179 return EFI_INVALID_PARAMETER;
180 }
181 DupDevicePath = DuplicateDevicePath(DevicePath);
182 DupDevicePathForFree = DupDevicePath;
183 //
184 // get blkio interface
185 //
186 Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid,&DupDevicePath,&Handle);
187 FreePool(DupDevicePathForFree);
188 if (EFI_ERROR (Status)) {
189 StatusBarSetStatusString (L"Read Disk Failed");
190 return Status;
191 }
192 Status = gBS->OpenProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID**)&BlkIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
193 if (EFI_ERROR (Status)) {
194 StatusBarSetStatusString (L"Read Disk Failed");
195 return Status;
196 }
197 //
198 // if Offset exceeds LastBlock,
199 // return error
200 //
201 if (Offset > BlkIo->Media->LastBlock || Offset + Size > BlkIo->Media->LastBlock) {
202 StatusBarSetStatusString (L"Invalid Offset + Size");
203 return EFI_LOAD_ERROR;
204 }
205
206 Bytes = BlkIo->Media->BlockSize * Size;
207 Buffer = AllocateZeroPool (Bytes);
208
209 if (Buffer == NULL) {
210 StatusBarSetStatusString (L"Read Disk Failed");
211 return EFI_OUT_OF_RESOURCES;
212 }
213
214 //
215 // read from disk
216 //
217 Status = BlkIo->ReadBlocks (
218 BlkIo,
219 BlkIo->Media->MediaId,
220 Offset,
221 Bytes,
222 Buffer
223 );
224
225 if (EFI_ERROR (Status)) {
226 FreePool (Buffer);
227 StatusBarSetStatusString (L"Read Disk Failed");
228 return EFI_LOAD_ERROR;
229 }
230
231 HBufferImageFree ();
232
233 //
234 // convert buffer to line list
235 //
236 Status = HBufferImageBufferToList (Buffer, Bytes);
237 FreePool (Buffer);
238
239 if (EFI_ERROR (Status)) {
240 StatusBarSetStatusString (L"Read Disk Failed");
241 return Status;
242 }
243
244 Status = HDiskImageSetDiskNameOffsetSize (DeviceName, Offset, Size);
245 if (EFI_ERROR (Status)) {
246 StatusBarSetStatusString (L"Read Disk Failed");
247 return EFI_OUT_OF_RESOURCES;
248 }
249 //
250 // initialize some variables
251 //
252 HDiskImage.BlockSize = BlkIo->Media->BlockSize;
253
254 HBufferImage.DisplayPosition.Row = 2;
255 HBufferImage.DisplayPosition.Column = 10;
256
257 HBufferImage.MousePosition.Row = 2;
258 HBufferImage.MousePosition.Column = 10;
259
260 HBufferImage.LowVisibleRow = 1;
261 HBufferImage.HighBits = TRUE;
262
263 HBufferImage.BufferPosition.Row = 1;
264 HBufferImage.BufferPosition.Column = 1;
265
266 if (!Recover) {
267 Str = CatSPrint(NULL, L"%d Lines Read", HBufferImage.NumLines);
268 if (Str == NULL) {
269 StatusBarSetStatusString (L"Read Disk Failed");
270 return EFI_OUT_OF_RESOURCES;
271 }
272
273 StatusBarSetStatusString (Str);
274 SHELL_FREE_NON_NULL (Str);
275
276 HMainEditor.SelectStart = 0;
277 HMainEditor.SelectEnd = 0;
278
279 }
280
281 //
282 // has line
283 //
284 if (HBufferImage.Lines != NULL) {
285 HBufferImage.CurrentLine = CR (
286 HBufferImage.ListHead->ForwardLink,
287 HEFI_EDITOR_LINE,
288 Link,
289 EFI_EDITOR_LINE_LIST
290 );
291 } else {
292 //
293 // create a dummy line
294 //
295 Line = HBufferImageCreateLine ();
296 if (Line == NULL) {
297 StatusBarSetStatusString (L"Read Disk Failed");
298 return EFI_OUT_OF_RESOURCES;
299 }
300
301 HBufferImage.CurrentLine = Line;
302 }
303
304 HBufferImage.Modified = FALSE;
305 HBufferImageNeedRefresh = TRUE;
306 HBufferImageOnlyLineNeedRefresh = FALSE;
307 HBufferImageMouseNeedRefresh = TRUE;
308
309 return EFI_SUCCESS;
310 }
311
312 /**
313 Save lines in HBufferImage to disk.
314 NOT ALLOW TO WRITE TO ANOTHER DISK!!!!!!!!!
315
316 @param[in] DeviceName The device name.
317 @param[in] Offset The offset.
318 @param[in] Size The size.
319
320 @retval EFI_SUCCESS The operation was successful.
321 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
322 @retval EFI_LOAD_ERROR A load error occurred.
323 @retval EFI_INVALID_PARAMETER A parameter was invalid.
324 **/
325 EFI_STATUS
326 HDiskImageSave (
327 IN CHAR16 *DeviceName,
328 IN UINTN Offset,
329 IN UINTN Size
330 )
331 {
332
333 CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath;
334 EFI_DEVICE_PATH_PROTOCOL *DupDevicePath;
335 EFI_DEVICE_PATH_PROTOCOL *DupDevicePathForFree;
336 EFI_BLOCK_IO_PROTOCOL *BlkIo;
337 EFI_STATUS Status;
338 EFI_HANDLE Handle;
339 VOID *Buffer;
340 UINTN Bytes;
341
342 //
343 // if not modified, directly return
344 //
345 if (HBufferImage.Modified == FALSE) {
346 return EFI_SUCCESS;
347 }
348
349 HBufferImage.BufferType = FileTypeDiskBuffer;
350
351 DevicePath = gEfiShellProtocol->GetDevicePathFromMap(DeviceName);
352 if (DevicePath == NULL) {
353 // StatusBarSetStatusString (L"Cannot Find Device");
354 return EFI_INVALID_PARAMETER;
355 }
356 DupDevicePath = DuplicateDevicePath(DevicePath);
357 DupDevicePathForFree = DupDevicePath;
358
359 //
360 // get blkio interface
361 //
362 Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid,&DupDevicePath,&Handle);
363 FreePool(DupDevicePathForFree);
364 if (EFI_ERROR (Status)) {
365 // StatusBarSetStatusString (L"Read Disk Failed");
366 return Status;
367 }
368 Status = gBS->OpenProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID**)&BlkIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
369 if (EFI_ERROR (Status)) {
370 // StatusBarSetStatusString (L"Read Disk Failed");
371 return Status;
372 }
373
374 Bytes = BlkIo->Media->BlockSize * Size;
375 Buffer = AllocateZeroPool (Bytes);
376
377 if (Buffer == NULL) {
378 return EFI_OUT_OF_RESOURCES;
379 }
380 //
381 // concatenate the line list to a buffer
382 //
383 Status = HBufferImageListToBuffer (Buffer, Bytes);
384 if (EFI_ERROR (Status)) {
385 FreePool (Buffer);
386 return Status;
387 }
388
389 //
390 // write the buffer to disk
391 //
392 Status = BlkIo->WriteBlocks (
393 BlkIo,
394 BlkIo->Media->MediaId,
395 Offset,
396 Bytes,
397 Buffer
398 );
399
400 FreePool (Buffer);
401
402 if (EFI_ERROR (Status)) {
403 return EFI_LOAD_ERROR;
404 }
405 //
406 // now not modified
407 //
408 HBufferImage.Modified = FALSE;
409
410 return EFI_SUCCESS;
411 }