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