]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.c
ShellPkg: Fixed build error 'variable set but not used'
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / HexEdit / BufferImage.c
1 /** @file
2 Defines HBufferImage - the view of the file that is visible at any point,
3 as well as the event handlers for editing the file
4
5 Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "HexEditor.h"
17
18 extern EFI_HANDLE HImageHandleBackup;
19
20 extern HEFI_EDITOR_FILE_IMAGE HFileImage;
21 extern HEFI_EDITOR_DISK_IMAGE HDiskImage;
22 extern HEFI_EDITOR_MEM_IMAGE HMemImage;
23
24 extern HEFI_EDITOR_FILE_IMAGE HFileImageBackupVar;
25 extern HEFI_EDITOR_DISK_IMAGE HDiskImageBackupVar;
26 extern HEFI_EDITOR_MEM_IMAGE HMemImageBackupVar;
27
28 extern BOOLEAN HEditorMouseAction;
29
30 extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;
31 extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditorBackupVar;
32
33 HEFI_EDITOR_BUFFER_IMAGE HBufferImage;
34 HEFI_EDITOR_BUFFER_IMAGE HBufferImageBackupVar;
35
36 //
37 // for basic initialization of HBufferImage
38 //
39 HEFI_EDITOR_BUFFER_IMAGE HBufferImageConst = {
40 NULL,
41 NULL,
42 0,
43 NULL,
44 {
45 0,
46 0
47 },
48 {
49 0,
50 0
51 },
52 {
53 0,
54 0
55 },
56 0,
57 TRUE,
58 FALSE,
59 FileTypeNone,
60 NULL,
61 NULL,
62 NULL
63 };
64
65 //
66 // the whole edit area needs to be refreshed
67 //
68 BOOLEAN HBufferImageNeedRefresh;
69
70 //
71 // only the current line in edit area needs to be refresh
72 //
73 BOOLEAN HBufferImageOnlyLineNeedRefresh;
74
75 BOOLEAN HBufferImageMouseNeedRefresh;
76
77 /**
78 Initialization function for HBufferImage
79
80 @retval EFI_SUCCESS The operation was successful.
81 @retval EFI_LOAD_ERROR A load error occured.
82 **/
83 EFI_STATUS
84 HBufferImageInit (
85 VOID
86 )
87 {
88 EFI_STATUS Status;
89
90 //
91 // basically initialize the HBufferImage
92 //
93 CopyMem (&HBufferImage, &HBufferImageConst, sizeof (HBufferImage));
94
95 //
96 // INIT listhead
97 //
98 HBufferImage.ListHead = AllocateZeroPool (sizeof (LIST_ENTRY));
99 if (HBufferImage.ListHead == NULL) {
100 return EFI_LOAD_ERROR;
101 }
102
103 InitializeListHead (HBufferImage.ListHead);
104
105 HBufferImage.DisplayPosition.Row = 2;
106 HBufferImage.DisplayPosition.Column = 10;
107 HBufferImage.MousePosition.Row = 2;
108 HBufferImage.MousePosition.Column = 10;
109
110 HBufferImage.FileImage = &HFileImage;
111 HBufferImage.DiskImage = &HDiskImage;
112 HBufferImage.MemImage = &HMemImage;
113
114 HBufferImageNeedRefresh = FALSE;
115 HBufferImageOnlyLineNeedRefresh = FALSE;
116 HBufferImageMouseNeedRefresh = FALSE;
117
118 HBufferImageBackupVar.FileImage = &HFileImageBackupVar;
119 HBufferImageBackupVar.DiskImage = &HDiskImageBackupVar;
120 HBufferImageBackupVar.MemImage = &HMemImageBackupVar;
121
122 Status = HFileImageInit ();
123 if (EFI_ERROR (Status)) {
124 return EFI_LOAD_ERROR;
125 }
126
127 Status = HDiskImageInit ();
128 if (EFI_ERROR (Status)) {
129 return EFI_LOAD_ERROR;
130 }
131
132 Status = HMemImageInit ();
133 if (EFI_ERROR (Status)) {
134 return EFI_LOAD_ERROR;
135 }
136
137 return EFI_SUCCESS;
138 }
139
140 /**
141 Backup function for HBufferImage. Only a few fields need to be backup.
142 This is for making the file buffer refresh as few as possible.
143
144 @retval EFI_SUCCESS The operation was successful.
145 **/
146 EFI_STATUS
147 HBufferImageBackup (
148 VOID
149 )
150 {
151 HBufferImageBackupVar.MousePosition = HBufferImage.MousePosition;
152
153 HBufferImageBackupVar.BufferPosition = HBufferImage.BufferPosition;
154
155 HBufferImageBackupVar.Modified = HBufferImage.Modified;
156
157 HBufferImageBackupVar.BufferType = HBufferImage.BufferType;
158 HBufferImageBackupVar.LowVisibleRow = HBufferImage.LowVisibleRow;
159 HBufferImageBackupVar.HighBits = HBufferImage.HighBits;
160
161 //
162 // three kinds of buffer supported
163 // file buffer
164 // disk buffer
165 // memory buffer
166 //
167 switch (HBufferImage.BufferType) {
168 case FileTypeFileBuffer:
169 HFileImageBackup ();
170 break;
171
172 case FileTypeDiskBuffer:
173 HDiskImageBackup ();
174 break;
175
176 case FileTypeMemBuffer:
177 HMemImageBackup ();
178 break;
179
180 default:
181 break;
182 }
183
184 return EFI_SUCCESS;
185 }
186
187 /**
188 Free all the lines in HBufferImage.
189 Fields affected:
190 Lines
191 CurrentLine
192 NumLines
193 ListHead
194
195 @retval EFI_SUCCESS The operation was successful.
196 **/
197 EFI_STATUS
198 HBufferImageFreeLines (
199 VOID
200 )
201 {
202 HFreeLines (HBufferImage.ListHead, HBufferImage.Lines);
203
204 HBufferImage.Lines = NULL;
205 HBufferImage.CurrentLine = NULL;
206 HBufferImage.NumLines = 0;
207
208 return EFI_SUCCESS;
209 }
210
211 /**
212 Cleanup function for HBufferImage
213
214 @retval EFI_SUCCESS The operation was successful.
215 **/
216 EFI_STATUS
217 HBufferImageCleanup (
218 VOID
219 )
220 {
221 EFI_STATUS Status;
222
223 //
224 // free all the lines
225 //
226 Status = HBufferImageFreeLines ();
227
228 SHELL_FREE_NON_NULL (HBufferImage.ListHead);
229 HBufferImage.ListHead = NULL;
230
231 HFileImageCleanup ();
232 HDiskImageCleanup ();
233
234 return Status;
235
236 }
237
238 /**
239 Print Line on Row
240
241 @param[in] Line The lline to print.
242 @param[in] Row The row on screen ( begin from 1 ).
243 @param[in] FRow The FRow.
244 @param[in] Orig The original color.
245 @param[in] New The color to print with.
246
247 @retval EFI_SUCCESS The operation was successful.
248 **/
249 EFI_STATUS
250 HBufferImagePrintLine (
251 IN HEFI_EDITOR_LINE *Line,
252 IN UINTN Row,
253 IN UINTN FRow,
254 IN HEFI_EDITOR_COLOR_UNION Orig,
255 IN HEFI_EDITOR_COLOR_UNION New
256
257 )
258 {
259
260 UINTN Index;
261 UINTN Pos;
262 BOOLEAN Selected;
263 BOOLEAN BeNewColor;
264 UINTN RowStart;
265 UINTN RowEnd;
266 UINTN ColStart;
267 UINTN ColEnd;
268
269 //
270 // variable initialization
271 //
272 ColStart = 0;
273 ColEnd = 0;
274 Selected = FALSE;
275
276 //
277 // print the selected area in opposite color
278 //
279 if (HMainEditor.SelectStart != 0 && HMainEditor.SelectEnd != 0) {
280 RowStart = (HMainEditor.SelectStart - 1) / 0x10 + 1;
281 RowEnd = (HMainEditor.SelectEnd - 1) / 0x10 + 1;
282
283 ColStart = (HMainEditor.SelectStart - 1) % 0x10 + 1;
284 ColEnd = (HMainEditor.SelectEnd - 1) % 0x10 + 1;
285
286 if (FRow >= RowStart && FRow <= RowEnd) {
287 Selected = TRUE;
288 }
289
290 if (FRow > RowStart) {
291 ColStart = 1;
292 }
293
294 if (FRow < RowEnd) {
295 ColEnd = 0x10;
296 }
297
298 }
299
300 if (!HEditorMouseAction) {
301 ShellPrintEx (
302 0,
303 (INT32)Row - 1,
304 L"%8X ",
305 ((INT32)Row - 2 + HBufferImage.LowVisibleRow - 1) * 0x10
306 );
307
308 }
309
310 for (Index = 0; Index < 0x08 && Index < Line->Size; Index++) {
311
312 BeNewColor = FALSE;
313
314 if (Selected) {
315 if (Index + 1 >= ColStart && Index + 1 <= ColEnd) {
316 BeNewColor = TRUE;
317 }
318 }
319
320 if (BeNewColor) {
321 gST->ConOut->SetAttribute (gST->ConOut, New.Data);
322 } else {
323 gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
324 }
325
326 Pos = 10 + (Index * 3);
327 if (Line->Buffer[Index] < 0x10) {
328 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"0");
329 Pos++;
330 }
331
332 if (Index < 0x07) {
333 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]);
334 } else {
335 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]);
336 }
337
338 }
339
340 gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
341 while (Index < 0x08) {
342 Pos = 10 + (Index * 3);
343 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
344 Index++;
345 }
346
347 while (Index < 0x10 && Index < Line->Size) {
348
349 BeNewColor = FALSE;
350
351 if (Selected) {
352 if (Index + 1 >= ColStart && Index + 1 <= ColEnd) {
353 BeNewColor = TRUE;
354 }
355 }
356
357 if (BeNewColor) {
358 gST->ConOut->SetAttribute (gST->ConOut, New.Data);
359 } else {
360 gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
361 }
362
363 Pos = 10 + (Index * 3) + 1;
364 if (Line->Buffer[Index] < 0x10) {
365 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"0");
366 Pos++;
367 }
368
369 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]);
370 Index++;
371 }
372
373 gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
374 while (Index < 0x10) {
375 Pos = 10 + (Index * 3) + 1;
376 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
377 Index++;
378 }
379 //
380 // restore the original color
381 //
382 gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
383
384 //
385 // PRINT the buffer content
386 //
387 if (!HEditorMouseAction) {
388 for (Index = 0; Index < 0x10 && Index < Line->Size; Index++) {
389 Pos = ASCII_POSITION + Index;
390
391 //
392 // learned from shelle.h -- IsValidChar
393 //
394 if (Line->Buffer[Index] >= L' ') {
395 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%c", (CHAR16) Line->Buffer[Index]);
396 } else {
397 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%c", '.');
398 }
399 }
400
401 while (Index < 0x10) {
402 Pos = ASCII_POSITION + Index;
403 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
404 Index++;
405 }
406 }
407 //
408 // restore the abundant blank in hex edit area to original color
409 //
410 if (Selected) {
411 if (ColEnd <= 7) {
412 Pos = 10 + (ColEnd - 1) * 3 + 2;
413 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
414 } else if (ColEnd == 8) {
415 Pos = 10 + (ColEnd - 1) * 3 + 2;
416 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
417 } else {
418 Pos = 10 + (ColEnd - 1) * 3 + 3;
419 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
420 }
421 }
422
423 return EFI_SUCCESS;
424 }
425
426 /**
427 Function to decide if a column number is stored in the high bits.
428
429 @param[in] Column The column to examine.
430 @param[out] FCol The actual column number.
431
432 @retval TRUE The actual column was in high bits and is now in FCol.
433 @retval FALSE There was not a column number in the high bits.
434 **/
435 BOOLEAN
436 HBufferImageIsAtHighBits (
437 IN UINTN Column,
438 OUT UINTN *FCol
439 )
440 {
441 Column -= 10;
442
443 //
444 // NOW AFTER THE SUB, Column start from 0
445 // 23 AND 24 ARE BOTH BLANK
446 //
447 if (Column == 24) {
448 *FCol = 0;
449 return FALSE;
450 }
451
452 if (Column > 24) {
453 Column--;
454 }
455
456 *FCol = (Column / 3) + 1;
457
458 if (Column % 3 == 0) {
459 return TRUE;
460 }
461
462 if ((Column % 3 == 2)) {
463 *FCol = 0;
464 }
465
466 return FALSE;
467 }
468
469 /**
470 Decide if a point is in the already selected area.
471
472 @param[in] MouseRow The row of the point to test.
473 @param[in] MouseCol The col of the point to test.
474
475 @retval TRUE The point is in the selected area.
476 @retval FALSE The point is not in the selected area.
477 **/
478 BOOLEAN
479 HBufferImageIsInSelectedArea (
480 IN UINTN MouseRow,
481 IN UINTN MouseCol
482 )
483 {
484 UINTN FRow;
485 UINTN RowStart;
486 UINTN RowEnd;
487 UINTN ColStart;
488 UINTN ColEnd;
489 UINTN MouseColStart;
490 UINTN MouseColEnd;
491
492 //
493 // judge mouse position whether is in selected area
494 //
495 //
496 // not select
497 //
498 if (HMainEditor.SelectStart == 0 || HMainEditor.SelectEnd == 0) {
499 return FALSE;
500 }
501 //
502 // calculate the select area
503 //
504 RowStart = (HMainEditor.SelectStart - 1) / 0x10 + 1;
505 RowEnd = (HMainEditor.SelectEnd - 1) / 0x10 + 1;
506
507 ColStart = (HMainEditor.SelectStart - 1) % 0x10 + 1;
508 ColEnd = (HMainEditor.SelectEnd - 1) % 0x10 + 1;
509
510 FRow = HBufferImage.LowVisibleRow + MouseRow - 2;
511 if (FRow < RowStart || FRow > RowEnd) {
512 return FALSE;
513 }
514
515 if (FRow > RowStart) {
516 ColStart = 1;
517 }
518
519 if (FRow < RowEnd) {
520 ColEnd = 0x10;
521 }
522
523 MouseColStart = 10 + (ColStart - 1) * 3;
524 if (ColStart > 8) {
525 MouseColStart++;
526 }
527
528 MouseColEnd = 10 + (ColEnd - 1) * 3 + 1;
529 if (ColEnd > 8) {
530 MouseColEnd++;
531 }
532
533 if (MouseCol < MouseColStart || MouseCol > MouseColEnd) {
534 return FALSE;
535 }
536
537 return TRUE;
538 }
539
540 /**
541 Set mouse position according to HBufferImage.MousePosition.
542
543 @retval EFI_SUCCESS The operation was successful.
544 **/
545 EFI_STATUS
546 HBufferImageRestoreMousePosition (
547 VOID
548 )
549 {
550 HEFI_EDITOR_COLOR_UNION Orig;
551 HEFI_EDITOR_COLOR_UNION New;
552 UINTN FRow;
553 UINTN FColumn;
554 BOOLEAN HasCharacter;
555 HEFI_EDITOR_LINE *CurrentLine;
556 HEFI_EDITOR_LINE *Line;
557 UINT8 Value;
558 BOOLEAN HighBits;
559
560 Line = NULL;
561 if (HMainEditor.MouseSupported) {
562
563 if (HBufferImageMouseNeedRefresh) {
564
565 HBufferImageMouseNeedRefresh = FALSE;
566
567 //
568 // if mouse position not moved and only mouse action
569 // so do not need to refresh mouse position
570 //
571 if ((
572 HBufferImage.MousePosition.Row == HBufferImageBackupVar.MousePosition.Row &&
573 HBufferImage.MousePosition.Column == HBufferImageBackupVar.MousePosition.Column
574 ) &&
575 HEditorMouseAction
576 ) {
577 return EFI_SUCCESS;
578 }
579 //
580 // backup the old screen attributes
581 //
582 Orig = HMainEditor.ColorAttributes;
583 New.Colors.Foreground = Orig.Colors.Background;
584 New.Colors.Background = Orig.Colors.Foreground;
585
586 //
587 // if in selected area,
588 // so do not need to refresh mouse
589 //
590 if (!HBufferImageIsInSelectedArea (
591 HBufferImageBackupVar.MousePosition.Row,
592 HBufferImageBackupVar.MousePosition.Column
593 )) {
594 gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
595 } else {
596 gST->ConOut->SetAttribute (gST->ConOut, New.Data);
597 }
598 //
599 // clear the old mouse position
600 //
601 FRow = HBufferImage.LowVisibleRow + HBufferImageBackupVar.MousePosition.Row - 2;
602
603 HighBits = HBufferImageIsAtHighBits (
604 HBufferImageBackupVar.MousePosition.Column,
605 &FColumn
606 );
607
608 HasCharacter = TRUE;
609 if (FRow > HBufferImage.NumLines || FColumn == 0) {
610 HasCharacter = FALSE;
611 } else {
612 CurrentLine = HBufferImage.CurrentLine;
613 Line = HMoveLine (FRow - HBufferImage.BufferPosition.Row);
614
615 if (Line == NULL || FColumn > Line->Size) {
616 HasCharacter = FALSE;
617 }
618
619 HBufferImage.CurrentLine = CurrentLine;
620 }
621
622 ShellPrintEx (
623 (INT32)HBufferImageBackupVar.MousePosition.Column - 1,
624 (INT32)HBufferImageBackupVar.MousePosition.Row - 1,
625 L" "
626 );
627
628 if (HasCharacter) {
629 if (HighBits) {
630 Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf0);
631 Value = (UINT8) (Value >> 4);
632 } else {
633 Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf);
634 }
635
636 ShellPrintEx (
637 (INT32)HBufferImageBackupVar.MousePosition.Column - 1,
638 (INT32)HBufferImageBackupVar.MousePosition.Row - 1,
639 L"%x",
640 Value
641 );
642 }
643
644 if (!HBufferImageIsInSelectedArea (
645 HBufferImage.MousePosition.Row,
646 HBufferImage.MousePosition.Column
647 )) {
648 gST->ConOut->SetAttribute (gST->ConOut, New.Data);
649 } else {
650 gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
651 }
652 //
653 // clear the old mouse position
654 //
655 FRow = HBufferImage.LowVisibleRow + HBufferImage.MousePosition.Row - 2;
656
657 HighBits = HBufferImageIsAtHighBits (
658 HBufferImage.MousePosition.Column,
659 &FColumn
660 );
661
662 HasCharacter = TRUE;
663 if (FRow > HBufferImage.NumLines || FColumn == 0) {
664 HasCharacter = FALSE;
665 } else {
666 CurrentLine = HBufferImage.CurrentLine;
667 Line = HMoveLine (FRow - HBufferImage.BufferPosition.Row);
668
669 if (Line == NULL || FColumn > Line->Size) {
670 HasCharacter = FALSE;
671 }
672
673 HBufferImage.CurrentLine = CurrentLine;
674 }
675
676 ShellPrintEx (
677 (INT32)HBufferImage.MousePosition.Column - 1,
678 (INT32)HBufferImage.MousePosition.Row - 1,
679 L" "
680 );
681
682 if (HasCharacter) {
683 if (HighBits) {
684 Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf0);
685 Value = (UINT8) (Value >> 4);
686 } else {
687 Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf);
688 }
689
690 ShellPrintEx (
691 (INT32)HBufferImage.MousePosition.Column - 1,
692 (INT32)HBufferImage.MousePosition.Row - 1,
693 L"%x",
694 Value
695 );
696 }
697 //
698 // end of HasCharacter
699 //
700 gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
701 }
702 //
703 // end of MouseNeedRefresh
704 //
705 }
706 //
707 // end of MouseSupported
708 //
709 return EFI_SUCCESS;
710 }
711
712 /**
713 Set cursor position according to HBufferImage.DisplayPosition.
714
715 @retval EFI_SUCCESS The operation was successful.
716 **/
717 EFI_STATUS
718 HBufferImageRestorePosition (
719 VOID
720 )
721 {
722 //
723 // set cursor position
724 //
725 gST->ConOut->SetCursorPosition (
726 gST->ConOut,
727 HBufferImage.DisplayPosition.Column - 1,
728 HBufferImage.DisplayPosition.Row - 1
729 );
730
731 return EFI_SUCCESS;
732 }
733
734 /**
735 Refresh function for HBufferImage.
736
737 @retval EFI_SUCCESS The operation was successful.
738 @retval EFI_LOAD_ERROR A Load error occured.
739
740 **/
741 EFI_STATUS
742 HBufferImageRefresh (
743 VOID
744 )
745 {
746 LIST_ENTRY *Link;
747 HEFI_EDITOR_LINE *Line;
748 UINTN Row;
749 HEFI_EDITOR_COLOR_UNION Orig;
750 HEFI_EDITOR_COLOR_UNION New;
751
752 UINTN StartRow;
753 UINTN EndRow;
754 UINTN FStartRow;
755 UINTN Tmp;
756
757 Orig = HMainEditor.ColorAttributes;
758 New.Colors.Foreground = Orig.Colors.Background;
759 New.Colors.Background = Orig.Colors.Foreground;
760
761 //
762 // if it's the first time after editor launch, so should refresh
763 //
764 if (HEditorFirst == FALSE) {
765 //
766 // no definite required refresh
767 // and file position displayed on screen has not been changed
768 //
769 if (!HBufferImageNeedRefresh &&
770 !HBufferImageOnlyLineNeedRefresh &&
771 HBufferImageBackupVar.LowVisibleRow == HBufferImage.LowVisibleRow
772 ) {
773 HBufferImageRestoreMousePosition ();
774 HBufferImageRestorePosition ();
775 return EFI_SUCCESS;
776 }
777 }
778
779 gST->ConOut->EnableCursor (gST->ConOut, FALSE);
780
781 //
782 // only need to refresh current line
783 //
784 if (HBufferImageOnlyLineNeedRefresh && HBufferImageBackupVar.LowVisibleRow == HBufferImage.LowVisibleRow) {
785
786 HBufferImagePrintLine (
787 HBufferImage.CurrentLine,
788 HBufferImage.DisplayPosition.Row,
789 HBufferImage.BufferPosition.Row,
790 Orig,
791 New
792 );
793 } else {
794 //
795 // the whole edit area need refresh
796 //
797 if (HEditorMouseAction && HMainEditor.SelectStart != 0 && HMainEditor.SelectEnd != 0) {
798 if (HMainEditor.SelectStart != HMainEditorBackupVar.SelectStart) {
799 if (HMainEditor.SelectStart >= HMainEditorBackupVar.SelectStart && HMainEditorBackupVar.SelectStart != 0) {
800 StartRow = (HMainEditorBackupVar.SelectStart - 1) / 0x10 + 1;
801 } else {
802 StartRow = (HMainEditor.SelectStart - 1) / 0x10 + 1;
803 }
804 } else {
805 StartRow = (HMainEditor.SelectStart - 1) / 0x10 + 1;
806 }
807
808 if (HMainEditor.SelectEnd <= HMainEditorBackupVar.SelectEnd) {
809 EndRow = (HMainEditorBackupVar.SelectEnd - 1) / 0x10 + 1;
810 } else {
811 EndRow = (HMainEditor.SelectEnd - 1) / 0x10 + 1;
812 }
813 //
814 // swap
815 //
816 if (StartRow > EndRow) {
817 Tmp = StartRow;
818 StartRow = EndRow;
819 EndRow = Tmp;
820 }
821
822 FStartRow = StartRow;
823
824 StartRow = 2 + StartRow - HBufferImage.LowVisibleRow;
825 EndRow = 2 + EndRow - HBufferImage.LowVisibleRow;
826
827 } else {
828 //
829 // not mouse selection actions
830 //
831 FStartRow = HBufferImage.LowVisibleRow;
832 StartRow = 2;
833 EndRow = (HMainEditor.ScreenSize.Row - 1);
834 }
835 //
836 // no line
837 //
838 if (HBufferImage.Lines == NULL) {
839 HBufferImageRestoreMousePosition ();
840 HBufferImageRestorePosition ();
841 gST->ConOut->EnableCursor (gST->ConOut, TRUE);
842 return EFI_SUCCESS;
843 }
844 //
845 // get the first line that will be displayed
846 //
847 Line = HMoveLine (FStartRow - HBufferImage.BufferPosition.Row);
848 if (Line == NULL) {
849 gST->ConOut->EnableCursor (gST->ConOut, TRUE);
850 return EFI_LOAD_ERROR;
851 }
852
853 Link = &(Line->Link);
854 Row = StartRow;
855 do {
856 Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
857
858 //
859 // print line at row
860 //
861 HBufferImagePrintLine (
862 Line,
863 Row,
864 HBufferImage.LowVisibleRow + Row - 2,
865 Orig,
866 New
867 );
868
869 Link = Link->ForwardLink;
870 Row++;
871 } while (Link != HBufferImage.ListHead && Row <= EndRow);
872
873 while (Row <= EndRow) {
874 EditorClearLine (Row, HMainEditor.ScreenSize.Column, HMainEditor.ScreenSize.Row);
875 Row++;
876 }
877 //
878 // while not file end and not screen full
879 //
880 }
881
882 HBufferImageRestoreMousePosition ();
883 HBufferImageRestorePosition ();
884
885 HBufferImageNeedRefresh = FALSE;
886 HBufferImageOnlyLineNeedRefresh = FALSE;
887 gST->ConOut->EnableCursor (gST->ConOut, TRUE);
888
889 return EFI_SUCCESS;
890 }
891
892 /**
893 Read an image into a buffer friom a source.
894
895 @param[in] FileName Pointer to the file name. OPTIONAL and ignored if not FileTypeFileBuffer.
896 @param[in] DiskName Pointer to the disk name. OPTIONAL and ignored if not FileTypeDiskBuffer.
897 @param[in] DiskOffset Offset into the disk. OPTIONAL and ignored if not FileTypeDiskBuffer.
898 @param[in] DiskSize Size of the disk buffer. OPTIONAL and ignored if not FileTypeDiskBuffer.
899 @param[in] MemOffset Offset into the Memory. OPTIONAL and ignored if not FileTypeMemBuffer.
900 @param[in] MemSize Size of the Memory buffer. OPTIONAL and ignored if not FileTypeMemBuffer.
901 @param[in] BufferType The type of buffer to save. IGNORED.
902 @param[in] Recover TRUE for recovermode, FALSE otherwise.
903
904 @return EFI_SUCCESS The operation was successful.
905 **/
906 EFI_STATUS
907 EFIAPI
908 HBufferImageRead (
909 IN CONST CHAR16 *FileName,
910 IN CONST CHAR16 *DiskName,
911 IN UINTN DiskOffset,
912 IN UINTN DiskSize,
913 IN UINTN MemOffset,
914 IN UINTN MemSize,
915 IN EDIT_FILE_TYPE BufferType,
916 IN BOOLEAN Recover
917 )
918 {
919 EFI_STATUS Status;
920 EDIT_FILE_TYPE BufferTypeBackup;
921
922 //
923 // variable initialization
924 //
925 Status = EFI_SUCCESS;
926 HBufferImage.BufferType = BufferType;
927
928 //
929 // three types of buffer supported
930 // file buffer
931 // disk buffer
932 // memory buffer
933 //
934 BufferTypeBackup = HBufferImage.BufferType;
935
936 switch (BufferType) {
937 case FileTypeFileBuffer:
938 Status = HFileImageRead (FileName, Recover);
939 break;
940
941 case FileTypeDiskBuffer:
942 Status = HDiskImageRead (DiskName, DiskOffset, DiskSize, Recover);
943 break;
944
945 case FileTypeMemBuffer:
946 Status = HMemImageRead (MemOffset, MemSize, Recover);
947 break;
948
949 default:
950 Status = EFI_NOT_FOUND;
951 break;
952 }
953
954 if (EFI_ERROR (Status)) {
955 HBufferImage.BufferType = BufferTypeBackup;
956 }
957
958 return Status;
959 }
960
961 /**
962 Save the current image.
963
964 @param[in] FileName Pointer to the file name. OPTIONAL and ignored if not FileTypeFileBuffer.
965 @param[in] DiskName Pointer to the disk name. OPTIONAL and ignored if not FileTypeDiskBuffer.
966 @param[in] DiskOffset Offset into the disk. OPTIONAL and ignored if not FileTypeDiskBuffer.
967 @param[in] DiskSize Size of the disk buffer. OPTIONAL and ignored if not FileTypeDiskBuffer.
968 @param[in] MemOffset Offset into the Memory. OPTIONAL and ignored if not FileTypeMemBuffer.
969 @param[in] MemSize Size of the Memory buffer. OPTIONAL and ignored if not FileTypeMemBuffer.
970 @param[in] BufferType The type of buffer to save. IGNORED.
971
972 @return EFI_SUCCESS The operation was successful.
973 **/
974 EFI_STATUS
975 HBufferImageSave (
976 IN CHAR16 *FileName,
977 IN CHAR16 *DiskName,
978 IN UINTN DiskOffset,
979 IN UINTN DiskSize,
980 IN UINTN MemOffset,
981 IN UINTN MemSize,
982 IN EDIT_FILE_TYPE BufferType
983 )
984 {
985 EFI_STATUS Status;
986 EDIT_FILE_TYPE BufferTypeBackup;
987
988 //
989 // variable initialization
990 //
991 Status = EFI_SUCCESS;
992 BufferTypeBackup = HBufferImage.BufferType;
993
994 switch (HBufferImage.BufferType) {
995 //
996 // file buffer
997 //
998 case FileTypeFileBuffer:
999 Status = HFileImageSave (FileName);
1000 break;
1001
1002 //
1003 // disk buffer
1004 //
1005 case FileTypeDiskBuffer:
1006 Status = HDiskImageSave (DiskName, DiskOffset, DiskSize);
1007 break;
1008
1009 //
1010 // memory buffer
1011 //
1012 case FileTypeMemBuffer:
1013 Status = HMemImageSave (MemOffset, MemSize);
1014 break;
1015
1016 default:
1017 Status = EFI_NOT_FOUND;
1018 break;
1019 }
1020
1021 if (EFI_ERROR (Status)) {
1022 HBufferImage.BufferType = BufferTypeBackup;
1023 }
1024
1025 return Status;
1026 }
1027
1028 /**
1029 Create a new line and append it to the line list.
1030 Fields affected:
1031 NumLines
1032 Lines
1033
1034 @retval NULL create line failed.
1035 @return the line created.
1036
1037 **/
1038 HEFI_EDITOR_LINE *
1039 HBufferImageCreateLine (
1040 VOID
1041 )
1042 {
1043 HEFI_EDITOR_LINE *Line;
1044
1045 //
1046 // allocate for line structure
1047 //
1048 Line = AllocateZeroPool (sizeof (HEFI_EDITOR_LINE));
1049 if (Line == NULL) {
1050 return NULL;
1051 }
1052
1053 Line->Signature = EFI_EDITOR_LINE_LIST;
1054 Line->Size = 0;
1055
1056 HBufferImage.NumLines++;
1057
1058 //
1059 // insert to line list
1060 //
1061 InsertTailList (HBufferImage.ListHead, &Line->Link);
1062
1063 if (HBufferImage.Lines == NULL) {
1064 HBufferImage.Lines = CR (
1065 HBufferImage.ListHead->ForwardLink,
1066 HEFI_EDITOR_LINE,
1067 Link,
1068 EFI_EDITOR_LINE_LIST
1069 );
1070 }
1071
1072 return Line;
1073 }
1074
1075 /**
1076 Free the current image.
1077
1078 @retval EFI_SUCCESS The operation was successful.
1079 **/
1080 EFI_STATUS
1081 HBufferImageFree (
1082 VOID
1083 )
1084 {
1085 //
1086 // free all lines
1087 //
1088 HBufferImageFreeLines ();
1089
1090 return EFI_SUCCESS;
1091 }
1092
1093 /**
1094 change char to int value based on Hex.
1095
1096 @param[in] Char The input char.
1097
1098 @return The character's index value.
1099 @retval -1 The operation failed.
1100 **/
1101 INTN
1102 EFIAPI
1103 HBufferImageCharToHex (
1104 IN CHAR16 Char
1105 )
1106 {
1107 //
1108 // change the character to hex
1109 //
1110 if (Char >= L'0' && Char <= L'9') {
1111 return (INTN) (Char - L'0');
1112 }
1113
1114 if (Char >= L'a' && Char <= L'f') {
1115 return (INTN) (Char - L'a' + 10);
1116 }
1117
1118 if (Char >= L'A' && Char <= L'F') {
1119 return (INTN) (Char - L'A' + 10);
1120 }
1121
1122 return -1;
1123 }
1124
1125 /**
1126 Add character.
1127
1128 @param[in] Char -- input char.
1129
1130 @retval EFI_SUCCESS The operation was successful.
1131 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1132 **/
1133 EFI_STATUS
1134 EFIAPI
1135 HBufferImageAddChar (
1136 IN CHAR16 Char
1137 )
1138 {
1139 HEFI_EDITOR_LINE *Line;
1140 HEFI_EDITOR_LINE *NewLine;
1141 INTN Value;
1142 UINT8 Old;
1143 UINTN FRow;
1144 UINTN FCol;
1145 BOOLEAN High;
1146
1147 Value = HBufferImageCharToHex (Char);
1148
1149 //
1150 // invalid input
1151 //
1152 if (Value == -1) {
1153 return EFI_SUCCESS;
1154 }
1155
1156 Line = HBufferImage.CurrentLine;
1157 FRow = HBufferImage.BufferPosition.Row;
1158 FCol = HBufferImage.BufferPosition.Column;
1159 High = HBufferImage.HighBits;
1160
1161 //
1162 // only needs to refresh current line
1163 //
1164 HBufferImageOnlyLineNeedRefresh = TRUE;
1165
1166 //
1167 // not a full line and beyond the last character
1168 //
1169 if (FCol > Line->Size) {
1170 //
1171 // cursor always at high 4 bits
1172 // and always put input to the low 4 bits
1173 //
1174 Line->Buffer[Line->Size] = (UINT8) Value;
1175 Line->Size++;
1176 High = FALSE;
1177 } else {
1178
1179 Old = Line->Buffer[FCol - 1];
1180
1181 //
1182 // always put the input to the low 4 bits
1183 //
1184 Old = (UINT8) (Old & 0x0f);
1185 Old = (UINT8) (Old << 4);
1186 Old = (UINT8) (Value + Old);
1187 Line->Buffer[FCol - 1] = Old;
1188
1189 //
1190 // at the low 4 bits of the last character of a full line
1191 // so if no next line, need to create a new line
1192 //
1193 if (!High && FCol == 0x10) {
1194
1195 HBufferImageOnlyLineNeedRefresh = FALSE;
1196 HBufferImageNeedRefresh = TRUE;
1197
1198 if (Line->Link.ForwardLink == HBufferImage.ListHead) {
1199 //
1200 // last line
1201 //
1202 // create a new line
1203 //
1204 NewLine = HBufferImageCreateLine ();
1205 if (NewLine == NULL) {
1206 return EFI_OUT_OF_RESOURCES;
1207 }
1208 //
1209 // end of NULL
1210 //
1211 }
1212 //
1213 // end of == ListHead
1214 //
1215 }
1216 //
1217 // end of == 0x10
1218 //
1219 // if already at end of this line, scroll it to the start of next line
1220 //
1221 if (FCol == 0x10 && !High) {
1222 //
1223 // definitely has next line
1224 //
1225 FRow++;
1226 FCol = 1;
1227 High = TRUE;
1228 } else {
1229 //
1230 // if not at end of this line, just move to next column
1231 //
1232 if (!High) {
1233 FCol++;
1234 }
1235
1236 if (High) {
1237 High = FALSE;
1238 } else {
1239 High = TRUE;
1240 }
1241
1242 }
1243 //
1244 // end of ==FALSE
1245 //
1246 }
1247 //
1248 // move cursor to right
1249 //
1250 HBufferImageMovePosition (FRow, FCol, High);
1251
1252 if (!HBufferImage.Modified) {
1253 HBufferImage.Modified = TRUE;
1254 }
1255
1256 return EFI_SUCCESS;
1257 }
1258
1259 /**
1260 Delete the previous character.
1261
1262 @retval EFI_SUCCESS The operationw as successful.
1263 **/
1264 EFI_STATUS
1265 EFIAPI
1266 HBufferImageDoBackspace (
1267 VOID
1268 )
1269 {
1270 HEFI_EDITOR_LINE *Line;
1271
1272 UINTN FileColumn;
1273 UINTN FPos;
1274 BOOLEAN LastLine;
1275
1276 //
1277 // variable initialization
1278 //
1279 LastLine = FALSE;
1280
1281 //
1282 // already the first character
1283 //
1284 if (HBufferImage.BufferPosition.Row == 1 && HBufferImage.BufferPosition.Column == 1) {
1285 return EFI_SUCCESS;
1286 }
1287
1288 FPos = (HBufferImage.BufferPosition.Row - 1) * 0x10 + HBufferImage.BufferPosition.Column - 1;
1289
1290 FileColumn = HBufferImage.BufferPosition.Column;
1291
1292 Line = HBufferImage.CurrentLine;
1293 LastLine = FALSE;
1294 if (Line->Link.ForwardLink == HBufferImage.ListHead && FileColumn > 1) {
1295 LastLine = TRUE;
1296 }
1297
1298 HBufferImageDeleteCharacterFromBuffer (FPos - 1, 1, NULL);
1299
1300 //
1301 // if is the last line
1302 // then only this line need to be refreshed
1303 //
1304 if (LastLine) {
1305 HBufferImageNeedRefresh = FALSE;
1306 HBufferImageOnlyLineNeedRefresh = TRUE;
1307 } else {
1308 HBufferImageNeedRefresh = TRUE;
1309 HBufferImageOnlyLineNeedRefresh = FALSE;
1310 }
1311
1312 if (!HBufferImage.Modified) {
1313 HBufferImage.Modified = TRUE;
1314 }
1315
1316 return EFI_SUCCESS;
1317 }
1318
1319 /**
1320 ASCII key + Backspace + return.
1321
1322 @param[in] Char The input char.
1323
1324 @retval EFI_SUCCESS The operation was successful.
1325 @retval EFI_LOAD_ERROR A load error occured.
1326 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1327 **/
1328 EFI_STATUS
1329 EFIAPI
1330 HBufferImageDoCharInput (
1331 IN CHAR16 Char
1332 )
1333 {
1334 EFI_STATUS Status;
1335
1336 Status = EFI_SUCCESS;
1337
1338 switch (Char) {
1339 case 0:
1340 break;
1341
1342 case 0x08:
1343 Status = HBufferImageDoBackspace ();
1344 break;
1345
1346 case 0x09:
1347 case 0x0a:
1348 case 0x0d:
1349 //
1350 // Tabs, Returns are thought as nothing
1351 //
1352 break;
1353
1354 default:
1355 //
1356 // DEAL WITH ASCII CHAR, filter out thing like ctrl+f
1357 //
1358 if (Char > 127 || Char < 32) {
1359 Status = StatusBarSetStatusString (L"Unknown Command");
1360 } else {
1361 Status = HBufferImageAddChar (Char);
1362 }
1363
1364 break;
1365 }
1366
1367 return Status;
1368 }
1369
1370 /**
1371 Check user specified FileRow is above current screen.
1372
1373 @param[in] FileRow Row of file position ( start from 1 ).
1374
1375 @retval TRUE It is above the current screen.
1376 @retval FALSE It is not above the current screen.
1377
1378 **/
1379 BOOLEAN
1380 HAboveCurrentScreen (
1381 IN UINTN FileRow
1382 )
1383 {
1384 if (FileRow < HBufferImage.LowVisibleRow) {
1385 return TRUE;
1386 }
1387
1388 return FALSE;
1389 }
1390
1391 /**
1392 Check user specified FileRow is under current screen.
1393
1394 @param[in] FileRow Row of file position ( start from 1 ).
1395
1396 @retval TRUE It is under the current screen.
1397 @retval FALSE It is not under the current screen.
1398
1399 **/
1400 BOOLEAN
1401 HUnderCurrentScreen (
1402 IN UINTN FileRow
1403 )
1404 {
1405 if (FileRow > HBufferImage.LowVisibleRow + (HMainEditor.ScreenSize.Row - 2) - 1) {
1406 return TRUE;
1407 }
1408
1409 return FALSE;
1410 }
1411
1412 /**
1413 According to cursor's file position, adjust screen display.
1414
1415 @param[in] NewFilePosRow Row of file position ( start from 1 ).
1416 @param[in] NewFilePosCol Column of file position ( start from 1 ).
1417 @param[in] HighBits Cursor will on high4 bits or low4 bits.
1418 **/
1419 VOID
1420 HBufferImageMovePosition (
1421 IN UINTN NewFilePosRow,
1422 IN UINTN NewFilePosCol,
1423 IN BOOLEAN HighBits
1424 )
1425 {
1426 INTN RowGap;
1427 UINTN Abs;
1428 BOOLEAN Above;
1429 BOOLEAN Under;
1430 UINTN NewDisplayCol;
1431
1432 //
1433 // CALCULATE gap between current file position and new file position
1434 //
1435 RowGap = NewFilePosRow - HBufferImage.BufferPosition.Row;
1436
1437 Under = HUnderCurrentScreen (NewFilePosRow);
1438 Above = HAboveCurrentScreen (NewFilePosRow);
1439
1440 HBufferImage.HighBits = HighBits;
1441
1442 //
1443 // if is below current screen
1444 //
1445 if (Under) {
1446 //
1447 // display row will be unchanged
1448 //
1449 HBufferImage.BufferPosition.Row = NewFilePosRow;
1450 } else {
1451 if (Above) {
1452 //
1453 // has enough above line, so display row unchanged
1454 // not has enough above lines, so the first line is
1455 // at the first display line
1456 //
1457 if (NewFilePosRow < (HBufferImage.DisplayPosition.Row - 2 + 1)) {
1458 HBufferImage.DisplayPosition.Row = NewFilePosRow + 2 - 1;
1459 }
1460
1461 HBufferImage.BufferPosition.Row = NewFilePosRow;
1462 } else {
1463 //
1464 // in current screen
1465 //
1466 HBufferImage.BufferPosition.Row = NewFilePosRow;
1467 if (RowGap <= 0) {
1468 Abs = (UINTN)ABS(RowGap);
1469 HBufferImage.DisplayPosition.Row -= Abs;
1470 } else {
1471 HBufferImage.DisplayPosition.Row += RowGap;
1472 }
1473
1474 }
1475 }
1476
1477 HBufferImage.LowVisibleRow = HBufferImage.BufferPosition.Row - (HBufferImage.DisplayPosition.Row - 2);
1478
1479 //
1480 // always in current screen
1481 //
1482 HBufferImage.BufferPosition.Column = NewFilePosCol;
1483
1484 NewDisplayCol = 10 + (NewFilePosCol - 1) * 3;
1485 if (NewFilePosCol > 0x8) {
1486 NewDisplayCol++;
1487 }
1488
1489 if (!HighBits) {
1490 NewDisplayCol++;
1491 }
1492
1493 HBufferImage.DisplayPosition.Column = NewDisplayCol;
1494
1495 //
1496 // let CurrentLine point to correct line;
1497 //
1498 HBufferImage.CurrentLine = HMoveCurrentLine (RowGap);
1499
1500 }
1501
1502 /**
1503 Scroll cursor to right.
1504
1505 @retval EFI_SUCCESS The operation was successful.
1506 **/
1507 EFI_STATUS
1508 HBufferImageScrollRight (
1509 VOID
1510 )
1511 {
1512 HEFI_EDITOR_LINE *Line;
1513 UINTN FRow;
1514 UINTN FCol;
1515
1516 //
1517 // scroll right will always move to the high4 bits of the next character
1518 //
1519 HBufferImageNeedRefresh = FALSE;
1520 HBufferImageOnlyLineNeedRefresh = FALSE;
1521
1522 Line = HBufferImage.CurrentLine;
1523
1524 FRow = HBufferImage.BufferPosition.Row;
1525 FCol = HBufferImage.BufferPosition.Column;
1526
1527 //
1528 // this line is not full and no next line
1529 //
1530 if (FCol > Line->Size) {
1531 return EFI_SUCCESS;
1532 }
1533 //
1534 // if already at end of this line, scroll it to the start of next line
1535 //
1536 if (FCol == 0x10) {
1537 //
1538 // has next line
1539 //
1540 if (Line->Link.ForwardLink != HBufferImage.ListHead) {
1541 FRow++;
1542 FCol = 1;
1543
1544 } else {
1545 return EFI_SUCCESS;
1546 }
1547 } else {
1548 //
1549 // if not at end of this line, just move to next column
1550 //
1551 FCol++;
1552
1553 }
1554
1555 HBufferImageMovePosition (FRow, FCol, TRUE);
1556
1557 return EFI_SUCCESS;
1558 }
1559
1560 /**
1561 Scroll cursor to left.
1562
1563 @retval EFI_SUCCESS The operation was successful.
1564 **/
1565 EFI_STATUS
1566 HBufferImageScrollLeft (
1567 VOID
1568 )
1569 {
1570
1571 HEFI_EDITOR_LINE *Line;
1572 UINTN FRow;
1573 UINTN FCol;
1574
1575 HBufferImageNeedRefresh = FALSE;
1576 HBufferImageOnlyLineNeedRefresh = FALSE;
1577
1578 Line = HBufferImage.CurrentLine;
1579
1580 FRow = HBufferImage.BufferPosition.Row;
1581 FCol = HBufferImage.BufferPosition.Column;
1582
1583 //
1584 // if already at start of this line, so move to the end of previous line
1585 //
1586 if (FCol <= 1) {
1587 //
1588 // has previous line
1589 //
1590 if (Line->Link.BackLink != HBufferImage.ListHead) {
1591 FRow--;
1592 Line = CR (Line->Link.BackLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
1593 FCol = Line->Size;
1594 } else {
1595 return EFI_SUCCESS;
1596 }
1597 } else {
1598 //
1599 // if not at start of this line, just move to previous column
1600 //
1601 FCol--;
1602 }
1603
1604 HBufferImageMovePosition (FRow, FCol, TRUE);
1605
1606 return EFI_SUCCESS;
1607 }
1608
1609 /**
1610 Scroll cursor to the next line
1611
1612 @retval EFI_SUCCESS The operation was successful.
1613 **/
1614 EFI_STATUS
1615 HBufferImageScrollDown (
1616 VOID
1617 )
1618 {
1619 HEFI_EDITOR_LINE *Line;
1620 UINTN FRow;
1621 UINTN FCol;
1622 BOOLEAN HighBits;
1623
1624 Line = HBufferImage.CurrentLine;
1625
1626 FRow = HBufferImage.BufferPosition.Row;
1627 FCol = HBufferImage.BufferPosition.Column;
1628 HighBits = HBufferImage.HighBits;
1629
1630 //
1631 // has next line
1632 //
1633 if (Line->Link.ForwardLink != HBufferImage.ListHead) {
1634 FRow++;
1635 Line = CR (Line->Link.ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
1636
1637 //
1638 // if the next line is not that long, so move to end of next line
1639 //
1640 if (FCol > Line->Size) {
1641 FCol = Line->Size + 1;
1642 HighBits = TRUE;
1643 }
1644
1645 } else {
1646 return EFI_SUCCESS;
1647 }
1648
1649 HBufferImageMovePosition (FRow, FCol, HighBits);
1650
1651 return EFI_SUCCESS;
1652 }
1653
1654 /**
1655 Scroll cursor to previous line
1656
1657 @retval EFI_SUCCESS The operation was successful.
1658 **/
1659 EFI_STATUS
1660 HBufferImageScrollUp (
1661 VOID
1662 )
1663 {
1664 HEFI_EDITOR_LINE *Line;
1665 UINTN FRow;
1666 UINTN FCol;
1667
1668 Line = HBufferImage.CurrentLine;
1669
1670 FRow = HBufferImage.BufferPosition.Row;
1671 FCol = HBufferImage.BufferPosition.Column;
1672
1673 //
1674 // has previous line
1675 //
1676 if (Line->Link.BackLink != HBufferImage.ListHead) {
1677 FRow--;
1678
1679 } else {
1680 return EFI_SUCCESS;
1681 }
1682
1683 HBufferImageMovePosition (FRow, FCol, HBufferImage.HighBits);
1684
1685 return EFI_SUCCESS;
1686 }
1687
1688 /**
1689 Scroll cursor to next page
1690
1691 @retval EFI_SUCCESS The operation was successful.
1692 **/
1693 EFI_STATUS
1694 HBufferImagePageDown (
1695 VOID
1696 )
1697 {
1698 HEFI_EDITOR_LINE *Line;
1699 UINTN FRow;
1700 UINTN FCol;
1701 UINTN Gap;
1702 BOOLEAN HighBits;
1703
1704 Line = HBufferImage.CurrentLine;
1705
1706 FRow = HBufferImage.BufferPosition.Row;
1707 FCol = HBufferImage.BufferPosition.Column;
1708 HighBits = HBufferImage.HighBits;
1709
1710 //
1711 // has next page
1712 //
1713 if (HBufferImage.NumLines >= FRow + (HMainEditor.ScreenSize.Row - 2)) {
1714 Gap = (HMainEditor.ScreenSize.Row - 2);
1715 } else {
1716 //
1717 // MOVE CURSOR TO LAST LINE
1718 //
1719 Gap = HBufferImage.NumLines - FRow;
1720 }
1721 //
1722 // get correct line
1723 //
1724 Line = HMoveLine (Gap);
1725
1726 //
1727 // if that line, is not that long, so move to the end of that line
1728 //
1729 if (Line != NULL && FCol > Line->Size) {
1730 FCol = Line->Size + 1;
1731 HighBits = TRUE;
1732 }
1733
1734 FRow += Gap;
1735
1736 HBufferImageMovePosition (FRow, FCol, HighBits);
1737
1738 return EFI_SUCCESS;
1739 }
1740
1741 /**
1742 Scroll cursor to previous page
1743
1744 @retval EFI_SUCCESS The operation was successful.
1745 **/
1746 EFI_STATUS
1747 HBufferImagePageUp (
1748 VOID
1749 )
1750 {
1751 UINTN FRow;
1752 UINTN FCol;
1753 UINTN Gap;
1754 INTN Retreat;
1755
1756 FRow = HBufferImage.BufferPosition.Row;
1757 FCol = HBufferImage.BufferPosition.Column;
1758
1759 //
1760 // has previous page
1761 //
1762 if (FRow > (HMainEditor.ScreenSize.Row - 2)) {
1763 Gap = (HMainEditor.ScreenSize.Row - 2);
1764 } else {
1765 //
1766 // the first line of file will displayed on the first line of screen
1767 //
1768 Gap = FRow - 1;
1769 }
1770
1771 Retreat = Gap;
1772 Retreat = -Retreat;
1773
1774 FRow -= Gap;
1775
1776 HBufferImageMovePosition (FRow, FCol, HBufferImage.HighBits);
1777
1778 return EFI_SUCCESS;
1779 }
1780
1781 /**
1782 Scroll cursor to start of line
1783
1784 @retval EFI_SUCCESS The operation was successful.
1785 **/
1786 EFI_STATUS
1787 HBufferImageHome (
1788 VOID
1789 )
1790 {
1791 UINTN FRow;
1792 UINTN FCol;
1793 BOOLEAN HighBits;
1794
1795 //
1796 // curosr will at the high bit
1797 //
1798 FRow = HBufferImage.BufferPosition.Row;
1799 FCol = 1;
1800 HighBits = TRUE;
1801
1802 //
1803 // move cursor position
1804 //
1805 HBufferImageMovePosition (FRow, FCol, HighBits);
1806
1807 return EFI_SUCCESS;
1808 }
1809
1810 /**
1811 Scroll cursor to end of line.
1812
1813 @retval EFI_SUCCESS Teh operation was successful.
1814 **/
1815 EFI_STATUS
1816 HBufferImageEnd (
1817 VOID
1818 )
1819 {
1820 HEFI_EDITOR_LINE *Line;
1821 UINTN FRow;
1822 UINTN FCol;
1823 BOOLEAN HighBits;
1824
1825 //
1826 // need refresh mouse
1827 //
1828 HBufferImageMouseNeedRefresh = TRUE;
1829
1830 Line = HBufferImage.CurrentLine;
1831
1832 FRow = HBufferImage.BufferPosition.Row;
1833
1834 if (Line->Size == 0x10) {
1835 FCol = Line->Size;
1836 HighBits = FALSE;
1837 } else {
1838 FCol = Line->Size + 1;
1839 HighBits = TRUE;
1840 }
1841 //
1842 // move cursor position
1843 //
1844 HBufferImageMovePosition (FRow, FCol, HighBits);
1845
1846 return EFI_SUCCESS;
1847 }
1848
1849 /**
1850 Get the size of the open buffer.
1851
1852 @retval The size in bytes.
1853 **/
1854 UINTN
1855 HBufferImageGetTotalSize (
1856 VOID
1857 )
1858 {
1859 UINTN Size;
1860
1861 HEFI_EDITOR_LINE *Line;
1862
1863 //
1864 // calculate the total size of whole line list's buffer
1865 //
1866 if (HBufferImage.Lines == NULL) {
1867 return 0;
1868 }
1869
1870 Line = CR (
1871 HBufferImage.ListHead->BackLink,
1872 HEFI_EDITOR_LINE,
1873 Link,
1874 EFI_EDITOR_LINE_LIST
1875 );
1876 //
1877 // one line at most 0x10
1878 //
1879 Size = 0x10 * (HBufferImage.NumLines - 1) + Line->Size;
1880
1881 return Size;
1882 }
1883
1884 /**
1885 Delete character from buffer.
1886
1887 @param[in] Pos Position, Pos starting from 0.
1888 @param[in] Count The Count of characters to delete.
1889 @param[out] DeleteBuffer The DeleteBuffer.
1890
1891 @retval EFI_SUCCESS Success
1892 **/
1893 EFI_STATUS
1894 HBufferImageDeleteCharacterFromBuffer (
1895 IN UINTN Pos,
1896 IN UINTN Count,
1897 OUT UINT8 *DeleteBuffer
1898 )
1899 {
1900 UINTN Index;
1901
1902 VOID *Buffer;
1903 UINT8 *BufferPtr;
1904 UINTN Size;
1905
1906 HEFI_EDITOR_LINE *Line;
1907 LIST_ENTRY *Link;
1908
1909 UINTN OldFCol;
1910 UINTN OldFRow;
1911 UINTN OldPos;
1912
1913 UINTN NewPos;
1914
1915 EFI_STATUS Status;
1916
1917 Size = HBufferImageGetTotalSize ();
1918
1919 if (Size < Count) {
1920 return EFI_LOAD_ERROR;
1921 }
1922
1923 if (Size == 0) {
1924 return EFI_SUCCESS;
1925 }
1926
1927 //
1928 // relocate all the HBufferImage fields
1929 //
1930 OldFRow = HBufferImage.BufferPosition.Row;
1931 OldFCol = HBufferImage.BufferPosition.Column;
1932 OldPos = (OldFRow - 1) * 0x10 + OldFCol - 1;
1933
1934 if (Pos > 0) {
1935 //
1936 // has character before it,
1937 // so locate according to block's previous character
1938 //
1939 NewPos = Pos - 1;
1940
1941 } else {
1942 //
1943 // has no character before it,
1944 // so locate according to block's next character
1945 //
1946 NewPos = 0;
1947 }
1948
1949 HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);
1950
1951 Buffer = AllocateZeroPool (Size);
1952 if (Buffer == NULL) {
1953 return EFI_OUT_OF_RESOURCES;
1954 }
1955
1956 HBufferImageListToBuffer (Buffer, Size);
1957
1958 BufferPtr = (UINT8 *) Buffer;
1959
1960 //
1961 // pass deleted buffer out
1962 //
1963 if (DeleteBuffer != NULL) {
1964 for (Index = 0; Index < Count; Index++) {
1965 DeleteBuffer[Index] = BufferPtr[Pos + Index];
1966 }
1967 }
1968 //
1969 // delete the part from Pos
1970 //
1971 for (Index = Pos; Index < Size - Count; Index++) {
1972 BufferPtr[Index] = BufferPtr[Index + Count];
1973 }
1974
1975 Size -= Count;
1976
1977 HBufferImageFreeLines ();
1978
1979 Status = HBufferImageBufferToList (Buffer, Size);
1980 FreePool (Buffer);
1981
1982 if (EFI_ERROR (Status)) {
1983 return Status;
1984 }
1985
1986 Link = HMainEditor.BufferImage->ListHead->ForwardLink;
1987 for (Index = 0; Index < NewPos / 0x10; Index++) {
1988 Link = Link->ForwardLink;
1989 }
1990
1991 Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
1992 HBufferImage.CurrentLine = Line;
1993
1994 //
1995 // if current cursor position if inside select area
1996 // then move it to the block's NEXT character
1997 //
1998 if (OldPos >= Pos && OldPos < (Pos + Count)) {
1999 NewPos = Pos;
2000 } else {
2001 if (OldPos < Pos) {
2002 NewPos = OldPos;
2003 } else {
2004 NewPos = OldPos - Count;
2005 }
2006 }
2007
2008 HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);
2009
2010 return EFI_SUCCESS;
2011 }
2012
2013 /**
2014 Add character to buffer, add before pos.
2015
2016 @param[in] Pos Position, Pos starting from 0.
2017 @param[in] Count Count of characters to add.
2018 @param[in] AddBuffer Add buffer.
2019
2020 @retval EFI_SUCCESS Success.
2021 **/
2022 EFI_STATUS
2023 HBufferImageAddCharacterToBuffer (
2024 IN UINTN Pos,
2025 IN UINTN Count,
2026 IN UINT8 *AddBuffer
2027 )
2028 {
2029 INTN Index;
2030
2031 VOID *Buffer;
2032 UINT8 *BufferPtr;
2033 UINTN Size;
2034
2035 HEFI_EDITOR_LINE *Line;
2036
2037 LIST_ENTRY *Link;
2038
2039 UINTN OldFCol;
2040 UINTN OldFRow;
2041 UINTN OldPos;
2042
2043 UINTN NewPos;
2044
2045 Size = HBufferImageGetTotalSize ();
2046
2047 //
2048 // relocate all the HBufferImage fields
2049 //
2050 OldFRow = HBufferImage.BufferPosition.Row;
2051 OldFCol = HBufferImage.BufferPosition.Column;
2052 OldPos = (OldFRow - 1) * 0x10 + OldFCol - 1;
2053
2054 //
2055 // move cursor before Pos
2056 //
2057 if (Pos > 0) {
2058 NewPos = Pos - 1;
2059 } else {
2060 NewPos = 0;
2061 }
2062
2063 HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);
2064
2065 Buffer = AllocateZeroPool (Size + Count);
2066 if (Buffer == NULL) {
2067 return EFI_OUT_OF_RESOURCES;
2068 }
2069
2070 HBufferImageListToBuffer (Buffer, Size);
2071
2072 BufferPtr = (UINT8 *) Buffer;
2073
2074 //
2075 // get a place to add
2076 //
2077 for (Index = (INTN) (Size + Count - 1); Index >= (INTN) Pos; Index--) {
2078 BufferPtr[Index] = BufferPtr[Index - Count];
2079 }
2080 //
2081 // add the buffer
2082 //
2083 for (Index = (INTN) 0; Index < (INTN) Count; Index++) {
2084 BufferPtr[Index + Pos] = AddBuffer[Index];
2085 }
2086
2087 Size += Count;
2088
2089 HBufferImageFreeLines ();
2090
2091 HBufferImageBufferToList (Buffer, Size);
2092
2093 FreePool (Buffer);
2094
2095 Link = HMainEditor.BufferImage->ListHead->ForwardLink;
2096 for (Index = 0; Index < (INTN) NewPos / 0x10; Index++) {
2097 Link = Link->ForwardLink;
2098 }
2099
2100 Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
2101 HBufferImage.CurrentLine = Line;
2102
2103 if (OldPos >= Pos) {
2104 NewPos = OldPos + Count;
2105 } else {
2106 NewPos = OldPos;
2107 }
2108
2109 HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);
2110
2111 return EFI_SUCCESS;
2112 }
2113
2114 /**
2115 Delete current character from line.
2116
2117 @retval EFI_SUCCESS The operationw as successful.
2118 **/
2119 EFI_STATUS
2120 EFIAPI
2121 HBufferImageDoDelete (
2122 VOID
2123 )
2124 {
2125
2126 HEFI_EDITOR_LINE *Line;
2127
2128 BOOLEAN LastLine;
2129 UINTN FileColumn;
2130 UINTN FPos;
2131
2132 FPos = (HBufferImage.BufferPosition.Row - 1) * 0x10 + HBufferImage.BufferPosition.Column - 1;
2133
2134 FileColumn = HBufferImage.BufferPosition.Column;
2135
2136 Line = HBufferImage.CurrentLine;
2137
2138 //
2139 // if beyond the last character
2140 //
2141 if (FileColumn > Line->Size) {
2142 return EFI_SUCCESS;
2143 }
2144
2145 LastLine = FALSE;
2146 if (Line->Link.ForwardLink == HBufferImage.ListHead) {
2147 LastLine = TRUE;
2148 }
2149
2150 HBufferImageDeleteCharacterFromBuffer (FPos, 1, NULL);
2151
2152 //
2153 // if is the last line
2154 // then only this line need to be refreshed
2155 //
2156 if (LastLine) {
2157 HBufferImageNeedRefresh = FALSE;
2158 HBufferImageOnlyLineNeedRefresh = TRUE;
2159 } else {
2160 HBufferImageNeedRefresh = TRUE;
2161 HBufferImageOnlyLineNeedRefresh = FALSE;
2162 }
2163
2164 if (!HBufferImage.Modified) {
2165 HBufferImage.Modified = TRUE;
2166 }
2167
2168 return EFI_SUCCESS;
2169 }
2170
2171 /**
2172 Change the raw buffer to a list of lines for the UI.
2173
2174 @param[in] Buffer The pointer to the buffer to fill.
2175 @param[in] Bytes The size of the buffer in bytes.
2176
2177 @retval EFI_SUCCESS The operation was successful.
2178 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
2179 **/
2180 EFI_STATUS
2181 EFIAPI
2182 HBufferImageBufferToList (
2183 IN VOID *Buffer,
2184 IN UINTN Bytes
2185 )
2186 {
2187 UINTN TempI;
2188 UINTN TempJ;
2189 UINTN Left;
2190 HEFI_EDITOR_LINE *Line;
2191 UINT8 *BufferPtr;
2192
2193 TempI = 0;
2194 Left = 0;
2195 BufferPtr = (UINT8 *) Buffer;
2196
2197 //
2198 // parse file content line by line
2199 //
2200 while (TempI < Bytes) {
2201 if (Bytes - TempI >= 0x10) {
2202 Left = 0x10;
2203 } else {
2204 Left = Bytes - TempI;
2205 }
2206
2207 //
2208 // allocate a new line
2209 //
2210 Line = HBufferImageCreateLine ();
2211 if (Line == NULL) {
2212 return EFI_OUT_OF_RESOURCES;
2213 }
2214
2215 Line->Size = Left;
2216
2217 for (TempJ = 0; TempJ < Left; TempJ++) {
2218 Line->Buffer[TempJ] = BufferPtr[TempI];
2219 TempI++;
2220 }
2221
2222 }
2223
2224 //
2225 // last line is a full line, SO create a new line
2226 //
2227 if (Left == 0x10 || Bytes == 0) {
2228 Line = HBufferImageCreateLine ();
2229 if (Line == NULL) {
2230 return EFI_OUT_OF_RESOURCES;
2231 }
2232 }
2233
2234 return EFI_SUCCESS;
2235 }
2236
2237 /**
2238 Change the list of lines from the UI to a raw buffer.
2239
2240 @param[in] Buffer The pointer to the buffer to fill.
2241 @param[in] Bytes The size of the buffer in bytes.
2242
2243 @retval EFI_SUCCESS The operation was successful.
2244 **/
2245 EFI_STATUS
2246 EFIAPI
2247 HBufferImageListToBuffer (
2248 IN VOID *Buffer,
2249 IN UINTN Bytes
2250 )
2251 {
2252 UINTN Count;
2253 UINTN Index;
2254 HEFI_EDITOR_LINE *Line;
2255 LIST_ENTRY *Link;
2256 UINT8 *BufferPtr;
2257
2258 //
2259 // change the line list to a large buffer
2260 //
2261 if (HBufferImage.Lines == NULL) {
2262 return EFI_SUCCESS;
2263 }
2264
2265 Link = &HBufferImage.Lines->Link;
2266 Count = 0;
2267 BufferPtr = (UINT8 *) Buffer;
2268
2269 //
2270 // deal line by line
2271 //
2272 while (Link != HBufferImage.ListHead) {
2273
2274 Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
2275
2276 //@todo shouldn't this be an error???
2277 if (Count + Line->Size > Bytes) {
2278 return EFI_SUCCESS;
2279 }
2280
2281 for (Index = 0; Index < Line->Size; Index++) {
2282 BufferPtr[Index] = Line->Buffer[Index];
2283 }
2284
2285 Count += Line->Size;
2286 BufferPtr += Line->Size;
2287
2288 Link = Link->ForwardLink;
2289 }
2290
2291 return EFI_SUCCESS;
2292 }
2293
2294 /**
2295 Move the mouse in the image buffer.
2296
2297 @param[in] TextX The x-coordinate.
2298 @param[in] TextY The y-coordinate.
2299 **/
2300 VOID
2301 EFIAPI
2302 HBufferImageAdjustMousePosition (
2303 IN INT32 TextX,
2304 IN INT32 TextY
2305 )
2306 {
2307 UINTN TempX;
2308 UINTN TempY;
2309 UINTN AbsX;
2310 UINTN AbsY;
2311
2312 //
2313 // TextX and TextY is mouse movement data returned by mouse driver
2314 // This function will change it to MousePosition
2315 //
2316 //
2317 // get absolute TempX value
2318 //
2319 if (TextX >= 0) {
2320 AbsX = TextX;
2321 } else {
2322 AbsX = -TextX;
2323 }
2324 //
2325 // get absolute TempY value
2326 //
2327 if (TextY >= 0) {
2328 AbsY = TextY;
2329 } else {
2330 AbsY = -TextY;
2331 }
2332
2333 TempX = HBufferImage.MousePosition.Column;
2334 TempY = HBufferImage.MousePosition.Row;
2335
2336 if (TextX >= 0) {
2337 TempX += TextX;
2338 } else {
2339 if (TempX >= AbsX) {
2340 TempX -= AbsX;
2341 } else {
2342 TempX = 0;
2343 }
2344 }
2345
2346 if (TextY >= 0) {
2347 TempY += TextY;
2348 } else {
2349 if (TempY >= AbsY) {
2350 TempY -= AbsY;
2351 } else {
2352 TempY = 0;
2353 }
2354 }
2355 //
2356 // check whether new mouse column position is beyond screen
2357 // if not, adjust it
2358 //
2359 if (TempX >= 10 && TempX <= (10 + 0x10 * 3 - 1)) {
2360 HBufferImage.MousePosition.Column = TempX;
2361 } else if (TempX < 10) {
2362 HBufferImage.MousePosition.Column = 10;
2363 } else if (TempX > (10 + 0x10 * 3 - 1)) {
2364 HBufferImage.MousePosition.Column = 10 + 0x10 * 3 - 1;
2365 }
2366 //
2367 // check whether new mouse row position is beyond screen
2368 // if not, adjust it
2369 //
2370 if (TempY >= 2 && TempY <= (HMainEditor.ScreenSize.Row - 1)) {
2371 HBufferImage.MousePosition.Row = TempY;
2372 } else if (TempY < 2) {
2373 HBufferImage.MousePosition.Row = 2;
2374 } else if (TempY > (HMainEditor.ScreenSize.Row - 1)) {
2375 HBufferImage.MousePosition.Row = (HMainEditor.ScreenSize.Row - 1);
2376 }
2377
2378 }
2379
2380 /**
2381 Dispatch input to different handler
2382
2383 @param[in] Key The input key:
2384 the keys can be:
2385 ASCII KEY
2386 Backspace/Delete
2387 Direction key: up/down/left/right/pgup/pgdn
2388 Home/End
2389 INS
2390
2391 @retval EFI_SUCCESS The operation was successful.
2392 @retval EFI_LOAD_ERROR A load error occured.
2393 @retval EFI_OUT_OF_RESOURCES A Memory allocation failed.
2394 **/
2395 EFI_STATUS
2396 HBufferImageHandleInput (
2397 IN EFI_INPUT_KEY *Key
2398 )
2399 {
2400 EFI_STATUS Status;
2401
2402 Status = EFI_SUCCESS;
2403
2404 switch (Key->ScanCode) {
2405 //
2406 // ordinary key
2407 //
2408 case SCAN_NULL:
2409 Status = HBufferImageDoCharInput (Key->UnicodeChar);
2410 break;
2411
2412 //
2413 // up arrow
2414 //
2415 case SCAN_UP:
2416 Status = HBufferImageScrollUp ();
2417 break;
2418
2419 //
2420 // down arrow
2421 //
2422 case SCAN_DOWN:
2423 Status = HBufferImageScrollDown ();
2424 break;
2425
2426 //
2427 // right arrow
2428 //
2429 case SCAN_RIGHT:
2430 Status = HBufferImageScrollRight ();
2431 break;
2432
2433 //
2434 // left arrow
2435 //
2436 case SCAN_LEFT:
2437 Status = HBufferImageScrollLeft ();
2438 break;
2439
2440 //
2441 // page up
2442 //
2443 case SCAN_PAGE_UP:
2444 Status = HBufferImagePageUp ();
2445 break;
2446
2447 //
2448 // page down
2449 //
2450 case SCAN_PAGE_DOWN:
2451 Status = HBufferImagePageDown ();
2452 break;
2453
2454 //
2455 // delete
2456 //
2457 case SCAN_DELETE:
2458 Status = HBufferImageDoDelete ();
2459 break;
2460
2461 //
2462 // home
2463 //
2464 case SCAN_HOME:
2465 Status = HBufferImageHome ();
2466 break;
2467
2468 //
2469 // end
2470 //
2471 case SCAN_END:
2472 Status = HBufferImageEnd ();
2473 break;
2474
2475 default:
2476 Status = StatusBarSetStatusString (L"Unknown Command");
2477 break;
2478 }
2479
2480 return Status;
2481 }
2482