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