]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.c
add Edit and HexEdit commands.
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / HexEdit / DiskImage.c
CommitLineData
632820d1 1/** @file\r
2 Functions to deal with Disk buffer.\r
3\r
4 Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "HexEditor.h"\r
16#include <Protocol/BlockIo.h>\r
17\r
18extern EFI_HANDLE HImageHandleBackup;\r
19extern HEFI_EDITOR_BUFFER_IMAGE HBufferImage;\r
20\r
21extern BOOLEAN HBufferImageNeedRefresh;\r
22extern BOOLEAN HBufferImageOnlyLineNeedRefresh;\r
23extern BOOLEAN HBufferImageMouseNeedRefresh;\r
24\r
25extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;\r
26\r
27HEFI_EDITOR_DISK_IMAGE HDiskImage;\r
28HEFI_EDITOR_DISK_IMAGE HDiskImageBackupVar;\r
29\r
30//\r
31// for basic initialization of HDiskImage\r
32//\r
33HEFI_EDITOR_DISK_IMAGE HDiskImageConst = {\r
34 NULL,\r
35 0,\r
36 0,\r
37 0\r
38};\r
39\r
40EFI_STATUS\r
41HDiskImageInit (\r
42 VOID\r
43 )\r
44/*++\r
45\r
46Routine Description: \r
47\r
48 Initialization function for HDiskImage\r
49\r
50Arguments: \r
51\r
52 None\r
53\r
54Returns: \r
55\r
56 EFI_SUCCESS\r
57 EFI_LOAD_ERROR\r
58\r
59--*/\r
60{\r
61 //\r
62 // basically initialize the HDiskImage\r
63 //\r
64 CopyMem (&HDiskImage, &HDiskImageConst, sizeof (HDiskImage));\r
65\r
66 CopyMem (&HDiskImageBackupVar, &HDiskImageConst, sizeof (HDiskImageBackupVar));\r
67\r
68 return EFI_SUCCESS;\r
69}\r
70\r
71EFI_STATUS\r
72HDiskImageBackup (\r
73 VOID\r
74 )\r
75/*++\r
76\r
77Routine Description: \r
78\r
79 Backup function for HDiskImage\r
80 Only a few fields need to be backup. \r
81 This is for making the Disk buffer refresh \r
82 as few as possible.\r
83\r
84Arguments: \r
85\r
86 None\r
87\r
88Returns: \r
89\r
90 EFI_SUCCESS - Success\r
91 EFI_OUT_OF_RESOURCES - gST->ConOut of resources\r
92\r
93--*/\r
94{\r
95 //\r
96 // backup the disk name, offset and size\r
97 //\r
98 //\r
99 SHELL_FREE_NON_NULL (HDiskImageBackupVar.Name);\r
100\r
101 HDiskImageBackupVar.Name = CatSPrint(NULL, L"%s", HDiskImage.Name);\r
102 if (HDiskImageBackupVar.Name == NULL) {\r
103 return EFI_OUT_OF_RESOURCES;\r
104 }\r
105\r
106 HDiskImageBackupVar.Offset = HDiskImage.Offset;\r
107 HDiskImageBackupVar.Size = HDiskImage.Size;\r
108\r
109 return EFI_SUCCESS;\r
110}\r
111\r
112EFI_STATUS\r
113HDiskImageCleanup (\r
114 VOID\r
115 )\r
116/*++\r
117\r
118Routine Description: \r
119\r
120 Cleanup function for HDiskImage\r
121\r
122Arguments: \r
123\r
124 None\r
125\r
126Returns: \r
127\r
128 EFI_SUCCESS\r
129\r
130--*/\r
131{\r
132 SHELL_FREE_NON_NULL (HDiskImage.Name);\r
133 SHELL_FREE_NON_NULL (HDiskImageBackupVar.Name);\r
134\r
135 return EFI_SUCCESS;\r
136}\r
137\r
138EFI_STATUS\r
139EFIAPI\r
140HDiskImageSetDiskNameOffsetSize (\r
141 IN CONST CHAR16 *Str,\r
142 IN UINTN Offset,\r
143 IN UINTN Size\r
144 )\r
145/*++\r
146\r
147Routine Description: \r
148\r
149 Set FileName field in HFileImage\r
150\r
151Arguments: \r
152\r
153 Str - File name to set\r
154 Offset - The offset\r
155 Size - The size\r
156\r
157Returns: \r
158\r
159 EFI_SUCCESS\r
160 EFI_OUT_OF_RESOURCES\r
161\r
162--*/\r
163{\r
164 UINTN Len;\r
165 UINTN Index;\r
166\r
167 //\r
168 // free the old file name\r
169 //\r
170 SHELL_FREE_NON_NULL (HDiskImage.Name);\r
171\r
172 Len = StrLen (Str);\r
173\r
174 HDiskImage.Name = AllocateZeroPool (2 * (Len + 1));\r
175 if (HDiskImage.Name == NULL) {\r
176 return EFI_OUT_OF_RESOURCES;\r
177 }\r
178\r
179 for (Index = 0; Index < Len; Index++) {\r
180 HDiskImage.Name[Index] = Str[Index];\r
181 }\r
182\r
183 HDiskImage.Name[Len] = L'\0';\r
184\r
185 HDiskImage.Offset = Offset;\r
186 HDiskImage.Size = Size;\r
187\r
188 return EFI_SUCCESS;\r
189}\r
190\r
191EFI_STATUS\r
192HDiskImageRead (\r
193 IN CONST CHAR16 *DeviceName,\r
194 IN UINTN Offset,\r
195 IN UINTN Size,\r
196 IN BOOLEAN Recover\r
197 )\r
198/*++\r
199\r
200Routine Description: \r
201\r
202 Read a disk from disk into HBufferImage\r
203\r
204Arguments: \r
205\r
206 DeviceName - filename to read\r
207 Offset - The offset\r
208 Size - The size\r
209 Recover - if is for recover, no information print\r
210\r
211Returns: \r
212\r
213 EFI_SUCCESS\r
214 EFI_LOAD_ERROR\r
215 EFI_OUT_OF_RESOURCES\r
216 EFI_INVALID_PARAMETER \r
217 \r
218--*/\r
219{\r
220 CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
221 EFI_DEVICE_PATH_PROTOCOL *DupDevicePath;\r
222 EFI_HANDLE Handle;\r
223 EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
224 EFI_STATUS Status;\r
225\r
226 VOID *Buffer;\r
227 CHAR16 *Str;\r
228 UINTN Bytes;\r
229\r
230 HEFI_EDITOR_LINE *Line;\r
231 UINT64 ByteOffset;\r
232\r
233 EDIT_FILE_TYPE BufferTypeBackup;\r
234\r
235 BufferTypeBackup = HBufferImage.BufferType;\r
236 HBufferImage.BufferType = FileTypeDiskBuffer;\r
237\r
238 DevicePath = gEfiShellProtocol->GetDevicePathFromMap(DeviceName);\r
239 if (DevicePath == NULL) {\r
240 StatusBarSetStatusString (L"Cannot Find Device");\r
241 return EFI_INVALID_PARAMETER;\r
242 }\r
243 DupDevicePath = DuplicateDevicePath(DevicePath);\r
244 //\r
245 // get blkio interface\r
246 //\r
247 Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid,&DupDevicePath,&Handle);\r
248 FreePool(DupDevicePath);\r
249 if (EFI_ERROR (Status)) {\r
250 StatusBarSetStatusString (L"Read Disk Failed");\r
251 return Status;\r
252 }\r
253 Status = gBS->OpenProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID**)&BlkIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
254 if (EFI_ERROR (Status)) {\r
255 StatusBarSetStatusString (L"Read Disk Failed");\r
256 return Status;\r
257 }\r
258 //\r
259 // if Offset exceeds LastBlock,\r
260 // return error\r
261 //\r
262 if (Offset > BlkIo->Media->LastBlock || Offset + Size > BlkIo->Media->LastBlock) {\r
263 StatusBarSetStatusString (L"Invalid Offset + Size");\r
264 return EFI_LOAD_ERROR;\r
265 }\r
266\r
267 Bytes = BlkIo->Media->BlockSize * Size;\r
268 Buffer = AllocateZeroPool (Bytes);\r
269\r
270 if (Buffer == NULL) {\r
271 StatusBarSetStatusString (L"Read Disk Failed");\r
272 return EFI_OUT_OF_RESOURCES;\r
273 }\r
274\r
275 ByteOffset = MultU64x32 (Offset, BlkIo->Media->BlockSize);\r
276\r
277 //\r
278 // read from disk\r
279 //\r
280 Status = BlkIo->ReadBlocks (\r
281 BlkIo,\r
282 BlkIo->Media->MediaId,\r
283 Offset,\r
284 Bytes,\r
285 Buffer\r
286 );\r
287\r
288 if (EFI_ERROR (Status)) {\r
289 FreePool (Buffer);\r
290 StatusBarSetStatusString (L"Read Disk Failed");\r
291 return EFI_LOAD_ERROR;\r
292 }\r
293\r
294 HBufferImageFree ();\r
295\r
296 //\r
297 // convert buffer to line list\r
298 //\r
299 Status = HBufferImageBufferToList (Buffer, Bytes);\r
300 FreePool (Buffer);\r
301\r
302 if (EFI_ERROR (Status)) {\r
303 StatusBarSetStatusString (L"Read Disk Failed");\r
304 return Status;\r
305 }\r
306\r
307 Status = HDiskImageSetDiskNameOffsetSize (DeviceName, Offset, Size);\r
308 if (EFI_ERROR (Status)) {\r
309 StatusBarSetStatusString (L"Read Disk Failed");\r
310 return EFI_OUT_OF_RESOURCES;\r
311 }\r
312 //\r
313 // initialize some variables\r
314 //\r
315 HDiskImage.BlockSize = BlkIo->Media->BlockSize;\r
316\r
317 HBufferImage.DisplayPosition.Row = 2;\r
318 HBufferImage.DisplayPosition.Column = 10;\r
319\r
320 HBufferImage.MousePosition.Row = 2;\r
321 HBufferImage.MousePosition.Column = 10;\r
322\r
323 HBufferImage.LowVisibleRow = 1;\r
324 HBufferImage.HighBits = TRUE;\r
325\r
326 HBufferImage.BufferPosition.Row = 1;\r
327 HBufferImage.BufferPosition.Column = 1;\r
328\r
329 if (!Recover) {\r
330 Str = CatSPrint(NULL, L"%d Lines Read", HBufferImage.NumLines);\r
331 if (Str == NULL) {\r
332 StatusBarSetStatusString (L"Read Disk Failed");\r
333 return EFI_OUT_OF_RESOURCES;\r
334 }\r
335\r
336 StatusBarSetStatusString (Str);\r
337 SHELL_FREE_NON_NULL (Str);\r
338\r
339 HMainEditor.SelectStart = 0;\r
340 HMainEditor.SelectEnd = 0;\r
341\r
342 }\r
343\r
344 //\r
345 // has line\r
346 //\r
347 if (HBufferImage.Lines != NULL) {\r
348 HBufferImage.CurrentLine = CR (\r
349 HBufferImage.ListHead->ForwardLink,\r
350 HEFI_EDITOR_LINE,\r
351 Link,\r
352 EFI_EDITOR_LINE_LIST\r
353 );\r
354 } else {\r
355 //\r
356 // create a dummy line\r
357 //\r
358 Line = HBufferImageCreateLine ();\r
359 if (Line == NULL) {\r
360 StatusBarSetStatusString (L"Read Disk Failed");\r
361 return EFI_OUT_OF_RESOURCES;\r
362 }\r
363\r
364 HBufferImage.CurrentLine = Line;\r
365 }\r
366\r
367 HBufferImage.Modified = FALSE;\r
368 HBufferImageNeedRefresh = TRUE;\r
369 HBufferImageOnlyLineNeedRefresh = FALSE;\r
370 HBufferImageMouseNeedRefresh = TRUE;\r
371\r
372 return EFI_SUCCESS;\r
373}\r
374\r
375EFI_STATUS\r
376HDiskImageSave (\r
377 IN CHAR16 *DeviceName,\r
378 IN UINTN Offset,\r
379 IN UINTN Size\r
380 )\r
381/*++\r
382\r
383Routine Description: \r
384\r
385 Save lines in HBufferImage to disk\r
386 NOT ALLOW TO WRITE TO ANOTHER DISK!!!!!!!!!\r
387\r
388Arguments: \r
389\r
390 DeviceName - The device name\r
391 Offset - The offset\r
392 Size - The size\r
393\r
394Returns: \r
395\r
396 EFI_SUCCESS\r
397 EFI_LOAD_ERROR\r
398 EFI_OUT_OF_RESOURCES\r
399 EFI_INVALID_PARAMETER\r
400\r
401--*/\r
402{\r
403\r
404 CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
405 EFI_DEVICE_PATH_PROTOCOL *DupDevicePath;\r
406 EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
407 EFI_STATUS Status;\r
408 EFI_HANDLE Handle;\r
409 VOID *Buffer;\r
410 UINTN Bytes;\r
411\r
412 UINT64 ByteOffset;\r
413\r
414 EDIT_FILE_TYPE BufferTypeBackup;\r
415\r
416 //\r
417 // if not modified, directly return\r
418 //\r
419 if (HBufferImage.Modified == FALSE) {\r
420 return EFI_SUCCESS;\r
421 }\r
422\r
423 BufferTypeBackup = HBufferImage.BufferType;\r
424 HBufferImage.BufferType = FileTypeDiskBuffer;\r
425\r
426 DevicePath = gEfiShellProtocol->GetDevicePathFromMap(DeviceName);\r
427 if (DevicePath == NULL) {\r
428// StatusBarSetStatusString (L"Cannot Find Device");\r
429 return EFI_INVALID_PARAMETER;\r
430 }\r
431 DupDevicePath = DuplicateDevicePath(DevicePath);\r
432\r
433 //\r
434 // get blkio interface\r
435 //\r
436 Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid,&DupDevicePath,&Handle);\r
437 FreePool(DupDevicePath);\r
438 if (EFI_ERROR (Status)) {\r
439// StatusBarSetStatusString (L"Read Disk Failed");\r
440 return Status;\r
441 }\r
442 Status = gBS->OpenProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID**)&BlkIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
443 if (EFI_ERROR (Status)) {\r
444// StatusBarSetStatusString (L"Read Disk Failed");\r
445 return Status;\r
446 }\r
447\r
448 Bytes = BlkIo->Media->BlockSize * Size;\r
449 Buffer = AllocateZeroPool (Bytes);\r
450\r
451 if (Buffer == NULL) {\r
452 return EFI_OUT_OF_RESOURCES;\r
453 }\r
454 //\r
455 // concatenate the line list to a buffer\r
456 //\r
457 Status = HBufferImageListToBuffer (Buffer, Bytes);\r
458 if (EFI_ERROR (Status)) {\r
459 FreePool (Buffer);\r
460 return Status;\r
461 }\r
462\r
463 ByteOffset = MultU64x32 (Offset, BlkIo->Media->BlockSize);\r
464\r
465 //\r
466 // write the buffer to disk\r
467 //\r
468 Status = BlkIo->WriteBlocks (\r
469 BlkIo,\r
470 BlkIo->Media->MediaId,\r
471 Offset,\r
472 Bytes,\r
473 Buffer\r
474 );\r
475\r
476 FreePool (Buffer);\r
477\r
478 if (EFI_ERROR (Status)) {\r
479 return EFI_LOAD_ERROR;\r
480 }\r
481 //\r
482 // now not modified\r
483 //\r
484 HBufferImage.Modified = FALSE;\r
485\r
486 return EFI_SUCCESS;\r
487}\r