]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.c
add Edit and HexEdit commands.
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / HexEdit / FileImage.c
CommitLineData
632820d1 1/** @file\r
2 Functions to deal with file buffer.\r
3\r
4 Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "HexEditor.h"\r
16\r
17extern EFI_HANDLE HImageHandleBackup;\r
18extern HEFI_EDITOR_BUFFER_IMAGE HBufferImage;\r
19\r
20extern BOOLEAN HBufferImageNeedRefresh;\r
21extern BOOLEAN HBufferImageOnlyLineNeedRefresh;\r
22extern BOOLEAN HBufferImageMouseNeedRefresh;\r
23\r
24extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;\r
25\r
26HEFI_EDITOR_FILE_IMAGE HFileImage;\r
27HEFI_EDITOR_FILE_IMAGE HFileImageBackupVar;\r
28\r
29//\r
30// for basic initialization of HFileImage\r
31//\r
32HEFI_EDITOR_BUFFER_IMAGE HFileImageConst = {\r
33 NULL,\r
34 0,\r
35 FALSE\r
36};\r
37\r
38EFI_STATUS\r
39HFileImageInit (\r
40 VOID\r
41 )\r
42/*++\r
43\r
44Routine Description: \r
45\r
46 Initialization function for HFileImage\r
47\r
48Arguments: \r
49\r
50 None\r
51\r
52Returns: \r
53\r
54 EFI_SUCCESS\r
55 EFI_LOAD_ERROR\r
56\r
57--*/\r
58{\r
59 //\r
60 // basically initialize the HFileImage\r
61 //\r
62 CopyMem (&HFileImage, &HFileImageConst, sizeof (HFileImage));\r
63\r
64 CopyMem (\r
65 &HFileImageBackupVar,\r
66 &HFileImageConst,\r
67 sizeof (HFileImageBackupVar)\r
68 );\r
69\r
70 return EFI_SUCCESS;\r
71}\r
72\r
73EFI_STATUS\r
74HFileImageBackup (\r
75 VOID\r
76 )\r
77/*++\r
78\r
79Routine Description: \r
80\r
81 Backup function for HFileImage\r
82 Only a few fields need to be backup. \r
83 This is for making the file buffer refresh \r
84 as few as possible.\r
85\r
86Arguments: \r
87\r
88 None\r
89\r
90Returns: \r
91\r
92 EFI_SUCCESS\r
93 EFI_OUT_OF_RESOURCES\r
94\r
95--*/\r
96{\r
97 SHELL_FREE_NON_NULL (HFileImageBackupVar.FileName);\r
98 HFileImageBackupVar.FileName = CatSPrint(NULL, L"%s", HFileImage.FileName);\r
99 if (HFileImageBackupVar.FileName == NULL) {\r
100 return EFI_OUT_OF_RESOURCES;\r
101 }\r
102\r
103 return EFI_SUCCESS;\r
104}\r
105\r
106EFI_STATUS\r
107HFileImageCleanup (\r
108 VOID\r
109 )\r
110/*++\r
111\r
112Routine Description: \r
113\r
114 Cleanup function for HFileImage\r
115\r
116Arguments: \r
117\r
118 None\r
119\r
120Returns: \r
121\r
122 EFI_SUCCESS\r
123\r
124--*/\r
125{\r
126\r
127 SHELL_FREE_NON_NULL (HFileImage.FileName);\r
128 SHELL_FREE_NON_NULL (HFileImageBackupVar.FileName);\r
129\r
130 return EFI_SUCCESS;\r
131}\r
132\r
133EFI_STATUS\r
134HFileImageSetFileName (\r
135 IN CONST CHAR16 *Str\r
136 )\r
137/*++\r
138\r
139Routine Description: \r
140\r
141 Set FileName field in HFileImage\r
142\r
143Arguments: \r
144\r
145 Str -- File name to set\r
146\r
147Returns: \r
148\r
149 EFI_SUCCESS\r
150 EFI_OUT_OF_RESOURCES\r
151\r
152--*/\r
153{\r
154 UINTN Size;\r
155 UINTN Index;\r
156\r
157 //\r
158 // free the old file name\r
159 //\r
160 SHELL_FREE_NON_NULL (HFileImage.FileName);\r
161\r
162 Size = StrLen (Str);\r
163\r
164 HFileImage.FileName = AllocateZeroPool (2 * (Size + 1));\r
165 if (HFileImage.FileName == NULL) {\r
166 return EFI_OUT_OF_RESOURCES;\r
167 }\r
168\r
169 for (Index = 0; Index < Size; Index++) {\r
170 HFileImage.FileName[Index] = Str[Index];\r
171 }\r
172\r
173 HFileImage.FileName[Size] = L'\0';\r
174\r
175 return EFI_SUCCESS;\r
176}\r
177\r
178EFI_STATUS\r
179HFileImageGetFileInfo (\r
180 IN EFI_FILE_HANDLE Handle,\r
181 IN CHAR16 *FileName,\r
182 OUT EFI_FILE_INFO **InfoOut\r
183 )\r
184/*++\r
185\r
186Routine Description: \r
187\r
188 Get this file's information\r
189\r
190Arguments: \r
191\r
192 Handle - in NT32 mode Directory handle, in other mode File Handle\r
193 FileName - The file name\r
194 InfoOut - parameter to pass file information out\r
195\r
196Returns: \r
197\r
198 EFI_SUCCESS\r
199 EFI_OUT_OF_RESOURCES\r
200 EFI_LOAD_ERROR\r
201\r
202--*/\r
203{\r
204\r
205 VOID *Info;\r
206 UINTN Size;\r
207 EFI_STATUS Status;\r
208\r
209 Size = SIZE_OF_EFI_FILE_INFO + 1024;\r
210 Info = AllocateZeroPool (Size);\r
211 if (!Info) {\r
212 return EFI_OUT_OF_RESOURCES;\r
213 }\r
214 //\r
215 // get file information\r
216 //\r
217 Status = Handle->GetInfo (Handle, &gEfiFileInfoGuid, &Size, Info);\r
218 if (EFI_ERROR (Status)) {\r
219 return EFI_LOAD_ERROR;\r
220 }\r
221\r
222 *InfoOut = (EFI_FILE_INFO *) Info;\r
223\r
224 return EFI_SUCCESS;\r
225\r
226}\r
227\r
228EFI_STATUS\r
229HFileImageRead (\r
230 IN CONST CHAR16 *FileName,\r
231 IN BOOLEAN Recover\r
232 )\r
233/*++\r
234\r
235Routine Description: \r
236\r
237 Read a file from disk into HBufferImage\r
238\r
239Arguments: \r
240\r
241 FileName -- filename to read\r
242 Recover -- if is for recover, no information print\r
243\r
244Returns: \r
245\r
246 EFI_SUCCESS\r
247 EFI_LOAD_ERROR\r
248 EFI_OUT_OF_RESOURCES\r
249 \r
250--*/\r
251{\r
252 HEFI_EDITOR_LINE *Line;\r
253 UINT8 *Buffer;\r
254 CHAR16 *UnicodeBuffer;\r
255 EFI_STATUS Status;\r
256\r
257 //\r
258 // variable initialization\r
259 //\r
260 Line = NULL;\r
261\r
262 //\r
263 // in this function, when you return error ( except EFI_OUT_OF_RESOURCES )\r
264 // you should set status string\r
265 // since this function maybe called before the editorhandleinput loop\r
266 // so any error will cause editor return\r
267 // so if you want to print the error status\r
268 // you should set the status string\r
269 //\r
270 Status = ReadFileIntoBuffer (FileName, (VOID**)&Buffer, &HFileImage.Size, &HFileImage.ReadOnly);\r
271 if (EFI_ERROR(Status)) {\r
272 UnicodeBuffer = CatSPrint(NULL, L"Read error on file &s: %r", FileName, Status);\r
273 if (UnicodeBuffer == NULL) {\r
274 SHELL_FREE_NON_NULL(Buffer);\r
275 return EFI_OUT_OF_RESOURCES;\r
276 }\r
277\r
278 StatusBarSetStatusString (UnicodeBuffer);\r
279 FreePool (UnicodeBuffer);\r
280 }\r
281\r
282 HFileImageSetFileName (FileName);\r
283\r
284 //\r
285 // free the old lines\r
286 //\r
287 HBufferImageFree ();\r
288\r
289 Status = HBufferImageBufferToList (Buffer, HFileImage.Size);\r
290 SHELL_FREE_NON_NULL (Buffer);\r
291 if (EFI_ERROR (Status)) {\r
292 StatusBarSetStatusString (L"Error parsing file.");\r
293 return Status;\r
294 }\r
295\r
296 HBufferImage.DisplayPosition.Row = 2;\r
297 HBufferImage.DisplayPosition.Column = 10;\r
298 HBufferImage.MousePosition.Row = 2;\r
299 HBufferImage.MousePosition.Column = 10;\r
300 HBufferImage.LowVisibleRow = 1;\r
301 HBufferImage.HighBits = TRUE;\r
302 HBufferImage.BufferPosition.Row = 1;\r
303 HBufferImage.BufferPosition.Column = 1;\r
304\r
305 if (!Recover) {\r
306 UnicodeBuffer = CatSPrint(NULL, L"%d Lines Read", HBufferImage.NumLines);\r
307 if (UnicodeBuffer == NULL) {\r
308 SHELL_FREE_NON_NULL(Buffer);\r
309 return EFI_OUT_OF_RESOURCES;\r
310 }\r
311\r
312 StatusBarSetStatusString (UnicodeBuffer);\r
313 FreePool (UnicodeBuffer);\r
314\r
315 HMainEditor.SelectStart = 0;\r
316 HMainEditor.SelectEnd = 0;\r
317 }\r
318\r
319 //\r
320 // has line\r
321 //\r
322 if (HBufferImage.Lines != 0) {\r
323 HBufferImage.CurrentLine = CR (HBufferImage.ListHead->ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
324 } else {\r
325 //\r
326 // create a dummy line\r
327 //\r
328 Line = HBufferImageCreateLine ();\r
329 if (Line == NULL) {\r
330 SHELL_FREE_NON_NULL(Buffer);\r
331 return EFI_OUT_OF_RESOURCES;\r
332 }\r
333\r
334 HBufferImage.CurrentLine = Line;\r
335 }\r
336\r
337 HBufferImage.Modified = FALSE;\r
338 HBufferImageNeedRefresh = TRUE;\r
339 HBufferImageOnlyLineNeedRefresh = FALSE;\r
340 HBufferImageMouseNeedRefresh = TRUE;\r
341\r
342 return EFI_SUCCESS;\r
343}\r
344\r
345EFI_STATUS\r
346HFileImageSave (\r
347 IN CHAR16 *FileName\r
348 )\r
349/*++\r
350\r
351Routine Description: \r
352\r
353 Save lines in HBufferImage to disk\r
354\r
355Arguments: \r
356\r
357 FileName - The file name\r
358\r
359Returns: \r
360\r
361 EFI_SUCCESS\r
362 EFI_LOAD_ERROR\r
363 EFI_OUT_OF_RESOURCES\r
364\r
365--*/\r
366{\r
367\r
368 LIST_ENTRY *Link;\r
369 HEFI_EDITOR_LINE *Line;\r
370 CHAR16 *Str;\r
371 EFI_STATUS Status;\r
372 UINTN NumLines;\r
373 SHELL_FILE_HANDLE FileHandle;\r
374 UINTN TotalSize;\r
375 UINT8 *Buffer;\r
376 UINT8 *Ptr;\r
377 EDIT_FILE_TYPE BufferTypeBackup;\r
378\r
379 BufferTypeBackup = HBufferImage.BufferType;\r
380 HBufferImage.BufferType = FileTypeFileBuffer;\r
381\r
382 //\r
383 // if is the old file\r
384 //\r
385 if (StrCmp (FileName, HFileImage.FileName) == 0) {\r
386 //\r
387 // check whether file exists on disk\r
388 //\r
389 if (ShellIsFile(FileName) == EFI_SUCCESS) {\r
390 //\r
391 // current file exists on disk\r
392 // so if not modified, then not save\r
393 //\r
394 if (HBufferImage.Modified == FALSE) {\r
395 return EFI_SUCCESS;\r
396 }\r
397 //\r
398 // if file is read-only, set error\r
399 //\r
400 if (HFileImage.ReadOnly == TRUE) {\r
401 StatusBarSetStatusString (L"Read Only File Can Not Be Saved");\r
402 return EFI_SUCCESS;\r
403 }\r
404 }\r
405 }\r
406\r
407 if (ShellIsDirectory(FileName) == EFI_SUCCESS) {\r
408 StatusBarSetStatusString (L"Directory Can Not Be Saved");\r
409 return EFI_LOAD_ERROR;\r
410 }\r
411\r
412 Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0);\r
413\r
414 if (!EFI_ERROR (Status)) {\r
415 //\r
416 // the file exits, delete it\r
417 //\r
418 Status = ShellDeleteFile (&FileHandle);\r
419 if (EFI_ERROR (Status) || Status == EFI_WARN_DELETE_FAILURE) {\r
420 StatusBarSetStatusString (L"Write File Failed");\r
421 return EFI_LOAD_ERROR;\r
422 }\r
423 }\r
424\r
425 //\r
426 // write all the lines back to disk\r
427 //\r
428 NumLines = 0;\r
429 TotalSize = 0;\r
430 for (Link = HBufferImage.ListHead->ForwardLink; Link != HBufferImage.ListHead; Link = Link->ForwardLink) {\r
431 Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
432\r
433 if (Line->Size != 0) {\r
434 TotalSize += Line->Size;\r
435 }\r
436 //\r
437 // end of if Line -> Size != 0\r
438 //\r
439 NumLines++;\r
440 }\r
441 //\r
442 // end of for Link\r
443 //\r
444 Buffer = AllocateZeroPool (TotalSize);\r
445 if (Buffer == NULL) {\r
446 return EFI_OUT_OF_RESOURCES;\r
447 }\r
448\r
449 Ptr = Buffer;\r
450 for (Link = HBufferImage.ListHead->ForwardLink; Link != HBufferImage.ListHead; Link = Link->ForwardLink) {\r
451 Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
452\r
453 if (Line->Size != 0) {\r
454 CopyMem (Ptr, Line->Buffer, Line->Size);\r
455 Ptr += Line->Size;\r
456 }\r
457 //\r
458 // end of if Line -> Size != 0\r
459 //\r
460 }\r
461\r
462\r
463 Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);\r
464\r
465 if (EFI_ERROR (Status)) {\r
466 StatusBarSetStatusString (L"Create File Failed");\r
467 return EFI_LOAD_ERROR;\r
468 }\r
469\r
470 Status = ShellWriteFile (FileHandle, &TotalSize, Buffer);\r
471 FreePool (Buffer);\r
472 if (EFI_ERROR (Status)) {\r
473 ShellDeleteFile (&FileHandle);\r
474 return EFI_LOAD_ERROR;\r
475 }\r
476\r
477 ShellCloseFile(&FileHandle);\r
478\r
479 HBufferImage.Modified = FALSE;\r
480\r
481 //\r
482 // set status string\r
483 //\r
484 Str = CatSPrint(NULL, L"%d Lines Wrote", NumLines);\r
485 StatusBarSetStatusString (Str);\r
486 FreePool (Str);\r
487\r
488 //\r
489 // now everything is ready , you can set the new file name to filebuffer\r
490 //\r
491 if (BufferTypeBackup != FileTypeFileBuffer || StringNoCaseCompare (&FileName, &HFileImage.FileName) != 0) {\r
492 //\r
493 // not the same\r
494 //\r
495 HFileImageSetFileName (FileName);\r
496 if (HFileImage.FileName == NULL) {\r
497 return EFI_OUT_OF_RESOURCES;\r
498 }\r
499 }\r
500\r
501 HFileImage.ReadOnly = FALSE;\r
502\r
503 return EFI_SUCCESS;\r
504}\r