1 /** @file
2 Functions to deal with file buffer.
3
4 Copyright (c) 2005 - 2015, 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
17 extern EFI_HANDLE HImageHandleBackup;
18 extern HEFI_EDITOR_BUFFER_IMAGE HBufferImage;
19
20 extern BOOLEAN HBufferImageNeedRefresh;
21 extern BOOLEAN HBufferImageOnlyLineNeedRefresh;
22 extern BOOLEAN HBufferImageMouseNeedRefresh;
23
24 extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;
25
26 HEFI_EDITOR_FILE_IMAGE HFileImage;
27 HEFI_EDITOR_FILE_IMAGE HFileImageBackupVar;
28
29 //
30 // for basic initialization of HFileImage
31 //
32 HEFI_EDITOR_BUFFER_IMAGE HFileImageConst = {
33 NULL,
34 0,
35 FALSE
36 };
37
38 /**
39 Initialization function for HFileImage
40
41 @retval EFI_SUCCESS The operation was successful.
42 **/
43 EFI_STATUS
HFileImageInit(VOID)44 HFileImageInit (
45 VOID
46 )
47 {
48 //
49 // basically initialize the HFileImage
50 //
51 CopyMem (&HFileImage, &HFileImageConst, sizeof (HFileImage));
52
53 CopyMem (
54 &HFileImageBackupVar,
55 &HFileImageConst,
56 sizeof (HFileImageBackupVar)
57 );
58
59 return EFI_SUCCESS;
60 }
61
62 /**
63 Backup function for HFileImage. Only a few fields need to be backup.
64 This is for making the file buffer refresh as few as possible.
65
66 @retval EFI_SUCCESS The operation was successful.
67 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
68 **/
69 EFI_STATUS
HFileImageBackup(VOID)70 HFileImageBackup (
71 VOID
72 )
73 {
74 SHELL_FREE_NON_NULL (HFileImageBackupVar.FileName);
75 HFileImageBackupVar.FileName = CatSPrint(NULL, L"%s", HFileImage.FileName);
76 if (HFileImageBackupVar.FileName == NULL) {
77 return EFI_OUT_OF_RESOURCES;
78 }
79
80 return EFI_SUCCESS;
81 }
82
83 /**
84 Cleanup function for HFileImage.
85
86 @retval EFI_SUCCESS The operation was successful.
87 **/
88 EFI_STATUS
HFileImageCleanup(VOID)89 HFileImageCleanup (
90 VOID
91 )
92 {
93
94 SHELL_FREE_NON_NULL (HFileImage.FileName);
95 SHELL_FREE_NON_NULL (HFileImageBackupVar.FileName);
96
97 return EFI_SUCCESS;
98 }
99
100 /**
101 Set FileName field in HFileImage
102
103 @param[in] Str File name to set.
104
105 @retval EFI_SUCCESS The operation was successful.
106 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
107 **/
108 EFI_STATUS
HFileImageSetFileName(IN CONST CHAR16 * Str)109 HFileImageSetFileName (
110 IN CONST CHAR16 *Str
111 )
112 {
113 UINTN Size;
114 UINTN Index;
115
116 //
117 // free the old file name
118 //
119 SHELL_FREE_NON_NULL (HFileImage.FileName);
120
121 Size = StrLen (Str);
122
123 HFileImage.FileName = AllocateZeroPool (2 * (Size + 1));
124 if (HFileImage.FileName == NULL) {
125 return EFI_OUT_OF_RESOURCES;
126 }
127
128 for (Index = 0; Index < Size; Index++) {
129 HFileImage.FileName[Index] = Str[Index];
130 }
131
132 HFileImage.FileName[Size] = L'\0';
133
134 return EFI_SUCCESS;
135 }
136
137 /**
138 Read a file from disk into HBufferImage.
139
140 @param[in] FileName filename to read.
141 @param[in] Recover if is for recover, no information print.
142
143 @retval EFI_SUCCESS The operation was successful.
144 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
145 @retval EFI_LOAD_ERROR A load error occured.
146 **/
147 EFI_STATUS
HFileImageRead(IN CONST CHAR16 * FileName,IN BOOLEAN Recover)148 HFileImageRead (
149 IN CONST CHAR16 *FileName,
150 IN BOOLEAN Recover
151 )
152 {
153 HEFI_EDITOR_LINE *Line;
154 UINT8 *Buffer;
155 CHAR16 *UnicodeBuffer;
156 EFI_STATUS Status;
157
158 //
159 // variable initialization
160 //
161 Line = NULL;
162
163 //
164 // in this function, when you return error ( except EFI_OUT_OF_RESOURCES )
165 // you should set status string
166 // since this function maybe called before the editorhandleinput loop
167 // so any error will cause editor return
168 // so if you want to print the error status
169 // you should set the status string
170 //
171 Status = ReadFileIntoBuffer (FileName, (VOID**)&Buffer, &HFileImage.Size, &HFileImage.ReadOnly);
172 //
173 // NULL pointer is only also a failure for a non-zero file size.
174 //
175 if ((EFI_ERROR(Status)) || (Buffer == NULL && HFileImage.Size != 0)) {
176 UnicodeBuffer = CatSPrint(NULL, L"Read error on file %s: %r", FileName, Status);
177 if (UnicodeBuffer == NULL) {
178 SHELL_FREE_NON_NULL(Buffer);
179 return EFI_OUT_OF_RESOURCES;
180 }
181
182 StatusBarSetStatusString (UnicodeBuffer);
183 FreePool (UnicodeBuffer);
184 return EFI_OUT_OF_RESOURCES;
185 }
186
187 HFileImageSetFileName (FileName);
188
189 //
190 // free the old lines
191 //
192 HBufferImageFree ();
193
194 Status = HBufferImageBufferToList (Buffer, HFileImage.Size);
195 SHELL_FREE_NON_NULL (Buffer);
196 if (EFI_ERROR (Status)) {
197 StatusBarSetStatusString (L"Error parsing file.");
198 return Status;
199 }
200
201 HBufferImage.DisplayPosition.Row = 2;
202 HBufferImage.DisplayPosition.Column = 10;
203 HBufferImage.MousePosition.Row = 2;
204 HBufferImage.MousePosition.Column = 10;
205 HBufferImage.LowVisibleRow = 1;
206 HBufferImage.HighBits = TRUE;
207 HBufferImage.BufferPosition.Row = 1;
208 HBufferImage.BufferPosition.Column = 1;
209 HBufferImage.BufferType = FileTypeFileBuffer;
210
211 if (!Recover) {
212 UnicodeBuffer = CatSPrint(NULL, L"%d Lines Read", HBufferImage.NumLines);
213 if (UnicodeBuffer == NULL) {
214 SHELL_FREE_NON_NULL(Buffer);
215 return EFI_OUT_OF_RESOURCES;
216 }
217
218 StatusBarSetStatusString (UnicodeBuffer);
219 FreePool (UnicodeBuffer);
220
221 HMainEditor.SelectStart = 0;
222 HMainEditor.SelectEnd = 0;
223 }
224
225 //
226 // has line
227 //
228 if (HBufferImage.Lines != 0) {
229 HBufferImage.CurrentLine = CR (HBufferImage.ListHead->ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
230 } else {
231 //
232 // create a dummy line
233 //
234 Line = HBufferImageCreateLine ();
235 if (Line == NULL) {
236 SHELL_FREE_NON_NULL(Buffer);
237 return EFI_OUT_OF_RESOURCES;
238 }
239
240 HBufferImage.CurrentLine = Line;
241 }
242
243 HBufferImage.Modified = FALSE;
244 HBufferImageNeedRefresh = TRUE;
245 HBufferImageOnlyLineNeedRefresh = FALSE;
246 HBufferImageMouseNeedRefresh = TRUE;
247
248 return EFI_SUCCESS;
249 }
250
251 /**
252 Save lines in HBufferImage to disk.
253
254 @param[in] FileName The file name.
255
256 @retval EFI_SUCCESS The operation was successful.
257 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
258 @retval EFI_LOAD_ERROR A load error occured.
259 **/
260 EFI_STATUS
HFileImageSave(IN CHAR16 * FileName)261 HFileImageSave (
262 IN CHAR16 *FileName
263 )
264 {
265
266 LIST_ENTRY *Link;
267 HEFI_EDITOR_LINE *Line;
268 CHAR16 *Str;
269 EFI_STATUS Status;
270 UINTN NumLines;
271 SHELL_FILE_HANDLE FileHandle;
272 UINTN TotalSize;
273 UINT8 *Buffer;
274 UINT8 *Ptr;
275 EDIT_FILE_TYPE BufferTypeBackup;
276
277 BufferTypeBackup = HBufferImage.BufferType;
278 HBufferImage.BufferType = FileTypeFileBuffer;
279
280 //
281 // if is the old file
282 //
283 if (HFileImage.FileName != NULL && FileName != NULL && StrCmp (FileName, HFileImage.FileName) == 0) {
284 //
285 // check whether file exists on disk
286 //
287 if (ShellIsFile(FileName) == EFI_SUCCESS) {
288 //
289 // current file exists on disk
290 // so if not modified, then not save
291 //
292 if (HBufferImage.Modified == FALSE) {
293 return EFI_SUCCESS;
294 }
295 //
296 // if file is read-only, set error
297 //
298 if (HFileImage.ReadOnly == TRUE) {
299 StatusBarSetStatusString (L"Read Only File Can Not Be Saved");
300 return EFI_SUCCESS;
301 }
302 }
303 }
304
305 if (ShellIsDirectory(FileName) == EFI_SUCCESS) {
306 StatusBarSetStatusString (L"Directory Can Not Be Saved");
307 return EFI_LOAD_ERROR;
308 }
309
310 Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0);
311
312 if (!EFI_ERROR (Status)) {
313 //
314 // the file exits, delete it
315 //
316 Status = ShellDeleteFile (&FileHandle);
317 if (EFI_ERROR (Status) || Status == EFI_WARN_DELETE_FAILURE) {
318 StatusBarSetStatusString (L"Write File Failed");
319 return EFI_LOAD_ERROR;
320 }
321 }
322
323 //
324 // write all the lines back to disk
325 //
326 NumLines = 0;
327 TotalSize = 0;
328 for (Link = HBufferImage.ListHead->ForwardLink; Link != HBufferImage.ListHead; Link = Link->ForwardLink) {
329 Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
330
331 if (Line->Size != 0) {
332 TotalSize += Line->Size;
333 }
334 //
335 // end of if Line -> Size != 0
336 //
337 NumLines++;
338 }
339 //
340 // end of for Link
341 //
342 Buffer = AllocateZeroPool (TotalSize);
343 if (Buffer == NULL) {
344 return EFI_OUT_OF_RESOURCES;
345 }
346
347 Ptr = Buffer;
348 for (Link = HBufferImage.ListHead->ForwardLink; Link != HBufferImage.ListHead; Link = Link->ForwardLink) {
349 Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
350
351 if (Line->Size != 0) {
352 CopyMem (Ptr, Line->Buffer, Line->Size);
353 Ptr += Line->Size;
354 }
355 //
356 // end of if Line -> Size != 0
357 //
358 }
359
360
361 Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
362
363 if (EFI_ERROR (Status)) {
364 StatusBarSetStatusString (L"Create File Failed");
365 return EFI_LOAD_ERROR;
366 }
367
368 Status = ShellWriteFile (FileHandle, &TotalSize, Buffer);
369 FreePool (Buffer);
370 if (EFI_ERROR (Status)) {
371 ShellDeleteFile (&FileHandle);
372 return EFI_LOAD_ERROR;
373 }
374
375 ShellCloseFile(&FileHandle);
376
377 HBufferImage.Modified = FALSE;
378
379 //
380 // set status string
381 //
382 Str = CatSPrint(NULL, L"%d Lines Wrote", NumLines);
383 StatusBarSetStatusString (Str);
384 FreePool (Str);
385
386 //
387 // now everything is ready , you can set the new file name to filebuffer
388 //
389 if ((BufferTypeBackup != FileTypeFileBuffer && FileName != NULL) ||
390 (FileName != NULL && HFileImage.FileName != NULL && StringNoCaseCompare (&FileName, &HFileImage.FileName) != 0)){
391 //
392 // not the same
393 //
394 HFileImageSetFileName (FileName);
395 if (HFileImage.FileName == NULL) {
396 return EFI_OUT_OF_RESOURCES;
397 }
398 }
399
400 HFileImage.ReadOnly = FALSE;
401
402 return EFI_SUCCESS;
403 }
404