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