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