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