FileImage.c 10 KB

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