]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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 SHELL_FREE_NON_NULL (HFileImage.FileName);
88 SHELL_FREE_NON_NULL (HFileImageBackupVar.FileName);
89
90 return EFI_SUCCESS;
91 }
92
93 /**
94 Set FileName field in HFileImage
95
96 @param[in] Str File name to set.
97
98 @retval EFI_SUCCESS The operation was successful.
99 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
100 **/
101 EFI_STATUS
102 HFileImageSetFileName (
103 IN CONST CHAR16 *Str
104 )
105 {
106 if (Str == HFileImage.FileName) {
107 //
108 // This function might be called using HFileImage.FileName as Str.
109 // Directly return without updating HFileImage.FileName.
110 //
111 return EFI_SUCCESS;
112 }
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 occurred.
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 occurred.
248 **/
249 EFI_STATUS
250 HFileImageSave (
251 IN CHAR16 *FileName
252 )
253 {
254 LIST_ENTRY *Link;
255 HEFI_EDITOR_LINE *Line;
256 CHAR16 *Str;
257 EFI_STATUS Status;
258 UINTN NumLines;
259 SHELL_FILE_HANDLE FileHandle;
260 UINTN TotalSize;
261 UINT8 *Buffer;
262 UINT8 *Ptr;
263 EDIT_FILE_TYPE BufferTypeBackup;
264
265 BufferTypeBackup = HBufferImage.BufferType;
266 HBufferImage.BufferType = FileTypeFileBuffer;
267
268 //
269 // if is the old file
270 //
271 if ((HFileImage.FileName != NULL) && (FileName != NULL) && (StrCmp (FileName, HFileImage.FileName) == 0)) {
272 //
273 // check whether file exists on disk
274 //
275 if (ShellIsFile (FileName) == EFI_SUCCESS) {
276 //
277 // current file exists on disk
278 // so if not modified, then not save
279 //
280 if (HBufferImage.Modified == FALSE) {
281 return EFI_SUCCESS;
282 }
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 //
325 // end of if Line -> Size != 0
326 //
327 NumLines++;
328 }
329
330 //
331 // end of for Link
332 //
333 Buffer = AllocateZeroPool (TotalSize);
334 if (Buffer == NULL) {
335 return EFI_OUT_OF_RESOURCES;
336 }
337
338 Ptr = Buffer;
339 for (Link = HBufferImage.ListHead->ForwardLink; Link != HBufferImage.ListHead; Link = Link->ForwardLink) {
340 Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
341
342 if (Line->Size != 0) {
343 CopyMem (Ptr, Line->Buffer, Line->Size);
344 Ptr += Line->Size;
345 }
346
347 //
348 // end of if Line -> Size != 0
349 //
350 }
351
352 Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
353
354 if (EFI_ERROR (Status)) {
355 StatusBarSetStatusString (L"Create File Failed");
356 return EFI_LOAD_ERROR;
357 }
358
359 Status = ShellWriteFile (FileHandle, &TotalSize, Buffer);
360 FreePool (Buffer);
361 if (EFI_ERROR (Status)) {
362 ShellDeleteFile (&FileHandle);
363 return EFI_LOAD_ERROR;
364 }
365
366 ShellCloseFile (&FileHandle);
367
368 HBufferImage.Modified = FALSE;
369
370 //
371 // set status string
372 //
373 Str = CatSPrint (NULL, L"%d Lines Written", NumLines);
374 StatusBarSetStatusString (Str);
375 FreePool (Str);
376
377 //
378 // now everything is ready , you can set the new file name to filebuffer
379 //
380 if (((BufferTypeBackup != FileTypeFileBuffer) && (FileName != NULL)) ||
381 ((FileName != NULL) && (HFileImage.FileName != NULL) && (StringNoCaseCompare (&FileName, &HFileImage.FileName) != 0)))
382 {
383 //
384 // not the same
385 //
386 HFileImageSetFileName (FileName);
387 if (HFileImage.FileName == NULL) {
388 return EFI_OUT_OF_RESOURCES;
389 }
390 }
391
392 HFileImage.ReadOnly = FALSE;
393
394 return EFI_SUCCESS;
395 }