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