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