• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2     Defines the Main Editor data type -
3      - Global variables
4      - Instances of the other objects of the editor
5      - Main Interfaces
6 
7   Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved. <BR>
8   This program and the accompanying materials
9   are licensed and made available under the terms and conditions of the BSD License
10   which accompanies this distribution.  The full text of the license may be found at
11   http://opensource.org/licenses/bsd-license.php
12 
13   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 
16 **/
17 
18 #include "HexEditor.h"
19 #include "EditStatusBar.h"
20 #include "EditInputBar.h"
21 
22 HEFI_EDITOR_COLOR_ATTRIBUTES    HOriginalColors;
23 INTN                            HOriginalMode;
24 
25 //
26 // the first time editor launch
27 //
28 BOOLEAN                         HEditorFirst;
29 
30 //
31 // it's time editor should exit
32 //
33 BOOLEAN                         HEditorExit;
34 
35 BOOLEAN                         HEditorMouseAction;
36 
37 extern HEFI_EDITOR_BUFFER_IMAGE HBufferImage;
38 extern HEFI_EDITOR_BUFFER_IMAGE HBufferImageBackupVar;
39 
40 extern BOOLEAN                  HBufferImageMouseNeedRefresh;
41 extern BOOLEAN                  HBufferImageNeedRefresh;
42 extern BOOLEAN                  HBufferImageOnlyLineNeedRefresh;
43 
44 HEFI_EDITOR_GLOBAL_EDITOR       HMainEditor;
45 HEFI_EDITOR_GLOBAL_EDITOR       HMainEditorBackupVar;
46 
47 //
48 // basic initialization for MainEditor
49 //
50 HEFI_EDITOR_GLOBAL_EDITOR       HMainEditorConst = {
51   &HBufferImage,
52   {
53     {0, 0}
54   },
55   {
56     0,
57     0
58   },
59   FALSE,
60   NULL,
61   0,
62   0,
63   1,
64   1
65 };
66 
67 /**
68   Help info that will be displayed.
69 **/
70 EFI_STRING_ID  HexMainMenuHelpInfo[] = {
71   STRING_TOKEN(STR_HEXEDIT_HELP_TITLE),
72   STRING_TOKEN(STR_HEXEDIT_HELP_BLANK),
73   STRING_TOKEN(STR_HEXEDIT_HELP_LIST_TITLE),
74   STRING_TOKEN(STR_HEXEDIT_HELP_DIV),
75   STRING_TOKEN(STR_HEXEDIT_HELP_GO_TO_OFFSET),
76   STRING_TOKEN(STR_HEXEDIT_HELP_SAVE_BUFFER),
77   STRING_TOKEN(STR_HEXEDIT_HELP_EXIT),
78   STRING_TOKEN(STR_HEXEDIT_HELP_SELECT_START),
79   STRING_TOKEN(STR_HEXEDIT_HELP_SELECT_END),
80   STRING_TOKEN(STR_HEXEDIT_HELP_CUT),
81   STRING_TOKEN(STR_HEXEDIT_HELP_PASTE),
82   STRING_TOKEN(STR_HEXEDIT_HELP_OPEN_FILE),
83   STRING_TOKEN(STR_HEXEDIT_HELP_OPEN_DISK),
84   STRING_TOKEN(STR_HEXEDIT_HELP_OPEN_MEMORY),
85   STRING_TOKEN(STR_HEXEDIT_HELP_BLANK),
86   STRING_TOKEN(STR_HEXEDIT_HELP_EXIT_HELP),
87   STRING_TOKEN(STR_HEXEDIT_HELP_BLANK),
88   STRING_TOKEN(STR_HEXEDIT_HELP_BLANK),
89   STRING_TOKEN(STR_HEXEDIT_HELP_BLANK),
90   STRING_TOKEN(STR_HEXEDIT_HELP_BLANK),
91   STRING_TOKEN(STR_HEXEDIT_HELP_BLANK),
92   STRING_TOKEN(STR_HEXEDIT_HELP_BLANK),
93   STRING_TOKEN(STR_HEXEDIT_HELP_DIV),
94   0
95 };
96 
97 
98 /**
99   show help menu.
100 
101   @retval EFI_SUCCESS             The operation was successful.
102 **/
103 EFI_STATUS
HMainCommandDisplayHelp(VOID)104 HMainCommandDisplayHelp (
105   VOID
106   )
107 {
108   INT32    CurrentLine;
109   CHAR16 * InfoString;
110   EFI_INPUT_KEY  Key;
111 
112   CurrentLine = 0;
113   // print helpInfo
114   for (CurrentLine = 0; 0 != HexMainMenuHelpInfo[CurrentLine]; CurrentLine++) {
115     InfoString = HiiGetString(gShellDebug1HiiHandle, HexMainMenuHelpInfo[CurrentLine]
116 , NULL);
117     ShellPrintEx (0,CurrentLine+1,L"%E%s%N",InfoString);
118   }
119 
120   // scan for ctrl+w
121   do {
122     gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
123   } while(SCAN_CONTROL_W != Key.UnicodeChar);
124 
125   // update screen with buffer's info
126   HBufferImageNeedRefresh = TRUE;
127   HBufferImageOnlyLineNeedRefresh = FALSE;
128   HBufferImageRefresh ();
129 
130   return EFI_SUCCESS;
131 }
132 
133 /**
134   Move cursor to specified lines.
135 
136   @retval EFI_SUCCESS   The operation was successful.
137 **/
138 EFI_STATUS
HMainCommandGoToOffset(VOID)139 HMainCommandGoToOffset (
140   VOID
141   )
142 {
143   UINTN       Size;
144   UINT64      Offset;
145   EFI_STATUS  Status;
146   UINTN       FRow;
147   UINTN       FCol;
148 
149   //
150   // variable initialization
151   //
152   Size    = 0;
153   Offset  = 0;
154   FRow    = 0;
155   FCol    = 0;
156 
157   //
158   // get offset
159   //
160   Status = InputBarSetPrompt (L"Go To Offset: ");
161   if (EFI_ERROR (Status)) {
162     return Status;
163   }
164 
165   Status = InputBarSetStringSize (8);
166   if (EFI_ERROR (Status)) {
167     return Status;
168   }
169 
170   while (1) {
171     Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
172 
173     //
174     // ESC pressed
175     //
176     if (Status == EFI_NOT_READY) {
177 
178       return EFI_SUCCESS;
179     }
180     //
181     // THE input string length should > 0
182     //
183     if (StrLen (InputBarGetString()) > 0) {
184       Status = ShellConvertStringToUint64 (InputBarGetString(), &Offset, TRUE, FALSE);
185       if (EFI_ERROR (Status)) {
186         StatusBarSetStatusString (L"Invalid Offset");
187         return EFI_SUCCESS;
188       }
189 
190       break;
191     }
192   }
193 
194   Size = HBufferImageGetTotalSize ();
195   if (Offset >= Size) {
196     StatusBarSetStatusString (L"Invalid Offset");
197     return EFI_SUCCESS;
198   }
199 
200   FRow  = (UINTN)DivU64x32(Offset , 0x10) + 1;
201   FCol  = (UINTN)ModU64x32(Offset , 0x10) + 1;
202 
203   HBufferImageMovePosition (FRow, FCol, TRUE);
204 
205   HBufferImageNeedRefresh         = TRUE;
206   HBufferImageOnlyLineNeedRefresh = FALSE;
207   HBufferImageMouseNeedRefresh    = TRUE;
208 
209   return EFI_SUCCESS;
210 }
211 
212 /**
213   Save current opened buffer.
214   If is file buffer, you can save to current file name or
215   save to another file name.
216 
217   @retval EFI_SUCCESS             The operation was successful.
218   @retval EFI_OUT_OF_RESOURCES    A memory allocation occured.
219   @retval EFI_LOAD_ERROR          A load error occured.
220 **/
221 EFI_STATUS
HMainCommandSaveBuffer(VOID)222 HMainCommandSaveBuffer (
223   VOID
224   )
225 {
226   EFI_STATUS          Status;
227   BOOLEAN             Done;
228   CHAR16              *FileName;
229   BOOLEAN             OldFile;
230   CHAR16              *Str;
231   EFI_FILE_INFO       *Info;
232   SHELL_FILE_HANDLE   ShellFileHandle;
233 
234   if (HMainEditor.BufferImage->BufferType != FileTypeFileBuffer) {
235     if (!HMainEditor.BufferImage->Modified) {
236       return EFI_SUCCESS;
237     }
238 
239     Status = InputBarSetPrompt (L"Dangerous to save disk/mem buffer. Save (Yes/No/Cancel) ? ");
240     if (EFI_ERROR (Status)) {
241       return Status;
242     }
243     //
244     // the answer is just one character
245     //
246     Status = InputBarSetStringSize (1);
247     if (EFI_ERROR (Status)) {
248       return Status;
249     }
250     //
251     // loop for user's answer
252     // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'
253     //
254     while (1) {
255       Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
256 
257       //
258       // ESC pressed
259       //
260       if (Status == EFI_NOT_READY) {
261         return EFI_SUCCESS;
262       }
263 
264       switch (InputBarGetString()[0]) {
265       case L'y':
266       case L'Y':
267         //
268         // want to save this buffer first
269         //
270         Status = HBufferImageSave (
271                   NULL,
272                   HMainEditor.BufferImage->DiskImage->Name,
273                   HMainEditor.BufferImage->DiskImage->Offset,
274                   HMainEditor.BufferImage->DiskImage->Size,
275                   HMainEditor.BufferImage->MemImage->Offset,
276                   HMainEditor.BufferImage->MemImage->Size,
277                   HMainEditor.BufferImage->BufferType
278                   );
279 
280         if (EFI_ERROR (Status)) {
281           StatusBarSetStatusString (L"BufferSave: Problems Writing");
282           return Status;
283         }
284 
285         return EFI_SUCCESS;
286 
287       case L'n':
288       case L'N':
289         //
290         // the file won't be saved
291         //
292         return EFI_SUCCESS;
293 
294       case L'c':
295       case L'C':
296         return EFI_SUCCESS;
297       }
298       //
299       // end of switch
300       //
301     }
302     //
303     // ENDOF WHILE
304     //
305   }
306   //
307   // ENDOF != FILEBUFFER
308   //
309   // This command will save currently opened file to disk.
310   // You can choose save to another file name or just save to
311   // current file name.
312   // Below is the scenario of Save File command: (
313   //    Suppose the old file name is A )
314   // 1. An Input Bar will be prompted:    "File To Save: [ old file name]"
315   //    IF user press ESC, Save File command ends .
316   //    IF user press Enter, input file name will be A.
317   //    IF user inputs a new file name B,  input file name will be B.
318   //
319   // 2. IF input file name is A, go to do Step 3.
320   //    IF input file name is B, go to do Step 4.
321   //
322   // 3. IF A is read only, Status Bar will show "Access Denied"
323   //       and Save File commands ends.
324   //    IF A is not read only, save file buffer to disk
325   //       and remove Modified flag in Title Bar , then Save File command ends.
326   //
327   // 4. IF B does not exist, create this file and save file buffer to it.
328   //       Go to do Step 7.
329   //    IF B exits, do Step 5.
330   //
331   // 5. An Input Bar will be prompted:
332   //       "File Exists. Overwrite ( Yes/No/Cancel ) ?"
333   //      IF user press 'y' or 'Y', do Step 6.
334   //      IF user press 'n' or 'N', Save File commands ends.
335   //      IF user press 'c' or 'C' or ESC, Save File commands ends.
336   //
337   // 6. IF B is a read-only file, Status Bar will show "Access Denied"
338   //       and Save File commands ends.
339   //    IF B can be read and write, save file buffer to B.
340   //
341   // 7. Update File Name field in Title Bar to B
342   //       and remove the Modified flag in Title Bar.
343   //
344   Str = CatSPrint(NULL,
345           L"File to Save: [%s]",
346           HMainEditor.BufferImage->FileImage->FileName
347           );
348   if (Str == NULL) {
349     return EFI_OUT_OF_RESOURCES;
350   }
351 
352   if (StrLen (Str) >= 50) {
353     //
354     // replace the long file name with "..."
355     //
356     Str[46] = L'.';
357     Str[47] = L'.';
358     Str[48] = L'.';
359     Str[49] = L']';
360     Str[50] = L'\0';
361   }
362 
363   Status = InputBarSetPrompt (Str);
364   if (EFI_ERROR (Status)) {
365     return Status;
366   }
367 
368   Status = InputBarSetStringSize (100);
369   if (EFI_ERROR (Status)) {
370     return Status;
371   }
372   //
373   // get new file name
374   //
375   Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
376 
377   //
378   // if user pressed ESC
379   //
380   if (Status == EFI_NOT_READY) {
381     SHELL_FREE_NON_NULL (Str);
382     return EFI_SUCCESS;
383   }
384 
385   SHELL_FREE_NON_NULL (Str);
386 
387   //
388   // if just enter pressed, so think save to current file name
389   //
390   if (StrLen (InputBarGetString()) == 0) {
391     FileName = CatSPrint(NULL,
392                 L"%s",
393                 HMainEditor.BufferImage->FileImage->FileName
394                 );
395   } else {
396     FileName = CatSPrint(NULL, L"%s", InputBarGetString());
397   }
398 
399   if (FileName == NULL) {
400     return EFI_OUT_OF_RESOURCES;
401   }
402 
403   if (!IsValidFileName (FileName)) {
404     StatusBarSetStatusString (L"Invalid File Name");
405     SHELL_FREE_NON_NULL (FileName);
406     return EFI_SUCCESS;
407   }
408 
409   OldFile = FALSE;
410 
411   //
412   // save to the old file
413   //
414   if (StringNoCaseCompare (
415         &FileName,
416         &HMainEditor.BufferImage->FileImage->FileName
417         ) == 0) {
418     OldFile = TRUE;
419   }
420 
421   if (OldFile) {
422     //
423     // if the file is read only, so can not write back to it.
424     //
425     if (HMainEditor.BufferImage->FileImage->ReadOnly) {
426       StatusBarSetStatusString (L"Access Denied");
427       SHELL_FREE_NON_NULL (FileName);
428       return EFI_SUCCESS;
429     }
430   } else {
431     Status = ShellOpenFileByName (FileName, &ShellFileHandle, EFI_FILE_MODE_READ, 0);
432 
433     if (!EFI_ERROR (Status)) {
434 
435       Info = ShellGetFileInfo(ShellFileHandle);
436 
437       ShellCloseFile(&ShellFileHandle);
438       //
439       // check if read only
440       //
441       if (Info->Attribute & EFI_FILE_READ_ONLY) {
442         StatusBarSetStatusString (L"Access Denied");
443         SHELL_FREE_NON_NULL (FileName);
444         return EFI_SUCCESS;
445       }
446 
447       SHELL_FREE_NON_NULL(Info);
448       //
449       // ask user whether to overwrite this file
450       //
451       Status = InputBarSetPrompt (L"File exists. Overwrite (Yes/No/Cancel) ? ");
452       if (EFI_ERROR (Status)) {
453         SHELL_FREE_NON_NULL (FileName);
454         return Status;
455       }
456 
457       Status = InputBarSetStringSize (1);
458       if (EFI_ERROR (Status)) {
459         SHELL_FREE_NON_NULL (FileName);
460         return Status;
461       }
462 
463       Done = FALSE;
464       while (!Done) {
465         Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
466 
467         if (Status == EFI_NOT_READY) {
468           SHELL_FREE_NON_NULL (FileName);
469           return EFI_SUCCESS;
470         }
471 
472         switch (InputBarGetString()[0]) {
473         case L'y':
474         case L'Y':
475           Done = TRUE;
476           break;
477         case L'n':
478         case L'N':
479           SHELL_FREE_NON_NULL (FileName);
480           return EFI_SUCCESS;
481         case L'c':
482         case L'C':
483           SHELL_FREE_NON_NULL (FileName);
484           return EFI_SUCCESS;
485         } // switch
486       } // while
487     } // if opened existing file
488   } // if OldFile
489 
490   //
491   // save file back to disk
492   //
493   Status = HBufferImageSave (
494             FileName,
495             HMainEditor.BufferImage->DiskImage->Name,
496             HMainEditor.BufferImage->DiskImage->Offset,
497             HMainEditor.BufferImage->DiskImage->Size,
498             HMainEditor.BufferImage->MemImage->Offset,
499             HMainEditor.BufferImage->MemImage->Size,
500             FileTypeFileBuffer
501             );
502   SHELL_FREE_NON_NULL (FileName);
503 
504   if (EFI_ERROR (Status)) {
505     return EFI_LOAD_ERROR;
506   }
507 
508   return EFI_SUCCESS;
509 }
510 
511 /**
512   Load a disk buffer editor.
513 
514   @retval EFI_SUCCESS             The operation was successful.
515   @retval EFI_OUT_OF_RESOURCES    A memory allocation occured.
516   @retval EFI_LOAD_ERROR          A load error occured.
517 **/
518 EFI_STATUS
HMainCommandSelectStart(VOID)519 HMainCommandSelectStart (
520   VOID
521   )
522 {
523   UINTN Start;
524 
525   Start = (HMainEditor.BufferImage->BufferPosition.Row - 1) * 0x10 + HMainEditor.BufferImage->BufferPosition.Column;
526 
527   //
528   // last line
529   //
530   if (HMainEditor.BufferImage->CurrentLine->Link.ForwardLink == HMainEditor.BufferImage->ListHead) {
531     if (HMainEditor.BufferImage->BufferPosition.Column > HMainEditor.BufferImage->CurrentLine->Size) {
532       StatusBarSetStatusString (L"Invalid Block Start");
533       return EFI_LOAD_ERROR;
534     }
535   }
536 
537   if (HMainEditor.SelectEnd != 0 && Start > HMainEditor.SelectEnd) {
538     StatusBarSetStatusString (L"Invalid Block Start");
539     return EFI_LOAD_ERROR;
540   }
541 
542   HMainEditor.SelectStart = Start;
543 
544   HBufferImageNeedRefresh = TRUE;
545 
546   return EFI_SUCCESS;
547 }
548 
549 /**
550   Load a disk buffer editor.
551 
552   @retval EFI_SUCCESS             The operation was successful.
553   @retval EFI_OUT_OF_RESOURCES    A memory allocation occured.
554   @retval EFI_LOAD_ERROR          A load error occured.
555 **/
556 EFI_STATUS
HMainCommandSelectEnd(VOID)557 HMainCommandSelectEnd (
558   VOID
559   )
560 {
561   UINTN End;
562 
563   End = (HMainEditor.BufferImage->BufferPosition.Row - 1) * 0x10 + HMainEditor.BufferImage->BufferPosition.Column;
564 
565   //
566   // last line
567   //
568   if (HMainEditor.BufferImage->CurrentLine->Link.ForwardLink == HMainEditor.BufferImage->ListHead) {
569     if (HMainEditor.BufferImage->BufferPosition.Column > HMainEditor.BufferImage->CurrentLine->Size) {
570       StatusBarSetStatusString (L"Invalid Block End");
571       return EFI_LOAD_ERROR;
572     }
573   }
574 
575   if (HMainEditor.SelectStart != 0 && End < HMainEditor.SelectStart) {
576     StatusBarSetStatusString (L"Invalid Block End");
577     return EFI_SUCCESS;
578   }
579 
580   HMainEditor.SelectEnd   = End;
581 
582   HBufferImageNeedRefresh = TRUE;
583 
584   return EFI_SUCCESS;
585 }
586 
587 /**
588   Cut current line to clipboard.
589 
590   @retval EFI_SUCCESS             The operation was successful.
591   @retval EFI_OUT_OF_RESOURCES    A memory allocation occured.
592   @retval EFI_LOAD_ERROR          A load error occured.
593 **/
594 EFI_STATUS
HMainCommandCut(VOID)595 HMainCommandCut (
596   VOID
597   )
598 {
599   UINTN             Index;
600   LIST_ENTRY    *Link;
601   UINT8             *Buffer;
602   UINTN             Count;
603 
604   //
605   // not select, so not allowed to cut
606   //
607   if (HMainEditor.SelectStart == 0) {
608     StatusBarSetStatusString (L"No Block is Selected");
609     return EFI_SUCCESS;
610   }
611   //
612   // not select, so not allowed to cut
613   //
614   if (HMainEditor.SelectEnd == 0) {
615     StatusBarSetStatusString (L"No Block is Selected");
616     return EFI_SUCCESS;
617   }
618 
619   Link = HMainEditor.BufferImage->ListHead->ForwardLink;
620   for (Index = 0; Index < (HMainEditor.SelectEnd - 1) / 0x10; Index++) {
621     Link = Link->ForwardLink;
622   }
623 
624   Count   = HMainEditor.SelectEnd - HMainEditor.SelectStart + 1;
625   Buffer  = AllocateZeroPool (Count);
626   if (Buffer == NULL) {
627     return EFI_OUT_OF_RESOURCES;
628   }
629   //
630   // cut the selected area
631   //
632   HBufferImageDeleteCharacterFromBuffer (
633     HMainEditor.SelectStart - 1,
634     Count,
635     Buffer
636     );
637 
638   //
639   // put to clipboard
640   //
641   HClipBoardSet (Buffer, Count);
642 
643   HBufferImageNeedRefresh         = TRUE;
644   HBufferImageOnlyLineNeedRefresh = FALSE;
645 
646   if (!HMainEditor.BufferImage->Modified) {
647     HMainEditor.BufferImage->Modified = TRUE;
648   }
649 
650   //
651   // now no select area
652   //
653   HMainEditor.SelectStart = 0;
654   HMainEditor.SelectEnd   = 0;
655 
656   return EFI_SUCCESS;
657 }
658 
659 /**
660   Paste line to file buffer.
661 
662   @retval EFI_SUCCESS             The operation was successful.
663   @retval EFI_OUT_OF_RESOURCES    A memory allocation occured.
664   @retval EFI_LOAD_ERROR          A load error occured.
665 **/
666 EFI_STATUS
HMainCommandPaste(VOID)667 HMainCommandPaste (
668   VOID
669   )
670 {
671 
672   BOOLEAN           OnlyLineRefresh;
673   HEFI_EDITOR_LINE  *Line;
674   UINT8             *Buffer;
675   UINTN             Count;
676   UINTN             FPos;
677 
678   Count = HClipBoardGet (&Buffer);
679   if (Count == 0 || Buffer == NULL) {
680     StatusBarSetStatusString (L"Nothing to Paste");
681     return EFI_SUCCESS;
682   }
683 
684   Line            = HMainEditor.BufferImage->CurrentLine;
685 
686   OnlyLineRefresh = FALSE;
687   if (Line->Link.ForwardLink == HMainEditor.BufferImage->ListHead && Line->Size + Count < 0x10) {
688     //
689     // is at last line, and after paste will not exceed
690     // so only this line need to be refreshed
691     //
692     // if after add, the line is 0x10, then will append a new line
693     // so the whole page will need be refreshed
694     //
695     OnlyLineRefresh = TRUE;
696 
697   }
698 
699   FPos = 0x10 * (HMainEditor.BufferImage->BufferPosition.Row - 1) + HMainEditor.BufferImage->BufferPosition.Column - 1;
700 
701   HBufferImageAddCharacterToBuffer (FPos, Count, Buffer);
702 
703   if (OnlyLineRefresh) {
704     HBufferImageNeedRefresh         = FALSE;
705     HBufferImageOnlyLineNeedRefresh = TRUE;
706   } else {
707     HBufferImageNeedRefresh         = TRUE;
708     HBufferImageOnlyLineNeedRefresh = FALSE;
709   }
710 
711   if (!HMainEditor.BufferImage->Modified) {
712     HMainEditor.BufferImage->Modified = TRUE;
713   }
714 
715   return EFI_SUCCESS;
716 
717 }
718 
719 /**
720   Exit editor.
721 
722   @retval EFI_SUCCESS             The operation was successful.
723   @retval EFI_OUT_OF_RESOURCES    A memory allocation occured.
724   @retval EFI_LOAD_ERROR          A load error occured.
725 **/
726 EFI_STATUS
HMainCommandExit(VOID)727 HMainCommandExit (
728   VOID
729   )
730 {
731   EFI_STATUS  Status;
732 
733   //
734   // Below is the scenario of Exit command:
735   // 1. IF currently opened file is not modified, exit the editor and
736   //       Exit command ends.
737   //    IF currently opened file is modified, do Step 2
738   //
739   // 2. An Input Bar will be prompted:
740   //       "File modified. Save ( Yes/No/Cancel )?"
741   //      IF user press 'y' or 'Y', currently opened file will be saved and
742   //         Editor exits
743   //      IF user press 'n' or 'N', currently opened file will not be saved
744   //         and Editor exits.
745   //      IF user press 'c' or 'C' or ESC, Exit command ends.
746   //
747   //
748   // if file has been modified, so will prompt user
749   //       whether to save the changes
750   //
751   if (HMainEditor.BufferImage->Modified) {
752 
753     Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? ");
754     if (EFI_ERROR (Status)) {
755       return Status;
756     }
757 
758     Status = InputBarSetStringSize (1);
759     if (EFI_ERROR (Status)) {
760       return Status;
761     }
762 
763     while (1) {
764       Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
765 
766       //
767       // ESC pressed
768       //
769       if (Status == EFI_NOT_READY) {
770         return EFI_SUCCESS;
771       }
772 
773       switch (InputBarGetString()[0]) {
774       case L'y':
775       case L'Y':
776         //
777         // write file back to disk
778         //
779         Status = HBufferImageSave (
780                   HMainEditor.BufferImage->FileImage->FileName,
781                   HMainEditor.BufferImage->DiskImage->Name,
782                   HMainEditor.BufferImage->DiskImage->Offset,
783                   HMainEditor.BufferImage->DiskImage->Size,
784                   HMainEditor.BufferImage->MemImage->Offset,
785                   HMainEditor.BufferImage->MemImage->Size,
786                   HMainEditor.BufferImage->BufferType
787                   );
788         if (!EFI_ERROR (Status)) {
789           HEditorExit = TRUE;
790         }
791 
792         return Status;
793 
794       case L'n':
795       case L'N':
796         HEditorExit = TRUE;
797         return EFI_SUCCESS;
798 
799       case L'c':
800       case L'C':
801         return EFI_SUCCESS;
802 
803       }
804     }
805   }
806 
807   HEditorExit = TRUE;
808   return EFI_SUCCESS;
809 
810 }
811 
812 /**
813   Load a file from disk to editor.
814 
815   @retval EFI_SUCCESS             The operation was successful.
816   @retval EFI_OUT_OF_RESOURCES    A memory allocation occured.
817   @retval EFI_LOAD_ERROR          A load error occured.
818 **/
819 EFI_STATUS
HMainCommandOpenFile(VOID)820 HMainCommandOpenFile (
821   VOID
822   )
823 {
824   BOOLEAN                         Done;
825   EFI_STATUS                      Status;
826   EDIT_FILE_TYPE                  BufferType;
827 
828   BufferType = HMainEditor.BufferImage->BufferType;
829 
830   //
831   //  This command will open a file from current working directory.
832   //  Read-only file can also be opened. But it can not be modified.
833   // Below is the scenario of Open File command:
834   // 1. IF currently opened file has not been modified, directly go to step .
835   //  IF currently opened file has been modified, an Input Bar will be
836   //     prompted as :
837   //      "File Modified. Save ( Yes/No/Cancel) ?"
838   //          IF user press 'y' or 'Y', currently opened file will be saved.
839   //          IF user press 'n' or 'N', currently opened file will
840   //             not be saved.
841   //          IF user press 'c' or 'C' or ESC, Open File command ends and
842   //             currently opened file is still opened.
843   //
844   // 2. An Input Bar will be prompted as :  "File Name to Open: "
845   //      IF user press ESC, Open File command ends and
846   //         currently opened file is still opened.
847   //      Any other inputs with a Return will cause
848   //          currently opened file close.
849   //
850   // 3. IF user input file name is an existing file ,
851   //       this file will be read and opened.
852   //    IF user input file name is a new file, this file will be created
853   //       and opened. This file's type ( UNICODE or ASCII ) is the same with
854   //       the old file.
855   //
856   //
857   // if current file is modified, so you need to choose whether to
858   //    save it first.
859   //
860   if (HMainEditor.BufferImage->Modified) {
861 
862     Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? ");
863     if (EFI_ERROR (Status)) {
864       return Status;
865     }
866     //
867     // the answer is just one character
868     //
869     Status = InputBarSetStringSize (1);
870     if (EFI_ERROR (Status)) {
871       return Status;
872     }
873     //
874     // loop for user's answer
875     // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'
876     //
877     Done = FALSE;
878     while (!Done) {
879       Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
880 
881       //
882       // ESC pressed
883       //
884       if (Status == EFI_NOT_READY) {
885         return EFI_SUCCESS;
886       }
887 
888       switch (InputBarGetString()[0]) {
889       case L'y':
890       case L'Y':
891         //
892         // want to save this buffer first
893         //
894         Status = HBufferImageSave (
895                   HMainEditor.BufferImage->FileImage->FileName,
896                   HMainEditor.BufferImage->DiskImage->Name,
897                   HMainEditor.BufferImage->DiskImage->Offset,
898                   HMainEditor.BufferImage->DiskImage->Size,
899                   HMainEditor.BufferImage->MemImage->Offset,
900                   HMainEditor.BufferImage->MemImage->Size,
901                   HMainEditor.BufferImage->BufferType
902                   );
903         if (EFI_ERROR (Status)) {
904           return Status;
905         }
906 
907         MainTitleBarRefresh (
908           HMainEditor.BufferImage->BufferType == FileTypeFileBuffer?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Name:NULL,
909           HMainEditor.BufferImage->BufferType,
910           HMainEditor.BufferImage->FileImage->ReadOnly,
911           FALSE,
912           HMainEditor.ScreenSize.Column,
913           HMainEditor.ScreenSize.Row,
914           HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Offset:HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Offset:0,
915           HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Size  :HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Size  :0
916           );
917         Done = TRUE;
918         break;
919 
920       case L'n':
921       case L'N':
922         //
923         // the file won't be saved
924         //
925         Done = TRUE;
926         break;
927 
928       case L'c':
929       case L'C':
930         return EFI_SUCCESS;
931       }
932     }
933   }
934   //
935   // TO get the open file name
936   //
937   Status = InputBarSetPrompt (L"File Name to Open: ");
938   if (EFI_ERROR (Status)) {
939     HBufferImageRead (
940       HMainEditor.BufferImage->FileImage->FileName,
941       HMainEditor.BufferImage->DiskImage->Name,
942       HMainEditor.BufferImage->DiskImage->Offset,
943       HMainEditor.BufferImage->DiskImage->Size,
944       HMainEditor.BufferImage->MemImage->Offset,
945       HMainEditor.BufferImage->MemImage->Size,
946       BufferType,
947       TRUE
948       );
949     return Status;
950   }
951 
952   Status = InputBarSetStringSize (100);
953   if (EFI_ERROR (Status)) {
954     Status = HBufferImageRead (
955               HMainEditor.BufferImage->FileImage->FileName,
956               HMainEditor.BufferImage->DiskImage->Name,
957               HMainEditor.BufferImage->DiskImage->Offset,
958               HMainEditor.BufferImage->DiskImage->Size,
959               HMainEditor.BufferImage->MemImage->Offset,
960               HMainEditor.BufferImage->MemImage->Size,
961               BufferType,
962               TRUE
963               );
964     return Status;
965   }
966 
967   while (1) {
968     Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
969 
970     //
971     // ESC pressed
972     //
973     if (Status == EFI_NOT_READY) {
974       Status = HBufferImageRead (
975                 HMainEditor.BufferImage->FileImage->FileName,
976                 HMainEditor.BufferImage->DiskImage->Name,
977                 HMainEditor.BufferImage->DiskImage->Offset,
978                 HMainEditor.BufferImage->DiskImage->Size,
979                 HMainEditor.BufferImage->MemImage->Offset,
980                 HMainEditor.BufferImage->MemImage->Size,
981                 BufferType,
982                 TRUE
983                 );
984 
985       return Status;
986     }
987     //
988     // THE input string length should > 0
989     //
990     if (StrLen (InputBarGetString()) > 0) {
991       //
992       // CHECK if filename's valid
993       //
994       if (!IsValidFileName (InputBarGetString())) {
995         HBufferImageRead (
996           HMainEditor.BufferImage->FileImage->FileName,
997           HMainEditor.BufferImage->DiskImage->Name,
998           HMainEditor.BufferImage->DiskImage->Offset,
999           HMainEditor.BufferImage->DiskImage->Size,
1000           HMainEditor.BufferImage->MemImage->Offset,
1001           HMainEditor.BufferImage->MemImage->Size,
1002           BufferType,
1003           TRUE
1004           );
1005 
1006         StatusBarSetStatusString (L"Invalid File Name");
1007         return EFI_SUCCESS;
1008       }
1009 
1010       break;
1011     }
1012   }
1013   //
1014   // read from disk
1015   //
1016   Status = HBufferImageRead (
1017             InputBarGetString(),
1018             HMainEditor.BufferImage->DiskImage->Name,
1019             HMainEditor.BufferImage->DiskImage->Offset,
1020             HMainEditor.BufferImage->DiskImage->Size,
1021             HMainEditor.BufferImage->MemImage->Offset,
1022             HMainEditor.BufferImage->MemImage->Size,
1023             FileTypeFileBuffer,
1024             FALSE
1025             );
1026 
1027   if (EFI_ERROR (Status)) {
1028     HBufferImageRead (
1029       HMainEditor.BufferImage->FileImage->FileName,
1030       HMainEditor.BufferImage->DiskImage->Name,
1031       HMainEditor.BufferImage->DiskImage->Offset,
1032       HMainEditor.BufferImage->DiskImage->Size,
1033       HMainEditor.BufferImage->MemImage->Offset,
1034       HMainEditor.BufferImage->MemImage->Size,
1035       BufferType,
1036       TRUE
1037       );
1038 
1039     return EFI_LOAD_ERROR;
1040   }
1041 
1042   return EFI_SUCCESS;
1043 }
1044 
1045 /**
1046   Load a disk buffer editor.
1047 
1048   @retval EFI_SUCCESS             The operation was successful.
1049   @retval EFI_OUT_OF_RESOURCES    A memory allocation occured.
1050   @retval EFI_LOAD_ERROR          A load error occured.
1051   @retval EFI_NOT_FOUND           The disk was not found.
1052 **/
1053 EFI_STATUS
HMainCommandOpenDisk(VOID)1054 HMainCommandOpenDisk (
1055   VOID
1056   )
1057 {
1058   UINT64                          Size;
1059   UINT64                          Offset;
1060   CHAR16                          *DeviceName;
1061   EFI_STATUS                      Status;
1062   BOOLEAN                         Done;
1063 
1064   EDIT_FILE_TYPE                  BufferType;
1065 
1066   //
1067   // variable initialization
1068   //
1069   Size        = 0;
1070   Offset      = 0;
1071   BufferType  = HMainEditor.BufferImage->BufferType;
1072 
1073   //
1074   // if current file is modified, so you need to choose
1075   // whether to save it first.
1076   //
1077   if (HMainEditor.BufferImage->Modified) {
1078 
1079     Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? ");
1080     if (EFI_ERROR (Status)) {
1081       return Status;
1082     }
1083     //
1084     // the answer is just one character
1085     //
1086     Status = InputBarSetStringSize (1);
1087     if (EFI_ERROR (Status)) {
1088       return Status;
1089     }
1090     //
1091     // loop for user's answer
1092     // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'
1093     //
1094     Done = FALSE;
1095     while (!Done) {
1096       Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
1097 
1098       //
1099       // ESC pressed
1100       //
1101       if (Status == EFI_NOT_READY) {
1102         return EFI_SUCCESS;
1103       }
1104 
1105       switch (InputBarGetString()[0]) {
1106       case L'y':
1107       case L'Y':
1108         //
1109         // want to save this buffer first
1110         //
1111         Status = HBufferImageSave (
1112                   HMainEditor.BufferImage->FileImage->FileName,
1113                   HMainEditor.BufferImage->DiskImage->Name,
1114                   HMainEditor.BufferImage->DiskImage->Offset,
1115                   HMainEditor.BufferImage->DiskImage->Size,
1116                   HMainEditor.BufferImage->MemImage->Offset,
1117                   HMainEditor.BufferImage->MemImage->Size,
1118                   BufferType
1119                   );
1120         if (EFI_ERROR (Status)) {
1121           return Status;
1122         }
1123 
1124         MainTitleBarRefresh (
1125           HMainEditor.BufferImage->BufferType == FileTypeFileBuffer?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Name:NULL,
1126           HMainEditor.BufferImage->BufferType,
1127           HMainEditor.BufferImage->FileImage->ReadOnly,
1128           FALSE,
1129           HMainEditor.ScreenSize.Column,
1130           HMainEditor.ScreenSize.Row,
1131           HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Offset:HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Offset:0,
1132           HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Size  :HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Size  :0
1133           );
1134         Done = TRUE;
1135         break;
1136 
1137       case L'n':
1138       case L'N':
1139         //
1140         // the file won't be saved
1141         //
1142         Done = TRUE;
1143         break;
1144 
1145       case L'c':
1146       case L'C':
1147         return EFI_SUCCESS;
1148       }
1149     }
1150   }
1151   //
1152   // get disk block device name
1153   //
1154   Status = InputBarSetPrompt (L"Block Device to Open: ");
1155   if (EFI_ERROR (Status)) {
1156     return Status;
1157   }
1158 
1159   Status = InputBarSetStringSize (100);
1160   if (EFI_ERROR (Status)) {
1161     return Status;
1162   }
1163 
1164   while (1) {
1165     Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
1166 
1167     //
1168     // ESC pressed
1169     //
1170     if (Status == EFI_NOT_READY) {
1171 
1172       return EFI_SUCCESS;
1173     }
1174     //
1175     // THE input string length should > 0
1176     //
1177     if (StrLen (InputBarGetString()) > 0) {
1178       break;
1179     }
1180   }
1181 
1182   DeviceName = CatSPrint(NULL, L"%s", InputBarGetString());
1183   if (DeviceName == NULL) {
1184     return EFI_OUT_OF_RESOURCES;
1185   }
1186   //
1187   // get starting offset
1188   //
1189   Status = InputBarSetPrompt (L"First Block No.: ");
1190   if (EFI_ERROR (Status)) {
1191     return Status;
1192   }
1193 
1194   Status = InputBarSetStringSize (16);
1195   if (EFI_ERROR (Status)) {
1196     return Status;
1197   }
1198 
1199   while (1) {
1200     Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
1201 
1202     //
1203     // ESC pressed
1204     //
1205     if (Status == EFI_NOT_READY) {
1206 
1207       return EFI_SUCCESS;
1208     }
1209     //
1210     // THE input string length should > 0
1211     //
1212     if (StrLen (InputBarGetString()) > 0) {
1213       Status = ShellConvertStringToUint64 (InputBarGetString(), &Offset, TRUE, FALSE);
1214       if (EFI_ERROR (Status)) {
1215         continue;
1216       }
1217 
1218       break;
1219     }
1220   }
1221   //
1222   // get Number of Blocks:
1223   //
1224   Status = InputBarSetPrompt (L"Number of Blocks: ");
1225   if (EFI_ERROR (Status)) {
1226     return Status;
1227   }
1228 
1229   Status = InputBarSetStringSize (8);
1230   if (EFI_ERROR (Status)) {
1231     return Status;
1232   }
1233 
1234   while (1) {
1235     Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
1236 
1237     //
1238     // ESC pressed
1239     //
1240     if (Status == EFI_NOT_READY) {
1241 
1242       return EFI_SUCCESS;
1243     }
1244     //
1245     // THE input string length should > 0
1246     //
1247     if (StrLen (InputBarGetString()) > 0) {
1248       Status = ShellConvertStringToUint64 (InputBarGetString(), &Size, TRUE, FALSE);
1249       if (EFI_ERROR (Status)) {
1250         continue;
1251       }
1252 
1253       if (Size == 0) {
1254         continue;
1255       }
1256 
1257       break;
1258     }
1259   }
1260 
1261   Status = HBufferImageRead (
1262             NULL,
1263             DeviceName,
1264             (UINTN)Offset,
1265             (UINTN)Size,
1266             0,
1267             0,
1268             FileTypeDiskBuffer,
1269             FALSE
1270             );
1271 
1272   if (EFI_ERROR (Status)) {
1273 
1274     HBufferImageRead (
1275       HMainEditor.BufferImage->FileImage->FileName,
1276       HMainEditor.BufferImage->DiskImage->Name,
1277       HMainEditor.BufferImage->DiskImage->Offset,
1278       HMainEditor.BufferImage->DiskImage->Size,
1279       HMainEditor.BufferImage->MemImage->Offset,
1280       HMainEditor.BufferImage->MemImage->Size,
1281       BufferType,
1282       TRUE
1283       );
1284     return EFI_NOT_FOUND;
1285   }
1286 
1287   return EFI_SUCCESS;
1288 }
1289 
1290 /**
1291   Load memory content to editor
1292 
1293   @retval EFI_SUCCESS             The operation was successful.
1294   @retval EFI_OUT_OF_RESOURCES    A memory allocation occured.
1295   @retval EFI_LOAD_ERROR          A load error occured.
1296   @retval EFI_NOT_FOUND           The disk was not found.
1297 **/
1298 EFI_STATUS
HMainCommandOpenMemory(VOID)1299 HMainCommandOpenMemory (
1300   VOID
1301   )
1302 {
1303   UINT64                          Size;
1304   UINT64                          Offset;
1305   EFI_STATUS                      Status;
1306   BOOLEAN                         Done;
1307   EDIT_FILE_TYPE                  BufferType;
1308 
1309   //
1310   // variable initialization
1311   //
1312   Size        = 0;
1313   Offset      = 0;
1314   BufferType  = HMainEditor.BufferImage->BufferType;
1315 
1316   //
1317   // if current buffer is modified, so you need to choose
1318   // whether to save it first.
1319   //
1320   if (HMainEditor.BufferImage->Modified) {
1321 
1322     Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? ");
1323     if (EFI_ERROR (Status)) {
1324       return Status;
1325     }
1326     //
1327     // the answer is just one character
1328     //
1329     Status = InputBarSetStringSize (1);
1330     if (EFI_ERROR (Status)) {
1331       return Status;
1332     }
1333     //
1334     // loop for user's answer
1335     // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'
1336     //
1337     Done = FALSE;
1338     while (!Done) {
1339       Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
1340 
1341       //
1342       // ESC pressed
1343       //
1344       if (Status == EFI_NOT_READY) {
1345         return EFI_SUCCESS;
1346       }
1347 
1348       switch (InputBarGetString()[0]) {
1349       case L'y':
1350       case L'Y':
1351         //
1352         // want to save this buffer first
1353         //
1354         Status = HBufferImageSave (
1355                   HMainEditor.BufferImage->FileImage->FileName,
1356                   HMainEditor.BufferImage->DiskImage->Name,
1357                   HMainEditor.BufferImage->DiskImage->Offset,
1358                   HMainEditor.BufferImage->DiskImage->Size,
1359                   HMainEditor.BufferImage->MemImage->Offset,
1360                   HMainEditor.BufferImage->MemImage->Size,
1361                   BufferType
1362                   );
1363         if (EFI_ERROR (Status)) {
1364           return Status;
1365         }
1366 
1367         MainTitleBarRefresh (
1368           HMainEditor.BufferImage->BufferType == FileTypeFileBuffer?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Name:NULL,
1369           HMainEditor.BufferImage->BufferType,
1370           HMainEditor.BufferImage->FileImage->ReadOnly,
1371           FALSE,
1372           HMainEditor.ScreenSize.Column,
1373           HMainEditor.ScreenSize.Row,
1374           HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Offset:HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Offset:0,
1375           HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Size  :HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Size  :0
1376           );
1377         Done = TRUE;
1378         break;
1379 
1380       case L'n':
1381       case L'N':
1382         //
1383         // the file won't be saved
1384         //
1385         Done = TRUE;
1386         break;
1387 
1388       case L'c':
1389       case L'C':
1390         return EFI_SUCCESS;
1391       }
1392     }
1393   }
1394   //
1395   // get starting offset
1396   //
1397   Status = InputBarSetPrompt (L"Starting Offset: ");
1398   if (EFI_ERROR (Status)) {
1399     return Status;
1400   }
1401 
1402   Status = InputBarSetStringSize (8);
1403   if (EFI_ERROR (Status)) {
1404     return Status;
1405   }
1406 
1407   while (1) {
1408     Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
1409 
1410     //
1411     // ESC pressed
1412     //
1413     if (Status == EFI_NOT_READY) {
1414 
1415       return EFI_SUCCESS;
1416     }
1417     //
1418     // THE input string length should > 0
1419     //
1420     if (StrLen (InputBarGetString()) > 0) {
1421       Status = ShellConvertStringToUint64 (InputBarGetString(), &Offset, TRUE, FALSE);
1422       if (EFI_ERROR (Status)) {
1423         continue;
1424       }
1425 
1426       break;
1427     }
1428   }
1429   //
1430   // get Number of Blocks:
1431   //
1432   Status = InputBarSetPrompt (L"Buffer Size: ");
1433   if (EFI_ERROR (Status)) {
1434     return Status;
1435   }
1436 
1437   Status = InputBarSetStringSize (8);
1438   if (EFI_ERROR (Status)) {
1439     return Status;
1440   }
1441 
1442   while (1) {
1443     Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
1444 
1445     //
1446     // ESC pressed
1447     //
1448     if (Status == EFI_NOT_READY) {
1449 
1450       return EFI_SUCCESS;
1451     }
1452     //
1453     // THE input string length should > 0
1454     //
1455     if (StrLen (InputBarGetString()) > 0) {
1456       Status = ShellConvertStringToUint64 (InputBarGetString(), &Size, TRUE, FALSE);
1457       if (EFI_ERROR (Status)) {
1458         continue;
1459       }
1460 
1461       if (Size == 0) {
1462         continue;
1463       }
1464 
1465       break;
1466     }
1467   }
1468 
1469   if ((Offset + Size - 1)> 0xffffffff) {
1470     StatusBarSetStatusString (L"Invalid parameter");
1471     return EFI_LOAD_ERROR;
1472   }
1473 
1474   Status = HBufferImageRead (
1475             NULL,
1476             NULL,
1477             0,
1478             0,
1479             (UINTN)Offset,
1480             (UINTN)Size,
1481             FileTypeMemBuffer,
1482             FALSE
1483             );
1484 
1485   if (EFI_ERROR (Status)) {
1486     StatusBarSetStatusString (L"Read Device Error!");
1487     HBufferImageRead (
1488       HMainEditor.BufferImage->FileImage->FileName,
1489       HMainEditor.BufferImage->DiskImage->Name,
1490       HMainEditor.BufferImage->DiskImage->Offset,
1491       HMainEditor.BufferImage->DiskImage->Size,
1492       HMainEditor.BufferImage->MemImage->Offset,
1493       HMainEditor.BufferImage->MemImage->Size,
1494       BufferType,
1495       TRUE
1496       );
1497     return EFI_NOT_FOUND;
1498   }
1499   return EFI_SUCCESS;
1500 
1501 }
1502 
1503 MENU_ITEM_FUNCTION HexMainControlBasedMenuFunctions[] = {
1504   NULL,
1505   NULL,                      /* Ctrl - A */
1506   NULL,                      /* Ctrl - B */
1507   NULL,                      /* Ctrl - C */
1508   HMainCommandSelectEnd,     /* Ctrl - D */
1509   HMainCommandDisplayHelp,   /* Ctrl - E */
1510   NULL,                      /* Ctrl - F */
1511   HMainCommandGoToOffset,    /* Ctrl - G */
1512   NULL,                      /* Ctrl - H */
1513   HMainCommandOpenDisk,      /* Ctrl - I */
1514   NULL,                      /* Ctrl - J */
1515   NULL,                      /* Ctrl - K */
1516   NULL,                      /* Ctrl - L */
1517   HMainCommandOpenMemory,    /* Ctrl - M */
1518   NULL,                      /* Ctrl - N */
1519   HMainCommandOpenFile,      /* Ctrl - O */
1520   NULL,                      /* Ctrl - P */
1521   HMainCommandExit,          /* Ctrl - Q */
1522   NULL,                      /* Ctrl - R */
1523   HMainCommandSaveBuffer,    /* Ctrl - S */
1524   HMainCommandSelectStart,   /* Ctrl - T */
1525   NULL,                      /* Ctrl - U */
1526   HMainCommandPaste,         /* Ctrl - V */
1527   NULL,                      /* Ctrl - W */
1528   HMainCommandCut,           /* Ctrl - X */
1529   NULL,                      /* Ctrl - Y */
1530   NULL,                      /* Ctrl - Z */
1531 };
1532 
1533 CONST EDITOR_MENU_ITEM HexEditorMenuItems[] = {
1534   {
1535     STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_GO_TO_OFFSET),
1536     STRING_TOKEN(STR_EDIT_LIBMENUBAR_F1),
1537     HMainCommandGoToOffset
1538   },
1539   {
1540     STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_SAVE_BUFFER),
1541     STRING_TOKEN(STR_EDIT_LIBMENUBAR_F2),
1542     HMainCommandSaveBuffer
1543   },
1544   {
1545     STRING_TOKEN(STR_EDIT_LIBMENUBAR_EXIT),
1546     STRING_TOKEN(STR_EDIT_LIBMENUBAR_F3),
1547     HMainCommandExit
1548   },
1549 
1550   {
1551     STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_SELECT_START),
1552     STRING_TOKEN(STR_EDIT_LIBMENUBAR_F4),
1553     HMainCommandSelectStart
1554   },
1555   {
1556     STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_SELECT_END),
1557     STRING_TOKEN(STR_EDIT_LIBMENUBAR_F5),
1558     HMainCommandSelectEnd
1559   },
1560   {
1561     STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_CUT),
1562     STRING_TOKEN(STR_EDIT_LIBMENUBAR_F6),
1563     HMainCommandCut
1564   },
1565   {
1566     STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_PASTE),
1567     STRING_TOKEN(STR_EDIT_LIBMENUBAR_F7),
1568     HMainCommandPaste
1569   },
1570 
1571   {
1572     STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_OPEN_FILE),
1573     STRING_TOKEN(STR_EDIT_LIBMENUBAR_F8),
1574     HMainCommandOpenFile
1575   },
1576   {
1577     STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_OPEN_DISK),
1578     STRING_TOKEN(STR_EDIT_LIBMENUBAR_F9),
1579     HMainCommandOpenDisk
1580   },
1581   {
1582     STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_OPEN_MEMORY),
1583     STRING_TOKEN(STR_EDIT_LIBMENUBAR_F10),
1584     HMainCommandOpenMemory
1585   },
1586 
1587   {
1588     0,
1589     0,
1590     NULL
1591   }
1592 };
1593 
1594 /**
1595   Init function for MainEditor
1596 
1597   @retval EFI_SUCCESS             The operation was successful.
1598   @retval EFI_LOAD_ERROR          A load error occured.
1599 **/
1600 EFI_STATUS
HMainEditorInit(VOID)1601 HMainEditorInit (
1602   VOID
1603   )
1604 {
1605   EFI_STATUS  Status;
1606   EFI_HANDLE  *HandleBuffer;
1607   UINTN       HandleCount;
1608   UINTN       Index;
1609 
1610   //
1611   // basic initialization
1612   //
1613   CopyMem (&HMainEditor, &HMainEditorConst, sizeof (HMainEditor));
1614 
1615   //
1616   // set screen attributes
1617   //
1618   HMainEditor.ColorAttributes.Colors.Foreground = gST->ConOut->Mode->Attribute & 0x000000ff;
1619 
1620   HMainEditor.ColorAttributes.Colors.Background = (UINT8) (gST->ConOut->Mode->Attribute >> 4);
1621 
1622   HOriginalColors = HMainEditor.ColorAttributes.Colors;
1623 
1624   HOriginalMode = gST->ConOut->Mode->Mode;
1625 
1626   //
1627   // query screen size
1628   //
1629   gST->ConOut->QueryMode (
1630         gST->ConOut,
1631         gST->ConOut->Mode->Mode,
1632         &(HMainEditor.ScreenSize.Column),
1633         &(HMainEditor.ScreenSize.Row)
1634         );
1635 
1636   //
1637   // Find mouse in System Table ConsoleInHandle
1638   //
1639   Status = gBS->HandleProtocol (
1640                 gST->ConIn,
1641                 &gEfiSimplePointerProtocolGuid,
1642                 (VOID**)&HMainEditor.MouseInterface
1643                 );
1644   if (EFI_ERROR (Status)) {
1645     //
1646     // If there is no Simple Pointer Protocol on System Table
1647     //
1648     HandleBuffer = NULL;
1649     HMainEditor.MouseInterface = NULL;
1650     Status = gBS->LocateHandleBuffer (
1651                   ByProtocol,
1652                   &gEfiSimplePointerProtocolGuid,
1653                   NULL,
1654                   &HandleCount,
1655                   &HandleBuffer
1656                   );
1657     if (!EFI_ERROR (Status) && HandleCount > 0) {
1658       //
1659       // Try to find the first available mouse device
1660       //
1661       for (Index = 0; Index < HandleCount; Index++) {
1662         Status = gBS->HandleProtocol (
1663                       HandleBuffer[Index],
1664                       &gEfiSimplePointerProtocolGuid,
1665                       (VOID**)&HMainEditor.MouseInterface
1666                       );
1667         if (!EFI_ERROR (Status)) {
1668           break;
1669         }
1670       }
1671     }
1672     if (HandleBuffer != NULL) {
1673       FreePool (HandleBuffer);
1674     }
1675   }
1676 
1677   if (!EFI_ERROR (Status) && HMainEditor.MouseInterface != NULL) {
1678     HMainEditor.MouseAccumulatorX  = 0;
1679     HMainEditor.MouseAccumulatorY  = 0;
1680     HMainEditor.MouseSupported     = TRUE;
1681   }
1682 
1683   //
1684   // below will call the five components' init function
1685   //
1686   Status = MainTitleBarInit (L"UEFI HEXEDIT");
1687   if (EFI_ERROR (Status)) {
1688     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_TITLE), gShellDebug1HiiHandle);
1689     return EFI_LOAD_ERROR;
1690   }
1691 
1692   Status = ControlHotKeyInit (HexMainControlBasedMenuFunctions);
1693   if (EFI_ERROR (Status)) {
1694     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_MAINMENU), gShellDebug1HiiHandle);
1695     return EFI_LOAD_ERROR;
1696   }
1697   Status = MenuBarInit (HexEditorMenuItems);
1698   if (EFI_ERROR (Status)) {
1699     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_MAINMENU), gShellDebug1HiiHandle);
1700     return EFI_LOAD_ERROR;
1701   }
1702 
1703   Status = StatusBarInit ();
1704   if (EFI_ERROR (Status)) {
1705     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_STATUS), gShellDebug1HiiHandle);
1706     return EFI_LOAD_ERROR;
1707   }
1708 
1709   InputBarInit ();
1710 
1711   Status = HBufferImageInit ();
1712   if (EFI_ERROR (Status)) {
1713     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_BUFFERIMAGE), gShellDebug1HiiHandle);
1714     return EFI_LOAD_ERROR;
1715   }
1716 
1717   Status = HClipBoardInit ();
1718   if (EFI_ERROR (Status)) {
1719     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_CLIPBOARD), gShellDebug1HiiHandle);
1720     return EFI_LOAD_ERROR;
1721   }
1722   //
1723   // clear whole screen and enable cursor
1724   //
1725   gST->ConOut->ClearScreen (gST->ConOut);
1726   gST->ConOut->EnableCursor (gST->ConOut, TRUE);
1727 
1728   //
1729   // initialize EditorFirst and EditorExit
1730   //
1731   HEditorFirst        = TRUE;
1732   HEditorExit         = FALSE;
1733   HEditorMouseAction  = FALSE;
1734 
1735   return EFI_SUCCESS;
1736 }
1737 
1738 /**
1739   Cleanup function for MainEditor.
1740 
1741   @retval EFI_SUCCESS             The operation was successful.
1742   @retval EFI_LOAD_ERROR          A load error occured.
1743 **/
1744 EFI_STATUS
HMainEditorCleanup(VOID)1745 HMainEditorCleanup (
1746   VOID
1747   )
1748 {
1749   EFI_STATUS  Status;
1750 
1751   //
1752   // call the five components' cleanup function
1753   //
1754   MainTitleBarCleanup ();
1755 
1756   MenuBarCleanup ();
1757 
1758   StatusBarCleanup ();
1759 
1760   InputBarCleanup ();
1761 
1762   Status = HBufferImageCleanup ();
1763   if (EFI_ERROR (Status)) {
1764     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_BUFFERIMAGE_CLEAN), gShellDebug1HiiHandle);
1765   }
1766 
1767   Status = HClipBoardCleanup ();
1768   if (EFI_ERROR (Status)) {
1769     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_CLIPBOARD_CLEAN), gShellDebug1HiiHandle);
1770   }
1771   //
1772   // restore old mode
1773   //
1774   if (HOriginalMode != gST->ConOut->Mode->Mode) {
1775     gST->ConOut->SetMode (gST->ConOut, HOriginalMode);
1776   }
1777 
1778   gST->ConOut->SetAttribute (
1779         gST->ConOut,
1780         EFI_TEXT_ATTR (HOriginalColors.Foreground, HOriginalColors.Background)
1781         );
1782   gST->ConOut->ClearScreen (gST->ConOut);
1783 
1784   return EFI_SUCCESS;
1785 }
1786 
1787 /**
1788   Refresh function for MainEditor.
1789 
1790   @retval EFI_SUCCESS             The operation was successful.
1791 **/
1792 EFI_STATUS
HMainEditorRefresh(VOID)1793 HMainEditorRefresh (
1794   VOID
1795   )
1796 {
1797   BOOLEAN NameChange;
1798   BOOLEAN ReadChange;
1799 
1800   NameChange = FALSE;
1801   ReadChange = FALSE;
1802 
1803   if (HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer) {
1804     if (HMainEditor.BufferImage->DiskImage != NULL &&
1805         HBufferImageBackupVar.DiskImage != NULL &&
1806         (HMainEditor.BufferImage->DiskImage->Offset != HBufferImageBackupVar.DiskImage->Offset ||
1807            HMainEditor.BufferImage->DiskImage->Size != HBufferImageBackupVar.DiskImage->Size) ){
1808       NameChange = TRUE;
1809     }
1810   } else if (HMainEditor.BufferImage->BufferType == FileTypeMemBuffer) {
1811     if (HMainEditor.BufferImage->MemImage != NULL &&
1812         HBufferImageBackupVar.MemImage != NULL &&
1813         (HMainEditor.BufferImage->MemImage->Offset != HBufferImageBackupVar.MemImage->Offset ||
1814            HMainEditor.BufferImage->MemImage->Size != HBufferImageBackupVar.MemImage->Size) ){
1815       NameChange = TRUE;
1816     }
1817   } else if (HMainEditor.BufferImage->BufferType == FileTypeFileBuffer) {
1818     if ( HMainEditor.BufferImage->FileImage != NULL &&
1819          HMainEditor.BufferImage->FileImage->FileName != NULL &&
1820          HBufferImageBackupVar.FileImage != NULL &&
1821          HBufferImageBackupVar.FileImage->FileName != NULL &&
1822          StrCmp (HMainEditor.BufferImage->FileImage->FileName, HBufferImageBackupVar.FileImage->FileName) != 0 ) {
1823       NameChange = TRUE;
1824     }
1825   }
1826   if ( HMainEditor.BufferImage->FileImage != NULL &&
1827        HBufferImageBackupVar.FileImage != NULL &&
1828        HMainEditor.BufferImage->FileImage->ReadOnly != HBufferImageBackupVar.FileImage->ReadOnly ) {
1829     ReadChange = TRUE;
1830   }
1831 
1832   //
1833   // to aVOID screen flicker
1834   // the stall value is from experience
1835   //
1836   gBS->Stall (50);
1837 
1838   //
1839   // call the components refresh function
1840   //
1841   if (HEditorFirst
1842     || NameChange
1843     || HMainEditor.BufferImage->BufferType != HBufferImageBackupVar.BufferType
1844     || HBufferImageBackupVar.Modified != HMainEditor.BufferImage->Modified
1845     || ReadChange ) {
1846 
1847     MainTitleBarRefresh (
1848       HMainEditor.BufferImage->BufferType == FileTypeFileBuffer&&HMainEditor.BufferImage->FileImage!=NULL?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer&&HMainEditor.BufferImage->DiskImage!=NULL?HMainEditor.BufferImage->DiskImage->Name:NULL,
1849       HMainEditor.BufferImage->BufferType,
1850       (BOOLEAN)(HMainEditor.BufferImage->FileImage!=NULL?HMainEditor.BufferImage->FileImage->ReadOnly:FALSE),
1851       HMainEditor.BufferImage->Modified,
1852       HMainEditor.ScreenSize.Column,
1853       HMainEditor.ScreenSize.Row,
1854       HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer&&HMainEditor.BufferImage->DiskImage!=NULL?HMainEditor.BufferImage->DiskImage->Offset:HMainEditor.BufferImage->BufferType == FileTypeMemBuffer&&HMainEditor.BufferImage->MemImage!=NULL?HMainEditor.BufferImage->MemImage->Offset:0,
1855       HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer&&HMainEditor.BufferImage->DiskImage!=NULL?HMainEditor.BufferImage->DiskImage->Size  :HMainEditor.BufferImage->BufferType == FileTypeMemBuffer&&HMainEditor.BufferImage->MemImage!=NULL?HMainEditor.BufferImage->MemImage->Size  :0
1856       );
1857     HBufferImageRefresh ();
1858   }
1859   if (HEditorFirst
1860     || HBufferImageBackupVar.DisplayPosition.Row != HMainEditor.BufferImage->DisplayPosition.Row
1861     || HBufferImageBackupVar.DisplayPosition.Column != HMainEditor.BufferImage->DisplayPosition.Column
1862     || StatusBarGetRefresh()) {
1863 
1864     StatusBarRefresh (
1865       HEditorFirst,
1866       HMainEditor.ScreenSize.Row,
1867       HMainEditor.ScreenSize.Column,
1868       (UINTN)(-1),
1869       (UINTN)(-1),
1870       FALSE
1871       );
1872     HBufferImageRefresh ();
1873   }
1874 
1875   if (HEditorFirst) {
1876     HBufferImageRefresh ();
1877   }
1878 
1879   //
1880   // EditorFirst is now set to FALSE
1881   //
1882   HEditorFirst = FALSE;
1883 
1884   return EFI_SUCCESS;
1885 }
1886 
1887 /**
1888   Handle the mouse input.
1889 
1890   @param[in] MouseState             The current mouse state.
1891   @param[out] BeforeLeftButtonDown  helps with selections.
1892 
1893   @retval EFI_SUCCESS             The operation was successful.
1894   @retval EFI_OUT_OF_RESOURCES    A memory allocation occured.
1895   @retval EFI_LOAD_ERROR          A load error occured.
1896   @retval EFI_NOT_FOUND           The disk was not found.
1897 **/
1898 EFI_STATUS
HMainEditorHandleMouseInput(IN EFI_SIMPLE_POINTER_STATE MouseState,OUT BOOLEAN * BeforeLeftButtonDown)1899 HMainEditorHandleMouseInput (
1900   IN  EFI_SIMPLE_POINTER_STATE       MouseState,
1901   OUT BOOLEAN                        *BeforeLeftButtonDown
1902   )
1903 {
1904 
1905   INT32             TextX;
1906   INT32             TextY;
1907   UINTN             FRow;
1908   UINTN             FCol;
1909   BOOLEAN           HighBits;
1910   LIST_ENTRY    *Link;
1911   HEFI_EDITOR_LINE  *Line;
1912   UINTN             Index;
1913   BOOLEAN           Action;
1914 
1915   Action = FALSE;
1916 
1917   //
1918   // have mouse movement
1919   //
1920   if (MouseState.RelativeMovementX || MouseState.RelativeMovementY) {
1921     //
1922     // handle
1923     //
1924     TextX = HGetTextX (MouseState.RelativeMovementX);
1925     TextY = HGetTextY (MouseState.RelativeMovementY);
1926 
1927     HBufferImageAdjustMousePosition (TextX, TextY);
1928 
1929     Action = TRUE;
1930 
1931   }
1932 
1933   if (MouseState.LeftButton) {
1934     HighBits = HBufferImageIsAtHighBits (
1935                 HMainEditor.BufferImage->MousePosition.Column,
1936                 &FCol
1937                 );
1938 
1939     //
1940     // not at an movable place
1941     //
1942     if (FCol == 0) {
1943       //
1944       // now just move mouse pointer to legal position
1945       //
1946       //
1947       // move mouse position to legal position
1948       //
1949       HMainEditor.BufferImage->MousePosition.Column -= 10;
1950       if (HMainEditor.BufferImage->MousePosition.Column > 24) {
1951         HMainEditor.BufferImage->MousePosition.Column--;
1952         FCol = HMainEditor.BufferImage->MousePosition.Column / 3 + 1 + 1;
1953       } else {
1954         if (HMainEditor.BufferImage->MousePosition.Column < 24) {
1955           FCol = HMainEditor.BufferImage->MousePosition.Column / 3 + 1 + 1;
1956         } else {
1957           //
1958           // == 24
1959           //
1960           FCol = 9;
1961         }
1962       }
1963 
1964       HighBits = TRUE;
1965 
1966     }
1967 
1968     FRow = HMainEditor.BufferImage->BufferPosition.Row +
1969       HMainEditor.BufferImage->MousePosition.Row -
1970       HMainEditor.BufferImage->DisplayPosition.Row;
1971 
1972     if (HMainEditor.BufferImage->NumLines < FRow) {
1973       //
1974       // dragging
1975       //
1976       //
1977       // now just move mouse pointer to legal position
1978       //
1979       FRow      = HMainEditor.BufferImage->NumLines;
1980       HighBits  = TRUE;
1981     }
1982 
1983     Link = HMainEditor.BufferImage->ListHead->ForwardLink;
1984     for (Index = 0; Index < FRow - 1; Index++) {
1985       Link = Link->ForwardLink;
1986     }
1987 
1988     Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
1989 
1990     //
1991     // dragging
1992     //
1993     //
1994     // now just move mouse pointer to legal position
1995     //
1996     if (FCol > Line->Size) {
1997       if (*BeforeLeftButtonDown) {
1998         HighBits = FALSE;
1999 
2000         if (Line->Size == 0) {
2001           if (FRow > 1) {
2002             FRow--;
2003             FCol = 16;
2004           } else {
2005             FRow  = 1;
2006             FCol  = 1;
2007           }
2008 
2009         } else {
2010           FCol = Line->Size;
2011         }
2012       } else {
2013         FCol      = Line->Size + 1;
2014         HighBits  = TRUE;
2015       }
2016     }
2017 
2018     HBufferImageMovePosition (FRow, FCol, HighBits);
2019 
2020     HMainEditor.BufferImage->MousePosition.Row    = HMainEditor.BufferImage->DisplayPosition.Row;
2021 
2022     HMainEditor.BufferImage->MousePosition.Column = HMainEditor.BufferImage->DisplayPosition.Column;
2023 
2024     *BeforeLeftButtonDown                         = TRUE;
2025 
2026     Action = TRUE;
2027   } else {
2028     //
2029     // else of if LButton
2030     //
2031     // release LButton
2032     //
2033     if (*BeforeLeftButtonDown) {
2034       Action = TRUE;
2035     }
2036     //
2037     // mouse up
2038     //
2039     *BeforeLeftButtonDown = FALSE;
2040   }
2041 
2042   if (Action) {
2043     return EFI_SUCCESS;
2044   }
2045 
2046   return EFI_NOT_FOUND;
2047 }
2048 
2049 /**
2050   Handle user key input. will route it to other components handle function.
2051 
2052   @retval EFI_SUCCESS             The operation was successful.
2053   @retval EFI_OUT_OF_RESOURCES    A memory allocation occured.
2054   @retval EFI_LOAD_ERROR          A load error occured.
2055 **/
2056 EFI_STATUS
HMainEditorKeyInput(VOID)2057 HMainEditorKeyInput (
2058   VOID
2059   )
2060 {
2061   EFI_INPUT_KEY             Key;
2062   EFI_STATUS                Status;
2063   EFI_SIMPLE_POINTER_STATE  MouseState;
2064   BOOLEAN                   LengthChange;
2065   UINTN                     Size;
2066   UINTN                     OldSize;
2067   BOOLEAN                   BeforeMouseIsDown;
2068   BOOLEAN                   MouseIsDown;
2069   BOOLEAN                   FirstDown;
2070   BOOLEAN                   MouseDrag;
2071   UINTN                     FRow;
2072   UINTN                     FCol;
2073   UINTN                     SelectStartBackup;
2074   UINTN                     SelectEndBackup;
2075 
2076   //
2077   // variable initialization
2078   //
2079   OldSize       = 0;
2080   FRow          = 0;
2081   FCol          = 0;
2082   LengthChange  = FALSE;
2083 
2084   MouseIsDown   = FALSE;
2085   FirstDown     = FALSE;
2086   MouseDrag     = FALSE;
2087 
2088   do {
2089 
2090     Status              = EFI_SUCCESS;
2091 
2092     HEditorMouseAction  = FALSE;
2093 
2094     //
2095     // backup some key elements, so that can aVOID some refresh work
2096     //
2097     HMainEditorBackup ();
2098 
2099     //
2100     // wait for user key input
2101     //
2102     //
2103     // change priority of checking mouse/keyboard activity dynamically
2104     // so prevent starvation of keyboard.
2105     // if last time, mouse moves then this time check keyboard
2106     //
2107     if (HMainEditor.MouseSupported) {
2108       Status = HMainEditor.MouseInterface->GetState (
2109                                             HMainEditor.MouseInterface,
2110                                             &MouseState
2111                                             );
2112       if (!EFI_ERROR (Status)) {
2113 
2114         BeforeMouseIsDown = MouseIsDown;
2115 
2116         Status            = HMainEditorHandleMouseInput (MouseState, &MouseIsDown);
2117 
2118         if (!EFI_ERROR (Status)) {
2119           if (!BeforeMouseIsDown) {
2120             //
2121             // mouse down
2122             //
2123             if (MouseIsDown) {
2124               FRow              = HBufferImage.BufferPosition.Row;
2125               FCol              = HBufferImage.BufferPosition.Column;
2126               SelectStartBackup = HMainEditor.SelectStart;
2127               SelectEndBackup   = HMainEditor.SelectEnd;
2128 
2129               FirstDown         = TRUE;
2130             }
2131           } else {
2132 
2133             SelectStartBackup = HMainEditor.SelectStart;
2134             SelectEndBackup   = HMainEditor.SelectEnd;
2135 
2136             //
2137             // begin to drag
2138             //
2139             if (MouseIsDown) {
2140               if (FirstDown) {
2141                 if (MouseState.RelativeMovementX || MouseState.RelativeMovementY) {
2142                   HMainEditor.SelectStart = 0;
2143                   HMainEditor.SelectEnd   = 0;
2144                   HMainEditor.SelectStart = (FRow - 1) * 0x10 + FCol;
2145 
2146                   MouseDrag               = TRUE;
2147                   FirstDown               = FALSE;
2148                 }
2149               } else {
2150                 if ((
2151                       (HBufferImage.BufferPosition.Row - 1) *
2152                     0x10 +
2153                     HBufferImage.BufferPosition.Column
2154                       ) >= HMainEditor.SelectStart
2155                         ) {
2156                   HMainEditor.SelectEnd = (HBufferImage.BufferPosition.Row - 1) *
2157                     0x10 +
2158                     HBufferImage.BufferPosition.Column;
2159                 } else {
2160                   HMainEditor.SelectEnd = 0;
2161                 }
2162               }
2163               //
2164               // end of if RelativeX/Y
2165               //
2166             } else {
2167               //
2168               // mouse is up
2169               //
2170               if (MouseDrag) {
2171                 if (HBufferImageGetTotalSize () == 0) {
2172                   HMainEditor.SelectStart = 0;
2173                   HMainEditor.SelectEnd   = 0;
2174                   FirstDown               = FALSE;
2175                   MouseDrag               = FALSE;
2176                 }
2177 
2178                 if ((
2179                       (HBufferImage.BufferPosition.Row - 1) *
2180                     0x10 +
2181                     HBufferImage.BufferPosition.Column
2182                       ) >= HMainEditor.SelectStart
2183                         ) {
2184                   HMainEditor.SelectEnd = (HBufferImage.BufferPosition.Row - 1) *
2185                     0x10 +
2186                     HBufferImage.BufferPosition.Column;
2187                 } else {
2188                   HMainEditor.SelectEnd = 0;
2189                 }
2190 
2191                 if (HMainEditor.SelectEnd == 0) {
2192                   HMainEditor.SelectStart = 0;
2193                 }
2194               }
2195 
2196               FirstDown = FALSE;
2197               MouseDrag = FALSE;
2198             }
2199 
2200             if (SelectStartBackup != HMainEditor.SelectStart || SelectEndBackup != HMainEditor.SelectEnd) {
2201               if ((SelectStartBackup - 1) / 0x10 != (HMainEditor.SelectStart - 1) / 0x10) {
2202                 HBufferImageNeedRefresh = TRUE;
2203               } else {
2204                 if ((SelectEndBackup - 1) / 0x10 != (HMainEditor.SelectEnd - 1) / 0x10) {
2205                   HBufferImageNeedRefresh = TRUE;
2206                 } else {
2207                   HBufferImageOnlyLineNeedRefresh = TRUE;
2208                 }
2209               }
2210             }
2211           }
2212 
2213           HEditorMouseAction            = TRUE;
2214           HBufferImageMouseNeedRefresh  = TRUE;
2215 
2216         } else if (Status == EFI_LOAD_ERROR) {
2217           StatusBarSetStatusString (L"Invalid Mouse Movement ");
2218         }
2219       }
2220     }
2221 
2222     Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
2223     if (!EFI_ERROR (Status)) {
2224       //
2225       // dispatch to different components' key handling function
2226       // so not everywhere has to set this variable
2227       //
2228       HBufferImageMouseNeedRefresh = TRUE;
2229 
2230       //
2231       // clear previous status string
2232       //
2233       StatusBarSetRefresh();
2234       if (EFI_SUCCESS == MenuBarDispatchControlHotKey(&Key)) {
2235         Status = EFI_SUCCESS;
2236       } else if (Key.ScanCode == SCAN_NULL) {
2237         Status = HBufferImageHandleInput (&Key);
2238       } else if (((Key.ScanCode >= SCAN_UP) && (Key.ScanCode <= SCAN_PAGE_DOWN))) {
2239         Status = HBufferImageHandleInput (&Key);
2240       } else if (((Key.ScanCode >= SCAN_F1) && Key.ScanCode <= (SCAN_F12))) {
2241         Status = MenuBarDispatchFunctionKey (&Key);
2242       } else {
2243         StatusBarSetStatusString (L"Unknown Command");
2244 
2245         HBufferImageMouseNeedRefresh = FALSE;
2246       }
2247 
2248       if (Status != EFI_SUCCESS && Status != EFI_OUT_OF_RESOURCES) {
2249         //
2250         // not already has some error status
2251         //
2252         if (StrCmp (L"", StatusBarGetString()) == 0) {
2253           StatusBarSetStatusString (L"Disk Error. Try Again");
2254         }
2255       }
2256     }
2257     //
2258     // decide if has to set length warning
2259     //
2260     if (HBufferImage.BufferType != HBufferImageBackupVar.BufferType) {
2261       LengthChange = FALSE;
2262     } else {
2263       //
2264       // still the old buffer
2265       //
2266       if (HBufferImage.BufferType != FileTypeFileBuffer) {
2267         Size = HBufferImageGetTotalSize ();
2268 
2269         switch (HBufferImage.BufferType) {
2270         case FileTypeDiskBuffer:
2271           OldSize = HBufferImage.DiskImage->Size * HBufferImage.DiskImage->BlockSize;
2272           break;
2273 
2274         case FileTypeMemBuffer:
2275           OldSize = HBufferImage.MemImage->Size;
2276           break;
2277 
2278         default:
2279           OldSize = 0;
2280           break;
2281         }
2282 
2283         if (!LengthChange) {
2284           if (OldSize != Size) {
2285             StatusBarSetStatusString (L"Disk/Mem Buffer Length should not be changed");
2286           }
2287         }
2288 
2289         if (OldSize != Size) {
2290           LengthChange = TRUE;
2291         } else {
2292           LengthChange = FALSE;
2293         }
2294       }
2295     }
2296     //
2297     // after handling, refresh editor
2298     //
2299     HMainEditorRefresh ();
2300 
2301   } while (Status != EFI_OUT_OF_RESOURCES && !HEditorExit);
2302 
2303   return Status;
2304 }
2305 
2306 /**
2307   Backup function for MainEditor.
2308 **/
2309 VOID
HMainEditorBackup(VOID)2310 HMainEditorBackup (
2311   VOID
2312   )
2313 {
2314   HMainEditorBackupVar.SelectStart  = HMainEditor.SelectStart;
2315   HMainEditorBackupVar.SelectEnd    = HMainEditor.SelectEnd;
2316   HBufferImageBackup ();
2317 }
2318