summaryrefslogtreecommitdiff
path: root/ShellPkg/Library/UefiShellDebug1CommandsLib
diff options
context:
space:
mode:
authorjcarsey <jcarsey@6f19259b-4bc3-4df7-8a09-765794883524>2011-03-25 21:15:07 +0000
committerjcarsey <jcarsey@6f19259b-4bc3-4df7-8a09-765794883524>2011-03-25 21:15:07 +0000
commit632820d1cf1ce7a18ef354255eaeae6fdbf383b9 (patch)
tree4bae0e4268fdf79eb2f3aa8035b413c95cb28f10 /ShellPkg/Library/UefiShellDebug1CommandsLib
parent5a0fe66eda4a187724b0eb9d660ab21296178af5 (diff)
downloadedk2-platforms-632820d1cf1ce7a18ef354255eaeae6fdbf383b9.tar.xz
add Edit and HexEdit commands.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11436 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'ShellPkg/Library/UefiShellDebug1CommandsLib')
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Edit.c158
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.c3353
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.h263
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c1830
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.h77
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.c92
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.h52
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditStrings.unibin0 -> 7356 bytes
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditor.h32
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditorTypes.h102
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.c2695
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.h250
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.c112
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.h40
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.c487
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.h48
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.c504
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.h56
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEdit.c247
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditor.h41
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditorTypes.h132
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexeditStrings.unibin0 -> 8516 bytes
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.c2294
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.h48
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.c412
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.h52
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.c541
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.h96
28 files changed, 14014 insertions, 0 deletions
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Edit.c b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Edit.c
new file mode 100644
index 0000000000..c4dbf80c96
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Edit.c
@@ -0,0 +1,158 @@
+/** @file
+ Main file for Edit shell Debug1 function.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDebug1CommandsLib.h"
+#include "TextEditor.h"
+
+/**
+ Function for 'edit' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunEdit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *Buffer;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ LIST_ENTRY *Package;
+ CONST CHAR16 *Cwd;
+ CHAR16 *Nfs;
+ CHAR16 *Spot;
+// SHELL_FILE_HANDLE TempHandle;
+
+ Buffer = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ Nfs = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetCount(Package) > 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Cwd = gEfiShellProtocol->GetCurDir(NULL);
+ if (Cwd == NULL) {
+ Cwd = ShellGetEnvironmentVariable(L"path");
+ if (Cwd != NULL) {
+ Nfs = StrnCatGrow(&Nfs, NULL, Cwd+3, 0);
+ if (Nfs != NULL) {
+ Spot = StrStr(Nfs, L";");
+ if (Spot != NULL) {
+ *Spot = CHAR_NULL;
+ }
+ Spot = StrStr(Nfs, L"\\");
+ if (Spot != NULL) {
+ Spot[1] = CHAR_NULL;
+ }
+ gEfiShellProtocol->SetCurDir(NULL, Nfs);
+ FreePool(Nfs);
+ }
+ }
+ }
+
+ Status = MainEditorInit ();
+
+ if (EFI_ERROR (Status)) {
+ gST->ConOut->ClearScreen (gST->ConOut);
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_MAIN_INIT_FAILED), gShellDebug1HiiHandle);
+ } else {
+ MainEditorBackup ();
+
+ //
+ // if editor launched with file named
+ //
+ if (ShellCommandLineGetCount(Package) == 2) {
+ FileBufferSetFileName (ShellCommandLineGetRawValue(Package, 1));
+// if (EFI_ERROR(ShellFileExists(MainEditor.FileBuffer->FileName))) {
+// Status = ShellOpenFileByName(MainEditor.FileBuffer->FileName, &TempHandle, EFI_FILE_MODE_CREATE|EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0);
+// if (!EFI_ERROR(Status)) {
+// ShellCloseFile(&TempHandle);
+// }
+// }
+ }
+
+ Status = FileBufferRead (MainEditor.FileBuffer->FileName, FALSE);
+ if (!EFI_ERROR (Status)) {
+ MainEditorRefresh ();
+
+ Status = MainEditorKeyInput ();
+ }
+
+ if (Status != EFI_OUT_OF_RESOURCES) {
+ //
+ // back up the status string
+ //
+ Buffer = CatSPrint (NULL, L"%s", StatusBarGetString());
+ }
+
+ MainEditorCleanup ();
+
+ //
+ // print editor exit code on screen
+ //
+ if (Status == EFI_SUCCESS) {
+ } else if (Status == EFI_OUT_OF_RESOURCES) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_GEN_OUT_MEM), gShellDebug1HiiHandle);
+ } else {
+ if (Buffer != NULL) {
+ if (StrCmp (Buffer, L"") != 0) {
+ //
+ // print out the status string
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_MAIN_BUFFER), gShellDebug1HiiHandle, Buffer);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_MAIN_UNKNOWN_EDITOR_ERR), gShellDebug1HiiHandle);
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_MAIN_UNKNOWN_EDITOR_ERR), gShellDebug1HiiHandle);
+ }
+ }
+
+ if (Status != EFI_OUT_OF_RESOURCES) {
+ SHELL_FREE_NON_NULL (Buffer);
+ }
+ }
+ }
+ ShellCommandLineFreeVarList (Package);
+ }
+ return ShellStatus;
+}
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.c b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.c
new file mode 100644
index 0000000000..5843c7807d
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.c
@@ -0,0 +1,3353 @@
+/** @file
+ Implements filebuffer interface functions.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "TextEditor.h"
+#include <Guid/FileSystemInfo.h>
+#include <Library/FileHandleLib.h>
+
+EFI_EDITOR_FILE_BUFFER FileBuffer;
+EFI_EDITOR_FILE_BUFFER FileBufferBackupVar;
+
+//
+// for basic initialization of FileBuffer
+//
+EFI_EDITOR_FILE_BUFFER FileBufferConst = {
+ NULL,
+ FileTypeUnicode,
+ NULL,
+ NULL,
+ 0,
+ {
+ 0,
+ 0
+ },
+ {
+ 0,
+ 0
+ },
+ {
+ 0,
+ 0
+ },
+ {
+ 0,
+ 0
+ },
+ FALSE,
+ TRUE,
+ FALSE,
+ NULL
+};
+
+//
+// the whole edit area needs to be refreshed
+//
+STATIC BOOLEAN FileBufferNeedRefresh;
+
+//
+// only the current line in edit area needs to be refresh
+//
+BOOLEAN FileBufferOnlyLineNeedRefresh;
+
+BOOLEAN FileBufferMouseNeedRefresh;
+
+extern BOOLEAN EditorMouseAction;
+
+/**
+ Initialization function for FileBuffer.
+
+ @param EFI_SUCCESS The initialization was successful.
+ @param EFI_LOAD_ERROR A default name could not be created.
+ @param EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferInit (
+ VOID
+ )
+{
+ //
+ // basically initialize the FileBuffer
+ //
+ CopyMem (&FileBuffer , &FileBufferConst, sizeof (EFI_EDITOR_FILE_BUFFER));
+ CopyMem (&FileBufferBackupVar, &FileBufferConst, sizeof (EFI_EDITOR_FILE_BUFFER));
+
+ //
+ // set default FileName
+ //
+ FileBuffer.FileName = EditGetDefaultFileName (L"txt");
+ if (FileBuffer.FileName == NULL) {
+ return EFI_LOAD_ERROR;
+ }
+
+ FileBuffer.ListHead = AllocateZeroPool (sizeof (LIST_ENTRY));
+ if (FileBuffer.ListHead == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ InitializeListHead (FileBuffer.ListHead);
+
+ FileBuffer.DisplayPosition.Row = 2;
+ FileBuffer.DisplayPosition.Column = 1;
+ FileBuffer.LowVisibleRange.Row = 2;
+ FileBuffer.LowVisibleRange.Column = 1;
+
+ FileBufferNeedRefresh = FALSE;
+ FileBufferMouseNeedRefresh = FALSE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Backup function for FileBuffer. Only backup the following items:
+ Mouse/Cursor position
+ File Name, Type, ReadOnly, Modified
+ Insert Mode
+
+ This is for making the file buffer refresh as few as possible.
+
+ @retval EFI_SUCCESS The backup operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferBackup (
+ VOID
+ )
+{
+ FileBufferBackupVar.MousePosition = FileBuffer.MousePosition;
+
+ SHELL_FREE_NON_NULL (FileBufferBackupVar.FileName);
+ FileBufferBackupVar.FileName = NULL;
+ FileBufferBackupVar.FileName = StrnCatGrow (&FileBufferBackupVar.FileName, NULL, FileBuffer.FileName, 0);
+
+ FileBufferBackupVar.ModeInsert = FileBuffer.ModeInsert;
+ FileBufferBackupVar.FileType = FileBuffer.FileType;
+
+ FileBufferBackupVar.FilePosition = FileBuffer.FilePosition;
+ FileBufferBackupVar.LowVisibleRange = FileBuffer.LowVisibleRange;
+
+ FileBufferBackupVar.FileModified = FileBuffer.FileModified;
+ FileBufferBackupVar.ReadOnly = FileBuffer.ReadOnly;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Advance to the next Count lines
+
+ @param[in] Count The line number to advance by.
+ @param[in] CurrentLine The pointer to the current line structure.
+ @param[in] LineList The pointer to the linked list of lines.
+
+ @retval NULL There was an error.
+ @return The line structure after the advance.
+**/
+EFI_EDITOR_LINE *
+EFIAPI
+InternalEditorMiscLineAdvance (
+ IN CONST UINTN Count,
+ IN CONST EFI_EDITOR_LINE *CurrentLine,
+ IN CONST LIST_ENTRY *LineList
+ )
+
+{
+ UINTN Index;
+ CONST EFI_EDITOR_LINE *Line;
+
+ if (CurrentLine == NULL || LineList == NULL) {
+ return NULL;
+ }
+
+ for (Line = CurrentLine, Index = 0; Index < Count; Index++) {
+ //
+ // if already last line
+ //
+ if (Line->Link.ForwardLink == LineList) {
+ return NULL;
+ }
+
+ Line = CR (Line->Link.ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+ }
+
+ return ((EFI_EDITOR_LINE *)Line);
+}
+
+/**
+ Retreat to the previous Count lines.
+
+ @param[in] Count The line number to retreat by.
+ @param[in] CurrentLine The pointer to the current line structure.
+ @param[in] LineList The pointer to the linked list of lines.
+
+ @retval NULL There was an error.
+ @return The line structure after the retreat.
+**/
+EFI_EDITOR_LINE *
+EFIAPI
+InternalEditorMiscLineRetreat (
+ IN CONST UINTN Count,
+ IN CONST EFI_EDITOR_LINE *CurrentLine,
+ IN CONST LIST_ENTRY *LineList
+ )
+
+{
+ UINTN Index;
+ CONST EFI_EDITOR_LINE *Line;
+
+ if (CurrentLine == NULL || LineList == NULL) {
+ return NULL;
+ }
+
+ for (Line = CurrentLine, Index = 0; Index < Count; Index++) {
+ //
+ // already the first line
+ //
+ if (Line->Link.BackLink == LineList) {
+ return NULL;
+ }
+
+ Line = CR (Line->Link.BackLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+ }
+
+ return ((EFI_EDITOR_LINE *)Line);
+}
+
+/**
+ Advance/Retreat lines
+
+ @param[in] Count line number to advance/retreat
+ >0 : advance
+ <0 : retreat
+
+ @retval NULL An error occured.
+ @return The line after advance/retreat.
+**/
+EFI_EDITOR_LINE *
+MoveLine (
+ IN CONST INTN Count
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN AbsCount;
+
+ //
+ // if < 0, then retreat
+ // if > 0, the advance
+ //
+ if (Count <= 0) {
+ AbsCount = -Count;
+ Line = InternalEditorMiscLineRetreat (AbsCount,MainEditor.FileBuffer->CurrentLine,MainEditor.FileBuffer->ListHead);
+ } else {
+ Line = InternalEditorMiscLineAdvance (Count,MainEditor.FileBuffer->CurrentLine,MainEditor.FileBuffer->ListHead);
+ }
+
+ return Line;
+}
+
+/**
+ Function to update the 'screen' to display the mouse position.
+
+ @retval EFI_SUCCESS The backup operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferRestoreMousePosition (
+ VOID
+ )
+{
+ EFI_EDITOR_COLOR_UNION Orig;
+ EFI_EDITOR_COLOR_UNION New;
+ UINTN FRow;
+ UINTN FColumn;
+ BOOLEAN HasCharacter;
+ EFI_EDITOR_LINE *CurrentLine;
+ EFI_EDITOR_LINE *Line;
+ CHAR16 Value;
+
+ //
+ // variable initialization
+ //
+ Line = NULL;
+
+ if (MainEditor.MouseSupported) {
+
+ if (FileBufferMouseNeedRefresh) {
+
+ FileBufferMouseNeedRefresh = FALSE;
+
+ //
+ // if mouse position not moved and only mouse action
+ // so do not need to refresh mouse position
+ //
+ if ((FileBuffer.MousePosition.Row == FileBufferBackupVar.MousePosition.Row &&
+ FileBuffer.MousePosition.Column == FileBufferBackupVar.MousePosition.Column)
+ && EditorMouseAction) {
+ return EFI_SUCCESS;
+ }
+ //
+ // backup the old screen attributes
+ //
+ Orig = MainEditor.ColorAttributes;
+ New.Colors.Foreground = Orig.Colors.Background;
+ New.Colors.Background = Orig.Colors.Foreground;
+
+ //
+ // clear the old mouse position
+ //
+ FRow = FileBuffer.LowVisibleRange.Row + FileBufferBackupVar.MousePosition.Row - 2;
+
+ FColumn = FileBuffer.LowVisibleRange.Column + FileBufferBackupVar.MousePosition.Column - 1;
+
+ HasCharacter = TRUE;
+ if (FRow > FileBuffer.NumLines) {
+ HasCharacter = FALSE;
+ } else {
+ CurrentLine = FileBuffer.CurrentLine;
+ Line = MoveLine (FRow - FileBuffer.FilePosition.Row);
+
+ if (FColumn > Line->Size) {
+ HasCharacter = FALSE;
+ }
+
+ FileBuffer.CurrentLine = CurrentLine;
+ }
+
+ ShellPrintEx (
+ (INT32)FileBufferBackupVar.MousePosition.Column - 1,
+ (INT32)FileBufferBackupVar.MousePosition.Row - 1,
+ L" "
+ );
+
+ if (HasCharacter) {
+ Value = (Line->Buffer[FColumn - 1]);
+ ShellPrintEx (
+ (INT32)FileBufferBackupVar.MousePosition.Column - 1,
+ (INT32)FileBufferBackupVar.MousePosition.Row - 1,
+ L"%c",
+ Value
+ );
+ }
+ //
+ // set the new mouse position
+ //
+ gST->ConOut->SetAttribute (gST->ConOut, New.Data);
+
+ //
+ // clear the old mouse position
+ //
+ FRow = FileBuffer.LowVisibleRange.Row + FileBuffer.MousePosition.Row - 2;
+ FColumn = FileBuffer.LowVisibleRange.Column + FileBuffer.MousePosition.Column - 1;
+
+ HasCharacter = TRUE;
+ if (FRow > FileBuffer.NumLines) {
+ HasCharacter = FALSE;
+ } else {
+ CurrentLine = FileBuffer.CurrentLine;
+ Line = MoveLine (FRow - FileBuffer.FilePosition.Row);
+
+ if (FColumn > Line->Size) {
+ HasCharacter = FALSE;
+ }
+
+ FileBuffer.CurrentLine = CurrentLine;
+ }
+
+ ShellPrintEx (
+ (INT32)FileBuffer.MousePosition.Column - 1,
+ (INT32)FileBuffer.MousePosition.Row - 1,
+ L" "
+ );
+
+ if (HasCharacter) {
+ Value = Line->Buffer[FColumn - 1];
+ ShellPrintEx (
+ (INT32)FileBuffer.MousePosition.Column - 1,
+ (INT32)FileBuffer.MousePosition.Row - 1,
+ L"%c",
+ Value
+ );
+ }
+ //
+ // end of HasCharacter
+ //
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
+ }
+ //
+ // end of MouseNeedRefresh
+ //
+ }
+ //
+ // end of MouseSupported
+ //
+ return EFI_SUCCESS;
+}
+
+/**
+ Free all the lines in FileBuffer
+ Fields affected:
+ Lines
+ CurrentLine
+ NumLines
+ ListHead
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferFreeLines (
+ VOID
+ )
+{
+ LIST_ENTRY *Link;
+ EFI_EDITOR_LINE *Line;
+
+ //
+ // free all the lines
+ //
+ if (FileBuffer.Lines != NULL) {
+
+ Line = FileBuffer.Lines;
+ Link = &(Line->Link);
+ do {
+ Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+ Link = Link->ForwardLink;
+
+ //
+ // free line's buffer and line itself
+ //
+ LineFree (Line);
+ } while (Link != FileBuffer.ListHead);
+ }
+ //
+ // clean the line list related structure
+ //
+ FileBuffer.Lines = NULL;
+ FileBuffer.CurrentLine = NULL;
+ FileBuffer.NumLines = 0;
+
+ FileBuffer.ListHead->ForwardLink = FileBuffer.ListHead;
+ FileBuffer.ListHead->BackLink = FileBuffer.ListHead;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Cleanup function for FileBuffer.
+
+ @retval EFI_SUCCESS The cleanup was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferCleanup (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ SHELL_FREE_NON_NULL (FileBuffer.FileName);
+
+ //
+ // free all the lines
+ //
+ Status = FileBufferFreeLines ();
+
+ SHELL_FREE_NON_NULL (FileBuffer.ListHead);
+ FileBuffer.ListHead = NULL;
+
+ SHELL_FREE_NON_NULL (FileBufferBackupVar.FileName);
+ return Status;
+
+}
+
+/**
+ Print a line specified by Line on a row specified by Row of the screen.
+
+ @param[in] Line The line to print.
+ @param[in] Row The row on the screen to print onto (begin from 1).
+
+ @retval EFI_SUCCESS The printing was successful.
+**/
+EFI_STATUS
+FileBufferPrintLine (
+ IN CONST EFI_EDITOR_LINE *Line,
+ IN CONST UINTN Row
+ )
+{
+
+ CHAR16 *Buffer;
+ UINTN Limit;
+ CHAR16 PrintLine[200];
+
+ //
+ // print start from correct character
+ //
+ Buffer = Line->Buffer + FileBuffer.LowVisibleRange.Column - 1;
+
+ Limit = Line->Size - FileBuffer.LowVisibleRange.Column + 1;
+ if (Limit > Line->Size) {
+ Limit = 0;
+ }
+
+ StrnCpy (PrintLine, Buffer, Limit > MainEditor.ScreenSize.Column ? MainEditor.ScreenSize.Column : Limit);
+ for (; Limit < MainEditor.ScreenSize.Column; Limit++) {
+ PrintLine[Limit] = L' ';
+ }
+
+ PrintLine[MainEditor.ScreenSize.Column] = CHAR_NULL;
+
+ ShellPrintEx (
+ 0,
+ (INT32)Row - 1,
+ L"%s",
+ PrintLine
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set the cursor position according to FileBuffer.DisplayPosition.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferRestorePosition (
+ VOID
+ )
+{
+ //
+ // set cursor position
+ //
+ return (gST->ConOut->SetCursorPosition (
+ gST->ConOut,
+ FileBuffer.DisplayPosition.Column - 1,
+ FileBuffer.DisplayPosition.Row - 1
+ ));
+}
+
+/**
+ Refresh the screen with whats in the buffer.
+
+ @retval EFI_SUCCESS The refresh was successful.
+ @retval EFI_LOAD_ERROR There was an error finding what to write.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferRefresh (
+ VOID
+ )
+{
+ LIST_ENTRY *Link;
+ EFI_EDITOR_LINE *Line;
+ UINTN Row;
+
+ //
+ // if it's the first time after editor launch, so should refresh
+ //
+ if (!EditorFirst) {
+ //
+ // no definite required refresh
+ // and file position displayed on screen has not been changed
+ //
+ if (!FileBufferNeedRefresh &&
+ !FileBufferOnlyLineNeedRefresh &&
+ FileBufferBackupVar.LowVisibleRange.Row == FileBuffer.LowVisibleRange.Row &&
+ FileBufferBackupVar.LowVisibleRange.Column == FileBuffer.LowVisibleRange.Column
+ ) {
+
+ FileBufferRestoreMousePosition ();
+ FileBufferRestorePosition ();
+
+ return EFI_SUCCESS;
+ }
+ }
+
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);
+
+ //
+ // only need to refresh current line
+ //
+ if (FileBufferOnlyLineNeedRefresh &&
+ FileBufferBackupVar.LowVisibleRange.Row == FileBuffer.LowVisibleRange.Row &&
+ FileBufferBackupVar.LowVisibleRange.Column == FileBuffer.LowVisibleRange.Column
+ ) {
+
+ EditorClearLine (FileBuffer.DisplayPosition.Row, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row);
+ FileBufferPrintLine (
+ FileBuffer.CurrentLine,
+ FileBuffer.DisplayPosition.Row
+ );
+ } else {
+ //
+ // the whole edit area need refresh
+ //
+
+ //
+ // no line
+ //
+ if (FileBuffer.Lines == NULL) {
+ FileBufferRestoreMousePosition ();
+ FileBufferRestorePosition ();
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+
+ return EFI_SUCCESS;
+ }
+ //
+ // get the first line that will be displayed
+ //
+ Line = MoveLine (FileBuffer.LowVisibleRange.Row - FileBuffer.FilePosition.Row);
+ if (Line == NULL) {
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+
+ return EFI_LOAD_ERROR;
+ }
+
+ Link = &(Line->Link);
+ Row = 2;
+ do {
+ Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+
+ //
+ // print line at row
+ //
+ FileBufferPrintLine (Line, Row);
+
+ Link = Link->ForwardLink;
+ Row++;
+ } while (Link != FileBuffer.ListHead && Row <= (MainEditor.ScreenSize.Row - 4));
+ //
+ // while not file end and not screen full
+ //
+ while (Row <= (MainEditor.ScreenSize.Row - 4)) {
+ EditorClearLine (Row, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row);
+ Row++;
+ }
+ }
+
+ FileBufferRestoreMousePosition ();
+ FileBufferRestorePosition ();
+
+ FileBufferNeedRefresh = FALSE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+ return EFI_SUCCESS;
+}
+
+/**
+ Create a new line and append it to the line list.
+ Fields affected:
+ NumLines
+ Lines
+
+ @retval NULL The create line failed.
+ @return The line created.
+**/
+EFI_EDITOR_LINE *
+EFIAPI
+FileBufferCreateLine (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+
+ //
+ // allocate a line structure
+ //
+ Line = AllocateZeroPool (sizeof (EFI_EDITOR_LINE));
+ if (Line == NULL) {
+ return NULL;
+ }
+ //
+ // initialize the structure
+ //
+ Line->Signature = LINE_LIST_SIGNATURE;
+ Line->Size = 0;
+ Line->TotalSize = 0;
+ Line->Type = NewLineTypeDefault;
+
+ //
+ // initial buffer of the line is "\0"
+ //
+ ASSERT(CHAR_NULL == CHAR_NULL);
+ Line->Buffer = CatSPrint (NULL, L"\0");
+ if (Line->Buffer == NULL) {
+ return NULL;
+ }
+
+ FileBuffer.NumLines++;
+
+ //
+ // insert the line into line list
+ //
+ InsertTailList (FileBuffer.ListHead, &Line->Link);
+
+ if (FileBuffer.Lines == NULL) {
+ FileBuffer.Lines = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+ }
+
+ return Line;
+}
+
+/**
+ Set FileName field in FileBuffer.
+
+ @param Str The file name to set.
+
+ @retval EFI_SUCCESS The filename was successfully set.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_INVALID_PARAMETER Str is not a valid filename.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferSetFileName (
+ IN CONST CHAR16 *Str
+ )
+{
+ //
+ // Verify the parameters
+ //
+ if (!IsValidFileName(Str)) {
+ return (EFI_INVALID_PARAMETER);
+ }
+ //
+ // free the old file name
+ //
+ SHELL_FREE_NON_NULL (FileBuffer.FileName);
+
+ //
+ // Allocate and set the new name
+ //
+ FileBuffer.FileName = CatSPrint (NULL, L"%s", Str);
+ if (FileBuffer.FileName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+/**
+ Free the existing file lines and reset the modified flag.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferFree (
+ VOID
+ )
+{
+ //
+ // free all the lines
+ //
+ FileBufferFreeLines ();
+ FileBuffer.FileModified = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Read a file from disk into the FileBuffer.
+
+ @param[in] FileName The filename to read.
+ @param[in] Recover TRUE if is for recover mode, no information printouts.
+
+ @retval EFI_SUCCESS The load was successful.
+ @retval EFI_LOAD_ERROR The load failed.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_INVALID_PARAMETER FileName is a directory.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferRead (
+ IN CONST CHAR16 *FileName,
+ IN CONST BOOLEAN Recover
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ EE_NEWLINE_TYPE Type;
+ UINTN LoopVar1;
+ UINTN LoopVar2;
+ UINTN LineSize;
+ VOID *Buffer;
+ CHAR16 *UnicodeBuffer;
+ UINT8 *AsciiBuffer;
+ UINTN FileSize;
+ SHELL_FILE_HANDLE FileHandle;
+ BOOLEAN CreateFile;
+ EFI_STATUS Status;
+ UINTN LineSizeBackup;
+ EFI_FILE_INFO *Info;
+
+ Line = NULL;
+ LoopVar1 = 0;
+ FileSize = 0;
+ UnicodeBuffer = NULL;
+ Type = NewLineTypeDefault;
+ FileHandle = NULL;
+ CreateFile = FALSE;
+
+ //
+ // in this function, when you return error ( except EFI_OUT_OF_RESOURCES )
+ // you should set status string via StatusBarSetStatusString(L"blah")
+ // since this function maybe called before the editorhandleinput loop
+ // so any error will cause editor return
+ // so if you want to print the error status
+ // you should set the status string
+ //
+
+ //
+ // try to open the file
+ //
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0);
+
+ if (!EFI_ERROR(Status)) {
+ CreateFile = FALSE;
+ if (FileHandle == NULL) {
+ StatusBarSetStatusString (L"Disk Error");
+ return EFI_LOAD_ERROR;
+ }
+
+ Info = ShellGetFileInfo(FileHandle);
+
+ if (Info->Attribute & EFI_FILE_DIRECTORY) {
+ StatusBarSetStatusString (L"Directory Can Not Be Edited");
+ FreePool (Info);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Info->Attribute & EFI_FILE_READ_ONLY) {
+ FileBuffer.ReadOnly = TRUE;
+ } else {
+ FileBuffer.ReadOnly = FALSE;
+ }
+ //
+ // get file size
+ //
+ FileSize = (UINTN) Info->FileSize;
+
+ FreePool (Info);
+ } else if (Status == EFI_NOT_FOUND) {
+ //
+ // file not exists. add create and try again
+ //
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_WRITE_PROTECTED ||
+ Status == EFI_ACCESS_DENIED ||
+ Status == EFI_NO_MEDIA ||
+ Status == EFI_MEDIA_CHANGED
+ ) {
+ StatusBarSetStatusString (L"Access Denied");
+ } else if (Status == EFI_DEVICE_ERROR || Status == EFI_VOLUME_CORRUPTED || Status == EFI_VOLUME_FULL) {
+ StatusBarSetStatusString (L"Disk Error");
+ } else {
+ StatusBarSetStatusString (L"Invalid File Name or Current-working-directory");
+ }
+
+ return Status;
+ } else {
+ //
+ // it worked. now delete it and move on with the name (now validated)
+ //
+ Status = ShellDeleteFile (&FileHandle);
+ if (Status == EFI_WARN_DELETE_FAILURE) {
+ Status = EFI_ACCESS_DENIED;
+ }
+ FileHandle = NULL;
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Access Denied");
+ return Status;
+ }
+ }
+ //
+ // file doesn't exist, so set CreateFile to TRUE
+ //
+ CreateFile = TRUE;
+ FileBuffer.ReadOnly = FALSE;
+
+ //
+ // all the check ends
+ // so now begin to set file name, free lines
+ //
+ if (StrCmp (FileName, FileBuffer.FileName) != 0) {
+ FileBufferSetFileName (FileName);
+ }
+ //
+ // free the old lines
+ //
+ FileBufferFree ();
+
+ }
+ //
+ // the file exists
+ //
+ if (!CreateFile) {
+ //
+ // allocate buffer to read file
+ //
+ Buffer = AllocateZeroPool (FileSize);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // read file into Buffer
+ //
+ Status = ShellReadFile (FileHandle, &FileSize, Buffer);
+ ShellCloseFile(&FileHandle);
+ FileHandle = NULL;
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Read File Failed");
+ SHELL_FREE_NON_NULL (Buffer);
+ return EFI_LOAD_ERROR;
+ }
+ //
+ // nothing in this file
+ //
+ if (FileSize == 0) {
+ SHELL_FREE_NON_NULL (Buffer);
+ //
+ // since has no head, so only can be an ASCII file
+ //
+ FileBuffer.FileType = FileTypeAscii;
+
+ goto Done;
+ }
+
+ AsciiBuffer = Buffer;
+
+ if (FileSize < 2) {
+ //
+ // size < Unicode file header, so only can be ASCII file
+ //
+ FileBuffer.FileType = FileTypeAscii;
+ } else {
+ //
+ // Unicode file
+ //
+ if (*(UINT16 *) Buffer == EFI_UNICODE_BYTE_ORDER_MARK) {
+ //
+ // Unicode file's size should be even
+ //
+ if ((FileSize % 2) != 0) {
+ StatusBarSetStatusString (L"File Format Wrong");
+ SHELL_FREE_NON_NULL (Buffer);
+ return EFI_LOAD_ERROR;
+ }
+
+ FileSize /= 2;
+
+ FileBuffer.FileType = FileTypeUnicode;
+ UnicodeBuffer = Buffer;
+
+ //
+ // pass this 0xff and 0xfe
+ //
+ UnicodeBuffer++;
+ FileSize--;
+ } else {
+ FileBuffer.FileType = FileTypeAscii;
+ }
+ //
+ // end of AsciiBuffer ==
+ //
+ }
+ //
+ // end of FileSize < 2
+ // all the check ends
+ // so now begin to set file name, free lines
+ //
+ if (StrCmp (FileName, FileBuffer.FileName) != 0) {
+ FileBufferSetFileName (FileName);
+ }
+
+ //
+ // free the old lines
+ //
+ FileBufferFree ();
+
+ //
+ // parse file content line by line
+ //
+ for (LoopVar1 = 0; LoopVar1 < FileSize; LoopVar1++) {
+ Type = NewLineTypeUnknown;
+
+ for (LineSize = LoopVar1; LineSize < FileSize; LineSize++) {
+ if (FileBuffer.FileType == FileTypeAscii) {
+ if (AsciiBuffer[LineSize] == CHAR_CARRIAGE_RETURN) {
+ Type = NewLineTypeCarriageReturn;
+
+ //
+ // has LF following
+ //
+ if (LineSize < FileSize - 1) {
+ if (AsciiBuffer[LineSize + 1] == CHAR_LINEFEED) {
+ Type = NewLineTypeCarriageReturnLineFeed;
+ }
+ }
+
+ break;
+ } else if (AsciiBuffer[LineSize] == CHAR_LINEFEED) {
+ Type = NewLineTypeLineFeed;
+
+ //
+ // has CR following
+ //
+ if (LineSize < FileSize - 1) {
+ if (AsciiBuffer[LineSize + 1] == CHAR_CARRIAGE_RETURN) {
+ Type = NewLineTypeLineFeedCarriageReturn;
+ }
+ }
+
+ break;
+ }
+ } else {
+ if (UnicodeBuffer[LineSize] == CHAR_CARRIAGE_RETURN) {
+ Type = NewLineTypeCarriageReturn;
+
+ //
+ // has LF following
+ //
+ if (LineSize < FileSize - 1) {
+ if (UnicodeBuffer[LineSize + 1] == CHAR_LINEFEED) {
+ Type = NewLineTypeCarriageReturnLineFeed;
+ }
+ }
+
+ break;
+ } else if (UnicodeBuffer[LineSize] == CHAR_LINEFEED) {
+ Type = NewLineTypeLineFeed;
+
+ //
+ // has CR following
+ //
+ if (LineSize < FileSize - 1) {
+ if (UnicodeBuffer[LineSize + 1] == CHAR_CARRIAGE_RETURN) {
+ Type = NewLineTypeLineFeedCarriageReturn;
+ }
+ }
+
+ break;
+ }
+ }
+ //
+ // endif == ASCII
+ //
+ }
+ //
+ // end of for LineSize
+ //
+ // if the type is wrong, then exit
+ //
+ if (Type == NewLineTypeUnknown) {
+ //
+ // Now if Type is NewLineTypeUnknown, it should be file end
+ //
+ Type = NewLineTypeDefault;
+ }
+
+ LineSizeBackup = LineSize;
+
+ //
+ // create a new line
+ //
+ Line = FileBufferCreateLine ();
+ if (Line == NULL) {
+ SHELL_FREE_NON_NULL (Buffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // calculate file length
+ //
+ LineSize -= LoopVar1;
+
+ //
+ // Unicode and one CHAR_NULL
+ //
+ SHELL_FREE_NON_NULL (Line->Buffer);
+ Line->Buffer = AllocateZeroPool (LineSize * 2 + 2);
+
+ if (Line->Buffer == NULL) {
+ RemoveEntryList (&Line->Link);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // copy this line to Line->Buffer
+ //
+ for (LoopVar2 = 0; LoopVar2 < LineSize; LoopVar2++) {
+ if (FileBuffer.FileType == FileTypeAscii) {
+ Line->Buffer[LoopVar2] = (CHAR16) AsciiBuffer[LoopVar1];
+ } else {
+ Line->Buffer[LoopVar2] = UnicodeBuffer[LoopVar1];
+ }
+
+ LoopVar1++;
+ }
+ //
+ // LoopVar1 now points to where CHAR_CARRIAGE_RETURN or CHAR_LINEFEED;
+ //
+ Line->Buffer[LineSize] = 0;
+
+ Line->Size = LineSize;
+ Line->TotalSize = LineSize;
+ Line->Type = Type;
+
+ if (Type == NewLineTypeCarriageReturnLineFeed || Type == NewLineTypeLineFeedCarriageReturn) {
+ LoopVar1++;
+ }
+
+ //
+ // last character is a return, SO create a new line
+ //
+ if (((Type == NewLineTypeCarriageReturnLineFeed || Type == NewLineTypeLineFeedCarriageReturn) && LineSizeBackup == FileSize - 2) ||
+ ((Type == NewLineTypeLineFeed || Type == NewLineTypeCarriageReturn) && LineSizeBackup == FileSize - 1)
+ ) {
+ Line = FileBufferCreateLine ();
+ if (Line == NULL) {
+ SHELL_FREE_NON_NULL (Buffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+ //
+ // end of if
+ //
+ }
+ //
+ // end of LoopVar1
+ //
+ SHELL_FREE_NON_NULL (Buffer);
+
+ }
+ //
+ // end of if CreateFile
+ //
+Done:
+
+ FileBuffer.DisplayPosition.Row = 2;
+ FileBuffer.DisplayPosition.Column = 1;
+ FileBuffer.LowVisibleRange.Row = 1;
+ FileBuffer.LowVisibleRange.Column = 1;
+ FileBuffer.FilePosition.Row = 1;
+ FileBuffer.FilePosition.Column = 1;
+ FileBuffer.MousePosition.Row = 2;
+ FileBuffer.MousePosition.Column = 1;
+
+ if (!Recover) {
+ UnicodeBuffer = CatSPrint (NULL, L"%d Lines Read", FileBuffer.NumLines);
+ if (UnicodeBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StatusBarSetStatusString (UnicodeBuffer);
+ FreePool (UnicodeBuffer);
+ }
+/*
+ //
+ // check whether we have fs?: in filename
+ //
+ LoopVar1 = 0;
+ FSMappingPtr = NULL;
+ while (FileName[LoopVar1] != 0) {
+ if (FileName[LoopVar1] == L':') {
+ FSMappingPtr = &FileName[LoopVar1];
+ break;
+ }
+
+ LoopVar1++;
+ }
+
+ if (FSMappingPtr == NULL) {
+ CurDir = ShellGetCurrentDir (NULL);
+ } else {
+ LoopVar1 = 0;
+ LoopVar2 = 0;
+ while (FileName[LoopVar1] != 0) {
+ if (FileName[LoopVar1] == L':') {
+ break;
+ }
+
+ FSMapping[LoopVar2++] = FileName[LoopVar1];
+
+ LoopVar1++;
+ }
+
+ FSMapping[LoopVar2] = 0;
+ CurDir = ShellGetCurrentDir (FSMapping);
+ }
+
+ if (CurDir != NULL) {
+ for (LoopVar1 = 0; LoopVar1 < StrLen (CurDir) && CurDir[LoopVar1] != ':'; LoopVar1++);
+
+ CurDir[LoopVar1] = 0;
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) ShellGetMap (CurDir);
+ FreePool (CurDir);
+ } else {
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = LibDevicePathToInterface (
+ &gEfiSimpleFileSystemProtocolGuid,
+ DevicePath,
+ (VOID **) &Vol
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = Vol->OpenVolume (Vol, &RootFs);
+ if (EFI_ERROR (Status)) {
+ return EFI_LOAD_ERROR;
+ }
+ //
+ // Get volume information of file system
+ //
+ Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + 100;
+ VolumeInfo = (EFI_FILE_SYSTEM_INFO *) AllocateZeroPool (Size);
+ Status = RootFs->GetInfo (RootFs, &gEfiFileSystemInfoGuid, &Size, VolumeInfo);
+ if (EFI_ERROR (Status)) {
+ RootFs->Close (RootFs);
+ return EFI_LOAD_ERROR;
+ }
+
+ if (VolumeInfo->ReadOnly) {
+ StatusBarSetStatusString (L"WARNING: Volume Read Only");
+ }
+
+ FreePool (VolumeInfo);
+ RootFs->Close (RootFs);
+ }
+//
+*/
+ //
+ // has line
+ //
+ if (FileBuffer.Lines != 0) {
+ FileBuffer.CurrentLine = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+ } else {
+ //
+ // create a dummy line
+ //
+ Line = FileBufferCreateLine ();
+ if (Line == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ FileBuffer.CurrentLine = Line;
+ }
+
+ FileBuffer.FileModified = FALSE;
+ FileBufferNeedRefresh = TRUE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+ FileBufferMouseNeedRefresh = TRUE;
+
+
+ return EFI_SUCCESS;
+}
+
+/**
+ According to FileBuffer.NewLineType & FileBuffer.FileType,
+ get the return buffer and size.
+
+ @param[in] Type The type of line.
+ @param[out] Buffer The buffer to fill.
+ @param[out] Size The amount of the buffer used on return.
+**/
+VOID
+EFIAPI
+GetNewLine (
+ IN CONST EE_NEWLINE_TYPE Type,
+ OUT CHAR8 *Buffer,
+ OUT UINT8 *Size
+ )
+{
+ UINT8 NewLineSize;
+
+ //
+ // give new line buffer,
+ // and will judge unicode or ascii
+ //
+ NewLineSize = 0;
+
+ //
+ // not legal new line type
+ //
+ if (Type != NewLineTypeLineFeed && Type != NewLineTypeCarriageReturn && Type != NewLineTypeCarriageReturnLineFeed && Type != NewLineTypeLineFeedCarriageReturn) {
+ *Size = 0;
+ return ;
+ }
+ //
+ // use_cr: give 0x0d
+ //
+ if (Type == NewLineTypeCarriageReturn) {
+ if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
+ Buffer[0] = 0x0d;
+ Buffer[1] = 0;
+ NewLineSize = 2;
+ } else {
+ Buffer[0] = 0x0d;
+ NewLineSize = 1;
+ }
+
+ *Size = NewLineSize;
+ return ;
+ }
+ //
+ // use_lf: give 0x0a
+ //
+ if (Type == NewLineTypeLineFeed) {
+ if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
+ Buffer[0] = 0x0a;
+ Buffer[1] = 0;
+ NewLineSize = 2;
+ } else {
+ Buffer[0] = 0x0a;
+ NewLineSize = 1;
+ }
+
+ *Size = NewLineSize;
+ return ;
+ }
+ //
+ // use_crlf: give 0x0d 0x0a
+ //
+ if (Type == NewLineTypeCarriageReturnLineFeed) {
+ if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
+ Buffer[0] = 0x0d;
+ Buffer[1] = 0;
+ Buffer[2] = 0x0a;
+ Buffer[3] = 0;
+
+ NewLineSize = 4;
+ } else {
+ Buffer[0] = 0x0d;
+ Buffer[1] = 0x0a;
+ NewLineSize = 2;
+ }
+
+ *Size = NewLineSize;
+ return ;
+ }
+ //
+ // use_lfcr: give 0x0a 0x0d
+ //
+ if (Type == NewLineTypeLineFeedCarriageReturn) {
+ if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
+ Buffer[0] = 0x0a;
+ Buffer[1] = 0;
+ Buffer[2] = 0x0d;
+ Buffer[3] = 0;
+
+ NewLineSize = 4;
+ } else {
+ Buffer[0] = 0x0a;
+ Buffer[1] = 0x0d;
+ NewLineSize = 2;
+ }
+
+ *Size = NewLineSize;
+ return ;
+ }
+
+}
+
+/**
+ Change a Unicode string to an ASCII string.
+
+ @param[in] UStr The Unicode string.
+ @param[in] Lenght The maximum size of AStr.
+ @param[out] AStr ASCII string to pass out.
+
+ @return The actuall length.
+**/
+UINTN
+EFIAPI
+UnicodeToAscii (
+ IN CONST CHAR16 *UStr,
+ IN CONST UINTN Length,
+ OUT CHAR8 *AStr
+ )
+{
+ UINTN Index;
+
+ //
+ // just buffer copy, not character copy
+ //
+ for (Index = 0; Index < Length; Index++) {
+ *AStr++ = (CHAR8) *UStr++;
+ }
+
+ return Index;
+}
+
+/**
+ Save lines in FileBuffer to disk
+
+ @param[in] FileName The file name for writing.
+
+ @retval EFI_SUCCESS Data was written.
+ @retval EFI_LOAD_ERROR
+ @retval EFI_OUT_OF_RESOURCES There were not enough resources to write the file.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferSave (
+ IN CONST CHAR16 *FileName
+ )
+{
+ SHELL_FILE_HANDLE FileHandle;
+ LIST_ENTRY *Link;
+ EFI_EDITOR_LINE *Line;
+ CHAR16 *Str;
+
+ EFI_STATUS Status;
+ UINTN Length;
+ UINTN NumLines;
+ CHAR8 NewLineBuffer[4];
+ UINT8 NewLineSize;
+
+ EFI_FILE_INFO *Info;
+
+ UINT64 Attribute;
+
+ EE_NEWLINE_TYPE Type;
+
+ UINTN TotalSize;
+ //
+ // 2M
+ //
+ CHAR8 *Cache;
+ UINTN LeftSize;
+ UINTN Size;
+ CHAR8 *Ptr;
+
+ Length = 0;
+ //
+ // 2M
+ //
+ TotalSize = 0x200000;
+
+ Attribute = 0;
+
+
+
+ //
+ // if is the old file
+ //
+ if (StrCmp (FileName, FileBuffer.FileName) == 0) {
+ //
+ // file has not been modified
+ //
+ if (!FileBuffer.FileModified) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // if file is read-only, set error
+ //
+ if (FileBuffer.ReadOnly) {
+ StatusBarSetStatusString (L"Read Only File Can Not Be Saved");
+ return EFI_SUCCESS;
+ }
+ }
+
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0);
+
+ if (!EFI_ERROR (Status)) {
+ Info = ShellGetFileInfo(FileHandle);
+
+ if (Info != NULL && Info->Attribute & EFI_FILE_DIRECTORY) {
+ StatusBarSetStatusString (L"Directory Can Not Be Saved");
+ ShellCloseFile(FileHandle);
+ FreePool(Info);
+ return EFI_LOAD_ERROR;
+ }
+
+ if (Info != NULL) {
+ Attribute = Info->Attribute & ~EFI_FILE_READ_ONLY;
+ FreePool(Info);
+ }
+
+ //
+ // if file exits, so delete it
+ //
+ Status = ShellDeleteFile (&FileHandle);
+ if (EFI_ERROR (Status) || Status == EFI_WARN_DELETE_FAILURE) {
+ StatusBarSetStatusString (L"Write File Failed");
+ return EFI_LOAD_ERROR;
+ }
+ }
+
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, Attribute);
+
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Create File Failed");
+ return EFI_LOAD_ERROR;
+ }
+
+ //
+ // if file is Unicode file, write Unicode header to it.
+ //
+ if (FileBuffer.FileType == FileTypeUnicode) {
+ Length = 2;
+ Status = ShellWriteFile (FileHandle, &Length, (VOID*)&gUnicodeFileTag);
+ if (EFI_ERROR (Status)) {
+ ShellDeleteFile (&FileHandle);
+ return EFI_LOAD_ERROR;
+ }
+ }
+
+ Cache = AllocateZeroPool (TotalSize);
+ if (Cache == NULL) {
+ ShellDeleteFile (&FileHandle);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // write all the lines back to disk
+ //
+ NumLines = 0;
+ Type = NewLineTypeCarriageReturnLineFeed;
+
+ Ptr = Cache;
+ LeftSize = TotalSize;
+
+ for (Link = FileBuffer.ListHead->ForwardLink; Link != FileBuffer.ListHead; Link = Link->ForwardLink) {
+ Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+
+ if (Line->Type != NewLineTypeDefault) {
+ Type = Line->Type;
+ }
+ //
+ // newline character is at most 4 bytes ( two Unicode characters )
+ //
+ Length = 4;
+ if (Line->Buffer != NULL && Line->Size != 0) {
+ if (FileBuffer.FileType == FileTypeAscii) {
+ Length += Line->Size;
+ } else {
+ Length += (Line->Size * 2);
+ }
+ //
+ // end if FileTypeAscii
+ //
+ }
+
+ //
+ // no cache room left, so write cache to disk
+ //
+ if (LeftSize < Length) {
+ Size = TotalSize - LeftSize;
+ Status = ShellWriteFile (FileHandle, &Size, Cache);
+ if (EFI_ERROR (Status)) {
+ ShellDeleteFile (&FileHandle);
+ FreePool (Cache);
+ return EFI_LOAD_ERROR;
+ }
+ Ptr = Cache;
+ LeftSize = TotalSize;
+ }
+
+ if (Line->Buffer != NULL && Line->Size != 0) {
+ if (FileBuffer.FileType == FileTypeAscii) {
+ UnicodeToAscii (Line->Buffer, Line->Size, Ptr);
+ Length = Line->Size;
+ } else {
+ Length = (Line->Size * 2);
+ CopyMem (Ptr, (CHAR8 *) Line->Buffer, Length);
+ }
+ //
+ // end if FileTypeAscii
+ //
+ Ptr += Length;
+ LeftSize -= Length;
+
+ }
+ //
+ // end of if Line -> Buffer != NULL && Line -> Size != 0
+ //
+ // if not the last line , write return buffer to disk
+ //
+ if (Link->ForwardLink != FileBuffer.ListHead) {
+ GetNewLine (Type, NewLineBuffer, &NewLineSize);
+ CopyMem (Ptr, (CHAR8 *) NewLineBuffer, NewLineSize);
+
+ Ptr += NewLineSize;
+ LeftSize -= NewLineSize;
+ }
+
+ NumLines++;
+ }
+
+ if (TotalSize != LeftSize) {
+ Size = TotalSize - LeftSize;
+ Status = ShellWriteFile (FileHandle, &Size, Cache);
+ if (EFI_ERROR (Status)) {
+ ShellDeleteFile (&FileHandle);
+ FreePool (Cache);
+ return EFI_LOAD_ERROR;
+ }
+ }
+
+ FreePool (Cache);
+
+ ShellCloseFile(&FileHandle);
+
+ FileBuffer.FileModified = FALSE;
+
+ //
+ // set status string
+ //
+ Str = CatSPrint (NULL, L"%d Lines Wrote", NumLines);
+ if (Str == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StatusBarSetStatusString (Str);
+ SHELL_FREE_NON_NULL (Str);
+
+ //
+ // now everything is ready , you can set the new file name to filebuffer
+ //
+ if (StrCmp (FileName, FileBuffer.FileName) != 0) {
+ //
+ // not the same
+ //
+ FileBufferSetFileName (FileName);
+ if (FileBuffer.FileName == NULL) {
+ ShellDeleteFile (&FileHandle);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ FileBuffer.ReadOnly = FALSE;
+ return EFI_SUCCESS;
+}
+
+/**
+ Scroll cursor to left 1 character position.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferScrollLeft (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+
+ Line = FileBuffer.CurrentLine;
+
+ FRow = FileBuffer.FilePosition.Row;
+ FCol = FileBuffer.FilePosition.Column;
+
+ //
+ // if already at start of this line, so move to the end of previous line
+ //
+ if (FCol <= 1) {
+ //
+ // has previous line
+ //
+ if (Line->Link.BackLink != FileBuffer.ListHead) {
+ FRow--;
+ Line = CR (Line->Link.BackLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+ FCol = Line->Size + 1;
+ } else {
+ return EFI_SUCCESS;
+ }
+ } else {
+ //
+ // if not at start of this line, just move to previous column
+ //
+ FCol--;
+ }
+
+ FileBufferMovePosition (FRow, FCol);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Delete a char in line
+
+ @param[in,out] Line The line to delete in.
+ @param[in] Pos Position to delete the char at ( start from 0 ).
+**/
+VOID
+EFIAPI
+LineDeleteAt (
+ IN OUT EFI_EDITOR_LINE *Line,
+ IN UINTN Pos
+ )
+{
+ UINTN Index;
+
+ //
+ // move the latter characters front
+ //
+ for (Index = Pos - 1; Index < Line->Size; Index++) {
+ Line->Buffer[Index] = Line->Buffer[Index + 1];
+ }
+
+ Line->Size--;
+}
+
+/**
+ Concatenate Src into Dest.
+
+ @param[in,out] Dest Destination string
+ @param[in] Src Src String.
+**/
+VOID
+EFIAPI
+LineCat (
+ IN OUT EFI_EDITOR_LINE *Dest,
+ IN EFI_EDITOR_LINE *Src
+ )
+{
+ CHAR16 *Str;
+ UINTN Size;
+
+ Size = Dest->Size;
+
+ Dest->Buffer[Size] = 0;
+
+ //
+ // concatenate the two strings
+ //
+ Str = CatSPrint (NULL, L"%s%s", Dest->Buffer, Src->Buffer);
+ if (Str == NULL) {
+ Dest->Buffer = NULL;
+ return ;
+ }
+
+ Dest->Size = Size + Src->Size;
+ Dest->TotalSize = Dest->Size;
+
+ FreePool (Dest->Buffer);
+ FreePool (Src->Buffer);
+
+ //
+ // put str to dest->buffer
+ //
+ Dest->Buffer = Str;
+}
+
+/**
+ Delete the previous character.
+
+ @retval EFI_SUCCESS The delete was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferDoBackspace (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ EFI_EDITOR_LINE *End;
+ LIST_ENTRY *Link;
+ UINTN FileColumn;
+
+ FileColumn = FileBuffer.FilePosition.Column;
+
+ Line = FileBuffer.CurrentLine;
+
+ //
+ // the first column
+ //
+ if (FileColumn == 1) {
+ //
+ // the first row
+ //
+ if (FileBuffer.FilePosition.Row == 1) {
+ return EFI_SUCCESS;
+ }
+
+ FileBufferScrollLeft ();
+
+ Line = FileBuffer.CurrentLine;
+ Link = Line->Link.ForwardLink;
+ End = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+
+ //
+ // concatenate this line with previous line
+ //
+ LineCat (Line, End);
+ if (Line->Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // remove End from line list
+ //
+ RemoveEntryList (&End->Link);
+ FreePool (End);
+
+ FileBuffer.NumLines--;
+
+ FileBufferNeedRefresh = TRUE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+
+ } else {
+ //
+ // just delete the previous character
+ //
+ LineDeleteAt (Line, FileColumn - 1);
+ FileBufferScrollLeft ();
+ FileBufferOnlyLineNeedRefresh = TRUE;
+ }
+
+ if (!FileBuffer.FileModified) {
+ FileBuffer.FileModified = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Add a return into line at current position.
+
+ @retval EFI_SUCCESS The insetrion of the character was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferDoReturn (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ EFI_EDITOR_LINE *NewLine;
+ UINTN FileColumn;
+ UINTN Index;
+ CHAR16 *Buffer;
+ UINTN Row;
+ UINTN Col;
+
+ FileBufferNeedRefresh = TRUE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+
+ Line = FileBuffer.CurrentLine;
+
+ FileColumn = FileBuffer.FilePosition.Column;
+
+ NewLine = AllocateZeroPool (sizeof (EFI_EDITOR_LINE));
+ if (NewLine == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewLine->Signature = LINE_LIST_SIGNATURE;
+ NewLine->Size = Line->Size - FileColumn + 1;
+ NewLine->TotalSize = NewLine->Size;
+ NewLine->Buffer = CatSPrint (NULL, L"\0");
+ if (NewLine->Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewLine->Type = NewLineTypeDefault;
+
+ if (NewLine->Size > 0) {
+ //
+ // UNICODE + CHAR_NULL
+ //
+ Buffer = AllocateZeroPool (2 * (NewLine->Size + 1));
+ if (Buffer == NULL) {
+ FreePool (NewLine->Buffer);
+ FreePool (NewLine);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ FreePool (NewLine->Buffer);
+
+ NewLine->Buffer = Buffer;
+
+ for (Index = 0; Index < NewLine->Size; Index++) {
+ NewLine->Buffer[Index] = Line->Buffer[Index + FileColumn - 1];
+ }
+
+ NewLine->Buffer[NewLine->Size] = CHAR_NULL;
+
+ Line->Buffer[FileColumn - 1] = CHAR_NULL;
+ Line->Size = FileColumn - 1;
+ }
+ //
+ // increase NumLines
+ //
+ FileBuffer.NumLines++;
+
+ //
+ // insert it into the correct position of line list
+ //
+ NewLine->Link.BackLink = &(Line->Link);
+ NewLine->Link.ForwardLink = Line->Link.ForwardLink;
+ Line->Link.ForwardLink->BackLink = &(NewLine->Link);
+ Line->Link.ForwardLink = &(NewLine->Link);
+
+ //
+ // move cursor to the start of next line
+ //
+ Row = FileBuffer.FilePosition.Row + 1;
+ Col = 1;
+
+ FileBufferMovePosition (Row, Col);
+
+ //
+ // set file is modified
+ //
+ if (!FileBuffer.FileModified) {
+ FileBuffer.FileModified = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Delete current character from current line. This is the effect caused
+ by the 'del' key.
+
+ @retval EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+FileBufferDoDelete (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ EFI_EDITOR_LINE *Next;
+ LIST_ENTRY *Link;
+ UINTN FileColumn;
+
+ Line = FileBuffer.CurrentLine;
+ FileColumn = FileBuffer.FilePosition.Column;
+
+ //
+ // the last column
+ //
+ if (FileColumn >= Line->Size + 1) {
+ //
+ // the last line
+ //
+ if (Line->Link.ForwardLink == FileBuffer.ListHead) {
+ return EFI_SUCCESS;
+ }
+ //
+ // since last character,
+ // so will add the next line to this line
+ //
+ Link = Line->Link.ForwardLink;
+ Next = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+ LineCat (Line, Next);
+ if (Line->Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ RemoveEntryList (&Next->Link);
+ FreePool (Next);
+
+ FileBuffer.NumLines--;
+
+ FileBufferNeedRefresh = TRUE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+
+ } else {
+ //
+ // just delete current character
+ //
+ LineDeleteAt (Line, FileColumn);
+ FileBufferOnlyLineNeedRefresh = TRUE;
+ }
+
+ if (!FileBuffer.FileModified) {
+ FileBuffer.FileModified = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Scroll cursor to right 1 character.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferScrollRight (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+
+ Line = FileBuffer.CurrentLine;
+ if (Line->Buffer == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ FRow = FileBuffer.FilePosition.Row;
+ FCol = FileBuffer.FilePosition.Column;
+
+ //
+ // if already at end of this line, scroll it to the start of next line
+ //
+ if (FCol > Line->Size) {
+ //
+ // has next line
+ //
+ if (Line->Link.ForwardLink != FileBuffer.ListHead) {
+ FRow++;
+ FCol = 1;
+ } else {
+ return EFI_SUCCESS;
+ }
+ } else {
+ //
+ // if not at end of this line, just move to next column
+ //
+ FCol++;
+ }
+
+ FileBufferMovePosition (FRow, FCol);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Insert a char into line
+
+
+ @param[in] Line The line to insert into.
+ @param[in] Char The char to insert.
+ @param[in] Pos The position to insert the char at ( start from 0 ).
+ @param[in] StrSize The current string size ( include CHAR_NULL ),unit is Unicode character.
+
+ @return The new string size ( include CHAR_NULL ) ( unit is Unicode character ).
+**/
+UINTN
+EFIAPI
+LineStrInsert (
+ IN EFI_EDITOR_LINE *Line,
+ IN CHAR16 Char,
+ IN UINTN Pos,
+ IN UINTN StrSize
+ )
+{
+ UINTN Index;
+ CHAR16 *TempStringPtr;
+ CHAR16 *Str;
+
+ Index = (StrSize) * 2;
+
+ Str = Line->Buffer;
+
+ //
+ // do not have free space
+ //
+ if (Line->TotalSize <= Line->Size) {
+ Str = ReallocatePool (Index, Index + 16, Str);
+ if (Str == NULL) {
+ return 0;
+ }
+
+ Line->TotalSize += 8;
+ }
+ //
+ // move the later part of the string one character right
+ //
+ TempStringPtr = Str;
+ for (Index = StrSize; Index > Pos; Index--) {
+ TempStringPtr[Index] = TempStringPtr[Index - 1];
+ }
+ //
+ // insert char into it.
+ //
+ TempStringPtr[Index] = Char;
+
+ Line->Buffer = Str;
+ Line->Size++;
+
+ return StrSize + 1;
+}
+
+/**
+ Add a character to the current line.
+
+ @param[in] Char The Character to input.
+
+ @retval EFI_SUCCESS The input was succesful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferAddChar (
+ IN CHAR16 Char
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN FilePos;
+
+ Line = FileBuffer.CurrentLine;
+
+ //
+ // only needs to refresh current line
+ //
+ FileBufferOnlyLineNeedRefresh = TRUE;
+
+ //
+ // when is insert mode, or cursor is at end of this line,
+ // so insert this character
+ // or replace the character.
+ //
+ FilePos = FileBuffer.FilePosition.Column - 1;
+ if (FileBuffer.ModeInsert || FilePos + 1 > Line->Size) {
+ LineStrInsert (Line, Char, FilePos, Line->Size + 1);
+ } else {
+ Line->Buffer[FilePos] = Char;
+ }
+ //
+ // move cursor to right
+ //
+ FileBufferScrollRight ();
+
+ if (!FileBuffer.FileModified) {
+ FileBuffer.FileModified = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Handles inputs from characters (ASCII key + Backspace + return)
+
+ @param[in] Char The input character.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR There was an error.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferDoCharInput (
+ IN CONST CHAR16 Char
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ switch (Char) {
+ case CHAR_NULL:
+ break;
+
+ case CHAR_BACKSPACE:
+ Status = FileBufferDoBackspace ();
+ break;
+
+ case CHAR_TAB:
+ //
+ // Tabs are ignored
+ //
+ break;
+
+ case CHAR_LINEFEED:
+ case CHAR_CARRIAGE_RETURN:
+ Status = FileBufferDoReturn ();
+ break;
+
+ default:
+ //
+ // DEAL WITH ASCII CHAR, filter out thing like ctrl+f
+ //
+ if (Char > 127 || Char < 32) {
+ Status = StatusBarSetStatusString (L"Unknown Command");
+ } else {
+ Status = FileBufferAddChar (Char);
+ }
+
+ break;
+
+ }
+
+ return Status;
+}
+
+/**
+ Scroll cursor to the next line.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferScrollDown (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+
+ Line = FileBuffer.CurrentLine;
+ if (Line->Buffer == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ FRow = FileBuffer.FilePosition.Row;
+ FCol = FileBuffer.FilePosition.Column;
+
+ //
+ // has next line
+ //
+ if (Line->Link.ForwardLink != FileBuffer.ListHead) {
+ FRow++;
+ Line = CR (Line->Link.ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+
+ //
+ // if the next line is not that long, so move to end of next line
+ //
+ if (FCol > Line->Size) {
+ FCol = Line->Size + 1;
+ }
+
+ } else {
+ return EFI_SUCCESS;
+ }
+
+ FileBufferMovePosition (FRow, FCol);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Scroll the cursor to previous line.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferScrollUp (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+
+ Line = FileBuffer.CurrentLine;
+
+ FRow = FileBuffer.FilePosition.Row;
+ FCol = FileBuffer.FilePosition.Column;
+
+ //
+ // has previous line
+ //
+ if (Line->Link.BackLink != FileBuffer.ListHead) {
+ FRow--;
+ Line = CR (Line->Link.BackLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+
+ //
+ // if previous line is not that long, so move to the end of previous line
+ //
+ if (FCol > Line->Size) {
+ FCol = Line->Size + 1;
+ }
+
+ } else {
+ return EFI_SUCCESS;
+ }
+
+ FileBufferMovePosition (FRow, FCol);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Scroll cursor to next page.
+
+ @retval EFI_SUCCESS The operation wa successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferPageDown (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+ UINTN Gap;
+
+ Line = FileBuffer.CurrentLine;
+
+ FRow = FileBuffer.FilePosition.Row;
+ FCol = FileBuffer.FilePosition.Column;
+
+ //
+ // has next page
+ //
+ if (FileBuffer.NumLines >= FRow + (MainEditor.ScreenSize.Row - 5)) {
+ Gap = (MainEditor.ScreenSize.Row - 5);
+ } else {
+ //
+ // MOVE CURSOR TO LAST LINE
+ //
+ Gap = FileBuffer.NumLines - FRow;
+ }
+ //
+ // get correct line
+ //
+ Line = MoveLine (Gap);
+
+ //
+ // if that line, is not that long, so move to the end of that line
+ //
+ if (FCol > Line->Size) {
+ FCol = Line->Size + 1;
+ }
+
+ FRow += Gap;
+
+ FileBufferMovePosition (FRow, FCol);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Scroll cursor to previous screen.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferPageUp (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+ UINTN Gap;
+ INTN Retreat;
+
+ Line = FileBuffer.CurrentLine;
+
+ FRow = FileBuffer.FilePosition.Row;
+ FCol = FileBuffer.FilePosition.Column;
+
+ //
+ // has previous page
+ //
+ if (FRow > (MainEditor.ScreenSize.Row - 5)) {
+ Gap = (MainEditor.ScreenSize.Row - 5);
+ } else {
+ //
+ // the first line of file will displayed on the first line of screen
+ //
+ Gap = FRow - 1;
+ }
+
+ Retreat = Gap;
+ Retreat = -Retreat;
+
+ //
+ // get correct line
+ //
+ Line = MoveLine (Retreat);
+
+ //
+ // if that line is not that long, so move to the end of that line
+ //
+ if (FCol > Line->Size) {
+ FCol = Line->Size + 1;
+ }
+
+ FRow -= Gap;
+
+ FileBufferMovePosition (FRow, FCol);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Scroll cursor to end of the current line.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferEnd (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+
+ Line = FileBuffer.CurrentLine;
+
+ FRow = FileBuffer.FilePosition.Row;
+
+ //
+ // goto the last column of the line
+ //
+ FCol = Line->Size + 1;
+
+ FileBufferMovePosition (FRow, FCol);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Dispatch input to different handler
+ @param[in] Key The input key. One of:
+ ASCII KEY
+ Backspace/Delete
+ Return
+ Direction key: up/down/left/right/pgup/pgdn
+ Home/End
+ INS
+
+ @retval EFI_SUCCESS The dispatch was done successfully.
+ @retval EFI_LOAD_ERROR The dispatch was not successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferHandleInput (
+ IN CONST EFI_INPUT_KEY *Key
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ switch (Key->ScanCode) {
+ //
+ // ordinary key input
+ //
+ case SCAN_NULL:
+ if (!FileBuffer.ReadOnly) {
+ Status = FileBufferDoCharInput (Key->UnicodeChar);
+ } else {
+ Status = StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
+ }
+
+ break;
+
+ //
+ // up arrow
+ //
+ case SCAN_UP:
+ Status = FileBufferScrollUp ();
+ break;
+
+ //
+ // down arrow
+ //
+ case SCAN_DOWN:
+ Status = FileBufferScrollDown ();
+ break;
+
+ //
+ // right arrow
+ //
+ case SCAN_RIGHT:
+ Status = FileBufferScrollRight ();
+ break;
+
+ //
+ // left arrow
+ //
+ case SCAN_LEFT:
+ Status = FileBufferScrollLeft ();
+ break;
+
+ //
+ // page up
+ //
+ case SCAN_PAGE_UP:
+ Status = FileBufferPageUp ();
+ break;
+
+ //
+ // page down
+ //
+ case SCAN_PAGE_DOWN:
+ Status = FileBufferPageDown ();
+ break;
+
+ //
+ // delete
+ //
+ case SCAN_DELETE:
+ if (!FileBuffer.ReadOnly) {
+ Status = FileBufferDoDelete ();
+ } else {
+ Status = StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
+ }
+
+ break;
+
+ //
+ // home
+ //
+ case SCAN_HOME:
+ FileBufferMovePosition (FileBuffer.FilePosition.Row, 1);
+ Status = EFI_SUCCESS;
+ break;
+
+ //
+ // end
+ //
+ case SCAN_END:
+ Status = FileBufferEnd ();
+ break;
+
+ //
+ // insert
+ //
+ case SCAN_INSERT:
+ FileBuffer.ModeInsert = (BOOLEAN)!FileBuffer.ModeInsert;
+ Status = EFI_SUCCESS;
+ break;
+
+ default:
+ Status = StatusBarSetStatusString (L"Unknown Command");
+ break;
+ }
+
+ return Status;
+}
+
+/**
+ Check user specified FileRow is above current screen.
+
+ @param[in] FileRow The row of file position ( start from 1 ).
+
+ @retval TRUE It is above the current screen.
+ @retval FALSE It is not above the current screen.
+**/
+BOOLEAN
+EFIAPI
+AboveCurrentScreen (
+ IN UINTN FileRow
+ )
+{
+ //
+ // if is to the above of the screen
+ //
+ if (FileRow < FileBuffer.LowVisibleRange.Row) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Check user specified FileRow is under current screen.
+
+ @param[in] FileRow The row of file position ( start from 1 ).
+
+ @retval TRUE It is under the current screen.
+ @retval FALSE It is not under the current screen.
+**/
+BOOLEAN
+EFIAPI
+UnderCurrentScreen (
+ IN UINTN FileRow
+ )
+{
+ //
+ // if is to the under of the screen
+ //
+ if (FileRow > FileBuffer.LowVisibleRange.Row + (MainEditor.ScreenSize.Row - 5) - 1) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Check user specified FileCol is left to current screen.
+
+ @param[in] FileCol The column of file position ( start from 1 ).
+
+ @retval TRUE It is to the left.
+ @retval FALSE It is not to the left.
+**/
+BOOLEAN
+EFIAPI
+LeftCurrentScreen (
+ IN UINTN FileCol
+ )
+{
+ //
+ // if is to the left of the screen
+ //
+ if (FileCol < FileBuffer.LowVisibleRange.Column) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Check user specified FileCol is right to current screen.
+
+ @param[in] FileCol The column of file position ( start from 1 ).
+
+ @retval TRUE It is to the right.
+ @retval FALSE It is not to the right.
+**/
+BOOLEAN
+EFIAPI
+RightCurrentScreen (
+ IN UINTN FileCol
+ )
+{
+ //
+ // if is to the right of the screen
+ //
+ if (FileCol > FileBuffer.LowVisibleRange.Column + MainEditor.ScreenSize.Column - 1) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Advance/Retreat lines and set CurrentLine in FileBuffer to it
+
+ @param[in] Count The line number to advance/retreat
+ >0 : advance
+ <0: retreat
+
+ @retval NULL An error occured.
+ @return The line after advance/retreat.
+**/
+EFI_EDITOR_LINE *
+EFIAPI
+MoveCurrentLine (
+ IN INTN Count
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN AbsCount;
+
+ if (Count <= 0) {
+ AbsCount = -Count;
+ Line = InternalEditorMiscLineRetreat (AbsCount,MainEditor.FileBuffer->CurrentLine,MainEditor.FileBuffer->ListHead);
+ } else {
+ Line = InternalEditorMiscLineAdvance (Count,MainEditor.FileBuffer->CurrentLine,MainEditor.FileBuffer->ListHead);
+ }
+
+ if (Line == NULL) {
+ return NULL;
+ }
+
+ MainEditor.FileBuffer->CurrentLine = Line;
+
+ return Line;
+}
+
+/**
+ According to cursor's file position, adjust screen display
+
+ @param[in] NewFilePosRow The row of file position ( start from 1 ).
+ @param[in] NewFilePosCol The column of file position ( start from 1 ).
+**/
+VOID
+EFIAPI
+FileBufferMovePosition (
+ IN CONST UINTN NewFilePosRow,
+ IN CONST UINTN NewFilePosCol
+ )
+{
+ INTN RowGap;
+ INTN ColGap;
+ UINTN Abs;
+ BOOLEAN Above;
+ BOOLEAN Under;
+ BOOLEAN Right;
+ BOOLEAN Left;
+
+ //
+ // CALCULATE gap between current file position and new file position
+ //
+ RowGap = NewFilePosRow - FileBuffer.FilePosition.Row;
+ ColGap = NewFilePosCol - FileBuffer.FilePosition.Column;
+
+ Under = UnderCurrentScreen (NewFilePosRow);
+ Above = AboveCurrentScreen (NewFilePosRow);
+ //
+ // if is below current screen
+ //
+ if (Under) {
+ //
+ // display row will be unchanged
+ //
+ FileBuffer.FilePosition.Row = NewFilePosRow;
+ } else {
+ if (Above) {
+ //
+ // has enough above line, so display row unchanged
+ // not has enough above lines, so the first line is at the
+ // first display line
+ //
+ if (NewFilePosRow < (FileBuffer.DisplayPosition.Row - 1)) {
+ FileBuffer.DisplayPosition.Row = NewFilePosRow + 1;
+ }
+
+ FileBuffer.FilePosition.Row = NewFilePosRow;
+ } else {
+ //
+ // in current screen
+ //
+ FileBuffer.FilePosition.Row = NewFilePosRow;
+ if (RowGap < 0) {
+ Abs = -RowGap;
+ FileBuffer.DisplayPosition.Row -= Abs;
+ } else {
+ FileBuffer.DisplayPosition.Row += RowGap;
+ }
+ }
+ }
+
+ FileBuffer.LowVisibleRange.Row = FileBuffer.FilePosition.Row - (FileBuffer.DisplayPosition.Row - 2);
+
+ Right = RightCurrentScreen (NewFilePosCol);
+ Left = LeftCurrentScreen (NewFilePosCol);
+
+ //
+ // if right to current screen
+ //
+ if (Right) {
+ //
+ // display column will be changed to end
+ //
+ FileBuffer.DisplayPosition.Column = MainEditor.ScreenSize.Column;
+ FileBuffer.FilePosition.Column = NewFilePosCol;
+ } else {
+ if (Left) {
+ //
+ // has enough left characters , so display row unchanged
+ // not has enough left characters,
+ // so the first character is at the first display column
+ //
+ if (NewFilePosCol < (FileBuffer.DisplayPosition.Column)) {
+ FileBuffer.DisplayPosition.Column = NewFilePosCol;
+ }
+
+ FileBuffer.FilePosition.Column = NewFilePosCol;
+ } else {
+ //
+ // in current screen
+ //
+ FileBuffer.FilePosition.Column = NewFilePosCol;
+ if (ColGap < 0) {
+ Abs = -ColGap;
+ FileBuffer.DisplayPosition.Column -= Abs;
+ } else {
+ FileBuffer.DisplayPosition.Column += ColGap;
+ }
+ }
+ }
+
+ FileBuffer.LowVisibleRange.Column = FileBuffer.FilePosition.Column - (FileBuffer.DisplayPosition.Column - 1);
+
+ //
+ // let CurrentLine point to correct line;
+ //
+ FileBuffer.CurrentLine = MoveCurrentLine (RowGap);
+
+}
+
+/**
+ Cut current line out and return a pointer to it.
+
+ @param[out] CutLine Upon a successful return pointer to the pointer to
+ the allocated cut line.
+
+ @retval EFI_SUCCESS The cut was successful.
+ @retval EFI_NOT_FOUND There was no selection to cut.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferCutLine (
+ OUT EFI_EDITOR_LINE **CutLine
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ EFI_EDITOR_LINE *NewLine;
+ UINTN Row;
+ UINTN Col;
+
+ if (FileBuffer.ReadOnly) {
+ StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
+ return EFI_SUCCESS;
+ }
+
+ Line = FileBuffer.CurrentLine;
+
+ //
+ // if is the last dummy line, SO CAN not cut
+ //
+ if (StrCmp (Line->Buffer, L"\0") == 0 && Line->Link.ForwardLink == FileBuffer.ListHead
+ //
+ // last line
+ //
+ ) {
+ //
+ // LAST LINE AND NOTHING ON THIS LINE, SO CUT NOTHING
+ //
+ StatusBarSetStatusString (L"Nothing to Cut");
+ return EFI_NOT_FOUND;
+ }
+ //
+ // if is the last line, so create a dummy line
+ //
+ if (Line->Link.ForwardLink == FileBuffer.ListHead) {
+ //
+ // last line
+ // create a new line
+ //
+ NewLine = FileBufferCreateLine ();
+ if (NewLine == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ FileBuffer.NumLines--;
+ Row = FileBuffer.FilePosition.Row;
+ Col = 1;
+ //
+ // move home
+ //
+ FileBuffer.CurrentLine = CR (
+ FileBuffer.CurrentLine->Link.ForwardLink,
+ EFI_EDITOR_LINE,
+ Link,
+ LINE_LIST_SIGNATURE
+ );
+
+ RemoveEntryList (&Line->Link);
+
+ FileBuffer.Lines = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+
+ FileBufferMovePosition (Row, Col);
+
+ FileBuffer.FileModified = TRUE;
+ FileBufferNeedRefresh = TRUE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+
+ *CutLine = Line;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Paste a line into line list.
+
+ @retval EFI_SUCCESS The paste was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferPasteLine (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ EFI_EDITOR_LINE *NewLine;
+ UINTN Row;
+ UINTN Col;
+
+ //
+ // if nothing is on clip board
+ // then do nothing
+ //
+ if (MainEditor.CutLine == NULL) {
+ return EFI_SUCCESS;
+ }
+ //
+ // read only file can not be pasted on
+ //
+ if (FileBuffer.ReadOnly) {
+ StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
+ return EFI_SUCCESS;
+ }
+
+ NewLine = LineDup (MainEditor.CutLine);
+ if (NewLine == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // insert it above current line
+ //
+ Line = FileBuffer.CurrentLine;
+ NewLine->Link.BackLink = Line->Link.BackLink;
+ NewLine->Link.ForwardLink = &Line->Link;
+
+ Line->Link.BackLink->ForwardLink = &NewLine->Link;
+ Line->Link.BackLink = &NewLine->Link;
+
+ FileBuffer.NumLines++;
+ FileBuffer.CurrentLine = NewLine;
+
+ FileBuffer.Lines = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+
+ Col = 1;
+ //
+ // move home
+ //
+ Row = FileBuffer.FilePosition.Row;
+
+ FileBufferMovePosition (Row, Col);
+
+ //
+ // after paste, set some value so that refresh knows to do something
+ //
+ FileBuffer.FileModified = TRUE;
+ FileBufferNeedRefresh = TRUE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Search string from current position on in file
+
+ @param[in] Str The search string.
+ @param[in] Offset The offset from current position.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_NOT_FOUND The string Str was not found.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferSearch (
+ IN CONST CHAR16 *Str,
+ IN CONST UINTN Offset
+ )
+{
+ CHAR16 *Current;
+ UINTN Position;
+ UINTN Row;
+ UINTN Column;
+ EFI_EDITOR_LINE *Line;
+ CHAR16 *CharPos;
+ LIST_ENTRY *Link;
+ BOOLEAN Found;
+
+ Column = 0;
+
+ //
+ // search if in current line
+ //
+ Current = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1 + Offset;
+
+ if (Current >= (FileBuffer.CurrentLine->Buffer + FileBuffer.CurrentLine->Size)) {
+ //
+ // the end
+ //
+ Current = FileBuffer.CurrentLine->Buffer + FileBuffer.CurrentLine->Size;
+ }
+
+ CharPos = StrStr (Current, Str);
+ if (CharPos != NULL) {
+ Position = CharPos - Current;
+ } else {
+ Position = 0;
+ }
+
+ //
+ // found
+ //
+ if (Position != 0) {
+ Column = (Position - 1) + FileBuffer.FilePosition.Column + Offset;
+ Row = FileBuffer.FilePosition.Row;
+ Found = TRUE;
+ } else {
+ //
+ // not found so find through next lines
+ //
+ Link = FileBuffer.CurrentLine->Link.ForwardLink;
+
+ Row = FileBuffer.FilePosition.Row + 1;
+ while (Link != FileBuffer.ListHead) {
+ Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+// Position = StrStr (Line->Buffer, Str);
+ CharPos = StrStr (Line->Buffer, Str);
+ if (CharPos != NULL) {
+ Position = CharPos - Line->Buffer;
+ }
+ if (Position != 0) {
+ //
+ // found
+ //
+ Column = Position;
+ break;
+ }
+
+ Row++;
+ Link = Link->ForwardLink;
+ }
+
+ if (Link == FileBuffer.ListHead) {
+ Found = FALSE;
+ } else {
+ Found = TRUE;
+ }
+ }
+
+ if (!Found) {
+ return EFI_NOT_FOUND;
+ }
+
+ FileBufferMovePosition (Row, Column);
+
+ //
+ // call refresh to fresh edit area,
+ // because the outer may loop to find multiply occurrence of this string
+ //
+ FileBufferRefresh ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Replace SearchLen characters from current position on with Replace.
+
+ This will modify the current buffer at the current position.
+
+ @param[in] Replace The string to replace.
+ @param[in] SearchLen Search string's length.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferReplace (
+ IN CONST CHAR16 *Replace,
+ IN CONST UINTN SearchLen
+ )
+{
+ UINTN ReplaceLen;
+ UINTN Index;
+ CHAR16 *Buffer;
+ UINTN NewSize;
+ UINTN OldSize;
+ UINTN Gap;
+
+ ReplaceLen = StrLen (Replace);
+
+ OldSize = FileBuffer.CurrentLine->Size + 1;
+ //
+ // include CHAR_NULL
+ //
+ NewSize = OldSize + (ReplaceLen - SearchLen);
+
+ if (ReplaceLen > SearchLen) {
+ //
+ // do not have the enough space
+ //
+ if (FileBuffer.CurrentLine->TotalSize + 1 <= NewSize) {
+ FileBuffer.CurrentLine->Buffer = ReallocatePool (
+ 2 * OldSize,
+ 2 * NewSize,
+ FileBuffer.CurrentLine->Buffer
+ );
+ FileBuffer.CurrentLine->TotalSize = NewSize - 1;
+ }
+
+ if (FileBuffer.CurrentLine->Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // the end CHAR_NULL character;
+ //
+ Buffer = FileBuffer.CurrentLine->Buffer + (NewSize - 1);
+ Gap = ReplaceLen - SearchLen;
+
+ //
+ // keep the latter part
+ //
+ for (Index = 0; Index < (FileBuffer.CurrentLine->Size - FileBuffer.FilePosition.Column - SearchLen + 2); Index++) {
+ *Buffer = *(Buffer - Gap);
+ Buffer--;
+ }
+ //
+ // set replace into it
+ //
+ Buffer = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column;
+ for (Index = 0; Index < ReplaceLen; Index++) {
+ Buffer[Index] = Replace[Index];
+ }
+ }
+
+ if (ReplaceLen < SearchLen) {
+ Buffer = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column;
+
+ for (Index = 0; Index < ReplaceLen; Index++) {
+ Buffer[Index] = Replace[Index];
+ }
+
+ Buffer += ReplaceLen;
+ Gap = SearchLen - ReplaceLen;
+
+ //
+ // set replace into it
+ //
+ for (Index = 0; Index < (FileBuffer.CurrentLine->Size - FileBuffer.FilePosition.Column - ReplaceLen + 2); Index++) {
+ *Buffer = *(Buffer + Gap);
+ Buffer++;
+ }
+ }
+
+ if (ReplaceLen == SearchLen) {
+ Buffer = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column;
+ for (Index = 0; Index < ReplaceLen; Index++) {
+ Buffer[Index] = Replace[Index];
+ }
+ }
+
+ FileBuffer.CurrentLine->Size += (ReplaceLen - SearchLen);
+
+ FileBufferOnlyLineNeedRefresh = TRUE;
+
+ FileBuffer.FileModified = TRUE;
+
+ MainTitleBarRefresh (MainEditor.FileBuffer->FileName, MainEditor.FileBuffer->FileType, MainEditor.FileBuffer->ReadOnly, MainEditor.FileBuffer->FileModified, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row);
+ FileBufferRestorePosition ();
+ FileBufferRefresh ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Move the mouse cursor position.
+
+ @param[in] TextX The new x-coordinate.
+ @param[in] TextY The new y-coordinate.
+**/
+VOID
+EFIAPI
+FileBufferAdjustMousePosition (
+ IN CONST INT32 TextX,
+ IN CONST INT32 TextY
+ )
+{
+ UINTN CoordinateX;
+ UINTN CoordinateY;
+ UINTN AbsX;
+ UINTN AbsY;
+
+ //
+ // TextX and TextY is mouse movement data returned by mouse driver
+ // This function will change it to MousePosition
+ //
+ //
+ // get absolute value
+ //
+
+ AbsX = ABS(TextX);
+ AbsY = ABS(TextY);
+
+ CoordinateX = FileBuffer.MousePosition.Column;
+ CoordinateY = FileBuffer.MousePosition.Row;
+
+ if (TextX >= 0) {
+ CoordinateX += TextX;
+ } else {
+ if (CoordinateX >= AbsX) {
+ CoordinateX -= AbsX;
+ } else {
+ CoordinateX = 0;
+ }
+ }
+
+ if (TextY >= 0) {
+ CoordinateY += TextY;
+ } else {
+ if (CoordinateY >= AbsY) {
+ CoordinateY -= AbsY;
+ } else {
+ CoordinateY = 0;
+ }
+ }
+ //
+ // check whether new mouse column position is beyond screen
+ // if not, adjust it
+ //
+ if (CoordinateX >= 1 && CoordinateX <= MainEditor.ScreenSize.Column) {
+ FileBuffer.MousePosition.Column = CoordinateX;
+ } else if (CoordinateX < 1) {
+ FileBuffer.MousePosition.Column = 1;
+ } else if (CoordinateX > MainEditor.ScreenSize.Column) {
+ FileBuffer.MousePosition.Column = MainEditor.ScreenSize.Column;
+ }
+ //
+ // check whether new mouse row position is beyond screen
+ // if not, adjust it
+ //
+ if (CoordinateY >= 2 && CoordinateY <= (MainEditor.ScreenSize.Row - 4)) {
+ FileBuffer.MousePosition.Row = CoordinateY;
+ } else if (CoordinateY < 2) {
+ FileBuffer.MousePosition.Row = 2;
+ } else if (CoordinateY > (MainEditor.ScreenSize.Row - 4)) {
+ FileBuffer.MousePosition.Row = (MainEditor.ScreenSize.Row - 4);
+ }
+
+}
+
+/**
+ Search and replace operation.
+
+ @param[in] SearchStr The string to search for.
+ @param[in] ReplaceStr The string to replace with.
+ @param[in] Offset The column to start at.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferReplaceAll (
+ IN CHAR16 *SearchStr,
+ IN CHAR16 *ReplaceStr,
+ IN UINTN Offset
+ )
+{
+ CHAR16 *Buffer;
+ UINTN Position;
+ UINTN Column;
+ UINTN ReplaceLen;
+ UINTN SearchLen;
+ UINTN Index;
+ UINTN NewSize;
+ UINTN OldSize;
+ UINTN Gap;
+ EFI_EDITOR_LINE *Line;
+ LIST_ENTRY *Link;
+ CHAR16 *CharPos;
+
+ SearchLen = StrLen (SearchStr);
+ ReplaceLen = StrLen (ReplaceStr);
+
+ Column = FileBuffer.FilePosition.Column + Offset - 1;
+
+ if (Column > FileBuffer.CurrentLine->Size) {
+ Column = FileBuffer.CurrentLine->Size;
+ }
+
+ Link = &(FileBuffer.CurrentLine->Link);
+
+ while (Link != FileBuffer.ListHead) {
+ Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+ CharPos = StrStr (Line->Buffer + Column, SearchStr);
+ if (CharPos != NULL) {
+ Position = CharPos - Line->Buffer;// + Column;
+ //
+ // found
+ //
+ if (ReplaceLen > SearchLen) {
+ OldSize = Line->Size + 1;
+ //
+ // include CHAR_NULL
+ //
+ NewSize = OldSize + (ReplaceLen - SearchLen);
+
+ //
+ // do not have the enough space
+ //
+ if (Line->TotalSize + 1 <= NewSize) {
+ Line->Buffer = ReallocatePool (
+ 2 * OldSize,
+ 2 * NewSize,
+ Line->Buffer
+ );
+ Line->TotalSize = NewSize - 1;
+ }
+
+ if (Line->Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // the end CHAR_NULL character;
+ //
+ Buffer = Line->Buffer + (NewSize - 1);
+ Gap = ReplaceLen - SearchLen;
+
+ //
+ // keep the latter part
+ //
+ for (Index = 0; Index < (Line->Size - Position - SearchLen + 1); Index++) {
+ *Buffer = *(Buffer - Gap);
+ Buffer--;
+ }
+
+ } else if (ReplaceLen < SearchLen){
+ Buffer = Line->Buffer + Position + ReplaceLen;
+ Gap = SearchLen - ReplaceLen;
+
+ for (Index = 0; Index < (Line->Size - Position - ReplaceLen + 1); Index++) {
+ *Buffer = *(Buffer + Gap);
+ Buffer++;
+ }
+ } else {
+ ASSERT(ReplaceLen == SearchLen);
+ }
+ //
+ // set replace into it
+ //
+ Buffer = Line->Buffer + Position;
+ for (Index = 0; Index < ReplaceLen; Index++) {
+ Buffer[Index] = ReplaceStr[Index];
+ }
+
+ Line->Size += (ReplaceLen - SearchLen);
+ Column += ReplaceLen;
+ } else {
+ //
+ // not found
+ //
+ Column = 0;
+ Link = Link->ForwardLink;
+ }
+ }
+ //
+ // call refresh to fresh edit area
+ //
+ FileBuffer.FileModified = TRUE;
+ FileBufferNeedRefresh = TRUE;
+ FileBufferRefresh ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set the modified state to TRUE.
+**/
+VOID
+EFIAPI
+FileBufferSetModified (
+ VOID
+ )
+{
+ FileBuffer.FileModified = TRUE;
+}
+
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.h b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.h
new file mode 100644
index 0000000000..9d4a08d7a3
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.h
@@ -0,0 +1,263 @@
+/** @file
+ Declares filebuffer interface functions.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LIB_FILE_BUFFER_H_
+#define _LIB_FILE_BUFFER_H_
+
+#include "TextEditorTypes.h"
+
+/**
+ Initialization function for FileBuffer.
+
+ @param EFI_SUCCESS The initialization was successful.
+ @param EFI_LOAD_ERROR A default name could not be created.
+ @param EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferInit (
+ VOID
+ );
+
+/**
+ Cleanup function for FileBuffer.
+
+ @retval EFI_SUCCESS The cleanup was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferCleanup (
+ VOID
+ );
+
+/**
+ Refresh the screen with whats in the buffer.
+
+ @retval EFI_SUCCESS The refresh was successful.
+ @retval EFI_LOAD_ERROR There was an error finding what to write.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferRefresh (
+ VOID
+ );
+
+/**
+ Dispatch input to different handler
+ @param[in] Key The input key. One of:
+ ASCII KEY
+ Backspace/Delete
+ Return
+ Direction key: up/down/left/right/pgup/pgdn
+ Home/End
+ INS
+
+ @retval EFI_SUCCESS The dispatch was done successfully.
+ @retval EFI_LOAD_ERROR The dispatch was not successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferHandleInput (
+ IN CONST EFI_INPUT_KEY * Key
+ );
+
+/**
+ Backup function for FileBuffer. Only backup the following items:
+ Mouse/Cursor position
+ File Name, Type, ReadOnly, Modified
+ Insert Mode
+
+ This is for making the file buffer refresh as few as possible.
+
+ @retval EFI_SUCCESS The backup operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferBackup (
+ VOID
+ );
+
+/**
+ Set the cursor position according to FileBuffer.DisplayPosition.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferRestorePosition (
+ VOID
+ );
+
+/**
+ Set FileName field in FileBuffer.
+
+ @param Str The file name to set.
+
+ @retval EFI_SUCCESS The filename was successfully set.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_INVALID_PARAMETER Str is not a valid filename.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferSetFileName (
+ IN CONST CHAR16 *Str
+ );
+
+/**
+ Read a file from disk into the FileBuffer.
+
+ @param[in] FileName The filename to read.
+ @param[in] Recover TRUE if is for recover mode, no information printouts.
+
+ @retval EFI_SUCCESS The load was successful.
+ @retval EFI_LOAD_ERROR The load failed.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_INVALID_PARAMETER FileName is a directory.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferRead (
+ IN CONST CHAR16 *FileName,
+ IN CONST BOOLEAN Recover
+ );
+
+/**
+ Save lines in FileBuffer to disk
+
+ @param[in] FileName The file name for writing.
+
+ @retval EFI_SUCCESS Data was written.
+ @retval EFI_LOAD_ERROR
+ @retval EFI_OUT_OF_RESOURCES There were not enough resources to write the file.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferSave (
+ CONST CHAR16 *FileName
+ );
+
+/**
+ According to cursor's file position, adjust screen display
+
+ @param[in] NewFilePosRow The row of file position ( start from 1 ).
+ @param[in] NewFilePosCol The column of file position ( start from 1 ).
+**/
+VOID
+EFIAPI
+FileBufferMovePosition (
+ IN CONST UINTN NewFilePosRow,
+ IN CONST UINTN NewFilePosCol
+ );
+
+/**
+ Cut current line out and return a pointer to it.
+
+ @param[out] CutLine Upon a successful return pointer to the pointer to
+ the allocated cut line.
+
+ @retval EFI_SUCCESS The cut was successful.
+ @retval EFI_NOT_FOUND There was no selection to cut.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferCutLine (
+ OUT EFI_EDITOR_LINE **CutLine
+ );
+
+/**
+ Paste a line into line list.
+
+ @retval EFI_SUCCESS The paste was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferPasteLine (
+ VOID
+ );
+
+/**
+ Search string from current position on in file
+
+ @param[in] Str The search string.
+ @param[in] Offset The offset from current position.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_NOT_FOUND The string Str was not found.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferSearch (
+ IN CONST CHAR16 *Str,
+ IN CONST UINTN Offset
+ );
+
+/**
+ Replace SearchLen characters from current position on with Replace.
+
+ This will modify the current buffer at the current position.
+
+ @param[in] Replace The string to replace.
+ @param[in] SearchLen Search string's length.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferReplace (
+ IN CONST CHAR16 *Replace,
+ IN CONST UINTN SearchLen
+ );
+
+/**
+ Search and replace operation.
+
+ @param[in] SearchStr The string to search for.
+ @param[in] ReplaceStr The string to replace with.
+ @param[in] Offset The column to start at.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferReplaceAll (
+ IN CHAR16 *SearchStr,
+ IN CHAR16 *ReplaceStr,
+ IN UINTN Offset
+ );
+
+/**
+ Move the mouse cursor position.
+
+ @param[in] TextX The new x-coordinate.
+ @param[in] TextY The new y-coordinate.
+**/
+VOID
+EFIAPI
+FileBufferAdjustMousePosition (
+ IN CONST INT32 TextX,
+ IN CONST INT32 TextY
+ );
+
+/**
+ Set the modified state to TRUE.
+**/
+VOID
+EFIAPI
+FileBufferSetModified (
+ VOID
+ );
+
+#endif
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c
new file mode 100644
index 0000000000..7749bdc547
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c
@@ -0,0 +1,1830 @@
+/** @file
+ Implements editor interface functions.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "TextEditor.h"
+#include "EditStatusBar.h"
+#include "EditInputBar.h"
+
+/**
+ Load a file from disk to editor
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+MainCommandOpenFile (
+ VOID
+ );
+
+/**
+ Switch a file from ASCII to UNICODE or vise-versa.
+
+ @retval EFI_SUCCESS The switch was ok or a warning was presented.
+**/
+EFI_STATUS
+EFIAPI
+MainCommandSwitchFileType (
+ VOID
+ );
+
+/**
+ move cursor to specified lines
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+MainCommandGotoLine (
+ VOID
+ );
+
+/**
+ Save current file to disk, you can save to current file name or
+ save to another file name.
+
+ @retval EFI_SUCCESS The file was saved correctly.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A file access error occured.
+**/
+EFI_STATUS
+EFIAPI
+MainCommandSaveFile (
+ VOID
+ );
+
+/**
+ exit editor
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+EFIAPI
+MainCommandExit (
+ VOID
+ );
+
+/**
+ search string in file buffer
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+EFIAPI
+MainCommandSearch (
+ VOID
+ );
+
+/*
+ search string in file buffer, and replace it with another str
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+EFIAPI
+MainCommandSearchReplace (
+ VOID
+ );
+
+/**
+ cut current line to clipboard
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+EFIAPI
+MainCommandCutLine (
+ VOID
+ );
+
+/**
+ paste line to file buffer.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+EFIAPI
+MainCommandPasteLine (
+ VOID
+ );
+
+EDITOR_MENU_ITEM MainMenuItems[] = {
+ {
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_GO_TO_LINE),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F1),
+ MainCommandGotoLine
+ },
+ {
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_SAVE_FILE),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F2),
+ MainCommandSaveFile
+ },
+ {
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_EXIT),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F3),
+ MainCommandExit
+ },
+
+ {
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_SEARCH),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F4),
+ MainCommandSearch
+ },
+ {
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_SEARCH_REPLACE),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F5),
+ MainCommandSearchReplace
+ },
+ {
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_CUT_LINE),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F6),
+ MainCommandCutLine
+ },
+ {
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_PASTE_LINE),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F7),
+ MainCommandPasteLine
+ },
+
+ {
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_OPEN_FILE),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F8),
+ MainCommandOpenFile
+ },
+ {
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_FILE_TYPE),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F9),
+ MainCommandSwitchFileType
+ },
+
+ {
+ 0,
+ 0,
+ NULL
+ }
+};
+
+
+/**
+ Load a file from disk to editor
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+MainCommandOpenFile (
+ VOID
+ )
+{
+ BOOLEAN Done;
+ EFI_STATUS Status;
+
+ //
+ // This command will open a file from current working directory.
+ // Read-only file can also be opened. But it can not be modified.
+ // Below is the scenario of Open File command:
+ // 1.IF currently opened file has not been modIFied, directly go to step .
+ // IF currently opened file has been modified,
+ // an Input Bar will be prompted as :
+ // "File Modified. Save ( Yes/No/Cancel) ?"
+ // IF user press 'y' or 'Y', currently opened file will be saved.
+ // IF user press 'n' or 'N', currently opened file will
+ // not be saved.
+ // IF user press 'c' or 'C' or ESC, Open File command ends and
+ // currently opened file is still opened.
+ //
+ // 2. An Input Bar will be prompted as : "File Name to Open: "
+ // IF user press ESC, Open File command ends and
+ // currently opened file is still opened.
+ // Any other inputs with a Return will
+ // cause currently opened file close.
+ //
+ // 3. IF user input file name is an existing file , this file will be read
+ // and opened.
+ // IF user input file name is a new file, this file will be created
+ // and opened. This file's type ( UNICODE or ASCII ) is the same
+ // with the old file.
+ // if current file is modified, so you need to choose
+ // whether to save it first.
+ //
+ if (MainEditor.FileBuffer->FileModified) {
+
+ Status = InputBarSetPrompt (L"File modified. Save (Yes/No/Cancel) ? ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // the answer is just one character
+ //
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // loop for user's answer
+ // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'
+ //
+ Done = FALSE;
+ while (!Done) {
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh();
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString()[0]) {
+ case L'y':
+ case L'Y':
+ //
+ // want to save this file first
+ //
+ Status = FileBufferSave (MainEditor.FileBuffer->FileName);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ MainTitleBarRefresh (MainEditor.FileBuffer->FileName, MainEditor.FileBuffer->FileType, MainEditor.FileBuffer->ReadOnly, MainEditor.FileBuffer->FileModified, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row);
+ FileBufferRestorePosition ();
+ Done = TRUE;
+ break;
+
+ case L'n':
+ case L'N':
+ //
+ // the file won't be saved
+ //
+ Done = TRUE;
+ break;
+
+ case L'c':
+ case L'C':
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ //
+ // TO get the open file name
+ //
+ Status = InputBarSetPrompt (L"File Name to Open: ");
+ if (EFI_ERROR (Status)) {
+ FileBufferRead (MainEditor.FileBuffer->FileName, TRUE);
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (100);
+ if (EFI_ERROR (Status)) {
+ FileBufferRead (MainEditor.FileBuffer->FileName, TRUE);
+ return Status;
+ }
+
+ while (1) {
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh();
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+ //
+ // The input string length should > 0
+ //
+ if (StrLen (InputBarGetString()) > 0) {
+ //
+ // CHECK if filename is valid
+ //
+ if (!IsValidFileName (InputBarGetString())) {
+ FileBufferRead (MainEditor.FileBuffer->FileName, TRUE);
+ StatusBarSetStatusString (L"Invalid File Name");
+ return EFI_SUCCESS;
+ }
+
+ break;
+ }
+ }
+ //
+ // read from disk
+ //
+ Status = FileBufferRead (InputBarGetString(), FALSE);
+
+ if (EFI_ERROR (Status)) {
+ FileBufferRead (MainEditor.FileBuffer->FileName, TRUE);
+ return EFI_LOAD_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Switch a file from ASCII to UNICODE or vise-versa.
+
+ @retval EFI_SUCCESS The switch was ok or a warning was presented.
+**/
+EFI_STATUS
+EFIAPI
+MainCommandSwitchFileType (
+ VOID
+ )
+{
+ //
+ // Below is the scenario of File Type command:
+ // After File Type is executed, file type will be changed to another type
+ // if file is read-only, can not be modified
+ //
+ if (MainEditor.FileBuffer->ReadOnly) {
+ StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
+ return EFI_SUCCESS;
+ }
+
+ if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
+ MainEditor.FileBuffer->FileType = FileTypeAscii;
+ } else {
+ MainEditor.FileBuffer->FileType = FileTypeUnicode;
+ }
+
+ MainEditor.FileBuffer->FileModified = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ cut current line to clipboard
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+EFIAPI
+MainCommandCutLine (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_EDITOR_LINE *Line;
+
+ //
+ // This command will cut current line ( where cursor is on ) to clip board.
+ // And cursor will move to the beginning of next line.
+ // Below is the scenario of Cut Line command:
+ // 1. IF cursor is on valid line, current line will be cut to clip board.
+ // IF cursor is not on valid line, an Status String will be prompted :
+ // "Nothing to Cut".
+ //
+ Status = FileBufferCutLine (&Line);
+ if (Status == EFI_NOT_FOUND) {
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ MainEditor.CutLine = Line;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ paste line to file buffer.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+EFIAPI
+MainCommandPasteLine (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Below is the scenario of Paste Line command:
+ // 1. IF nothing is on clipboard, a Status String will be prompted :
+ // "No Line to Paste" and Paste Line command ends.
+ // IF something is on clipboard, insert it above current line.
+ // nothing on clipboard
+ //
+ if (MainEditor.CutLine == NULL) {
+ StatusBarSetStatusString (L"No Line to Paste");
+ return EFI_SUCCESS;
+ }
+
+ Status = FileBufferPasteLine ();
+
+ return Status;
+}
+
+
+/**
+ search string in file buffer
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+EFIAPI
+MainCommandSearch (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *Buffer;
+ BOOLEAN Done;
+ UINTN Offset;
+
+ //
+ // Below is the scenario of Search command:
+ // 1. An Input Bar will be prompted : "Enter Search String:".
+ // IF user press ESC, Search command ends.
+ // IF user just press Enter, Search command ends.
+ // IF user inputs the search string, do Step 2.
+ //
+ // 2. IF input search string is found, cursor will move to the first
+ // occurrence and do Step 3.
+ // IF input search string is not found, a Status String
+ // "Search String Not Found" will be prompted and Search command ends.
+ //
+ // 3. An Input Bar will be prompted: "Find Next (Yes/No/Cancel ) ?".
+ // IF user press ESC, Search command ends.
+ // IF user press 'y' or 'Y', do Step 2.
+ // IF user press 'n' or 'N', Search command ends.
+ // IF user press 'c' or 'C', Search command ends.
+ //
+ Status = InputBarSetPrompt (L"Enter Search String: ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (40);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh();
+
+ //
+ // ESC
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+ //
+ // just enter pressed
+ //
+ if (StrLen (InputBarGetString()) == 0) {
+ return EFI_SUCCESS;
+ }
+
+ Buffer = CatSPrint (NULL, L"%s", InputBarGetString());
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // the first time , search from current position
+ //
+ Offset = 0;
+ do {
+ //
+ // since search may be continued to search multiple times
+ // so we need to backup editor each time
+ //
+ MainEditorBackup ();
+
+ Status = FileBufferSearch (Buffer, Offset);
+
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ }
+ //
+ // Find next
+ //
+ Status = InputBarSetPrompt (L"Find Next (Yes/No) ?");
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return Status;
+ }
+
+ Done = FALSE;
+ while (!Done) {
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh();
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ FreePool (Buffer);
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString()[0]) {
+ case L'y':
+ case L'Y':
+ Done = TRUE;
+ break;
+
+ case L'n':
+ case L'N':
+ FreePool (Buffer);
+ return EFI_SUCCESS;
+
+ }
+ //
+ // end of which
+ //
+ }
+ //
+ // end of while !Done
+ // for search second, third time, search from current position + strlen
+ //
+ Offset = StrLen (Buffer);
+
+ } while (1);
+ //
+ // end of do
+ //
+ FreePool (Buffer);
+ StatusBarSetStatusString (L"Search String Not Found");
+
+ return EFI_SUCCESS;
+}
+
+/*
+ search string in file buffer, and replace it with another str
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+EFIAPI
+MainCommandSearchReplace (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *Search;
+ CHAR16 *Replace;
+ BOOLEAN Done;
+ BOOLEAN First;
+ BOOLEAN ReplaceOption;
+ UINTN SearchLen;
+ UINTN ReplaceLen;
+ BOOLEAN ReplaceAll;
+
+ ReplaceOption = FALSE;
+
+ //
+ // Below is the scenario of Search/Replace command:
+ // 1. An Input Bar is prompted : "Enter Search String:".
+ // IF user press ESC, Search/Replace command ends.
+ // IF user just press Enter, Search/Replace command ends.
+ // IF user inputs the search string S, do Step 2.
+ //
+ // 2. An Input Bar is prompted: "Replace With:".
+ // IF user press ESC, Search/Replace command ends.
+ // IF user inputs the replace string R, do Step 3.
+ //
+ // 3. IF input search string is not found, an Status String
+ // "Search String Not Found" will be prompted
+ // and Search/Replace command ends
+ // IF input search string is found, do Step 4.
+ //
+ // 4. An Input Bar will be prompted: "Replace ( Yes/No/All/Cancel )?"
+ // IF user press 'y' or 'Y', S will be replaced with R and do Step 5
+ // IF user press 'n' or 'N', S will not be replaced and do Step 5.
+ // IF user press 'a' or 'A', all the S from file current position on
+ // will be replaced with R and Search/Replace command ends.
+ // IF user press 'c' or 'C' or ESC, Search/Replace command ends.
+ //
+ // 5. An Input Bar will be prompted: "Find Next (Yes/No/Cancel) ?".
+ // IF user press ESC, Search/Replace command ends.
+ // IF user press 'y' or 'Y', do Step 3.
+ // IF user press 'n' or 'N', Search/Replace command ends.
+ // IF user press 'c' or 'C', Search/Replace command ends.
+ // input search string
+ //
+ Status = InputBarSetPrompt (L"Enter Search String: ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (40);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh();
+
+ //
+ // ESC
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+ //
+ // if just pressed enter
+ //
+ if (StrLen (InputBarGetString()) == 0) {
+ return EFI_SUCCESS;
+ }
+
+ Search = CatSPrint (NULL, L"%s", InputBarGetString());
+ if (Search == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SearchLen = StrLen (Search);
+
+ //
+ // input replace string
+ //
+ Status = InputBarSetPrompt (L"Replace With: ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (40);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh();
+
+ //
+ // ESC
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ Replace = CatSPrint (NULL, L"%s", InputBarGetString());
+ if (Replace == NULL) {
+ FreePool (Search);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ReplaceLen = StrLen (Replace);
+
+ First = TRUE;
+ ReplaceAll = FALSE;
+ do {
+ //
+ // since search may be continued to search multiple times
+ // so we need to backup editor each time
+ //
+ MainEditorBackup ();
+
+ if (First) {
+ Status = FileBufferSearch (Search, 0);
+ } else {
+ //
+ // if just replace, so skip this replace string
+ // if replace string is an empty string, so skip to next character
+ //
+ if (ReplaceOption) {
+ Status = FileBufferSearch (Search, (ReplaceLen == 0) ? 1 : ReplaceLen);
+ } else {
+ Status = FileBufferSearch (Search, SearchLen);
+ }
+ }
+
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ }
+ //
+ // replace or not?
+ //
+ Status = InputBarSetPrompt (L"Replace (Yes/No/All/Cancel) ?");
+
+ if (EFI_ERROR (Status)) {
+ FreePool (Search);
+ FreePool (Replace);
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ FreePool (Search);
+ FreePool (Replace);
+ return Status;
+ }
+
+ Done = FALSE;
+ while (!Done) {
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh();
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ FreePool (Search);
+ FreePool (Replace);
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString()[0]) {
+ case L'y':
+ case L'Y':
+ Done = TRUE;
+ ReplaceOption = TRUE;
+ break;
+
+ case L'n':
+ case L'N':
+ Done = TRUE;
+ ReplaceOption = FALSE;
+ break;
+
+ case L'a':
+ case L'A':
+ Done = TRUE;
+ ReplaceOption = TRUE;
+ ReplaceAll = TRUE;
+ break;
+
+ case L'c':
+ case L'C':
+ FreePool (Search);
+ FreePool (Replace);
+ return EFI_SUCCESS;
+
+ }
+ //
+ // end of which
+ //
+ }
+ //
+ // end of while !Done
+ // Decide to Replace
+ //
+ if (ReplaceOption) {
+ //
+ // file is read-only
+ //
+ if (MainEditor.FileBuffer->ReadOnly) {
+ StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
+ return EFI_SUCCESS;
+ }
+ //
+ // replace all
+ //
+ if (ReplaceAll) {
+ Status = FileBufferReplaceAll (Search, Replace, 0);
+ FreePool (Search);
+ FreePool (Replace);
+ return Status;
+ }
+ //
+ // replace
+ //
+ Status = FileBufferReplace (Replace, SearchLen);
+ if (EFI_ERROR (Status)) {
+ FreePool (Search);
+ FreePool (Replace);
+ return Status;
+ }
+ }
+ //
+ // Find next
+ //
+ Status = InputBarSetPrompt (L"Find Next (Yes/No) ?");
+ if (EFI_ERROR (Status)) {
+ FreePool (Search);
+ FreePool (Replace);
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ FreePool (Search);
+ FreePool (Replace);
+ return Status;
+ }
+
+ Done = FALSE;
+ while (!Done) {
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh();
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ FreePool (Search);
+ FreePool (Replace);
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString()[0]) {
+ case L'y':
+ case L'Y':
+ Done = TRUE;
+ break;
+
+ case L'n':
+ case L'N':
+ FreePool (Search);
+ FreePool (Replace);
+ return EFI_SUCCESS;
+
+ }
+ //
+ // end of which
+ //
+ }
+ //
+ // end of while !Done
+ //
+ First = FALSE;
+
+ } while (1);
+ //
+ // end of do
+ //
+ FreePool (Search);
+ FreePool (Replace);
+
+ StatusBarSetStatusString (L"Search String Not Found");
+
+ return EFI_SUCCESS;
+}
+
+/**
+ exit editor
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+EFIAPI
+MainCommandExit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Below is the scenario of Exit command:
+ // 1. IF currently opened file is not modified, exit the editor and
+ // Exit command ends.
+ // IF currently opened file is modified, do Step 2
+ //
+ // 2. An Input Bar will be prompted:
+ // "File modified. Save ( Yes/No/Cancel )?"
+ // IF user press 'y' or 'Y', currently opened file will be saved
+ // and Editor exits
+ // IF user press 'n' or 'N', currently opened file will not be saved
+ // and Editor exits.
+ // IF user press 'c' or 'C' or ESC, Exit command ends.
+ // if file has been modified, so will prompt user whether to save the changes
+ //
+ if (MainEditor.FileBuffer->FileModified) {
+
+ Status = InputBarSetPrompt (L"File modified. Save (Yes/No/Cancel) ? ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ while (1) {
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh();
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString()[0]) {
+ case L'y':
+ case L'Y':
+ //
+ // write file back to disk
+ //
+ Status = FileBufferSave (MainEditor.FileBuffer->FileName);
+ if (!EFI_ERROR (Status)) {
+ EditorExit = TRUE;
+ }
+
+ return Status;
+
+ case L'n':
+ case L'N':
+ EditorExit = TRUE;
+ return EFI_SUCCESS;
+
+ case L'c':
+ case L'C':
+ return EFI_SUCCESS;
+
+ }
+ }
+ }
+
+ EditorExit = TRUE;
+ return EFI_SUCCESS;
+
+}
+
+/**
+ move cursor to specified lines
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+MainCommandGotoLine (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Row;
+
+ //
+ // Below is the scenario of Go To Line command:
+ // 1. An Input Bar will be prompted : "Go To Line:".
+ // IF user press ESC, Go To Line command ends.
+ // IF user just press Enter, cursor remains unchanged.
+ // IF user inputs line number, do Step 2.
+ //
+ // 2. IF input line number is valid, move cursor to the beginning
+ // of specified line and Go To Line command ends.
+ // IF input line number is invalid, a Status String will be prompted:
+ // "No Such Line" and Go To Line command ends.
+ //
+ Status = InputBarSetPrompt (L"Go To Line: ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // line number's digit <= 6
+ //
+ Status = InputBarSetStringSize (6);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh();
+
+ //
+ // press ESC
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+ //
+ // if JUST press enter
+ //
+ if (StrLen (InputBarGetString()) == 0) {
+ return EFI_SUCCESS;
+ }
+
+ Row = ShellStrToUintn (InputBarGetString());
+
+ //
+ // invalid line number
+ //
+ if (Row > MainEditor.FileBuffer->NumLines || Row <= 0) {
+ StatusBarSetStatusString (L"No Such Line");
+ return EFI_SUCCESS;
+ }
+ //
+ // move cursor to that line's start
+ //
+ FileBufferMovePosition (Row, 1);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Save current file to disk, you can save to current file name or
+ save to another file name.
+
+ @retval EFI_SUCCESS The file was saved correctly.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A file access error occured.
+**/
+EFI_STATUS
+EFIAPI
+MainCommandSaveFile (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *FileName;
+ BOOLEAN OldFile;
+ CHAR16 *Str;
+ SHELL_FILE_HANDLE FileHandle;
+ EFI_FILE_INFO *Info;
+
+ //
+ // This command will save currently opened file to disk.
+ // You can choose save to another file name or just save to
+ // current file name.
+ // Below is the scenario of Save File command:
+ // ( Suppose the old file name is A )
+ // 1. An Input Bar will be prompted: "File To Save: [ old file name]"
+ // IF user press ESC, Save File command ends .
+ // IF user press Enter, input file name will be A.
+ // IF user inputs a new file name B, input file name will be B.
+ //
+ // 2. IF input file name is A, go to do Step 3.
+ // IF input file name is B, go to do Step 4.
+ //
+ // 3. IF A is read only, Status Bar will show "Access Denied" and
+ // Save File commands ends.
+ // IF A is not read only, save file buffer to disk and remove modified
+ // flag in Title Bar , then Save File command ends.
+ //
+ // 4. IF B does not exist, create this file and save file buffer to it.
+ // Go to do Step 7.
+ // IF B exits, do Step 5.
+ //
+ // 5.An Input Bar will be prompted:
+ // "File Exists. Overwrite ( Yes/No/Cancel )?"
+ // IF user press 'y' or 'Y', do Step 6.
+ // IF user press 'n' or 'N', Save File commands ends.
+ // IF user press 'c' or 'C' or ESC, Save File commands ends.
+ //
+ // 6. IF B is a read-only file, Status Bar will show "Access Denied" and
+ // Save File commands ends.
+ // IF B can be read and write, save file buffer to B.
+ //
+ // 7. Update File Name field in Title Bar to B and remove the modified
+ // flag in Title Bar.
+ //
+ Str = CatSPrint (NULL, L"File to Save: [%s]", MainEditor.FileBuffer->FileName);
+ if (Str == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (StrLen (Str) >= 50) {
+ //
+ // replace the long file name with "..."
+ //
+ Str[46] = L'.';
+ Str[47] = L'.';
+ Str[48] = L'.';
+ Str[49] = L']';
+ Str[50] = CHAR_NULL;
+ }
+
+ Status = InputBarSetPrompt (Str);
+ FreePool(Str);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+
+ Status = InputBarSetStringSize (100);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // get new file name
+ //
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh();
+
+ //
+ // if user pressed ESC
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // if just enter pressed, so think save to current file name
+ //
+ if (StrLen (InputBarGetString()) == 0) {
+ FileName = CatSPrint (NULL, L"%s", MainEditor.FileBuffer->FileName);
+ } else {
+ FileName = CatSPrint (NULL, L"%s", InputBarGetString());
+ }
+
+ if (FileName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (!IsValidFileName (FileName)) {
+ StatusBarSetStatusString (L"Invalid File Name");
+ FreePool (FileName);
+ return EFI_SUCCESS;
+ }
+
+ OldFile = FALSE;
+
+ //
+ // save to the old file
+ //
+ if (StringNoCaseCompare (&FileName, &MainEditor.FileBuffer->FileName) == 0) {
+ OldFile = TRUE;
+ }
+
+ if (OldFile) {
+ //
+ // if the file is read only, so can not write back to it.
+ //
+ if (MainEditor.FileBuffer->ReadOnly == TRUE) {
+ StatusBarSetStatusString (L"Access Denied");
+ FreePool (FileName);
+ return EFI_SUCCESS;
+ }
+ } else {
+ //
+ // if the file exists
+ //
+ if (ShellFileExists(FileName) != EFI_NOT_FOUND) {
+ //
+ // check for read only
+ //
+ Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_READ, 0);
+ if (EFI_ERROR(Status)) {
+ StatusBarSetStatusString (L"Open Failed");
+ FreePool (FileName);
+ return EFI_SUCCESS;
+ }
+
+ Info = ShellGetFileInfo(FileHandle);
+ if (Info == NULL) {
+ StatusBarSetStatusString (L"Access Denied");
+ FreePool (FileName);
+ return (EFI_SUCCESS);
+ }
+
+ if (Info->Attribute & EFI_FILE_READ_ONLY) {
+ StatusBarSetStatusString (L"Access Denied - Read Only");
+ FreePool (Info);
+ FreePool (FileName);
+ return (EFI_SUCCESS);
+ }
+ FreePool (Info);
+
+ //
+ // ask user whether to overwrite this file
+ //
+ Status = InputBarSetPrompt (L"File exists. Overwrite (Yes/No/Cancel) ? ");
+ if (EFI_ERROR (Status)) {
+ SHELL_FREE_NON_NULL (FileName);
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ SHELL_FREE_NON_NULL (FileName);
+ return Status;
+ }
+
+ while (TRUE) {
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh();
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ SHELL_FREE_NON_NULL (FileName);
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString()[0]) {
+ case L'y':
+ case L'Y':
+ break;
+
+ case L'n':
+ case L'N':
+ case L'c':
+ case L'C':
+ SHELL_FREE_NON_NULL (FileName);
+ return EFI_SUCCESS;
+ } // end switch
+ } // while (!done)
+ } // file does exist
+ } // if old file name same
+
+ //
+ // save file to disk with specified name
+ //
+ FileBufferSetModified();
+ Status = FileBufferSave (FileName);
+ SHELL_FREE_NON_NULL (FileName);
+
+ return Status;
+}
+
+EFI_EDITOR_COLOR_ATTRIBUTES OriginalColors;
+INTN OriginalMode;
+
+//
+// the first time editor launch
+//
+BOOLEAN EditorFirst;
+
+//
+// it's time editor should exit
+//
+BOOLEAN EditorExit;
+
+BOOLEAN EditorMouseAction;
+
+extern EFI_EDITOR_FILE_BUFFER FileBuffer;
+
+extern BOOLEAN FileBufferMouseNeedRefresh;
+
+extern EFI_EDITOR_FILE_BUFFER FileBufferBackupVar;
+
+EFI_EDITOR_GLOBAL_EDITOR MainEditor;
+
+//
+// basic initialization for MainEditor
+//
+EFI_EDITOR_GLOBAL_EDITOR MainEditorConst = {
+ &FileBuffer,
+ {
+ 0,
+ 0
+ },
+ {
+ 0,
+ 0
+ },
+ NULL,
+ FALSE,
+ NULL
+};
+
+/**
+ The initialization function for MainEditor.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+EFIAPI
+MainEditorInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+ UINTN Index;
+
+ //
+ // basic initialization
+ //
+ CopyMem (&MainEditor, &MainEditorConst, sizeof (MainEditor));
+
+ //
+ // set screen attributes
+ //
+ MainEditor.ColorAttributes.Colors.Foreground = gST->ConOut->Mode->Attribute & 0x000000ff;
+
+ MainEditor.ColorAttributes.Colors.Background = (UINT8) (gST->ConOut->Mode->Attribute >> 4);
+ OriginalColors = MainEditor.ColorAttributes.Colors;
+
+ OriginalMode = gST->ConOut->Mode->Mode;
+
+ //
+ // query screen size
+ //
+ gST->ConOut->QueryMode (
+ gST->ConOut,
+ gST->ConOut->Mode->Mode,
+ &(MainEditor.ScreenSize.Column),
+ &(MainEditor.ScreenSize.Row)
+ );
+
+ //
+ // Find mouse in System Table ConsoleInHandle
+ //
+ Status = gBS->HandleProtocol (
+ gST->ConIn,
+ &gEfiSimplePointerProtocolGuid,
+ (VOID**)&MainEditor.MouseInterface
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // If there is no Simple Pointer Protocol on System Table
+ //
+ HandleBuffer = NULL;
+ MainEditor.MouseInterface = NULL;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSimplePointerProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (!EFI_ERROR (Status) && HandleCount > 0) {
+ //
+ // Try to find the first available mouse device
+ //
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiSimplePointerProtocolGuid,
+ (VOID**)&MainEditor.MouseInterface
+ );
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ }
+ }
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+ }
+
+ if (!EFI_ERROR (Status) && MainEditor.MouseInterface != NULL) {
+ MainEditor.MouseAccumulatorX = 0;
+ MainEditor.MouseAccumulatorY = 0;
+ MainEditor.MouseSupported = TRUE;
+ }
+
+ //
+ // below will call the five components' init function
+ //
+ Status = MainTitleBarInit (L"UEFI EDIT 2.0");
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_TITLEBAR), gShellDebug1HiiHandle);
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = MenuBarInit (MainMenuItems);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_MAINMENU), gShellDebug1HiiHandle);
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = StatusBarInit ();
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_STATUSBAR), gShellDebug1HiiHandle);
+ return EFI_LOAD_ERROR;
+ }
+
+ InputBarInit ();
+
+ Status = FileBufferInit ();
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_FILEBUFFER), gShellDebug1HiiHandle);
+ return EFI_LOAD_ERROR;
+ }
+ //
+ // clear whole screen and enable cursor
+ //
+ gST->ConOut->ClearScreen (gST->ConOut);
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+
+ //
+ // initialize EditorFirst and EditorExit
+ //
+ EditorFirst = TRUE;
+ EditorExit = FALSE;
+ EditorMouseAction = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The cleanup function for MainEditor.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+EFIAPI
+MainEditorCleanup (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // call the five components' cleanup function
+ // if error, do not exit
+ // just print some warning
+ //
+ MainTitleBarCleanup();
+ StatusBarCleanup();
+ InputBarCleanup();
+ MenuBarCleanup ();
+
+ Status = FileBufferCleanup ();
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_FILEBUFFER_CLEANUP), gShellDebug1HiiHandle);
+ }
+ //
+ // restore old mode
+ //
+ if (OriginalMode != gST->ConOut->Mode->Mode) {
+ gST->ConOut->SetMode (gST->ConOut, OriginalMode);
+ }
+ //
+ // restore old screen color
+ //
+ gST->ConOut->SetAttribute (
+ gST->ConOut,
+ EFI_TEXT_ATTR (OriginalColors.Foreground, OriginalColors.Background)
+ );
+
+ gST->ConOut->ClearScreen (gST->ConOut);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Refresh the main editor component.
+**/
+VOID
+EFIAPI
+MainEditorRefresh (
+ VOID
+ )
+{
+ //
+ // The Stall value is from experience. NOT from spec. avoids 'flicker'
+ //
+ gBS->Stall (50);
+
+ //
+ // call the components refresh function
+ //
+ if (EditorFirst
+ || StrCmp (FileBufferBackupVar.FileName, FileBuffer.FileName) != 0
+ || FileBufferBackupVar.FileType != FileBuffer.FileType
+ || FileBufferBackupVar.FileModified != FileBuffer.FileModified
+ || FileBufferBackupVar.ReadOnly != FileBuffer.ReadOnly) {
+
+ MainTitleBarRefresh (MainEditor.FileBuffer->FileName, MainEditor.FileBuffer->FileType, MainEditor.FileBuffer->ReadOnly, MainEditor.FileBuffer->FileModified, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row);
+ FileBufferRestorePosition ();
+ FileBufferRefresh ();
+ }
+ if (EditorFirst
+ || FileBufferBackupVar.FilePosition.Row != FileBuffer.FilePosition.Row
+ || FileBufferBackupVar.FilePosition.Column != FileBuffer.FilePosition.Column
+ || FileBufferBackupVar.ModeInsert != FileBuffer.ModeInsert
+ || StatusBarGetRefresh()) {
+
+ StatusBarRefresh (EditorFirst, MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column, MainEditor.FileBuffer->FilePosition.Row, MainEditor.FileBuffer->FilePosition.Column, MainEditor.FileBuffer->ModeInsert);
+ FileBufferRestorePosition ();
+ FileBufferRefresh ();
+ }
+
+ if (EditorFirst) {
+ MenuBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ FileBufferRestorePosition ();
+ }
+
+ //
+ // EditorFirst is now set to FALSE
+ //
+ EditorFirst = FALSE;
+}
+
+/**
+ Get's the resultant location of the cursor based on the relative movement of the Mouse.
+
+ @param[in] GuidX The relative mouse movement.
+
+ @return The X location of the mouse.
+**/
+INT32
+EFIAPI
+GetTextX (
+ IN INT32 GuidX
+ )
+{
+ INT32 Gap;
+
+ MainEditor.MouseAccumulatorX += GuidX;
+ Gap = (MainEditor.MouseAccumulatorX * (INT32) MainEditor.ScreenSize.Column) / (INT32) (50 * (INT32) MainEditor.MouseInterface->Mode->ResolutionX);
+ MainEditor.MouseAccumulatorX = (MainEditor.MouseAccumulatorX * (INT32) MainEditor.ScreenSize.Column) % (INT32) (50 * (INT32) MainEditor.MouseInterface->Mode->ResolutionX);
+ MainEditor.MouseAccumulatorX = MainEditor.MouseAccumulatorX / (INT32) MainEditor.ScreenSize.Column;
+ return Gap;
+}
+
+/**
+ Get's the resultant location of the cursor based on the relative movement of the Mouse.
+
+ @param[in] GuidY The relative mouse movement.
+
+ @return The Y location of the mouse.
+**/
+INT32
+EFIAPI
+GetTextY (
+ IN INT32 GuidY
+ )
+{
+ INT32 Gap;
+
+ MainEditor.MouseAccumulatorY += GuidY;
+ Gap = (MainEditor.MouseAccumulatorY * (INT32) MainEditor.ScreenSize.Row) / (INT32) (50 * (INT32) MainEditor.MouseInterface->Mode->ResolutionY);
+ MainEditor.MouseAccumulatorY = (MainEditor.MouseAccumulatorY * (INT32) MainEditor.ScreenSize.Row) % (INT32) (50 * (INT32) MainEditor.MouseInterface->Mode->ResolutionY);
+ MainEditor.MouseAccumulatorY = MainEditor.MouseAccumulatorY / (INT32) MainEditor.ScreenSize.Row;
+
+ return Gap;
+}
+
+/**
+ Support mouse movement. Move the cursor.
+
+ @param[in] MouseState The current mouse state.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_NOT_FOUND There was no mouse support found.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+MainEditorHandleMouseInput (
+ IN EFI_SIMPLE_POINTER_STATE MouseState
+ )
+{
+
+ INT32 TextX;
+ INT32 TextY;
+ UINTN FRow;
+ UINTN FCol;
+
+ LIST_ENTRY *Link;
+ EFI_EDITOR_LINE *Line;
+
+ UINTN Index;
+ BOOLEAN Action;
+
+ //
+ // mouse action means:
+ // mouse movement
+ // mouse left button
+ //
+ Action = FALSE;
+
+ //
+ // have mouse movement
+ //
+ if (MouseState.RelativeMovementX || MouseState.RelativeMovementY) {
+ //
+ // handle
+ //
+ TextX = GetTextX (MouseState.RelativeMovementX);
+ TextY = GetTextY (MouseState.RelativeMovementY);
+
+ FileBufferAdjustMousePosition (TextX, TextY);
+
+ Action = TRUE;
+
+ }
+
+ //
+ // if left button pushed down
+ //
+ if (MouseState.LeftButton) {
+
+ FCol = MainEditor.FileBuffer->MousePosition.Column - 1 + 1;
+
+ FRow = MainEditor.FileBuffer->FilePosition.Row +
+ MainEditor.FileBuffer->MousePosition.Row -
+ MainEditor.FileBuffer->DisplayPosition.Row;
+
+ //
+ // beyond the file line length
+ //
+ if (MainEditor.FileBuffer->NumLines < FRow) {
+ FRow = MainEditor.FileBuffer->NumLines;
+ }
+
+ Link = MainEditor.FileBuffer->ListHead->ForwardLink;
+ for (Index = 0; Index < FRow - 1; Index++) {
+ Link = Link->ForwardLink;
+ }
+
+ Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+
+ //
+ // beyond the line's column length
+ //
+ if (FCol > Line->Size + 1) {
+ FCol = Line->Size + 1;
+ }
+
+ FileBufferMovePosition (FRow, FCol);
+
+ MainEditor.FileBuffer->MousePosition.Row = MainEditor.FileBuffer->DisplayPosition.Row;
+
+ MainEditor.FileBuffer->MousePosition.Column = MainEditor.FileBuffer->DisplayPosition.Column;
+
+ Action = TRUE;
+ }
+ //
+ // mouse has action
+ //
+ if (Action) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // no mouse action
+ //
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Handle user key input. This routes to other functions for the actions.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+MainEditorKeyInput (
+ VOID
+ )
+{
+ EFI_INPUT_KEY Key;
+ EFI_STATUS Status;
+ EFI_SIMPLE_POINTER_STATE MouseState;
+
+ do {
+
+ Status = EFI_SUCCESS;
+ EditorMouseAction = FALSE;
+
+ //
+ // backup some key elements, so that can aVOID some refresh work
+ //
+ MainEditorBackup ();
+
+ //
+ // change priority of checking mouse/keyboard activity dynamically
+ // so prevent starvation of keyboard.
+ // if last time, mouse moves then this time check keyboard
+ //
+ if (MainEditor.MouseSupported) {
+ Status = MainEditor.MouseInterface->GetState (
+ MainEditor.MouseInterface,
+ &MouseState
+ );
+ if (!EFI_ERROR (Status)) {
+
+ Status = MainEditorHandleMouseInput (MouseState);
+
+ if (!EFI_ERROR (Status)) {
+ EditorMouseAction = TRUE;
+ FileBufferMouseNeedRefresh = TRUE;
+ } else if (Status == EFI_LOAD_ERROR) {
+ StatusBarSetStatusString (L"Invalid Mouse Movement ");
+ }
+ }
+ }
+
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ if (!EFI_ERROR (Status)) {
+ //
+ // dispatch to different components' key handling function
+ // so not everywhere has to set this variable
+ //
+ FileBufferMouseNeedRefresh = TRUE;
+ //
+ // clear previous status string
+ //
+ StatusBarSetRefresh();
+
+ //
+ // dispatch to different components' key handling function
+ //
+ if ((Key.ScanCode == SCAN_NULL) || ((Key.ScanCode >= SCAN_UP) && (Key.ScanCode <= SCAN_PAGE_DOWN))) {
+ Status = FileBufferHandleInput (&Key);
+ } else if ((Key.ScanCode >= SCAN_F1) && (Key.ScanCode <= SCAN_F12)) {
+ Status = MenuBarDispatchFunctionKey (&Key);
+ } else {
+ StatusBarSetStatusString (L"Unknown Command");
+ FileBufferMouseNeedRefresh = FALSE;
+ }
+
+ if (Status != EFI_SUCCESS && Status != EFI_OUT_OF_RESOURCES) {
+ //
+ // not already has some error status
+ //
+ if (StatusBarGetString() != NULL && StrCmp (L"", StatusBarGetString()) == 0) {
+ StatusBarSetStatusString (L"Disk Error. Try Again");
+ }
+ }
+
+ }
+ //
+ // after handling, refresh editor
+ //
+ MainEditorRefresh ();
+
+ } while (Status != EFI_OUT_OF_RESOURCES && !EditorExit);
+
+ return Status;
+}
+
+/**
+ Set clipboard
+
+ @param[in] Line A pointer to the line to be set to clipboard
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+MainEditorSetCutLine (
+ EFI_EDITOR_LINE *Line
+ )
+{
+ if (Line == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ if (MainEditor.CutLine != NULL) {
+ //
+ // free the old clipboard
+ //
+ LineFree (MainEditor.CutLine);
+ }
+ //
+ // duplicate the line to clipboard
+ //
+ MainEditor.CutLine = LineDup (Line);
+ if (MainEditor.CutLine == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Backup function for MainEditor
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+MainEditorBackup (
+ VOID
+ )
+{
+ FileBufferBackup ();
+
+ return EFI_SUCCESS;
+}
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.h b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.h
new file mode 100644
index 0000000000..c45859deda
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.h
@@ -0,0 +1,77 @@
+/** @file
+ Declares editor interface functions.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LIB_EDITOR_H_
+#define _LIB_EDITOR_H_
+
+#include "TextEditorTypes.h"
+
+/**
+ The initialization function for MainEditor.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+EFIAPI
+MainEditorInit (
+ VOID
+ );
+
+/**
+ The cleanup function for MainEditor.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+EFIAPI
+MainEditorCleanup (
+ VOID
+ );
+
+/**
+ Refresh the main editor component.
+**/
+VOID
+EFIAPI
+MainEditorRefresh (
+ VOID
+ );
+
+/**
+ Handle user key input. This routes to other functions for the actions.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+MainEditorKeyInput (
+ VOID
+ );
+
+/**
+ Backup function for MainEditor
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+MainEditorBackup (
+ VOID
+ );
+
+#endif
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.c b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.c
new file mode 100644
index 0000000000..ade78b8f90
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.c
@@ -0,0 +1,92 @@
+/** @file
+ Implementation of various string and line routines.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "TextEditor.h"
+#include "Misc.h"
+
+/**
+ Duplicate a EFI_EDITOR_LINE structure.
+
+ @param Src The line structure to copy from.
+
+ @retval NULL A memory allocation failed.
+ @return a pointer to the newly allcoated line.
+**/
+EFI_EDITOR_LINE *
+EFIAPI
+LineDup (
+ IN EFI_EDITOR_LINE *Src
+ )
+{
+ EFI_EDITOR_LINE *Dest;
+
+ //
+ // allocate for the line structure
+ //
+ Dest = AllocateZeroPool (sizeof (EFI_EDITOR_LINE));
+ if (Dest == NULL) {
+ return NULL;
+ }
+ //
+ // allocate and set the line buffer
+ //
+ Dest->Buffer = CatSPrint (NULL, L"%s", Src->Buffer);
+ if (Dest->Buffer == NULL) {
+ FreePool (Dest);
+ return NULL;
+ }
+
+ //
+ // set the other structure members
+ //
+ Dest->Signature = LINE_LIST_SIGNATURE;
+ Dest->Size = Src->Size;
+ Dest->TotalSize = Dest->Size;
+ Dest->Type = Src->Type;
+ Dest->Link = Src->Link;
+
+ return Dest;
+}
+
+/**
+ Free a EFI_EDITOR_LINE structure.
+
+ @param Src The line structure to free.
+**/
+VOID
+EFIAPI
+LineFree (
+ IN EFI_EDITOR_LINE *Src
+ )
+{
+ if (Src == NULL) {
+ return ;
+ }
+ //
+ // free the line buffer and then the line structure itself
+ //
+ SHELL_FREE_NON_NULL (Src->Buffer);
+ SHELL_FREE_NON_NULL (Src);
+
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.h b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.h
new file mode 100644
index 0000000000..583de3b42c
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.h
@@ -0,0 +1,52 @@
+/** @file
+ Declares generic editor helper functions.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LIB_MISC_H_
+#define _LIB_MISC_H_
+
+#include "TextEditorTypes.h"
+
+
+
+/**
+ Free a EFI_EDITOR_LINE structure.
+
+ @param Src The line structure to free.
+**/
+VOID
+EFIAPI
+LineFree (
+ IN EFI_EDITOR_LINE *Src
+ );
+
+/**
+ Duplicate a EFI_EDITOR_LINE structure.
+
+ @param Src The line structure to copy from.
+
+ @retval NULL A memory allocation failed.
+ @return a pointer to the newly allcoated line.
+**/
+EFI_EDITOR_LINE *
+EFIAPI
+LineDup (
+ IN EFI_EDITOR_LINE *Src
+ );
+
+
+
+
+
+
+#endif
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditStrings.uni b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditStrings.uni
new file mode 100644
index 0000000000..09a0d47b28
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditStrings.uni
Binary files differ
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditor.h b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditor.h
new file mode 100644
index 0000000000..774f01a291
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditor.h
@@ -0,0 +1,32 @@
+/** @file
+ Main include file for Edit shell Debug1 function.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _EFI_EDIT_H_
+#define _EFI_EDIT_H_
+
+#include "TextEditorTypes.h"
+
+#include "MainTextEditor.h"
+#include "FileBuffer.h"
+#include "EditTitleBar.h"
+#include "EditStatusBar.h"
+#include "EditInputBar.h"
+#include "EditMenuBar.h"
+#include "Misc.h"
+
+extern EFI_EDITOR_GLOBAL_EDITOR MainEditor;
+extern BOOLEAN EditorFirst;
+extern BOOLEAN EditorExit;
+
+#endif // _EFI_EDIT_H_
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditorTypes.h b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditorTypes.h
new file mode 100644
index 0000000000..9bcf39e028
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditorTypes.h
@@ -0,0 +1,102 @@
+/** @file
+ Declares editor types.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _EDITOR_TYPE_H_
+#define _EDITOR_TYPE_H_
+
+#include "UefiShellDebug1CommandsLib.h"
+#include "EditTitleBar.h"
+#include "EditMenuBar.h"
+
+#define MIN_POOL_SIZE 125
+#define MAX_STRING_LENGTH 127
+
+typedef struct {
+ UINTN Row;
+ UINTN Column;
+} EFI_EDITOR_POSITION;
+
+typedef
+EFI_STATUS
+(*EFI_MENU_ITEM_FUNCTION) (
+ VOID
+ );
+
+typedef enum {
+ NewLineTypeDefault,
+ NewLineTypeLineFeed,
+ NewLineTypeCarriageReturn,
+ NewLineTypeCarriageReturnLineFeed,
+ NewLineTypeLineFeedCarriageReturn,
+ NewLineTypeUnknown
+} EE_NEWLINE_TYPE;
+
+#define LINE_LIST_SIGNATURE 'eell'
+typedef struct _EFI_EDITOR_LINE {
+ UINTN Signature;
+ CHAR16 *Buffer;
+ UINTN Size; // unit is Unicode
+ UINTN TotalSize; // unit is Unicode, exclude CHAR_NULL
+ EE_NEWLINE_TYPE Type;
+ LIST_ENTRY Link;
+} EFI_EDITOR_LINE;
+
+typedef struct {
+ UINT32 Foreground : 4;
+ UINT32 Background : 4;
+} EFI_EDITOR_COLOR_ATTRIBUTES;
+
+typedef union {
+ EFI_EDITOR_COLOR_ATTRIBUTES Colors;
+ UINTN Data;
+} EFI_EDITOR_COLOR_UNION;
+
+typedef struct {
+ UINTN Columns;
+ UINTN Rows;
+} EFI_EDITOR_TEXT_MODE;
+
+typedef struct {
+ CHAR16 *FileName; // file name current edited in editor
+ EDIT_FILE_TYPE FileType; // Unicode file or ASCII file
+ LIST_ENTRY *ListHead; // list head of lines
+ EFI_EDITOR_LINE *Lines; // lines of current file
+ UINTN NumLines; // total line numbers
+ EFI_EDITOR_POSITION DisplayPosition; // cursor position in screen
+ EFI_EDITOR_POSITION FilePosition; // cursor position in file
+ EFI_EDITOR_POSITION MousePosition; // mouse position in screen
+ // file position of first byte displayed on screen
+ //
+ EFI_EDITOR_POSITION LowVisibleRange;
+
+ BOOLEAN FileModified; // file is modified or not
+ BOOLEAN ModeInsert; // input mode INS or OVR
+ BOOLEAN ReadOnly; // file is read-only or not
+ EFI_EDITOR_LINE *CurrentLine; // current line cursor is at
+} EFI_EDITOR_FILE_BUFFER;
+
+typedef struct {
+ EFI_EDITOR_FILE_BUFFER *FileBuffer;
+
+ EFI_EDITOR_COLOR_UNION ColorAttributes;
+ EFI_EDITOR_POSITION ScreenSize; // row number and column number
+ EFI_EDITOR_LINE *CutLine; // clip board
+ BOOLEAN MouseSupported;
+ EFI_SIMPLE_POINTER_PROTOCOL *MouseInterface;
+ INT32 MouseAccumulatorX;
+ INT32 MouseAccumulatorY;
+
+} EFI_EDITOR_GLOBAL_EDITOR;
+
+#endif
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.c b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.c
new file mode 100644
index 0000000000..04ebd24edc
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.c
@@ -0,0 +1,2695 @@
+/** @file
+ Defines HBufferImage - the view of the file that is visible at any point,
+ as well as the event handlers for editing the file
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HexEditor.h"
+
+extern EFI_HANDLE HImageHandleBackup;
+
+extern HEFI_EDITOR_FILE_IMAGE HFileImage;
+extern HEFI_EDITOR_DISK_IMAGE HDiskImage;
+extern HEFI_EDITOR_MEM_IMAGE HMemImage;
+
+extern HEFI_EDITOR_FILE_IMAGE HFileImageBackupVar;
+extern HEFI_EDITOR_DISK_IMAGE HDiskImageBackupVar;
+extern HEFI_EDITOR_MEM_IMAGE HMemImageBackupVar;
+
+extern BOOLEAN HEditorMouseAction;
+
+extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;
+extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditorBackupVar;
+
+HEFI_EDITOR_BUFFER_IMAGE HBufferImage;
+HEFI_EDITOR_BUFFER_IMAGE HBufferImageBackupVar;
+
+//
+// for basic initialization of HBufferImage
+//
+HEFI_EDITOR_BUFFER_IMAGE HBufferImageConst = {
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ {
+ 0,
+ 0
+ },
+ {
+ 0,
+ 0
+ },
+ {
+ 0,
+ 0
+ },
+ 0,
+ TRUE,
+ FALSE,
+ FileTypeNone,
+ NULL,
+ NULL,
+ NULL
+};
+
+//
+// the whole edit area needs to be refreshed
+//
+BOOLEAN HBufferImageNeedRefresh;
+
+//
+// only the current line in edit area needs to be refresh
+//
+BOOLEAN HBufferImageOnlyLineNeedRefresh;
+
+BOOLEAN HBufferImageMouseNeedRefresh;
+
+EFI_STATUS
+HBufferImageInit (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initialization function for HBufferImage
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_LOAD_ERROR
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // basically initialize the HBufferImage
+ //
+ CopyMem (&HBufferImage, &HBufferImageConst, sizeof (HBufferImage));
+
+ //
+ // INIT listhead
+ //
+ HBufferImage.ListHead = AllocateZeroPool (sizeof (LIST_ENTRY));
+ if (HBufferImage.ListHead == NULL) {
+ return EFI_LOAD_ERROR;
+ }
+
+ InitializeListHead (HBufferImage.ListHead);
+
+ HBufferImage.DisplayPosition.Row = 2;
+ HBufferImage.DisplayPosition.Column = 10;
+ HBufferImage.MousePosition.Row = 2;
+ HBufferImage.MousePosition.Column = 10;
+
+ HBufferImage.FileImage = &HFileImage;
+ HBufferImage.DiskImage = &HDiskImage;
+ HBufferImage.MemImage = &HMemImage;
+
+ HBufferImageNeedRefresh = FALSE;
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+ HBufferImageMouseNeedRefresh = FALSE;
+
+ HBufferImageBackupVar.FileImage = &HFileImageBackupVar;
+ HBufferImageBackupVar.DiskImage = &HDiskImageBackupVar;
+ HBufferImageBackupVar.MemImage = &HMemImageBackupVar;
+
+ Status = HFileImageInit ();
+ if (EFI_ERROR (Status)) {
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = HDiskImageInit ();
+ if (EFI_ERROR (Status)) {
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = HMemImageInit ();
+ if (EFI_ERROR (Status)) {
+ return EFI_LOAD_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HBufferImageBackup (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Backup function for HBufferImage
+ Only a few fields need to be backup.
+ This is for making the file buffer refresh
+ as few as possible.
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ HBufferImageBackupVar.MousePosition = HBufferImage.MousePosition;
+
+ HBufferImageBackupVar.BufferPosition = HBufferImage.BufferPosition;
+
+ HBufferImageBackupVar.Modified = HBufferImage.Modified;
+
+ HBufferImageBackupVar.BufferType = HBufferImage.BufferType;
+ HBufferImageBackupVar.LowVisibleRow = HBufferImage.LowVisibleRow;
+ HBufferImageBackupVar.HighBits = HBufferImage.HighBits;
+
+ //
+ // three kinds of buffer supported
+ // file buffer
+ // disk buffer
+ // memory buffer
+ //
+ switch (HBufferImage.BufferType) {
+ case FileTypeFileBuffer:
+ HFileImageBackup ();
+ break;
+
+ case FileTypeDiskBuffer:
+ HDiskImageBackup ();
+ break;
+
+ case FileTypeMemBuffer:
+ HMemImageBackup ();
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HBufferImageFreeLines (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Free all the lines in HBufferImage
+ Fields affected:
+ Lines
+ CurrentLine
+ NumLines
+ ListHead
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ HFreeLines (HBufferImage.ListHead, HBufferImage.Lines);
+
+ HBufferImage.Lines = NULL;
+ HBufferImage.CurrentLine = NULL;
+ HBufferImage.NumLines = 0;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HBufferImageCleanup (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Cleanup function for HBufferImage
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // free all the lines
+ //
+ Status = HBufferImageFreeLines ();
+
+ SHELL_FREE_NON_NULL (HBufferImage.ListHead);
+ HBufferImage.ListHead = NULL;
+
+ HFileImageCleanup ();
+ HDiskImageCleanup ();
+ HMemImageCleanup ();
+
+ return Status;
+
+}
+
+EFI_STATUS
+HBufferImagePrintLine (
+ IN HEFI_EDITOR_LINE *Line,
+ IN UINTN Row,
+ IN UINTN FRow,
+ IN HEFI_EDITOR_COLOR_UNION Orig,
+ IN HEFI_EDITOR_COLOR_UNION New
+
+ )
+/*++
+
+Routine Description:
+
+ Print Line on Row
+
+Arguments:
+
+ Line - Line to print
+ Row - Row on screen ( begin from 1 )
+ FRow - FRow
+ Orig - Orig
+ New - Light display
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+
+ UINTN Index;
+ UINTN Pos;
+ BOOLEAN Selected;
+ BOOLEAN BeNewColor;
+ UINTN RowStart;
+ UINTN RowEnd;
+ UINTN ColStart;
+ UINTN ColEnd;
+
+ //
+ // variable initialization
+ //
+ ColStart = 0;
+ ColEnd = 0;
+ Selected = FALSE;
+
+ //
+ // print the selected area in opposite color
+ //
+ if (HMainEditor.SelectStart != 0 && HMainEditor.SelectEnd != 0) {
+ RowStart = (HMainEditor.SelectStart - 1) / 0x10 + 1;
+ RowEnd = (HMainEditor.SelectEnd - 1) / 0x10 + 1;
+
+ ColStart = (HMainEditor.SelectStart - 1) % 0x10 + 1;
+ ColEnd = (HMainEditor.SelectEnd - 1) % 0x10 + 1;
+
+ if (FRow >= RowStart && FRow <= RowEnd) {
+ Selected = TRUE;
+ }
+
+ if (FRow > RowStart) {
+ ColStart = 1;
+ }
+
+ if (FRow < RowEnd) {
+ ColEnd = 0x10;
+ }
+
+ }
+
+ if (HEditorMouseAction == FALSE) {
+ ShellPrintEx (
+ 0,
+ (INT32)Row - 1,
+ L"%8X ",
+ ((INT32)Row - 2 + HBufferImage.LowVisibleRow - 1) * 0x10
+ );
+
+ }
+
+ for (Index = 0; Index < 0x08 && Index < Line->Size; Index++) {
+
+ BeNewColor = FALSE;
+
+ if (Selected) {
+ if (Index + 1 >= ColStart && Index + 1 <= ColEnd) {
+ BeNewColor = TRUE;
+ }
+ }
+
+ if (BeNewColor) {
+ gST->ConOut->SetAttribute (gST->ConOut, New.Data);
+ } else {
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
+ }
+
+ Pos = 10 + (Index * 3);
+ if (Line->Buffer[Index] < 0x10) {
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"0");
+ Pos++;
+ }
+
+ if (Index < 0x07) {
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]);
+ } else {
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]);
+ }
+
+ }
+
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
+ while (Index < 0x08) {
+ Pos = 10 + (Index * 3);
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
+ Index++;
+ }
+
+ while (Index < 0x10 && Index < Line->Size) {
+
+ BeNewColor = FALSE;
+
+ if (Selected) {
+ if (Index + 1 >= ColStart && Index + 1 <= ColEnd) {
+ BeNewColor = TRUE;
+ }
+ }
+
+ if (BeNewColor) {
+ gST->ConOut->SetAttribute (gST->ConOut, New.Data);
+ } else {
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
+ }
+
+ Pos = 10 + (Index * 3) + 1;
+ if (Line->Buffer[Index] < 0x10) {
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"0");
+ Pos++;
+ }
+
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]);
+ Index++;
+ }
+
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
+ while (Index < 0x10) {
+ Pos = 10 + (Index * 3) + 1;
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
+ Index++;
+ }
+ //
+ // restore the original color
+ //
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
+
+ //
+ // PRINT the buffer content
+ //
+ if (HEditorMouseAction == FALSE) {
+ for (Index = 0; Index < 0x10 && Index < Line->Size; Index++) {
+ Pos = ASCII_POSITION + Index;
+
+ //
+ // learned from shelle.h -- IsValidChar
+ //
+ if (Line->Buffer[Index] >= L' ') {
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%c", (CHAR16) Line->Buffer[Index]);
+ } else {
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%c", '.');
+ }
+ }
+
+ while (Index < 0x10) {
+ Pos = ASCII_POSITION + Index;
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
+ Index++;
+ }
+ }
+ //
+ // restore the abundant blank in hex edit area to original color
+ //
+ if (Selected) {
+ if (ColEnd <= 7) {
+ Pos = 10 + (ColEnd - 1) * 3 + 2;
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
+ } else if (ColEnd == 8) {
+ Pos = 10 + (ColEnd - 1) * 3 + 2;
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
+ } else {
+ Pos = 10 + (ColEnd - 1) * 3 + 3;
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+HBufferImageIsAtHighBits (
+ IN UINTN Column,
+ OUT UINTN *FCol
+ )
+{
+ Column -= 10;
+
+ //
+ // NOW AFTER THE SUB, Column start from 0
+ // 23 AND 24 ARE BOTH BLANK
+ //
+ if (Column == 24) {
+ *FCol = 0;
+ return FALSE;
+ }
+
+ if (Column > 24) {
+ Column--;
+ }
+
+ *FCol = (Column / 3) + 1;
+
+ if (!(Column % 3)) {
+ return TRUE;
+ }
+
+ if ((Column % 3 == 2)) {
+ *FCol = 0;
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+HBufferImageIsInSelectedArea (
+ IN UINTN MouseRow,
+ IN UINTN MouseCol
+ )
+{
+ UINTN FRow;
+ UINTN RowStart;
+ UINTN RowEnd;
+ UINTN ColStart;
+ UINTN ColEnd;
+ UINTN MouseColStart;
+ UINTN MouseColEnd;
+
+ //
+ // judge mouse position whether is in selected area
+ //
+ //
+ // not select
+ //
+ if (HMainEditor.SelectStart == 0 || HMainEditor.SelectEnd == 0) {
+ return FALSE;
+ }
+ //
+ // calculate the select area
+ //
+ RowStart = (HMainEditor.SelectStart - 1) / 0x10 + 1;
+ RowEnd = (HMainEditor.SelectEnd - 1) / 0x10 + 1;
+
+ ColStart = (HMainEditor.SelectStart - 1) % 0x10 + 1;
+ ColEnd = (HMainEditor.SelectEnd - 1) % 0x10 + 1;
+
+ FRow = HBufferImage.LowVisibleRow + MouseRow - 2;
+ if (FRow < RowStart || FRow > RowEnd) {
+ return FALSE;
+ }
+
+ if (FRow > RowStart) {
+ ColStart = 1;
+ }
+
+ if (FRow < RowEnd) {
+ ColEnd = 0x10;
+ }
+
+ MouseColStart = 10 + (ColStart - 1) * 3;
+ if (ColStart > 8) {
+ MouseColStart++;
+ }
+
+ MouseColEnd = 10 + (ColEnd - 1) * 3 + 1;
+ if (ColEnd > 8) {
+ MouseColEnd++;
+ }
+
+ if (MouseCol < MouseColStart || MouseCol > MouseColEnd) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+EFI_STATUS
+HBufferImageRestoreMousePosition (
+ VOID
+ )
+{
+ HEFI_EDITOR_COLOR_UNION Orig;
+ HEFI_EDITOR_COLOR_UNION New;
+ UINTN FRow;
+ UINTN FColumn;
+ BOOLEAN HasCharacter;
+ HEFI_EDITOR_LINE *CurrentLine;
+ HEFI_EDITOR_LINE *Line;
+ UINT8 Value;
+ BOOLEAN HighBits;
+
+ Line = NULL;
+ if (HMainEditor.MouseSupported) {
+
+ if (HBufferImageMouseNeedRefresh) {
+
+ HBufferImageMouseNeedRefresh = FALSE;
+
+ //
+ // if mouse position not moved and only mouse action
+ // so do not need to refresh mouse position
+ //
+ if ((
+ HBufferImage.MousePosition.Row == HBufferImageBackupVar.MousePosition.Row &&
+ HBufferImage.MousePosition.Column == HBufferImageBackupVar.MousePosition.Column
+ ) &&
+ HEditorMouseAction
+ ) {
+ return EFI_SUCCESS;
+ }
+ //
+ // backup the old screen attributes
+ //
+ Orig = HMainEditor.ColorAttributes;
+ New.Colors.Foreground = Orig.Colors.Background;
+ New.Colors.Background = Orig.Colors.Foreground;
+
+ //
+ // if in selected area,
+ // so do not need to refresh mouse
+ //
+ if (!HBufferImageIsInSelectedArea (
+ HBufferImageBackupVar.MousePosition.Row,
+ HBufferImageBackupVar.MousePosition.Column
+ )) {
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
+ } else {
+ gST->ConOut->SetAttribute (gST->ConOut, New.Data);
+ }
+ //
+ // clear the old mouse position
+ //
+ FRow = HBufferImage.LowVisibleRow + HBufferImageBackupVar.MousePosition.Row - 2;
+
+ HighBits = HBufferImageIsAtHighBits (
+ HBufferImageBackupVar.MousePosition.Column,
+ &FColumn
+ );
+
+ HasCharacter = TRUE;
+ if (FRow > HBufferImage.NumLines || FColumn == 0) {
+ HasCharacter = FALSE;
+ } else {
+ CurrentLine = HBufferImage.CurrentLine;
+ Line = HMoveLine (FRow - HBufferImage.BufferPosition.Row);
+
+ if (FColumn > Line->Size) {
+ HasCharacter = FALSE;
+ }
+
+ HBufferImage.CurrentLine = CurrentLine;
+ }
+
+ ShellPrintEx (
+ (INT32)HBufferImageBackupVar.MousePosition.Column - 1,
+ (INT32)HBufferImageBackupVar.MousePosition.Row - 1,
+ L" "
+ );
+
+ if (HasCharacter) {
+ if (HighBits) {
+ Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf0);
+ Value = (UINT8) (Value >> 4);
+ } else {
+ Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf);
+ }
+
+ ShellPrintEx (
+ (INT32)HBufferImageBackupVar.MousePosition.Column - 1,
+ (INT32)HBufferImageBackupVar.MousePosition.Row - 1,
+ L"%x",
+ Value
+ );
+ }
+
+ if (!HBufferImageIsInSelectedArea (
+ HBufferImage.MousePosition.Row,
+ HBufferImage.MousePosition.Column
+ )) {
+ gST->ConOut->SetAttribute (gST->ConOut, New.Data);
+ } else {
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
+ }
+ //
+ // clear the old mouse position
+ //
+ FRow = HBufferImage.LowVisibleRow + HBufferImage.MousePosition.Row - 2;
+
+ HighBits = HBufferImageIsAtHighBits (
+ HBufferImage.MousePosition.Column,
+ &FColumn
+ );
+
+ HasCharacter = TRUE;
+ if (FRow > HBufferImage.NumLines || FColumn == 0) {
+ HasCharacter = FALSE;
+ } else {
+ CurrentLine = HBufferImage.CurrentLine;
+ Line = HMoveLine (FRow - HBufferImage.BufferPosition.Row);
+
+ if (FColumn > Line->Size) {
+ HasCharacter = FALSE;
+ }
+
+ HBufferImage.CurrentLine = CurrentLine;
+ }
+
+ ShellPrintEx (
+ (INT32)HBufferImage.MousePosition.Column - 1,
+ (INT32)HBufferImage.MousePosition.Row - 1,
+ L" "
+ );
+
+ if (HasCharacter) {
+ if (HighBits) {
+ Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf0);
+ Value = (UINT8) (Value >> 4);
+ } else {
+ Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf);
+ }
+
+ ShellPrintEx (
+ (INT32)HBufferImage.MousePosition.Column - 1,
+ (INT32)HBufferImage.MousePosition.Row - 1,
+ L"%x",
+ Value
+ );
+ }
+ //
+ // end of HasCharacter
+ //
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
+ }
+ //
+ // end of MouseNeedRefresh
+ //
+ }
+ //
+ // end of MouseSupported
+ //
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HBufferImageRestorePosition (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Set cursor position according to HBufferImage.DisplayPosition.
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ //
+ // set cursor position
+ //
+ gST->ConOut->SetCursorPosition (
+ gST->ConOut,
+ HBufferImage.DisplayPosition.Column - 1,
+ HBufferImage.DisplayPosition.Row - 1
+ );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HBufferImageRefresh (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Refresh function for HBufferImage
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_LOAD_ERROR
+
+--*/
+{
+ LIST_ENTRY *Link;
+ HEFI_EDITOR_LINE *Line;
+ UINTN Row;
+ HEFI_EDITOR_COLOR_UNION Orig;
+ HEFI_EDITOR_COLOR_UNION New;
+
+ UINTN StartRow;
+ UINTN EndRow;
+ UINTN FStartRow;
+ UINTN FEndRow;
+ UINTN Tmp;
+
+ Orig = HMainEditor.ColorAttributes;
+ New.Colors.Foreground = Orig.Colors.Background;
+ New.Colors.Background = Orig.Colors.Foreground;
+
+ //
+ // if it's the first time after editor launch, so should refresh
+ //
+ if (HEditorFirst == FALSE) {
+ //
+ // no definite required refresh
+ // and file position displayed on screen has not been changed
+ //
+ if (HBufferImageNeedRefresh == FALSE &&
+ HBufferImageOnlyLineNeedRefresh == FALSE &&
+ HBufferImageBackupVar.LowVisibleRow == HBufferImage.LowVisibleRow
+ ) {
+ HBufferImageRestoreMousePosition ();
+ HBufferImageRestorePosition ();
+ return EFI_SUCCESS;
+ }
+ }
+
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);
+
+ //
+ // only need to refresh current line
+ //
+ if (HBufferImageOnlyLineNeedRefresh == TRUE && HBufferImageBackupVar.LowVisibleRow == HBufferImage.LowVisibleRow) {
+
+ HBufferImagePrintLine (
+ HBufferImage.CurrentLine,
+ HBufferImage.DisplayPosition.Row,
+ HBufferImage.BufferPosition.Row,
+ Orig,
+ New
+ );
+ } else {
+ //
+ // the whole edit area need refresh
+ //
+ if (HEditorMouseAction && HMainEditor.SelectStart != 0 && HMainEditor.SelectEnd != 0) {
+ if (HMainEditor.SelectStart != HMainEditorBackupVar.SelectStart) {
+ if (HMainEditor.SelectStart >= HMainEditorBackupVar.SelectStart && HMainEditorBackupVar.SelectStart != 0) {
+ StartRow = (HMainEditorBackupVar.SelectStart - 1) / 0x10 + 1;
+ } else {
+ StartRow = (HMainEditor.SelectStart - 1) / 0x10 + 1;
+ }
+ } else {
+ StartRow = (HMainEditor.SelectStart - 1) / 0x10 + 1;
+ }
+
+ if (HMainEditor.SelectEnd <= HMainEditorBackupVar.SelectEnd) {
+ EndRow = (HMainEditorBackupVar.SelectEnd - 1) / 0x10 + 1;
+ } else {
+ EndRow = (HMainEditor.SelectEnd - 1) / 0x10 + 1;
+ }
+ //
+ // swap
+ //
+ if (StartRow > EndRow) {
+ Tmp = StartRow;
+ StartRow = EndRow;
+ EndRow = Tmp;
+ }
+
+ FStartRow = StartRow;
+ FEndRow = EndRow;
+
+ StartRow = 2 + StartRow - HBufferImage.LowVisibleRow;
+ EndRow = 2 + EndRow - HBufferImage.LowVisibleRow;
+
+ } else {
+ //
+ // not mouse selection actions
+ //
+ FStartRow = HBufferImage.LowVisibleRow;
+ StartRow = 2;
+ EndRow = (HMainEditor.ScreenSize.Row - 4);
+ }
+ //
+ // no line
+ //
+ if (HBufferImage.Lines == NULL) {
+ HBufferImageRestoreMousePosition ();
+ HBufferImageRestorePosition ();
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+ return EFI_SUCCESS;
+ }
+ //
+ // get the first line that will be displayed
+ //
+ Line = HMoveLine (FStartRow - HBufferImage.BufferPosition.Row);
+ if (Line == NULL) {
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+ return EFI_LOAD_ERROR;
+ }
+
+ Link = &(Line->Link);
+ Row = StartRow;
+ do {
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+
+ //
+ // print line at row
+ //
+ HBufferImagePrintLine (
+ Line,
+ Row,
+ HBufferImage.LowVisibleRow + Row - 2,
+ Orig,
+ New
+ );
+
+ Link = Link->ForwardLink;
+ Row++;
+ } while (Link != HBufferImage.ListHead && Row <= EndRow);
+
+ while (Row <= EndRow) {
+ HEditorClearLine (Row);
+ Row++;
+ }
+ //
+ // while not file end and not screen full
+ //
+ }
+
+ HBufferImageRestoreMousePosition ();
+ HBufferImageRestorePosition ();
+
+ HBufferImageNeedRefresh = FALSE;
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HBufferImageRead (
+ IN CONST CHAR16 *FileName,
+ IN CONST CHAR16 *DiskName,
+ IN UINTN DiskOffset,
+ IN UINTN DiskSize,
+ IN UINTN MemOffset,
+ IN UINTN MemSize,
+ IN EDIT_FILE_TYPE BufferType,
+ IN BOOLEAN Recover
+ )
+{
+ EFI_STATUS Status;
+ EDIT_FILE_TYPE BufferTypeBackup;
+
+ //
+ // variable initialization
+ //
+ Status = EFI_SUCCESS;
+
+ //
+ // three types of buffer supported
+ // file buffer
+ // disk buffer
+ // memory buffer
+ //
+ BufferTypeBackup = HBufferImage.BufferType;
+
+ switch (BufferType) {
+ case FileTypeFileBuffer:
+ Status = HFileImageRead (FileName, Recover);
+ break;
+
+ case FileTypeDiskBuffer:
+ Status = HDiskImageRead (DiskName, DiskOffset, DiskSize, Recover);
+ break;
+
+ case FileTypeMemBuffer:
+ Status = HMemImageRead (MemOffset, MemSize, Recover);
+ break;
+ }
+
+ if (EFI_ERROR (Status)) {
+ HBufferImage.BufferType = BufferTypeBackup;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+HBufferImageSave (
+ IN CHAR16 *FileName,
+ IN CHAR16 *DiskName,
+ IN UINTN DiskOffset,
+ IN UINTN DiskSize,
+ IN UINTN MemOffset,
+ IN UINTN MemSize,
+ IN EDIT_FILE_TYPE BufferType
+ )
+{
+ EFI_STATUS Status;
+ EDIT_FILE_TYPE BufferTypeBackup;
+
+ //
+ // variable initialization
+ //
+ Status = EFI_SUCCESS;
+ BufferTypeBackup = HBufferImage.BufferType;
+
+ switch (HBufferImage.BufferType) {
+ //
+ // file buffer
+ //
+ case FileTypeFileBuffer:
+ Status = HFileImageSave (FileName);
+ break;
+
+ //
+ // disk buffer
+ //
+ case FileTypeDiskBuffer:
+ Status = HDiskImageSave (DiskName, DiskOffset, DiskSize);
+ break;
+
+ //
+ // memory buffer
+ //
+ case FileTypeMemBuffer:
+ Status = HMemImageSave (MemOffset, MemSize);
+ break;
+ }
+
+ if (EFI_ERROR (Status)) {
+ HBufferImage.BufferType = BufferTypeBackup;
+ }
+
+ return Status;
+}
+
+HEFI_EDITOR_LINE *
+HBufferImageCreateLine (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Create a new line and append it to the line list
+ Fields affected:
+ NumLines
+ Lines
+
+Arguments:
+
+ None
+
+Returns:
+
+ NULL -- create line failed
+ Not NULL -- the line created
+
+--*/
+{
+ HEFI_EDITOR_LINE *Line;
+
+ //
+ // allocate for line structure
+ //
+ Line = AllocateZeroPool (sizeof (HEFI_EDITOR_LINE));
+ if (Line == NULL) {
+ return NULL;
+ }
+
+ Line->Signature = EFI_EDITOR_LINE_LIST;
+ Line->Size = 0;
+
+ HBufferImage.NumLines++;
+
+ //
+ // insert to line list
+ //
+ InsertTailList (HBufferImage.ListHead, &Line->Link);
+
+ if (HBufferImage.Lines == NULL) {
+ HBufferImage.Lines = CR (
+ HBufferImage.ListHead->ForwardLink,
+ HEFI_EDITOR_LINE,
+ Link,
+ EFI_EDITOR_LINE_LIST
+ );
+ }
+
+ return Line;
+}
+
+EFI_STATUS
+HBufferImageFree (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Function called when load a new file in. It will free all the old lines
+ and set FileModified field to FALSE
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ //
+ // free all lines
+ //
+ HBufferImageFreeLines ();
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HBufferImageHandleInput (
+ IN EFI_INPUT_KEY *Key
+ )
+/*++
+
+Routine Description:
+
+ Dispatch input to different handler
+
+Arguments:
+
+ Key -- input key
+ the keys can be:
+ ASCII KEY
+ Backspace/Delete
+ Direction key: up/down/left/right/pgup/pgdn
+ Home/End
+ INS
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_LOAD_ERROR
+ EFI_OUT_OF_RESOURCES
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ switch (Key->ScanCode) {
+ //
+ // ordinary key
+ //
+ case SCAN_NULL:
+ Status = HBufferImageDoCharInput (Key->UnicodeChar);
+ break;
+
+ //
+ // up arrow
+ //
+ case SCAN_UP:
+ Status = HBufferImageScrollUp ();
+ break;
+
+ //
+ // down arrow
+ //
+ case SCAN_DOWN:
+ Status = HBufferImageScrollDown ();
+ break;
+
+ //
+ // right arrow
+ //
+ case SCAN_RIGHT:
+ Status = HBufferImageScrollRight ();
+ break;
+
+ //
+ // left arrow
+ //
+ case SCAN_LEFT:
+ Status = HBufferImageScrollLeft ();
+ break;
+
+ //
+ // page up
+ //
+ case SCAN_PAGE_UP:
+ Status = HBufferImagePageUp ();
+ break;
+
+ //
+ // page down
+ //
+ case SCAN_PAGE_DOWN:
+ Status = HBufferImagePageDown ();
+ break;
+
+ //
+ // delete
+ //
+ case SCAN_DELETE:
+ Status = HBufferImageDoDelete ();
+ break;
+
+ //
+ // home
+ //
+ case SCAN_HOME:
+ Status = HBufferImageHome ();
+ break;
+
+ //
+ // end
+ //
+ case SCAN_END:
+ Status = HBufferImageEnd ();
+ break;
+
+ default:
+ Status = StatusBarSetStatusString (L"Unknown Command");
+ break;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+HBufferImageDoCharInput (
+ IN CHAR16 Char
+ )
+/*++
+
+Routine Description:
+
+ ASCII key + Backspace + return
+
+Arguments:
+
+ Char -- input char
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_LOAD_ERROR
+ EFI_OUT_OF_RESOURCES
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ switch (Char) {
+ case 0:
+ break;
+
+ case 0x08:
+ Status = HBufferImageDoBackspace ();
+ break;
+
+ case 0x09:
+ case 0x0a:
+ case 0x0d:
+ //
+ // Tabs, Returns are thought as nothing
+ //
+ break;
+
+ default:
+ //
+ // DEAL WITH ASCII CHAR, filter out thing like ctrl+f
+ //
+ if (Char > 127 || Char < 32) {
+ Status = StatusBarSetStatusString (L"Unknown Command");
+ } else {
+ Status = HBufferImageAddChar (Char);
+ }
+
+ break;
+ }
+
+ return Status;
+}
+
+INTN
+HBufferImageCharToHex (
+ IN CHAR16 Char
+ )
+/*++
+
+Routine Description:
+
+ change char to int value based on Hex
+
+Arguments:
+
+ Char -- input char
+
+Returns:
+
+ int value;
+
+
+--*/
+{
+ //
+ // change the character to hex
+ //
+ if (Char >= L'0' && Char <= L'9') {
+ return (INTN) (Char - L'0');
+ }
+
+ if (Char >= L'a' && Char <= L'f') {
+ return (INTN) (Char - L'a' + 10);
+ }
+
+ if (Char >= L'A' && Char <= L'F') {
+ return (INTN) (Char - L'A' + 10);
+ }
+
+ return -1;
+}
+
+EFI_STATUS
+HBufferImageAddChar (
+ IN CHAR16 Char
+ )
+/*++
+
+Routine Description:
+
+ Add character
+
+Arguments:
+
+ Char -- input char
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_OUT_OF_RESOURCES
+
+--*/
+{
+ HEFI_EDITOR_LINE *Line;
+ HEFI_EDITOR_LINE *NewLine;
+ INTN Value;
+ UINT8 Old;
+ UINTN FRow;
+ UINTN FCol;
+ BOOLEAN High;
+
+ Value = HBufferImageCharToHex (Char);
+
+ //
+ // invalid input
+ //
+ if (Value == -1) {
+ return EFI_SUCCESS;
+ }
+
+ Line = HBufferImage.CurrentLine;
+ FRow = HBufferImage.BufferPosition.Row;
+ FCol = HBufferImage.BufferPosition.Column;
+ High = HBufferImage.HighBits;
+
+ //
+ // only needs to refresh current line
+ //
+ HBufferImageOnlyLineNeedRefresh = TRUE;
+
+ //
+ // not a full line and beyond the last character
+ //
+ if (FCol > Line->Size) {
+ //
+ // cursor always at high 4 bits
+ // and always put input to the low 4 bits
+ //
+ Line->Buffer[Line->Size] = (UINT8) Value;
+ Line->Size++;
+ High = FALSE;
+ } else {
+
+ Old = Line->Buffer[FCol - 1];
+
+ //
+ // always put the input to the low 4 bits
+ //
+ Old = (UINT8) (Old & 0x0f);
+ Old = (UINT8) (Old << 4);
+ Old = (UINT8) (Value + Old);
+ Line->Buffer[FCol - 1] = Old;
+
+ //
+ // at the low 4 bits of the last character of a full line
+ // so if no next line, need to create a new line
+ //
+ if (High == FALSE && FCol == 0x10) {
+
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+ HBufferImageNeedRefresh = TRUE;
+
+ if (Line->Link.ForwardLink == HBufferImage.ListHead) {
+ //
+ // last line
+ //
+ // create a new line
+ //
+ NewLine = HBufferImageCreateLine ();
+ if (NewLine == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // end of NULL
+ //
+ }
+ //
+ // end of == ListHead
+ //
+ }
+ //
+ // end of == 0x10
+ //
+ // if already at end of this line, scroll it to the start of next line
+ //
+ if (FCol == 0x10 && High == FALSE) {
+ //
+ // definitely has next line
+ //
+ FRow++;
+ FCol = 1;
+ High = TRUE;
+ } else {
+ //
+ // if not at end of this line, just move to next column
+ //
+ if (!High) {
+ FCol++;
+ }
+
+ if (High) {
+ High = FALSE;
+ } else {
+ High = TRUE;
+ }
+
+ }
+ //
+ // end of ==FALSE
+ //
+ }
+ //
+ // move cursor to right
+ //
+ HBufferImageMovePosition (FRow, FCol, High);
+
+ if (!HBufferImage.Modified) {
+ HBufferImage.Modified = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+HInCurrentScreen (
+ IN UINTN FileRow
+ )
+/*++
+
+Routine Description:
+
+ Check user specified FileRow and FileCol is in current screen
+
+Arguments:
+
+ FileRow -- Row of file position ( start from 1 )
+
+
+Returns:
+
+ TRUE
+ FALSE
+
+--*/
+{
+ if (FileRow >= HBufferImage.LowVisibleRow && FileRow <= HBufferImage.LowVisibleRow + (HMainEditor.ScreenSize.Row - 5) - 1) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+HAboveCurrentScreen (
+ IN UINTN FileRow
+ )
+/*++
+
+Routine Description:
+
+ Check user specified FileRow is above current screen
+
+Arguments:
+
+ FileRow -- Row of file position ( start from 1 )
+
+Returns:
+
+ TRUE
+ FALSE
+
+--*/
+{
+ if (FileRow < HBufferImage.LowVisibleRow) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+HUnderCurrentScreen (
+ IN UINTN FileRow
+ )
+/*++
+
+Routine Description:
+
+ Check user specified FileRow is under current screen
+
+Arguments:
+
+ FileRow -- Row of file position ( start from 1 )
+
+Returns:
+
+ TRUE
+ FALSE
+
+--*/
+{
+ if (FileRow > HBufferImage.LowVisibleRow + (HMainEditor.ScreenSize.Row - 5) - 1) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+VOID
+HBufferImageMovePosition (
+ IN UINTN NewFilePosRow,
+ IN UINTN NewFilePosCol,
+ IN BOOLEAN HighBits
+ )
+/*++
+
+Routine Description:
+
+ According to cursor's file position, adjust screen display
+
+Arguments:
+
+ NewFilePosRow -- Row of file position ( start from 1 )
+ NewFilePosCol -- Column of file position ( start from 1 )
+ HighBits -- cursor will on high4 bits or low4 bits
+
+Returns:
+
+ None
+
+--*/
+{
+ INTN RowGap;
+ UINTN Abs;
+ BOOLEAN Above;
+ BOOLEAN Under;
+ UINTN NewDisplayCol;
+
+ //
+ // CALCULATE gap between current file position and new file position
+ //
+ RowGap = NewFilePosRow - HBufferImage.BufferPosition.Row;
+
+ Under = HUnderCurrentScreen (NewFilePosRow);
+ Above = HAboveCurrentScreen (NewFilePosRow);
+
+ HBufferImage.HighBits = HighBits;
+
+ //
+ // if is below current screen
+ //
+ if (Under) {
+ //
+ // display row will be unchanged
+ //
+ HBufferImage.BufferPosition.Row = NewFilePosRow;
+ } else {
+ if (Above) {
+ //
+ // has enough above line, so display row unchanged
+ // not has enough above lines, so the first line is
+ // at the first display line
+ //
+ if (NewFilePosRow < (HBufferImage.DisplayPosition.Row - 2 + 1)) {
+ HBufferImage.DisplayPosition.Row = NewFilePosRow + 2 - 1;
+ }
+
+ HBufferImage.BufferPosition.Row = NewFilePosRow;
+ } else {
+ //
+ // in current screen
+ //
+ HBufferImage.BufferPosition.Row = NewFilePosRow;
+ if (RowGap <= 0) {
+ Abs = -RowGap;
+ HBufferImage.DisplayPosition.Row -= Abs;
+ } else {
+ HBufferImage.DisplayPosition.Row += RowGap;
+ }
+
+ }
+ }
+
+ HBufferImage.LowVisibleRow = HBufferImage.BufferPosition.Row - (HBufferImage.DisplayPosition.Row - 2);
+
+ //
+ // always in current screen
+ //
+ HBufferImage.BufferPosition.Column = NewFilePosCol;
+
+ NewDisplayCol = 10 + (NewFilePosCol - 1) * 3;
+ if (NewFilePosCol > 0x8) {
+ NewDisplayCol++;
+ }
+
+ if (HighBits == FALSE) {
+ NewDisplayCol++;
+ }
+
+ HBufferImage.DisplayPosition.Column = NewDisplayCol;
+
+ //
+ // let CurrentLine point to correct line;
+ //
+ HBufferImage.CurrentLine = HMoveCurrentLine (RowGap);
+
+}
+
+EFI_STATUS
+HBufferImageScrollRight (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Scroll cursor to right
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ HEFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+
+ //
+ // scroll right will always move to the high4 bits of the next character
+ //
+ HBufferImageNeedRefresh = FALSE;
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+
+ Line = HBufferImage.CurrentLine;
+
+ FRow = HBufferImage.BufferPosition.Row;
+ FCol = HBufferImage.BufferPosition.Column;
+
+ //
+ // this line is not full and no next line
+ //
+ if (FCol > Line->Size) {
+ return EFI_SUCCESS;
+ }
+ //
+ // if already at end of this line, scroll it to the start of next line
+ //
+ if (FCol == 0x10) {
+ //
+ // has next line
+ //
+ if (Line->Link.ForwardLink != HBufferImage.ListHead) {
+ FRow++;
+ FCol = 1;
+
+ } else {
+ return EFI_SUCCESS;
+ }
+ } else {
+ //
+ // if not at end of this line, just move to next column
+ //
+ FCol++;
+
+ }
+
+ HBufferImageMovePosition (FRow, FCol, TRUE);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HBufferImageScrollLeft (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Scroll cursor to left
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+
+ HEFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+
+ HBufferImageNeedRefresh = FALSE;
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+
+ Line = HBufferImage.CurrentLine;
+
+ FRow = HBufferImage.BufferPosition.Row;
+ FCol = HBufferImage.BufferPosition.Column;
+
+ //
+ // if already at start of this line, so move to the end of previous line
+ //
+ if (FCol <= 1) {
+ //
+ // has previous line
+ //
+ if (Line->Link.BackLink != HBufferImage.ListHead) {
+ FRow--;
+ Line = CR (Line->Link.BackLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+ FCol = Line->Size;
+ } else {
+ return EFI_SUCCESS;
+ }
+ } else {
+ //
+ // if not at start of this line, just move to previous column
+ //
+ FCol--;
+ }
+
+ HBufferImageMovePosition (FRow, FCol, TRUE);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HBufferImageScrollDown (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Scroll cursor to the next line
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ HEFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+ BOOLEAN HighBits;
+
+ Line = HBufferImage.CurrentLine;
+
+ FRow = HBufferImage.BufferPosition.Row;
+ FCol = HBufferImage.BufferPosition.Column;
+ HighBits = HBufferImage.HighBits;
+
+ //
+ // has next line
+ //
+ if (Line->Link.ForwardLink != HBufferImage.ListHead) {
+ FRow++;
+ Line = CR (Line->Link.ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+
+ //
+ // if the next line is not that long, so move to end of next line
+ //
+ if (FCol > Line->Size) {
+ FCol = Line->Size + 1;
+ HighBits = TRUE;
+ }
+
+ } else {
+ return EFI_SUCCESS;
+ }
+
+ HBufferImageMovePosition (FRow, FCol, HighBits);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HBufferImageScrollUp (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Scroll cursor to previous line
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ HEFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+
+ Line = HBufferImage.CurrentLine;
+
+ FRow = HBufferImage.BufferPosition.Row;
+ FCol = HBufferImage.BufferPosition.Column;
+
+ //
+ // has previous line
+ //
+ if (Line->Link.BackLink != HBufferImage.ListHead) {
+ FRow--;
+
+ } else {
+ return EFI_SUCCESS;
+ }
+
+ HBufferImageMovePosition (FRow, FCol, HBufferImage.HighBits);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HBufferImagePageDown (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Scroll cursor to next page
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ HEFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+ UINTN Gap;
+ BOOLEAN HighBits;
+
+ Line = HBufferImage.CurrentLine;
+
+ FRow = HBufferImage.BufferPosition.Row;
+ FCol = HBufferImage.BufferPosition.Column;
+ HighBits = HBufferImage.HighBits;
+
+ //
+ // has next page
+ //
+ if (HBufferImage.NumLines >= FRow + (HMainEditor.ScreenSize.Row - 5)) {
+ Gap = (HMainEditor.ScreenSize.Row - 5);
+ } else {
+ //
+ // MOVE CURSOR TO LAST LINE
+ //
+ Gap = HBufferImage.NumLines - FRow;
+ }
+ //
+ // get correct line
+ //
+ Line = HMoveLine (Gap);
+
+ //
+ // if that line, is not that long, so move to the end of that line
+ //
+ if (FCol > Line->Size) {
+ FCol = Line->Size + 1;
+ HighBits = TRUE;
+ }
+
+ FRow += Gap;
+
+ HBufferImageMovePosition (FRow, FCol, HighBits);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HBufferImagePageUp (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Scroll cursor to previous page
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ HEFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+ UINTN Gap;
+ INTN Retreat;
+
+ Line = HBufferImage.CurrentLine;
+
+ FRow = HBufferImage.BufferPosition.Row;
+ FCol = HBufferImage.BufferPosition.Column;
+
+ //
+ // has previous page
+ //
+ if (FRow > (HMainEditor.ScreenSize.Row - 5)) {
+ Gap = (HMainEditor.ScreenSize.Row - 5);
+ } else {
+ //
+ // the first line of file will displayed on the first line of screen
+ //
+ Gap = FRow - 1;
+ }
+
+ Retreat = Gap;
+ Retreat = -Retreat;
+
+ //
+ // get correct line
+ //
+ Line = HMoveLine (Retreat);
+
+ FRow -= Gap;
+
+ HBufferImageMovePosition (FRow, FCol, HBufferImage.HighBits);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HBufferImageHome (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Scroll cursor to start of line
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ HEFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+ BOOLEAN HighBits;
+
+ Line = HBufferImage.CurrentLine;
+
+ //
+ // curosr will at the high bit
+ //
+ FRow = HBufferImage.BufferPosition.Row;
+ FCol = 1;
+ HighBits = TRUE;
+
+ //
+ // move cursor position
+ //
+ HBufferImageMovePosition (FRow, FCol, HighBits);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HBufferImageEnd (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Scroll cursor to end of line
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ HEFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+ BOOLEAN HighBits;
+
+ //
+ // need refresh mouse
+ //
+ HBufferImageMouseNeedRefresh = TRUE;
+
+ Line = HBufferImage.CurrentLine;
+
+ FRow = HBufferImage.BufferPosition.Row;
+
+ if (Line->Size == 0x10) {
+ FCol = Line->Size;
+ HighBits = FALSE;
+ } else {
+ FCol = Line->Size + 1;
+ HighBits = TRUE;
+ }
+ //
+ // move cursor position
+ //
+ HBufferImageMovePosition (FRow, FCol, HighBits);
+
+ return EFI_SUCCESS;
+}
+
+UINTN
+HBufferImageGetTotalSize (
+ VOID
+ )
+{
+ UINTN Size;
+
+ HEFI_EDITOR_LINE *Line;
+
+ //
+ // calculate the total size of whole line list's buffer
+ //
+ if (HBufferImage.Lines == NULL) {
+ return 0;
+ }
+
+ Line = CR (
+ HBufferImage.ListHead->BackLink,
+ HEFI_EDITOR_LINE,
+ Link,
+ EFI_EDITOR_LINE_LIST
+ );
+ //
+ // one line at most 0x10
+ //
+ Size = 0x10 * (HBufferImage.NumLines - 1) + Line->Size;
+
+ return Size;
+}
+
+EFI_STATUS
+HBufferImageDeleteCharacterFromBuffer (
+ IN UINTN Pos,
+ IN UINTN Count,
+ OUT UINT8 *DeleteBuffer
+ )
+/*++
+Routine Description:
+
+ Delete character from buffer
+
+Arguments:
+
+ Pos - Position, Pos starting from 0
+ Count - Count
+ DeleteBuffer - DeleteBuffer
+
+Returns:
+
+ EFI_SUCCESS Success
+
+--*/
+{
+ UINTN Index;
+
+ VOID *Buffer;
+ UINT8 *BufferPtr;
+ UINTN Size;
+
+ HEFI_EDITOR_LINE *Line;
+ LIST_ENTRY *Link;
+ UINTN StartRow;
+
+ UINTN OldFCol;
+ UINTN OldFRow;
+ UINTN OldPos;
+
+ UINTN NewPos;
+
+ EFI_STATUS Status;
+
+ //
+ // get the line that start position is at
+ //
+ StartRow = Pos / 0x10;
+
+ Size = HBufferImageGetTotalSize ();
+
+ if (Size < Count) {
+ return EFI_LOAD_ERROR;
+ }
+
+ if (Size == 0) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // relocate all the HBufferImage fields
+ //
+ OldFRow = HBufferImage.BufferPosition.Row;
+ OldFCol = HBufferImage.BufferPosition.Column;
+ OldPos = (OldFRow - 1) * 0x10 + OldFCol - 1;
+
+ if (Pos > 0) {
+ //
+ // has character before it,
+ // so locate according to block's previous character
+ //
+ NewPos = Pos - 1;
+
+ } else {
+ //
+ // has no character before it,
+ // so locate according to block's next character
+ //
+ NewPos = 0;
+ }
+
+ HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);
+
+ Buffer = AllocateZeroPool (Size);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ HBufferImageListToBuffer (Buffer, Size);
+
+ BufferPtr = (UINT8 *) Buffer;
+
+ //
+ // pass deleted buffer out
+ //
+ if (DeleteBuffer != NULL) {
+ for (Index = 0; Index < Count; Index++) {
+ DeleteBuffer[Index] = BufferPtr[Pos + Index];
+ }
+ }
+ //
+ // delete the part from Pos
+ //
+ for (Index = Pos; Index < Size - Count; Index++) {
+ BufferPtr[Index] = BufferPtr[Index + Count];
+ }
+
+ Size -= Count;
+
+ HBufferImageFreeLines ();
+
+ Status = HBufferImageBufferToList (Buffer, Size);
+ FreePool (Buffer);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Link = HMainEditor.BufferImage->ListHead->ForwardLink;
+ for (Index = 0; Index < NewPos / 0x10; Index++) {
+ Link = Link->ForwardLink;
+ }
+
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+ HBufferImage.CurrentLine = Line;
+
+ //
+ // if current cursor position if inside select area
+ // then move it to the block's NEXT character
+ //
+ if (OldPos >= Pos && OldPos < (Pos + Count)) {
+ NewPos = Pos;
+ } else {
+ if (OldPos < Pos) {
+ NewPos = OldPos;
+ } else {
+ NewPos = OldPos - Count;
+ }
+ }
+
+ HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HBufferImageAddCharacterToBuffer (
+ IN UINTN Pos,
+ IN UINTN Count,
+ IN UINT8 *AddBuffer
+ )
+/*++'
+Routine Description:
+
+ Add character to buffer, add before pos
+
+Arguments:
+
+ Pos - Position, Pos starting from 0
+ Count - Count
+ AddBuffer - Add buffer
+
+Returns:
+
+ EFI_SUCCESS Success
+
+--*/
+{
+ INTN Index;
+
+ VOID *Buffer;
+ UINT8 *BufferPtr;
+ UINTN Size;
+
+ HEFI_EDITOR_LINE *Line;
+
+ LIST_ENTRY *Link;
+ UINTN StartRow;
+
+ UINTN OldFCol;
+ UINTN OldFRow;
+ UINTN OldPos;
+
+ UINTN NewPos;
+
+ //
+ // get the line that start position is at
+ //
+ StartRow = Pos / 0x10;
+
+ Size = HBufferImageGetTotalSize ();
+
+ //
+ // relocate all the HBufferImage fields
+ //
+ OldFRow = HBufferImage.BufferPosition.Row;
+ OldFCol = HBufferImage.BufferPosition.Column;
+ OldPos = (OldFRow - 1) * 0x10 + OldFCol - 1;
+
+ //
+ // move cursor before Pos
+ //
+ if (Pos > 0) {
+ NewPos = Pos - 1;
+ } else {
+ NewPos = 0;
+ }
+
+ HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);
+
+ Buffer = AllocateZeroPool (Size + Count);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ HBufferImageListToBuffer (Buffer, Size);
+
+ BufferPtr = (UINT8 *) Buffer;
+
+ //
+ // get a place to add
+ //
+ for (Index = (INTN) (Size + Count - 1); Index >= (INTN) Pos; Index--) {
+ BufferPtr[Index] = BufferPtr[Index - Count];
+ }
+ //
+ // add the buffer
+ //
+ for (Index = (INTN) 0; Index < (INTN) Count; Index++) {
+ BufferPtr[Index + Pos] = AddBuffer[Index];
+ }
+
+ Size += Count;
+
+ HBufferImageFreeLines ();
+
+ HBufferImageBufferToList (Buffer, Size);
+
+ FreePool (Buffer);
+
+ Link = HMainEditor.BufferImage->ListHead->ForwardLink;
+ for (Index = 0; Index < (INTN) NewPos / 0x10; Index++) {
+ Link = Link->ForwardLink;
+ }
+
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+ HBufferImage.CurrentLine = Line;
+
+ if (OldPos >= Pos) {
+ NewPos = OldPos + Count;
+ } else {
+ NewPos = OldPos;
+ }
+
+ HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HBufferImageDoBackspace (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ delete the previous character
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ HEFI_EDITOR_LINE *Line;
+
+ UINTN FileColumn;
+ UINTN FPos;
+ BOOLEAN LastLine;
+
+ //
+ // variable initialization
+ //
+ LastLine = FALSE;
+
+ //
+ // already the first character
+ //
+ if (HBufferImage.BufferPosition.Row == 1 && HBufferImage.BufferPosition.Column == 1) {
+ return EFI_SUCCESS;
+ }
+
+ FPos = (HBufferImage.BufferPosition.Row - 1) * 0x10 + HBufferImage.BufferPosition.Column - 1;
+
+ FileColumn = HBufferImage.BufferPosition.Column;
+
+ Line = HBufferImage.CurrentLine;
+ LastLine = FALSE;
+ if (Line->Link.ForwardLink == HBufferImage.ListHead && FileColumn > 1) {
+ LastLine = TRUE;
+ }
+
+ HBufferImageDeleteCharacterFromBuffer (FPos - 1, 1, NULL);
+
+ //
+ // if is the last line
+ // then only this line need to be refreshed
+ //
+ if (LastLine) {
+ HBufferImageNeedRefresh = FALSE;
+ HBufferImageOnlyLineNeedRefresh = TRUE;
+ } else {
+ HBufferImageNeedRefresh = TRUE;
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+ }
+
+ if (!HBufferImage.Modified) {
+ HBufferImage.Modified = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HBufferImageDoDelete (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Delete current character from line
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+
+ HEFI_EDITOR_LINE *Line;
+
+ BOOLEAN LastLine;
+ UINTN FileColumn;
+ UINTN FPos;
+
+ FPos = (HBufferImage.BufferPosition.Row - 1) * 0x10 + HBufferImage.BufferPosition.Column - 1;
+
+ FileColumn = HBufferImage.BufferPosition.Column;
+
+ Line = HBufferImage.CurrentLine;
+
+ //
+ // if beyond the last character
+ //
+ if (FileColumn > Line->Size) {
+ return EFI_SUCCESS;
+ }
+
+ LastLine = FALSE;
+ if (Line->Link.ForwardLink == HBufferImage.ListHead) {
+ LastLine = TRUE;
+ }
+
+ HBufferImageDeleteCharacterFromBuffer (FPos, 1, NULL);
+
+ //
+ // if is the last line
+ // then only this line need to be refreshed
+ //
+ if (LastLine) {
+ HBufferImageNeedRefresh = FALSE;
+ HBufferImageOnlyLineNeedRefresh = TRUE;
+ } else {
+ HBufferImageNeedRefresh = TRUE;
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+ }
+
+ if (!HBufferImage.Modified) {
+ HBufferImage.Modified = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HBufferImageBufferToList (
+ IN VOID *Buffer,
+ IN UINTN Bytes
+ )
+{
+ UINTN i;
+ UINTN j;
+ UINTN Left;
+ HEFI_EDITOR_LINE *Line;
+ UINT8 *BufferPtr;
+
+ i = 0;
+ Left = 0;
+ BufferPtr = (UINT8 *) Buffer;
+
+ //
+ // parse file content line by line
+ //
+ while (i < Bytes) {
+ if (Bytes - i >= 0x10) {
+ Left = 0x10;
+ } else {
+ Left = Bytes - i;
+ }
+
+ //
+ // allocate a new line
+ //
+ Line = HBufferImageCreateLine ();
+ if (Line == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Line->Size = Left;
+
+ for (j = 0; j < Left; j++) {
+ Line->Buffer[j] = BufferPtr[i];
+ i++;
+ }
+
+ }
+
+ //
+ // last line is a full line, SO create a new line
+ //
+ if (Left == 0x10 || Bytes == 0) {
+ Line = HBufferImageCreateLine ();
+ if (Line == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HBufferImageListToBuffer (
+ IN VOID *Buffer,
+ IN UINTN Bytes
+ )
+{
+ UINTN Count;
+ UINTN Index;
+ HEFI_EDITOR_LINE *Line;
+ LIST_ENTRY *Link;
+ UINT8 *BufferPtr;
+
+ //
+ // change the line list to a large buffer
+ //
+ if (HBufferImage.Lines == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ Link = &HBufferImage.Lines->Link;
+ Count = 0;
+ BufferPtr = (UINT8 *) Buffer;
+
+ //
+ // deal line by line
+ //
+ while (Link != HBufferImage.ListHead) {
+
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+
+ if (Count + Line->Size > Bytes) {
+ return EFI_SUCCESS;
+ }
+
+ for (Index = 0; Index < Line->Size; Index++) {
+ BufferPtr[Index] = Line->Buffer[Index];
+ }
+
+ Count += Line->Size;
+ BufferPtr += Line->Size;
+
+ Link = Link->ForwardLink;
+ }
+
+ return EFI_SUCCESS;
+}
+
+VOID
+HBufferImageAdjustMousePosition (
+ IN INT32 TextX,
+ IN INT32 TextY
+ )
+{
+ UINTN X;
+ UINTN Y;
+ UINTN AbsX;
+ UINTN AbsY;
+
+ //
+ // TextX and TextY is mouse movement data returned by mouse driver
+ // This function will change it to MousePosition
+ //
+ //
+ // get absolute X value
+ //
+ if (TextX >= 0) {
+ AbsX = TextX;
+ } else {
+ AbsX = -TextX;
+ }
+ //
+ // get absolute Y value
+ //
+ if (TextY >= 0) {
+ AbsY = TextY;
+ } else {
+ AbsY = -TextY;
+ }
+
+ X = HBufferImage.MousePosition.Column;
+ Y = HBufferImage.MousePosition.Row;
+
+ if (TextX >= 0) {
+ X += TextX;
+ } else {
+ if (X >= AbsX) {
+ X -= AbsX;
+ } else {
+ X = 0;
+ }
+ }
+
+ if (TextY >= 0) {
+ Y += TextY;
+ } else {
+ if (Y >= AbsY) {
+ Y -= AbsY;
+ } else {
+ Y = 0;
+ }
+ }
+ //
+ // check whether new mouse column position is beyond screen
+ // if not, adjust it
+ //
+ if (X >= 10 && X <= (10 + 0x10 * 3 - 1)) {
+ HBufferImage.MousePosition.Column = X;
+ } else if (X < 10) {
+ HBufferImage.MousePosition.Column = 10;
+ } else if (X > (10 + 0x10 * 3 - 1)) {
+ HBufferImage.MousePosition.Column = 10 + 0x10 * 3 - 1;
+ }
+ //
+ // check whether new mouse row position is beyond screen
+ // if not, adjust it
+ //
+ if (Y >= 2 && Y <= (HMainEditor.ScreenSize.Row - 4)) {
+ HBufferImage.MousePosition.Row = Y;
+ } else if (Y < 2) {
+ HBufferImage.MousePosition.Row = 2;
+ } else if (Y > (HMainEditor.ScreenSize.Row - 4)) {
+ HBufferImage.MousePosition.Row = (HMainEditor.ScreenSize.Row - 4);
+ }
+
+}
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.h b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.h
new file mode 100644
index 0000000000..d661e50524
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.h
@@ -0,0 +1,250 @@
+/** @file
+ Defines BufferImage - the view of the file that is visible at any point,
+ as well as the event handlers for editing the file
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LIB_BUFFER_IMAGE_H_
+#define _LIB_BUFFER_IMAGE_H_
+
+#include "HexEditor.h"
+
+EFI_STATUS
+HBufferImageInit (
+ VOID
+ );
+EFI_STATUS
+HBufferImageCleanup (
+ VOID
+ );
+EFI_STATUS
+HBufferImageRefresh (
+ VOID
+ );
+EFI_STATUS
+HBufferImageHide (
+ VOID
+ );
+EFI_STATUS
+HBufferImageHandleInput (
+ EFI_INPUT_KEY *
+ );
+EFI_STATUS
+HBufferImageBackup (
+ VOID
+ );
+
+EFI_STATUS
+HBufferImageRead (
+ IN CONST CHAR16 *,
+ IN CONST CHAR16 *,
+ IN UINTN,
+ IN UINTN,
+ IN UINTN,
+ IN UINTN,
+ IN EDIT_FILE_TYPE,
+ IN BOOLEAN
+ );
+
+EFI_STATUS
+HBufferImageSave (
+ IN CHAR16 *,
+ IN CHAR16 *,
+ IN UINTN,
+ IN UINTN,
+ IN UINTN,
+ IN UINTN,
+ IN EDIT_FILE_TYPE
+ );
+
+INTN
+HBufferImageCharToHex (
+ IN CHAR16
+ );
+
+EFI_STATUS
+HBufferImageRestoreMousePosition (
+ VOID
+ );
+EFI_STATUS
+HBufferImageRestorePosition (
+ VOID
+ );
+
+VOID
+HBufferImageMovePosition (
+ IN UINTN,
+ IN UINTN,
+ IN BOOLEAN
+ );
+
+EFI_STATUS
+HBufferImageHandleInput (
+ EFI_INPUT_KEY *
+ );
+
+HEFI_EDITOR_LINE *
+HBufferImageCreateLine (
+ VOID
+ );
+
+EFI_STATUS
+HBufferImageDoCharInput (
+ CHAR16
+ );
+EFI_STATUS
+HBufferImageAddChar (
+ CHAR16
+ );
+
+BOOLEAN
+HInCurrentScreen (
+ UINTN
+ );
+BOOLEAN
+HAboveCurrentScreen (
+ UINTN
+ );
+BOOLEAN
+HUnderCurrentScreen (
+ UINTN
+ );
+
+EFI_STATUS
+HBufferImageScrollRight (
+ VOID
+ );
+EFI_STATUS
+HBufferImageScrollLeft (
+ VOID
+ );
+EFI_STATUS
+HBufferImageScrollDown (
+ VOID
+ );
+EFI_STATUS
+HBufferImageScrollUp (
+ VOID
+ );
+EFI_STATUS
+HBufferImagePageUp (
+ VOID
+ );
+EFI_STATUS
+HBufferImagePageDown (
+ VOID
+ );
+EFI_STATUS
+HBufferImageHome (
+ VOID
+ );
+EFI_STATUS
+HBufferImageEnd (
+ VOID
+ );
+
+EFI_STATUS
+HBufferImageDoBackspace (
+ VOID
+ );
+EFI_STATUS
+HBufferImageDoDelete (
+ VOID
+ );
+
+EFI_STATUS
+HBufferImageCutLine (
+ HEFI_EDITOR_LINE **
+ );
+EFI_STATUS
+HBufferImagePasteLine (
+ VOID
+ );
+
+EFI_STATUS
+HBufferImageGetFileInfo (
+ EFI_FILE_HANDLE,
+ CHAR16 *,
+ EFI_FILE_INFO **
+ );
+
+EFI_STATUS
+HBufferImageSearch (
+ CHAR16 *,
+ UINTN
+ );
+EFI_STATUS
+HBufferImageReplace (
+ CHAR16 *,
+ UINTN
+ );
+
+EFI_STATUS
+HBufferImageFree (
+ VOID
+ ) ;
+
+EFI_STATUS
+HBufferImageDeleteCharacterFromBuffer (
+ IN UINTN,
+ IN UINTN,
+ UINT8 *
+ );
+
+EFI_STATUS
+HBufferImageAddCharacterToBuffer (
+ IN UINTN,
+ IN UINTN,
+ UINT8 *
+ );
+
+EFI_STATUS
+HBufferImageBufferToList (
+ IN VOID *,
+ IN UINTN
+ );
+
+EFI_STATUS
+HBufferImageListToBuffer (
+ IN VOID *,
+ IN UINTN
+ );
+
+VOID
+HBufferImageAdjustMousePosition (
+ INT32,
+ INT32
+ );
+
+BOOLEAN
+HBufferImageIsAtHighBits (
+ UINTN,
+ UINTN *
+ ) ;
+
+EFI_STATUS
+HBufferImageCutLine (
+ HEFI_EDITOR_LINE **
+ );
+
+UINTN
+HBufferImageGetTotalSize (
+ VOID
+ );
+
+BOOLEAN
+HBufferImageIsInSelectedArea (
+ UINTN,
+ UINTN
+ );
+
+#endif
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.c b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.c
new file mode 100644
index 0000000000..2408027abb
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.c
@@ -0,0 +1,112 @@
+/** @file
+ Functions to deal with Clip Board
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HexEditor.h"
+
+HEFI_EDITOR_CLIPBOARD HClipBoard;
+
+//
+// for basic initialization of HClipBoard
+//
+HEFI_EDITOR_CLIPBOARD HClipBoardConst = {
+ NULL,
+ 0
+};
+
+EFI_STATUS
+HClipBoardInit (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initialization function for HDiskImage
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_LOAD_ERROR
+
+--*/
+{
+ //
+ // basiclly initialize the HDiskImage
+ //
+ CopyMem (&HClipBoard, &HClipBoardConst, sizeof (HClipBoard));
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HClipBoardCleanup (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initialization function for HDiskImage
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_LOAD_ERROR
+
+--*/
+{
+
+ SHELL_FREE_NON_NULL (HClipBoard.Buffer);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HClipBoardSet (
+ IN UINT8 *Buffer,
+ IN UINTN Size
+ )
+{
+ //
+ // free the old clipboard buffer
+ // and set new clipboard buffer
+ //
+ SHELL_FREE_NON_NULL (HClipBoard.Buffer);
+ HClipBoard.Buffer = Buffer;
+
+ HClipBoard.Size = Size;
+
+ return EFI_SUCCESS;
+}
+
+UINTN
+HClipBoardGet (
+ OUT UINT8 **Buffer
+ )
+{
+ //
+ // return the clipboard buffer
+ //
+ *Buffer = HClipBoard.Buffer;
+
+ return HClipBoard.Size;
+}
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.h b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.h
new file mode 100644
index 0000000000..9165d98f30
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.h
@@ -0,0 +1,40 @@
+/** @file
+ Defines DiskImage - the view of the file that is visible at any point,
+ as well as the event handlers for editing the file
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LIB_CLIP_BOARD_H_
+#define _LIB_CLIP_BOARD_H_
+
+#include "HexEditor.h"
+
+EFI_STATUS
+HClipBoardInit (
+ VOID
+ );
+EFI_STATUS
+HClipBoardCleanup (
+ VOID
+ );
+
+EFI_STATUS
+HClipBoardSet (
+ UINT8 *,
+ UINTN
+ );
+UINTN
+HClipBoardGet (
+ UINT8 **
+ );
+
+#endif
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.c b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.c
new file mode 100644
index 0000000000..140db71671
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.c
@@ -0,0 +1,487 @@
+/** @file
+ Functions to deal with Disk buffer.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HexEditor.h"
+#include <Protocol/BlockIo.h>
+
+extern EFI_HANDLE HImageHandleBackup;
+extern HEFI_EDITOR_BUFFER_IMAGE HBufferImage;
+
+extern BOOLEAN HBufferImageNeedRefresh;
+extern BOOLEAN HBufferImageOnlyLineNeedRefresh;
+extern BOOLEAN HBufferImageMouseNeedRefresh;
+
+extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;
+
+HEFI_EDITOR_DISK_IMAGE HDiskImage;
+HEFI_EDITOR_DISK_IMAGE HDiskImageBackupVar;
+
+//
+// for basic initialization of HDiskImage
+//
+HEFI_EDITOR_DISK_IMAGE HDiskImageConst = {
+ NULL,
+ 0,
+ 0,
+ 0
+};
+
+EFI_STATUS
+HDiskImageInit (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initialization function for HDiskImage
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_LOAD_ERROR
+
+--*/
+{
+ //
+ // basically initialize the HDiskImage
+ //
+ CopyMem (&HDiskImage, &HDiskImageConst, sizeof (HDiskImage));
+
+ CopyMem (&HDiskImageBackupVar, &HDiskImageConst, sizeof (HDiskImageBackupVar));
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HDiskImageBackup (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Backup function for HDiskImage
+ Only a few fields need to be backup.
+ This is for making the Disk buffer refresh
+ as few as possible.
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS - Success
+ EFI_OUT_OF_RESOURCES - gST->ConOut of resources
+
+--*/
+{
+ //
+ // backup the disk name, offset and size
+ //
+ //
+ SHELL_FREE_NON_NULL (HDiskImageBackupVar.Name);
+
+ HDiskImageBackupVar.Name = CatSPrint(NULL, L"%s", HDiskImage.Name);
+ if (HDiskImageBackupVar.Name == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ HDiskImageBackupVar.Offset = HDiskImage.Offset;
+ HDiskImageBackupVar.Size = HDiskImage.Size;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HDiskImageCleanup (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Cleanup function for HDiskImage
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ SHELL_FREE_NON_NULL (HDiskImage.Name);
+ SHELL_FREE_NON_NULL (HDiskImageBackupVar.Name);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+HDiskImageSetDiskNameOffsetSize (
+ IN CONST CHAR16 *Str,
+ IN UINTN Offset,
+ IN UINTN Size
+ )
+/*++
+
+Routine Description:
+
+ Set FileName field in HFileImage
+
+Arguments:
+
+ Str - File name to set
+ Offset - The offset
+ Size - The size
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_OUT_OF_RESOURCES
+
+--*/
+{
+ UINTN Len;
+ UINTN Index;
+
+ //
+ // free the old file name
+ //
+ SHELL_FREE_NON_NULL (HDiskImage.Name);
+
+ Len = StrLen (Str);
+
+ HDiskImage.Name = AllocateZeroPool (2 * (Len + 1));
+ if (HDiskImage.Name == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Index = 0; Index < Len; Index++) {
+ HDiskImage.Name[Index] = Str[Index];
+ }
+
+ HDiskImage.Name[Len] = L'\0';
+
+ HDiskImage.Offset = Offset;
+ HDiskImage.Size = Size;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HDiskImageRead (
+ IN CONST CHAR16 *DeviceName,
+ IN UINTN Offset,
+ IN UINTN Size,
+ IN BOOLEAN Recover
+ )
+/*++
+
+Routine Description:
+
+ Read a disk from disk into HBufferImage
+
+Arguments:
+
+ DeviceName - filename to read
+ Offset - The offset
+ Size - The size
+ Recover - if is for recover, no information print
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_LOAD_ERROR
+ EFI_OUT_OF_RESOURCES
+ EFI_INVALID_PARAMETER
+
+--*/
+{
+ CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *DupDevicePath;
+ EFI_HANDLE Handle;
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+ EFI_STATUS Status;
+
+ VOID *Buffer;
+ CHAR16 *Str;
+ UINTN Bytes;
+
+ HEFI_EDITOR_LINE *Line;
+ UINT64 ByteOffset;
+
+ EDIT_FILE_TYPE BufferTypeBackup;
+
+ BufferTypeBackup = HBufferImage.BufferType;
+ HBufferImage.BufferType = FileTypeDiskBuffer;
+
+ DevicePath = gEfiShellProtocol->GetDevicePathFromMap(DeviceName);
+ if (DevicePath == NULL) {
+ StatusBarSetStatusString (L"Cannot Find Device");
+ return EFI_INVALID_PARAMETER;
+ }
+ DupDevicePath = DuplicateDevicePath(DevicePath);
+ //
+ // get blkio interface
+ //
+ Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid,&DupDevicePath,&Handle);
+ FreePool(DupDevicePath);
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Read Disk Failed");
+ return Status;
+ }
+ Status = gBS->OpenProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID**)&BlkIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Read Disk Failed");
+ return Status;
+ }
+ //
+ // if Offset exceeds LastBlock,
+ // return error
+ //
+ if (Offset > BlkIo->Media->LastBlock || Offset + Size > BlkIo->Media->LastBlock) {
+ StatusBarSetStatusString (L"Invalid Offset + Size");
+ return EFI_LOAD_ERROR;
+ }
+
+ Bytes = BlkIo->Media->BlockSize * Size;
+ Buffer = AllocateZeroPool (Bytes);
+
+ if (Buffer == NULL) {
+ StatusBarSetStatusString (L"Read Disk Failed");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ByteOffset = MultU64x32 (Offset, BlkIo->Media->BlockSize);
+
+ //
+ // read from disk
+ //
+ Status = BlkIo->ReadBlocks (
+ BlkIo,
+ BlkIo->Media->MediaId,
+ Offset,
+ Bytes,
+ Buffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ StatusBarSetStatusString (L"Read Disk Failed");
+ return EFI_LOAD_ERROR;
+ }
+
+ HBufferImageFree ();
+
+ //
+ // convert buffer to line list
+ //
+ Status = HBufferImageBufferToList (Buffer, Bytes);
+ FreePool (Buffer);
+
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Read Disk Failed");
+ return Status;
+ }
+
+ Status = HDiskImageSetDiskNameOffsetSize (DeviceName, Offset, Size);
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Read Disk Failed");
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // initialize some variables
+ //
+ HDiskImage.BlockSize = BlkIo->Media->BlockSize;
+
+ HBufferImage.DisplayPosition.Row = 2;
+ HBufferImage.DisplayPosition.Column = 10;
+
+ HBufferImage.MousePosition.Row = 2;
+ HBufferImage.MousePosition.Column = 10;
+
+ HBufferImage.LowVisibleRow = 1;
+ HBufferImage.HighBits = TRUE;
+
+ HBufferImage.BufferPosition.Row = 1;
+ HBufferImage.BufferPosition.Column = 1;
+
+ if (!Recover) {
+ Str = CatSPrint(NULL, L"%d Lines Read", HBufferImage.NumLines);
+ if (Str == NULL) {
+ StatusBarSetStatusString (L"Read Disk Failed");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StatusBarSetStatusString (Str);
+ SHELL_FREE_NON_NULL (Str);
+
+ HMainEditor.SelectStart = 0;
+ HMainEditor.SelectEnd = 0;
+
+ }
+
+ //
+ // has line
+ //
+ if (HBufferImage.Lines != NULL) {
+ HBufferImage.CurrentLine = CR (
+ HBufferImage.ListHead->ForwardLink,
+ HEFI_EDITOR_LINE,
+ Link,
+ EFI_EDITOR_LINE_LIST
+ );
+ } else {
+ //
+ // create a dummy line
+ //
+ Line = HBufferImageCreateLine ();
+ if (Line == NULL) {
+ StatusBarSetStatusString (L"Read Disk Failed");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ HBufferImage.CurrentLine = Line;
+ }
+
+ HBufferImage.Modified = FALSE;
+ HBufferImageNeedRefresh = TRUE;
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+ HBufferImageMouseNeedRefresh = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HDiskImageSave (
+ IN CHAR16 *DeviceName,
+ IN UINTN Offset,
+ IN UINTN Size
+ )
+/*++
+
+Routine Description:
+
+ Save lines in HBufferImage to disk
+ NOT ALLOW TO WRITE TO ANOTHER DISK!!!!!!!!!
+
+Arguments:
+
+ DeviceName - The device name
+ Offset - The offset
+ Size - The size
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_LOAD_ERROR
+ EFI_OUT_OF_RESOURCES
+ EFI_INVALID_PARAMETER
+
+--*/
+{
+
+ CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *DupDevicePath;
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ VOID *Buffer;
+ UINTN Bytes;
+
+ UINT64 ByteOffset;
+
+ EDIT_FILE_TYPE BufferTypeBackup;
+
+ //
+ // if not modified, directly return
+ //
+ if (HBufferImage.Modified == FALSE) {
+ return EFI_SUCCESS;
+ }
+
+ BufferTypeBackup = HBufferImage.BufferType;
+ HBufferImage.BufferType = FileTypeDiskBuffer;
+
+ DevicePath = gEfiShellProtocol->GetDevicePathFromMap(DeviceName);
+ if (DevicePath == NULL) {
+// StatusBarSetStatusString (L"Cannot Find Device");
+ return EFI_INVALID_PARAMETER;
+ }
+ DupDevicePath = DuplicateDevicePath(DevicePath);
+
+ //
+ // get blkio interface
+ //
+ Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid,&DupDevicePath,&Handle);
+ FreePool(DupDevicePath);
+ if (EFI_ERROR (Status)) {
+// StatusBarSetStatusString (L"Read Disk Failed");
+ return Status;
+ }
+ Status = gBS->OpenProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID**)&BlkIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR (Status)) {
+// StatusBarSetStatusString (L"Read Disk Failed");
+ return Status;
+ }
+
+ Bytes = BlkIo->Media->BlockSize * Size;
+ Buffer = AllocateZeroPool (Bytes);
+
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // concatenate the line list to a buffer
+ //
+ Status = HBufferImageListToBuffer (Buffer, Bytes);
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return Status;
+ }
+
+ ByteOffset = MultU64x32 (Offset, BlkIo->Media->BlockSize);
+
+ //
+ // write the buffer to disk
+ //
+ Status = BlkIo->WriteBlocks (
+ BlkIo,
+ BlkIo->Media->MediaId,
+ Offset,
+ Bytes,
+ Buffer
+ );
+
+ FreePool (Buffer);
+
+ if (EFI_ERROR (Status)) {
+ return EFI_LOAD_ERROR;
+ }
+ //
+ // now not modified
+ //
+ HBufferImage.Modified = FALSE;
+
+ return EFI_SUCCESS;
+}
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.h b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.h
new file mode 100644
index 0000000000..eaa8e2615d
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.h
@@ -0,0 +1,48 @@
+/** @file
+ Defines DiskImage - the view of the file that is visible at any point,
+ as well as the event handlers for editing the file
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LIB_DISK_IMAGE_H_
+#define _LIB_DISK_IMAGE_H_
+
+#include "HexEditor.h"
+
+EFI_STATUS
+HDiskImageInit (
+ VOID
+ );
+EFI_STATUS
+HDiskImageCleanup (
+ VOID
+ );
+EFI_STATUS
+HDiskImageBackup (
+ VOID
+ );
+
+EFI_STATUS
+HDiskImageRead (
+ IN CONST CHAR16 *,
+ IN UINTN,
+ IN UINTN,
+ IN BOOLEAN
+ );
+EFI_STATUS
+HDiskImageSave (
+ IN CHAR16 *,
+ IN UINTN,
+ IN UINTN
+ );
+
+#endif
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.c b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.c
new file mode 100644
index 0000000000..adf7928197
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.c
@@ -0,0 +1,504 @@
+/** @file
+ Functions to deal with file buffer.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HexEditor.h"
+
+extern EFI_HANDLE HImageHandleBackup;
+extern HEFI_EDITOR_BUFFER_IMAGE HBufferImage;
+
+extern BOOLEAN HBufferImageNeedRefresh;
+extern BOOLEAN HBufferImageOnlyLineNeedRefresh;
+extern BOOLEAN HBufferImageMouseNeedRefresh;
+
+extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;
+
+HEFI_EDITOR_FILE_IMAGE HFileImage;
+HEFI_EDITOR_FILE_IMAGE HFileImageBackupVar;
+
+//
+// for basic initialization of HFileImage
+//
+HEFI_EDITOR_BUFFER_IMAGE HFileImageConst = {
+ NULL,
+ 0,
+ FALSE
+};
+
+EFI_STATUS
+HFileImageInit (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initialization function for HFileImage
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_LOAD_ERROR
+
+--*/
+{
+ //
+ // basically initialize the HFileImage
+ //
+ CopyMem (&HFileImage, &HFileImageConst, sizeof (HFileImage));
+
+ CopyMem (
+ &HFileImageBackupVar,
+ &HFileImageConst,
+ sizeof (HFileImageBackupVar)
+ );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HFileImageBackup (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Backup function for HFileImage
+ Only a few fields need to be backup.
+ This is for making the file buffer refresh
+ as few as possible.
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_OUT_OF_RESOURCES
+
+--*/
+{
+ SHELL_FREE_NON_NULL (HFileImageBackupVar.FileName);
+ HFileImageBackupVar.FileName = CatSPrint(NULL, L"%s", HFileImage.FileName);
+ if (HFileImageBackupVar.FileName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HFileImageCleanup (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Cleanup function for HFileImage
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+
+ SHELL_FREE_NON_NULL (HFileImage.FileName);
+ SHELL_FREE_NON_NULL (HFileImageBackupVar.FileName);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HFileImageSetFileName (
+ IN CONST CHAR16 *Str
+ )
+/*++
+
+Routine Description:
+
+ Set FileName field in HFileImage
+
+Arguments:
+
+ Str -- File name to set
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_OUT_OF_RESOURCES
+
+--*/
+{
+ UINTN Size;
+ UINTN Index;
+
+ //
+ // free the old file name
+ //
+ SHELL_FREE_NON_NULL (HFileImage.FileName);
+
+ Size = StrLen (Str);
+
+ HFileImage.FileName = AllocateZeroPool (2 * (Size + 1));
+ if (HFileImage.FileName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Index = 0; Index < Size; Index++) {
+ HFileImage.FileName[Index] = Str[Index];
+ }
+
+ HFileImage.FileName[Size] = L'\0';
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HFileImageGetFileInfo (
+ IN EFI_FILE_HANDLE Handle,
+ IN CHAR16 *FileName,
+ OUT EFI_FILE_INFO **InfoOut
+ )
+/*++
+
+Routine Description:
+
+ Get this file's information
+
+Arguments:
+
+ Handle - in NT32 mode Directory handle, in other mode File Handle
+ FileName - The file name
+ InfoOut - parameter to pass file information out
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_OUT_OF_RESOURCES
+ EFI_LOAD_ERROR
+
+--*/
+{
+
+ VOID *Info;
+ UINTN Size;
+ EFI_STATUS Status;
+
+ Size = SIZE_OF_EFI_FILE_INFO + 1024;
+ Info = AllocateZeroPool (Size);
+ if (!Info) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // get file information
+ //
+ Status = Handle->GetInfo (Handle, &gEfiFileInfoGuid, &Size, Info);
+ if (EFI_ERROR (Status)) {
+ return EFI_LOAD_ERROR;
+ }
+
+ *InfoOut = (EFI_FILE_INFO *) Info;
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+HFileImageRead (
+ IN CONST CHAR16 *FileName,
+ IN BOOLEAN Recover
+ )
+/*++
+
+Routine Description:
+
+ Read a file from disk into HBufferImage
+
+Arguments:
+
+ FileName -- filename to read
+ Recover -- if is for recover, no information print
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_LOAD_ERROR
+ EFI_OUT_OF_RESOURCES
+
+--*/
+{
+ HEFI_EDITOR_LINE *Line;
+ UINT8 *Buffer;
+ CHAR16 *UnicodeBuffer;
+ EFI_STATUS Status;
+
+ //
+ // variable initialization
+ //
+ Line = NULL;
+
+ //
+ // in this function, when you return error ( except EFI_OUT_OF_RESOURCES )
+ // you should set status string
+ // since this function maybe called before the editorhandleinput loop
+ // so any error will cause editor return
+ // so if you want to print the error status
+ // you should set the status string
+ //
+ Status = ReadFileIntoBuffer (FileName, (VOID**)&Buffer, &HFileImage.Size, &HFileImage.ReadOnly);
+ if (EFI_ERROR(Status)) {
+ UnicodeBuffer = CatSPrint(NULL, L"Read error on file &s: %r", FileName, Status);
+ if (UnicodeBuffer == NULL) {
+ SHELL_FREE_NON_NULL(Buffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StatusBarSetStatusString (UnicodeBuffer);
+ FreePool (UnicodeBuffer);
+ }
+
+ HFileImageSetFileName (FileName);
+
+ //
+ // free the old lines
+ //
+ HBufferImageFree ();
+
+ Status = HBufferImageBufferToList (Buffer, HFileImage.Size);
+ SHELL_FREE_NON_NULL (Buffer);
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Error parsing file.");
+ return Status;
+ }
+
+ HBufferImage.DisplayPosition.Row = 2;
+ HBufferImage.DisplayPosition.Column = 10;
+ HBufferImage.MousePosition.Row = 2;
+ HBufferImage.MousePosition.Column = 10;
+ HBufferImage.LowVisibleRow = 1;
+ HBufferImage.HighBits = TRUE;
+ HBufferImage.BufferPosition.Row = 1;
+ HBufferImage.BufferPosition.Column = 1;
+
+ if (!Recover) {
+ UnicodeBuffer = CatSPrint(NULL, L"%d Lines Read", HBufferImage.NumLines);
+ if (UnicodeBuffer == NULL) {
+ SHELL_FREE_NON_NULL(Buffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StatusBarSetStatusString (UnicodeBuffer);
+ FreePool (UnicodeBuffer);
+
+ HMainEditor.SelectStart = 0;
+ HMainEditor.SelectEnd = 0;
+ }
+
+ //
+ // has line
+ //
+ if (HBufferImage.Lines != 0) {
+ HBufferImage.CurrentLine = CR (HBufferImage.ListHead->ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+ } else {
+ //
+ // create a dummy line
+ //
+ Line = HBufferImageCreateLine ();
+ if (Line == NULL) {
+ SHELL_FREE_NON_NULL(Buffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ HBufferImage.CurrentLine = Line;
+ }
+
+ HBufferImage.Modified = FALSE;
+ HBufferImageNeedRefresh = TRUE;
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+ HBufferImageMouseNeedRefresh = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HFileImageSave (
+ IN CHAR16 *FileName
+ )
+/*++
+
+Routine Description:
+
+ Save lines in HBufferImage to disk
+
+Arguments:
+
+ FileName - The file name
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_LOAD_ERROR
+ EFI_OUT_OF_RESOURCES
+
+--*/
+{
+
+ LIST_ENTRY *Link;
+ HEFI_EDITOR_LINE *Line;
+ CHAR16 *Str;
+ EFI_STATUS Status;
+ UINTN NumLines;
+ SHELL_FILE_HANDLE FileHandle;
+ UINTN TotalSize;
+ UINT8 *Buffer;
+ UINT8 *Ptr;
+ EDIT_FILE_TYPE BufferTypeBackup;
+
+ BufferTypeBackup = HBufferImage.BufferType;
+ HBufferImage.BufferType = FileTypeFileBuffer;
+
+ //
+ // if is the old file
+ //
+ if (StrCmp (FileName, HFileImage.FileName) == 0) {
+ //
+ // check whether file exists on disk
+ //
+ if (ShellIsFile(FileName) == EFI_SUCCESS) {
+ //
+ // current file exists on disk
+ // so if not modified, then not save
+ //
+ if (HBufferImage.Modified == FALSE) {
+ return EFI_SUCCESS;
+ }
+ //
+ // if file is read-only, set error
+ //
+ if (HFileImage.ReadOnly == TRUE) {
+ StatusBarSetStatusString (L"Read Only File Can Not Be Saved");
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ if (ShellIsDirectory(FileName) == EFI_SUCCESS) {
+ StatusBarSetStatusString (L"Directory Can Not Be Saved");
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0);
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // the file exits, delete it
+ //
+ Status = ShellDeleteFile (&FileHandle);
+ if (EFI_ERROR (Status) || Status == EFI_WARN_DELETE_FAILURE) {
+ StatusBarSetStatusString (L"Write File Failed");
+ return EFI_LOAD_ERROR;
+ }
+ }
+
+ //
+ // write all the lines back to disk
+ //
+ NumLines = 0;
+ TotalSize = 0;
+ for (Link = HBufferImage.ListHead->ForwardLink; Link != HBufferImage.ListHead; Link = Link->ForwardLink) {
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+
+ if (Line->Size != 0) {
+ TotalSize += Line->Size;
+ }
+ //
+ // end of if Line -> Size != 0
+ //
+ NumLines++;
+ }
+ //
+ // end of for Link
+ //
+ Buffer = AllocateZeroPool (TotalSize);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Ptr = Buffer;
+ for (Link = HBufferImage.ListHead->ForwardLink; Link != HBufferImage.ListHead; Link = Link->ForwardLink) {
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+
+ if (Line->Size != 0) {
+ CopyMem (Ptr, Line->Buffer, Line->Size);
+ Ptr += Line->Size;
+ }
+ //
+ // end of if Line -> Size != 0
+ //
+ }
+
+
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
+
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Create File Failed");
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = ShellWriteFile (FileHandle, &TotalSize, Buffer);
+ FreePool (Buffer);
+ if (EFI_ERROR (Status)) {
+ ShellDeleteFile (&FileHandle);
+ return EFI_LOAD_ERROR;
+ }
+
+ ShellCloseFile(&FileHandle);
+
+ HBufferImage.Modified = FALSE;
+
+ //
+ // set status string
+ //
+ Str = CatSPrint(NULL, L"%d Lines Wrote", NumLines);
+ StatusBarSetStatusString (Str);
+ FreePool (Str);
+
+ //
+ // now everything is ready , you can set the new file name to filebuffer
+ //
+ if (BufferTypeBackup != FileTypeFileBuffer || StringNoCaseCompare (&FileName, &HFileImage.FileName) != 0) {
+ //
+ // not the same
+ //
+ HFileImageSetFileName (FileName);
+ if (HFileImage.FileName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ HFileImage.ReadOnly = FALSE;
+
+ return EFI_SUCCESS;
+}
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.h b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.h
new file mode 100644
index 0000000000..ae386d2fc9
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.h
@@ -0,0 +1,56 @@
+/** @file
+ Defines FileImage - the view of the file that is visible at any point,
+ as well as the event handlers for editing the file
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LIB_FILE_IMAGE_H_
+#define _LIB_FILE_IMAGE_H_
+
+#include "HexEditor.h"
+
+EFI_STATUS
+HFileImageInit (
+ VOID
+ );
+EFI_STATUS
+HFileImageCleanup (
+ VOID
+ );
+EFI_STATUS
+HFileImageBackup (
+ VOID
+ );
+
+EFI_STATUS
+HFileImageSetFileName (
+ IN CONST CHAR16 *
+ );
+
+EFI_STATUS
+HFileImageGetFileInfo (
+ EFI_FILE_HANDLE,
+ CHAR16 *,
+ EFI_FILE_INFO **
+ );
+
+EFI_STATUS
+HFileImageRead (
+ IN CONST CHAR16 *,
+ IN BOOLEAN
+ );
+EFI_STATUS
+HFileImageSave (
+ IN CHAR16 *
+ );
+
+#endif
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEdit.c b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEdit.c
new file mode 100644
index 0000000000..511eb9e636
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEdit.c
@@ -0,0 +1,247 @@
+/** @file
+ Main entry point of editor
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDebug1CommandsLib.h"
+#include "HexEditor.h"
+
+//
+// Global Variables
+//
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-f", TypeFlag},
+ {L"-d", TypeFlag},
+ {L"-m", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'hexedit' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunHexEdit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *Buffer;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ LIST_ENTRY *Package;
+ CONST CHAR16 *Cwd;
+ CHAR16 *NFS;
+ CHAR16 *Spot;
+ CONST CHAR16 *Name;
+ UINTN Offset;
+ UINTN Size;
+ UINT64 LastOffset;
+ EDIT_FILE_TYPE WhatToDo;
+
+ Buffer = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ NFS = NULL;
+ Cwd = NULL;
+ Buffer = NULL;
+ Name = NULL;
+ Spot = NULL;
+ Offset = 0;
+ Size = 0;
+ LastOffset = 0;
+ WhatToDo = FileTypeNone;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // Check for -d
+ //
+ if (ShellCommandLineGetFlag(Package, L"-d")){
+ if (ShellCommandLineGetCount(Package) < 4) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetCount(Package) > 4) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ WhatToDo = FileTypeDiskBuffer;
+ Name = ShellCommandLineGetRawValue(Package, 1);
+ Offset = ShellStrToUintn(ShellCommandLineGetRawValue(Package, 2));
+ Size = ShellStrToUintn(ShellCommandLineGetRawValue(Package, 3));
+ }
+ }
+
+ //
+ // check for -f
+ //
+ if (ShellCommandLineGetFlag(Package, L"-f") && (WhatToDo == FileTypeNone)){
+ if (ShellCommandLineGetCount(Package) > 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Name = ShellCommandLineGetRawValue(Package, 1);
+ if (!IsValidFileName(Name)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, Name);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ WhatToDo = FileTypeFileBuffer;
+ }
+ }
+ }
+
+ //
+ // check for -m
+ //
+ if (ShellCommandLineGetFlag(Package, L"-m") && (WhatToDo == FileTypeNone)){
+ if (ShellCommandLineGetCount(Package) < 3) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetCount(Package) > 3) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ WhatToDo = FileTypeMemBuffer;
+ Offset = ShellStrToUintn(ShellCommandLineGetRawValue(Package, 1));
+ Size = ShellStrToUintn(ShellCommandLineGetRawValue(Package, 2));
+ }
+ }
+ ShellCommandLineFreeVarList (Package);
+
+ if (ShellStatus == SHELL_SUCCESS && WhatToDo == FileTypeNone) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+
+ if (ShellStatus == SHELL_SUCCESS) {
+ //
+ // Do the editor
+ //
+ Status = HMainEditorInit ();
+ if (EFI_ERROR (Status)) {
+ gST->ConOut->ClearScreen (gST->ConOut);
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_INIT_FAILED), gShellDebug1HiiHandle);
+ } else {
+ HMainEditorBackup ();
+ switch (WhatToDo) {
+ case FileTypeFileBuffer:
+ Status = HBufferImageRead (
+ Name,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ FileTypeFileBuffer,
+ FALSE
+ );
+ break;
+
+ case FileTypeDiskBuffer:
+ Status = HBufferImageRead (
+ NULL,
+ Name,
+ Offset,
+ Size,
+ 0,
+ 0,
+ FileTypeDiskBuffer,
+ FALSE
+ );
+ break;
+
+ case FileTypeMemBuffer:
+ Status = HBufferImageRead (
+ NULL,
+ NULL,
+ 0,
+ 0,
+ (UINT32) Offset,
+ Size,
+ FileTypeMemBuffer,
+ FALSE
+ );
+ break;
+
+ }
+ if (!EFI_ERROR (Status)) {
+ HMainEditorRefresh ();
+ Status = HMainEditorKeyInput ();
+ }
+ if (Status != EFI_OUT_OF_RESOURCES) {
+ //
+ // back up the status string
+ //
+ Buffer = CatSPrint (NULL, L"%s", StatusBarGetString());
+ }
+ }
+
+ //
+ // cleanup
+ //
+ HMainEditorCleanup ();
+
+ if (!EFI_ERROR (Status)) {
+ if (ShellStatus == SHELL_SUCCESS) {
+ ShellStatus = SHELL_UNSUPPORTED;
+ }
+ }
+
+ //
+ // print editor exit code on screen
+ //
+ if (Status == EFI_OUT_OF_RESOURCES) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle);
+ } else if (EFI_ERROR(Status)){
+ if (Buffer != NULL) {
+ if (StrCmp (Buffer, L"") != 0) {
+ //
+ // print out the status string
+ //
+ ShellPrintEx(-1, -1, L"%s", gShellDebug1HiiHandle, Buffer);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_UNKNOWN_EDITOR), gShellDebug1HiiHandle);
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_UNKNOWN_EDITOR), gShellDebug1HiiHandle);
+ }
+ }
+ }
+ }
+
+ SHELL_FREE_NON_NULL (Buffer);
+ return ShellStatus;
+}
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditor.h b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditor.h
new file mode 100644
index 0000000000..d0a4bf4aae
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditor.h
@@ -0,0 +1,41 @@
+/** @file
+ Main include file for hex editor
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _EFI_SHELL_HEXEDIT_H_
+#define _EFI_SHELL_HEXEDIT_H_
+
+#include "UefiShellDebug1CommandsLib.h"
+#include "HexEditorTypes.h"
+
+#include "MainHexEditor.h"
+
+#include "BufferImage.h"
+#include "FileImage.h"
+#include "DiskImage.h"
+#include "MemImage.h"
+
+#include "EditTitleBar.h"
+#include "EditStatusBar.h"
+#include "EditInputBar.h"
+#include "EditMenuBar.h"
+
+#include "Misc.h"
+
+#include "Clipboard.h"
+
+extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;
+extern BOOLEAN HEditorFirst;
+extern BOOLEAN HEditorExit;
+
+#endif // _HEDITOR_H
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditorTypes.h b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditorTypes.h
new file mode 100644
index 0000000000..51c9f44cd5
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditorTypes.h
@@ -0,0 +1,132 @@
+/** @file
+ data types that are used by editor
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _HEDITOR_TYPE_H_
+#define _HEDITOR_TYPE_H_
+
+#include "UefiShellDebug1CommandsLib.h"
+#include "EditTitleBar.h"
+
+#define EFI_EDITOR_LINE_LIST 'eell'
+
+#define ASCII_POSITION ((0x10 * 3) + 12)
+
+
+typedef struct {
+ UINTN Row;
+ UINTN Column;
+} HEFI_EDITOR_POSITION;
+
+typedef
+EFI_STATUS
+(*HEFI_MENU_ITEM_FUNCTION) (
+ VOID
+ );
+
+typedef struct {
+ CHAR16 Name[50];
+ CHAR16 Key[3];
+ HEFI_MENU_ITEM_FUNCTION Function;
+} HMENU_ITEMS;
+
+typedef struct _HEFI_EDITOR_LINE {
+ UINTN Signature;
+ UINT8 Buffer[0x10];
+ UINTN Size; // unit is Unicode
+ LIST_ENTRY Link;
+} HEFI_EDITOR_LINE;
+
+typedef struct _HEFI_EDITOR_MENU_ITEM {
+ CHAR16 NameToken;
+ CHAR16 FunctionKeyToken;
+ HEFI_MENU_ITEM_FUNCTION Function;
+} HEFI_EDITOR_MENU_ITEM;
+
+typedef struct {
+ UINT32 Foreground : 4;
+ UINT32 Background : 4;
+} HEFI_EDITOR_COLOR_ATTRIBUTES;
+
+typedef union {
+ HEFI_EDITOR_COLOR_ATTRIBUTES Colors;
+ UINT8 Data;
+} HEFI_EDITOR_COLOR_UNION;
+
+typedef struct {
+ UINTN Columns;
+ UINTN Rows;
+} HEFI_EDITOR_TEXT_MODE;
+
+
+typedef struct {
+ CHAR16 *Name;
+
+ UINTN BlockSize;
+ UINTN Size;
+ UINTN Offset;
+} HEFI_EDITOR_DISK_IMAGE;
+
+typedef struct {
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoFncs;
+
+ UINTN Offset;
+ UINTN Size;
+} HEFI_EDITOR_MEM_IMAGE;
+
+typedef struct {
+ CHAR16 *FileName;
+ UINTN Size; // file size
+ BOOLEAN ReadOnly; // file is read-only or not
+} HEFI_EDITOR_FILE_IMAGE;
+
+typedef struct {
+ LIST_ENTRY *ListHead; // list head of lines
+ HEFI_EDITOR_LINE *Lines; // lines of current file
+ UINTN NumLines; // number of lines
+ HEFI_EDITOR_LINE *CurrentLine; // current line cursor is at
+ HEFI_EDITOR_POSITION DisplayPosition; // cursor position in screen
+ HEFI_EDITOR_POSITION MousePosition; // mouse position in screen
+ HEFI_EDITOR_POSITION BufferPosition; // cursor position in buffer
+ UINTN LowVisibleRow; // the lowest visible row of file position
+ BOOLEAN HighBits; // cursor is at the high4 bits or low4 bits
+ BOOLEAN Modified; // BUFFER is modified or not
+ EDIT_FILE_TYPE BufferType;
+
+ HEFI_EDITOR_FILE_IMAGE *FileImage;
+ HEFI_EDITOR_DISK_IMAGE *DiskImage;
+ HEFI_EDITOR_MEM_IMAGE *MemImage;
+
+} HEFI_EDITOR_BUFFER_IMAGE;
+
+typedef struct {
+ UINT8 *Buffer;
+ UINTN Size;
+} HEFI_EDITOR_CLIPBOARD;
+
+typedef struct {
+ HEFI_EDITOR_BUFFER_IMAGE *BufferImage;
+ HEFI_EDITOR_CLIPBOARD *Clipboard;
+
+ HEFI_EDITOR_COLOR_UNION ColorAttributes;
+ HEFI_EDITOR_POSITION ScreenSize; // row number and column number
+ BOOLEAN MouseSupported;
+ EFI_SIMPLE_POINTER_PROTOCOL *MouseInterface;
+ INT32 MouseAccumulatorX;
+ INT32 MouseAccumulatorY;
+
+ UINTN SelectStart; // starting from 1
+ UINTN SelectEnd; // starting from 1
+} HEFI_EDITOR_GLOBAL_EDITOR;
+
+#endif
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexeditStrings.uni b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexeditStrings.uni
new file mode 100644
index 0000000000..3389444f62
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexeditStrings.uni
Binary files differ
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.c b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.c
new file mode 100644
index 0000000000..387a1e2d1e
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.c
@@ -0,0 +1,2294 @@
+/** @file
+ Defines the Main Editor data type -
+ - Global variables
+ - Instances of the other objects of the editor
+ - Main Interfaces
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HexEditor.h"
+#include "EditStatusBar.h"
+#include "EditInputBar.h"
+
+HEFI_EDITOR_COLOR_ATTRIBUTES HOriginalColors;
+INTN HOriginalMode;
+
+//
+// the first time editor launch
+//
+BOOLEAN HEditorFirst;
+
+//
+// it's time editor should exit
+//
+BOOLEAN HEditorExit;
+
+BOOLEAN HEditorMouseAction;
+
+extern HEFI_EDITOR_BUFFER_IMAGE HBufferImage;
+extern HEFI_EDITOR_BUFFER_IMAGE HBufferImageBackupVar;
+
+extern HEFI_EDITOR_CLIPBOARD HClipBoard;
+
+extern BOOLEAN HBufferImageMouseNeedRefresh;
+extern BOOLEAN HBufferImageNeedRefresh;
+extern BOOLEAN HBufferImageOnlyLineNeedRefresh;
+
+HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;
+HEFI_EDITOR_GLOBAL_EDITOR HMainEditorBackupVar;
+
+//
+// basic initialization for MainEditor
+//
+HEFI_EDITOR_GLOBAL_EDITOR HMainEditorConst = {
+ &HBufferImage,
+ &HClipBoard,
+ {
+ 0,
+ 0
+ },
+ {
+ 0,
+ 0
+ },
+ FALSE,
+ NULL,
+ 0,
+ 0,
+ 1,
+ 1
+};
+
+EFI_STATUS
+HMainCommandGoToOffset (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ move cursor to specified lines
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ UINTN Size;
+ UINT64 Offset;
+ EFI_STATUS Status;
+ UINTN FRow;
+ UINTN FCol;
+
+ //
+ // variable initialization
+ //
+ Size = 0;
+ Offset = 0;
+ FRow = 0;
+ FCol = 0;
+
+ //
+ // get offset
+ //
+ Status = InputBarSetPrompt (L"Go To Offset: ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (8);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ while (1) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+
+ return EFI_SUCCESS;
+ }
+ //
+ // THE input string length should > 0
+ //
+ if (StrLen (InputBarGetString()) > 0) {
+ Status = ShellConvertStringToUint64 (InputBarGetString(), &Offset, TRUE, FALSE);
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Invalid Offset");
+ return EFI_SUCCESS;
+ }
+
+ break;
+ }
+ }
+
+ Size = HBufferImageGetTotalSize ();
+ if (Offset >= Size) {
+ StatusBarSetStatusString (L"Invalid Offset");
+ return EFI_SUCCESS;
+ }
+
+ FRow = (UINTN)DivU64x32(Offset , 0x10) + 1;
+ FCol = (UINTN)ModU64x32(Offset , 0x10) + 1;
+
+ HBufferImageMovePosition (FRow, FCol, TRUE);
+
+ HBufferImageNeedRefresh = TRUE;
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+ HBufferImageMouseNeedRefresh = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HMainCommandSaveBuffer (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ save current opened buffer .
+ if is file buffer, you can save to current file name or
+ save to another file name
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_OUT_OF_RESOURCES
+ EFI_LOAD_ERROR
+
+--*/
+{
+ EFI_STATUS Status;
+ BOOLEAN Done;
+ CHAR16 *FileName;
+ BOOLEAN OldFile;
+ CHAR16 *Str;
+ EFI_FILE_INFO *Info;
+ SHELL_FILE_HANDLE ShellFileHandle;
+
+ if (HMainEditor.BufferImage->BufferType != FileTypeFileBuffer) {
+ if (HMainEditor.BufferImage->Modified == FALSE) {
+ return EFI_SUCCESS;
+ }
+
+ Status = InputBarSetPrompt (L"Dangerous to save disk/mem buffer. Save (Yes/No/Cancel) ? ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // the answer is just one character
+ //
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // loop for user's answer
+ // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'
+ //
+ while (1) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString()[0]) {
+ case L'y':
+ case L'Y':
+ //
+ // want to save this buffer first
+ //
+ Status = HBufferImageSave (
+ NULL,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ HMainEditor.BufferImage->BufferType
+ );
+
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"BufferSave: Problems Writing");
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+
+ case L'n':
+ case L'N':
+ //
+ // the file won't be saved
+ //
+ return EFI_SUCCESS;
+ break;
+
+ case L'c':
+ case L'C':
+ return EFI_SUCCESS;
+ }
+ //
+ // end of switch
+ //
+ }
+ //
+ // ENDOF WHILE
+ //
+ }
+ //
+ // ENDOF != FILEBUFFER
+ //
+ // This command will save currently opened file to disk.
+ // You can choose save to another file name or just save to
+ // current file name.
+ // Below is the scenario of Save File command: (
+ // Suppose the old file name is A )
+ // 1. An Input Bar will be prompted: "File To Save: [ old file name]"
+ // IF user press ESC, Save File command ends .
+ // IF user press Enter, input file name will be A.
+ // IF user inputs a new file name B, input file name will be B.
+ //
+ // 2. IF input file name is A, go to do Step 3.
+ // IF input file name is B, go to do Step 4.
+ //
+ // 3. IF A is read only, Status Bar will show "Access Denied"
+ // and Save File commands ends.
+ // IF A is not read only, save file buffer to disk
+ // and remove Modified flag in Title Bar , then Save File command ends.
+ //
+ // 4. IF B does not exist, create this file and save file buffer to it.
+ // Go to do Step 7.
+ // IF B exits, do Step 5.
+ //
+ // 5. An Input Bar will be prompted:
+ // "File Exists. Overwrite ( Yes/No/Cancel ) ?"
+ // IF user press 'y' or 'Y', do Step 6.
+ // IF user press 'n' or 'N', Save File commands ends.
+ // IF user press 'c' or 'C' or ESC, Save File commands ends.
+ //
+ // 6. IF B is a read-only file, Status Bar will show "Access Denied"
+ // and Save File commands ends.
+ // IF B can be read and write, save file buffer to B.
+ //
+ // 7. Update File Name field in Title Bar to B
+ // and remove the Modified flag in Title Bar.
+ //
+ Str = CatSPrint(NULL,
+ L"File to Save: [%s]",
+ HMainEditor.BufferImage->FileImage->FileName
+ );
+ if (Str == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (StrLen (Str) >= 50) {
+ //
+ // replace the long file name with "..."
+ //
+ Str[46] = L'.';
+ Str[47] = L'.';
+ Str[48] = L'.';
+ Str[49] = L']';
+ Str[50] = L'\0';
+ }
+
+ Status = InputBarSetPrompt (Str);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (100);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // get new file name
+ //
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // if user pressed ESC
+ //
+ if (Status == EFI_NOT_READY) {
+ SHELL_FREE_NON_NULL (Str);
+ return EFI_SUCCESS;
+ }
+
+ SHELL_FREE_NON_NULL (Str);
+
+ //
+ // if just enter pressed, so think save to current file name
+ //
+ if (StrLen (InputBarGetString()) == 0) {
+ FileName = CatSPrint(NULL,
+ L"%s",
+ HMainEditor.BufferImage->FileImage->FileName
+ );
+ } else {
+ FileName = CatSPrint(NULL, L"%s", InputBarGetString());
+ }
+
+ if (FileName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (!IsValidFileName (FileName)) {
+ StatusBarSetStatusString (L"Invalid File Name");
+ SHELL_FREE_NON_NULL (FileName);
+ return EFI_SUCCESS;
+ }
+
+ OldFile = FALSE;
+
+ //
+ // save to the old file
+ //
+ if (StringNoCaseCompare (
+ &FileName,
+ &HMainEditor.BufferImage->FileImage->FileName
+ ) == 0) {
+ OldFile = TRUE;
+ }
+
+ if (OldFile) {
+ //
+ // if the file is read only, so can not write back to it.
+ //
+ if (HMainEditor.BufferImage->FileImage->ReadOnly == TRUE) {
+ StatusBarSetStatusString (L"Access Denied");
+ SHELL_FREE_NON_NULL (FileName);
+ return EFI_SUCCESS;
+ }
+ } else {
+ Status = ShellOpenFileByName (FileName, &ShellFileHandle, EFI_FILE_MODE_READ, 0);
+
+ if (!EFI_ERROR (Status)) {
+
+ Info = ShellGetFileInfo(ShellFileHandle);
+
+ ShellCloseFile(&ShellFileHandle);
+ //
+ // check if read only
+ //
+ if (Info->Attribute & EFI_FILE_READ_ONLY) {
+ StatusBarSetStatusString (L"Access Denied");
+ SHELL_FREE_NON_NULL (FileName);
+ return EFI_SUCCESS;
+ }
+
+ SHELL_FREE_NON_NULL(Info);
+ //
+ // ask user whether to overwrite this file
+ //
+ Status = InputBarSetPrompt (L"File exists. Overwrite (Yes/No/Cancel) ? ");
+ if (EFI_ERROR (Status)) {
+ SHELL_FREE_NON_NULL (FileName);
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ SHELL_FREE_NON_NULL (FileName);
+ return Status;
+ }
+
+ Done = FALSE;
+ while (!Done) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ if (Status == EFI_NOT_READY) {
+ SHELL_FREE_NON_NULL (FileName);
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString()[0]) {
+ case L'y':
+ case L'Y':
+ Done = TRUE;
+ break;
+ case L'n':
+ case L'N':
+ SHELL_FREE_NON_NULL (FileName);
+ return EFI_SUCCESS;
+ case L'c':
+ case L'C':
+ SHELL_FREE_NON_NULL (FileName);
+ return EFI_SUCCESS;
+ } // switch
+ } // while
+ } // if opened existing file
+ } // if OldFile
+
+ //
+ // save file back to disk
+ //
+ Status = HBufferImageSave (
+ FileName,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ FileTypeFileBuffer
+ );
+ SHELL_FREE_NON_NULL (FileName);
+
+ if (EFI_ERROR (Status)) {
+ return EFI_LOAD_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HMainCommandSelectStart (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Load a disk buffer editor
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_LOAD_ERROR
+ EFI_OUT_OF_RESOURCES
+
+--*/
+{
+ UINTN Start;
+
+ Start = (HMainEditor.BufferImage->BufferPosition.Row - 1) * 0x10 + HMainEditor.BufferImage->BufferPosition.Column;
+
+ //
+ // last line
+ //
+ if (HMainEditor.BufferImage->CurrentLine->Link.ForwardLink == HMainEditor.BufferImage->ListHead) {
+ if (HMainEditor.BufferImage->BufferPosition.Column > HMainEditor.BufferImage->CurrentLine->Size) {
+ StatusBarSetStatusString (L"Invalid Block Start");
+ return EFI_LOAD_ERROR;
+ }
+ }
+
+ if (HMainEditor.SelectEnd != 0 && Start > HMainEditor.SelectEnd) {
+ StatusBarSetStatusString (L"Invalid Block Start");
+ return EFI_LOAD_ERROR;
+ }
+
+ HMainEditor.SelectStart = Start;
+
+ HBufferImageNeedRefresh = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HMainCommandSelectEnd (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Load a disk buffer editor
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_LOAD_ERROR
+ EFI_OUT_OF_RESOURCES
+
+--*/
+{
+ UINTN End;
+
+ End = (HMainEditor.BufferImage->BufferPosition.Row - 1) * 0x10 + HMainEditor.BufferImage->BufferPosition.Column;
+
+ //
+ // last line
+ //
+ if (HMainEditor.BufferImage->CurrentLine->Link.ForwardLink == HMainEditor.BufferImage->ListHead) {
+ if (HMainEditor.BufferImage->BufferPosition.Column > HMainEditor.BufferImage->CurrentLine->Size) {
+ StatusBarSetStatusString (L"Invalid Block End");
+ return EFI_LOAD_ERROR;
+ }
+ }
+
+ if (HMainEditor.SelectStart != 0 && End < HMainEditor.SelectStart) {
+ StatusBarSetStatusString (L"Invalid Block End");
+ return EFI_SUCCESS;
+ }
+
+ HMainEditor.SelectEnd = End;
+
+ HBufferImageNeedRefresh = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HMainCommandCut (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ cut current line to clipboard
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_OUT_OF_RESOURCES
+ EFI_LOAD_ERROR
+
+--*/
+{
+ UINTN Index;
+ HEFI_EDITOR_LINE *Line;
+ LIST_ENTRY *Link;
+ UINT8 *Buffer;
+ UINTN Count;
+
+ //
+ // not select, so not allowed to cut
+ //
+ if (HMainEditor.SelectStart == 0) {
+ StatusBarSetStatusString (L"No Block is Selected");
+ return EFI_SUCCESS;
+ }
+ //
+ // not select, so not allowed to cut
+ //
+ if (HMainEditor.SelectEnd == 0) {
+ StatusBarSetStatusString (L"No Block is Selected");
+ return EFI_SUCCESS;
+ }
+
+ Link = HMainEditor.BufferImage->ListHead->ForwardLink;
+ for (Index = 0; Index < (HMainEditor.SelectEnd - 1) / 0x10; Index++) {
+ Link = Link->ForwardLink;
+ }
+
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+
+ Count = HMainEditor.SelectEnd - HMainEditor.SelectStart + 1;
+ Buffer = AllocateZeroPool (Count);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // cut the selected area
+ //
+ HBufferImageDeleteCharacterFromBuffer (
+ HMainEditor.SelectStart - 1,
+ Count,
+ Buffer
+ );
+
+ //
+ // put to clipboard
+ //
+ HClipBoardSet (Buffer, Count);
+
+ HBufferImageNeedRefresh = TRUE;
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+
+ if (!HMainEditor.BufferImage->Modified) {
+ HMainEditor.BufferImage->Modified = TRUE;
+ }
+
+ //
+ // now no select area
+ //
+ HMainEditor.SelectStart = 0;
+ HMainEditor.SelectEnd = 0;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HMainCommandPaste (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ paste line to file buffer
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_OUT_OF_RESOURCES
+ EFI_LOAD_ERROR
+
+
+--*/
+{
+
+ BOOLEAN OnlyLineRefresh;
+ HEFI_EDITOR_LINE *Line;
+ UINT8 *Buffer;
+ UINTN Count;
+ UINTN FPos;
+
+ Count = HClipBoardGet (&Buffer);
+ if (Count == 0 || Buffer == NULL) {
+ StatusBarSetStatusString (L"Nothing to Paste");
+ return EFI_SUCCESS;
+ }
+
+ Line = HMainEditor.BufferImage->CurrentLine;
+
+ OnlyLineRefresh = FALSE;
+ if (Line->Link.ForwardLink == HMainEditor.BufferImage->ListHead && Line->Size + Count < 0x10) {
+ //
+ // is at last line, and after paste will not exceed
+ // so only this line need to be refreshed
+ //
+ // if after add, the line is 0x10, then will append a new line
+ // so the whole page will need be refreshed
+ //
+ OnlyLineRefresh = TRUE;
+
+ }
+
+ FPos = 0x10 * (HMainEditor.BufferImage->BufferPosition.Row - 1) + HMainEditor.BufferImage->BufferPosition.Column - 1;
+
+ HBufferImageAddCharacterToBuffer (FPos, Count, Buffer);
+
+ if (OnlyLineRefresh) {
+ HBufferImageNeedRefresh = FALSE;
+ HBufferImageOnlyLineNeedRefresh = TRUE;
+ } else {
+ HBufferImageNeedRefresh = TRUE;
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+ }
+
+ if (!HMainEditor.BufferImage->Modified) {
+ HMainEditor.BufferImage->Modified = TRUE;
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+HMainCommandExit (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ exit editor
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_OUT_OF_RESOURCES
+ EFI_LOAD_ERROR
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // Below is the scenario of Exit command:
+ // 1. IF currently opened file is not modified, exit the editor and
+ // Exit command ends.
+ // IF currently opened file is modified, do Step 2
+ //
+ // 2. An Input Bar will be prompted:
+ // "File modified. Save ( Yes/No/Cancel )?"
+ // IF user press 'y' or 'Y', currently opened file will be saved and
+ // Editor exits
+ // IF user press 'n' or 'N', currently opened file will not be saved
+ // and Editor exits.
+ // IF user press 'c' or 'C' or ESC, Exit command ends.
+ //
+ //
+ // if file has been modified, so will prompt user
+ // whether to save the changes
+ //
+ if (HMainEditor.BufferImage->Modified) {
+
+ Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ while (1) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString()[0]) {
+ case L'y':
+ case L'Y':
+ //
+ // write file back to disk
+ //
+ Status = HBufferImageSave (
+ HMainEditor.BufferImage->FileImage->FileName,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ HMainEditor.BufferImage->BufferType
+ );
+ if (!EFI_ERROR (Status)) {
+ HEditorExit = TRUE;
+ }
+
+ return Status;
+
+ case L'n':
+ case L'N':
+ HEditorExit = TRUE;
+ return EFI_SUCCESS;
+
+ case L'c':
+ case L'C':
+ return EFI_SUCCESS;
+
+ }
+ }
+ }
+
+ HEditorExit = TRUE;
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+HMainCommandOpenFile (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Load a file from disk to editor
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_LOAD_ERROR
+ EFI_OUT_OF_RESOURCES
+
+--*/
+{
+ BOOLEAN Done;
+ EFI_STATUS Status;
+ EDIT_FILE_TYPE BufferType;
+
+ BufferType = HMainEditor.BufferImage->BufferType;
+
+ //
+ // This command will open a file from current working directory.
+ // Read-only file can also be opened. But it can not be modified.
+ // Below is the scenario of Open File command:
+ // 1. IF currently opened file has not been modified, directly go to step .
+ // IF currently opened file has been modified, an Input Bar will be
+ // prompted as :
+ // "File Modified. Save ( Yes/No/Cancel) ?"
+ // IF user press 'y' or 'Y', currently opened file will be saved.
+ // IF user press 'n' or 'N', currently opened file will
+ // not be saved.
+ // IF user press 'c' or 'C' or ESC, Open File command ends and
+ // currently opened file is still opened.
+ //
+ // 2. An Input Bar will be prompted as : "File Name to Open: "
+ // IF user press ESC, Open File command ends and
+ // currently opened file is still opened.
+ // Any other inputs with a Return will cause
+ // currently opened file close.
+ //
+ // 3. IF user input file name is an existing file ,
+ // this file will be read and opened.
+ // IF user input file name is a new file, this file will be created
+ // and opened. This file's type ( UNICODE or ASCII ) is the same with
+ // the old file.
+ //
+ //
+ // if current file is modified, so you need to choose whether to
+ // save it first.
+ //
+ if (HMainEditor.BufferImage->Modified) {
+
+ Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // the answer is just one character
+ //
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // loop for user's answer
+ // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'
+ //
+ Done = FALSE;
+ while (!Done) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString()[0]) {
+ case L'y':
+ case L'Y':
+ //
+ // want to save this buffer first
+ //
+ Status = HBufferImageSave (
+ HMainEditor.BufferImage->FileImage->FileName,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ HMainEditor.BufferImage->BufferType
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ MainTitleBarRefresh (
+ HMainEditor.BufferImage->BufferType == FileTypeFileBuffer?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Name:NULL,
+ HMainEditor.BufferImage->BufferType,
+ HMainEditor.BufferImage->FileImage->ReadOnly,
+ FALSE,
+ HMainEditor.ScreenSize.Column,
+ HMainEditor.ScreenSize.Row
+ );
+ Done = TRUE;
+ break;
+
+ case L'n':
+ case L'N':
+ //
+ // the file won't be saved
+ //
+ Done = TRUE;
+ break;
+
+ case L'c':
+ case L'C':
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ //
+ // TO get the open file name
+ //
+ Status = InputBarSetPrompt (L"File Name to Open: ");
+ if (EFI_ERROR (Status)) {
+ HBufferImageRead (
+ HMainEditor.BufferImage->FileImage->FileName,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ BufferType,
+ TRUE
+ );
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (100);
+ if (EFI_ERROR (Status)) {
+ Status = HBufferImageRead (
+ HMainEditor.BufferImage->FileImage->FileName,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ BufferType,
+ TRUE
+ );
+ return Status;
+ }
+
+ while (1) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ Status = HBufferImageRead (
+ HMainEditor.BufferImage->FileImage->FileName,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ BufferType,
+ TRUE
+ );
+
+ return Status;
+ }
+ //
+ // THE input string length should > 0
+ //
+ if (StrLen (InputBarGetString()) > 0) {
+ //
+ // CHECK if filename's valid
+ //
+ if (!IsValidFileName (InputBarGetString())) {
+ HBufferImageRead (
+ HMainEditor.BufferImage->FileImage->FileName,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ BufferType,
+ TRUE
+ );
+
+ StatusBarSetStatusString (L"Invalid File Name");
+ return EFI_SUCCESS;
+ }
+
+ break;
+ }
+ }
+ //
+ // read from disk
+ //
+ Status = HBufferImageRead (
+ InputBarGetString(),
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ FileTypeFileBuffer,
+ FALSE
+ );
+
+ if (EFI_ERROR (Status)) {
+ HBufferImageRead (
+ HMainEditor.BufferImage->FileImage->FileName,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ BufferType,
+ TRUE
+ );
+
+ return EFI_LOAD_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HMainCommandOpenDisk (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Load a disk buffer editor
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_LOAD_ERROR
+ EFI_OUT_OF_RESOURCES
+ EFI_NOT_FOUND
+
+--*/
+{
+ UINT64 Size;
+ UINT64 Offset;
+ CHAR16 *DeviceName;
+ EFI_STATUS Status;
+ BOOLEAN Done;
+
+ EDIT_FILE_TYPE BufferType;
+
+ //
+ // variable initialization
+ //
+ Size = 0;
+ Offset = 0;
+ BufferType = HMainEditor.BufferImage->BufferType;
+
+ //
+ // if current file is modified, so you need to choose
+ // whether to save it first.
+ //
+ if (HMainEditor.BufferImage->Modified) {
+
+ Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // the answer is just one character
+ //
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // loop for user's answer
+ // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'
+ //
+ Done = FALSE;
+ while (!Done) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString()[0]) {
+ case L'y':
+ case L'Y':
+ //
+ // want to save this buffer first
+ //
+ Status = HBufferImageSave (
+ HMainEditor.BufferImage->FileImage->FileName,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ BufferType
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ MainTitleBarRefresh (
+ HMainEditor.BufferImage->BufferType == FileTypeFileBuffer?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Name:NULL,
+ HMainEditor.BufferImage->BufferType,
+ HMainEditor.BufferImage->FileImage->ReadOnly,
+ FALSE,
+ HMainEditor.ScreenSize.Column,
+ HMainEditor.ScreenSize.Row
+ );
+ Done = TRUE;
+ break;
+
+ case L'n':
+ case L'N':
+ //
+ // the file won't be saved
+ //
+ Done = TRUE;
+ break;
+
+ case L'c':
+ case L'C':
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ //
+ // get disk block device name
+ //
+ Status = InputBarSetPrompt (L"Block Device to Open: ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (100);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ while (1) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+
+ return EFI_SUCCESS;
+ }
+ //
+ // THE input string length should > 0
+ //
+ if (StrLen (InputBarGetString()) > 0) {
+ break;
+ }
+ }
+
+ DeviceName = CatSPrint(NULL, L"%s", InputBarGetString());
+ if (DeviceName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // get starting offset
+ //
+ Status = InputBarSetPrompt (L"First Block No.: ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (16);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ while (1) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+
+ return EFI_SUCCESS;
+ }
+ //
+ // THE input string length should > 0
+ //
+ if (StrLen (InputBarGetString()) > 0) {
+ Status = ShellConvertStringToUint64 (InputBarGetString(), &Offset, TRUE, FALSE);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ break;
+ }
+ }
+ //
+ // get Number of Blocks:
+ //
+ Status = InputBarSetPrompt (L"Number of Blocks: ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (8);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ while (1) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+
+ return EFI_SUCCESS;
+ }
+ //
+ // THE input string length should > 0
+ //
+ if (StrLen (InputBarGetString()) > 0) {
+ Status = ShellConvertStringToUint64 (InputBarGetString(), &Size, TRUE, FALSE);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if (Size == 0) {
+ continue;
+ }
+
+ break;
+ }
+ }
+
+ Status = HBufferImageRead (
+ NULL,
+ DeviceName,
+ (UINTN)Offset,
+ (UINTN)Size,
+ 0,
+ 0,
+ FileTypeDiskBuffer,
+ FALSE
+ );
+
+ if (EFI_ERROR (Status)) {
+
+ HBufferImageRead (
+ HMainEditor.BufferImage->FileImage->FileName,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ BufferType,
+ TRUE
+ );
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HMainCommandOpenMemory (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Load memory content to editor
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_LOAD_ERROR
+ EFI_OUT_OF_RESOURCES
+ EFI_NOT_FOUND
+
+--*/
+{
+ UINT64 Size;
+ UINT64 Offset;
+ EFI_STATUS Status;
+ BOOLEAN Done;
+ EDIT_FILE_TYPE BufferType;
+
+ //
+ // variable initialization
+ //
+ Size = 0;
+ Offset = 0;
+ BufferType = HMainEditor.BufferImage->BufferType;
+
+ //
+ // if current buffer is modified, so you need to choose
+ // whether to save it first.
+ //
+ if (HMainEditor.BufferImage->Modified) {
+
+ Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // the answer is just one character
+ //
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // loop for user's answer
+ // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'
+ //
+ Done = FALSE;
+ while (!Done) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString()[0]) {
+ case L'y':
+ case L'Y':
+ //
+ // want to save this buffer first
+ //
+ Status = HBufferImageSave (
+ HMainEditor.BufferImage->FileImage->FileName,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ BufferType
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ MainTitleBarRefresh (
+ HMainEditor.BufferImage->BufferType == FileTypeFileBuffer?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Name:NULL,
+ HMainEditor.BufferImage->BufferType,
+ HMainEditor.BufferImage->FileImage->ReadOnly,
+ FALSE,
+ HMainEditor.ScreenSize.Column,
+ HMainEditor.ScreenSize.Row
+ );
+ Done = TRUE;
+ break;
+
+ case L'n':
+ case L'N':
+ //
+ // the file won't be saved
+ //
+ Done = TRUE;
+ break;
+
+ case L'c':
+ case L'C':
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ //
+ // get starting offset
+ //
+ Status = InputBarSetPrompt (L"Starting Offset: ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (8);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ while (1) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+
+ return EFI_SUCCESS;
+ }
+ //
+ // THE input string length should > 0
+ //
+ if (StrLen (InputBarGetString()) > 0) {
+ Status = ShellConvertStringToUint64 (InputBarGetString(), &Offset, TRUE, FALSE);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ break;
+ }
+ }
+ //
+ // get Number of Blocks:
+ //
+ Status = InputBarSetPrompt (L"Buffer Size: ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (8);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ while (1) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+
+ return EFI_SUCCESS;
+ }
+ //
+ // THE input string length should > 0
+ //
+ if (StrLen (InputBarGetString()) > 0) {
+ Status = ShellConvertStringToUint64 (InputBarGetString(), &Size, TRUE, FALSE);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if (Size == 0) {
+ continue;
+ }
+
+ break;
+ }
+ }
+
+ if ((Offset + Size - 1)> 0xffffffff) {
+ StatusBarSetStatusString (L"Invalid parameter");
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = HBufferImageRead (
+ NULL,
+ NULL,
+ 0,
+ 0,
+ (UINTN)Offset,
+ (UINTN)Size,
+ FileTypeMemBuffer,
+ FALSE
+ );
+
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Read Device Error!");
+ HBufferImageRead (
+ HMainEditor.BufferImage->FileImage->FileName,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ BufferType,
+ TRUE
+ );
+ return EFI_NOT_FOUND;
+ }
+ return EFI_SUCCESS;
+
+}
+
+CONST EDITOR_MENU_ITEM HexEditorMenuItems[] = {
+ {
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_GO_TO_OFFSET),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F1),
+ HMainCommandGoToOffset
+ },
+ {
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_SAVE_BUFFER),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F2),
+ HMainCommandSaveBuffer
+ },
+ {
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_EXIT),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F3),
+ HMainCommandExit
+ },
+
+ {
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_SELECT_START),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F4),
+ HMainCommandSelectStart
+ },
+ {
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_SELECT_END),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F5),
+ HMainCommandSelectEnd
+ },
+ {
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_CUT),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F6),
+ HMainCommandCut
+ },
+ {
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_PASTE),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F7),
+ HMainCommandPaste
+ },
+
+ {
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_OPEN_FILE),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F8),
+ HMainCommandOpenFile
+ },
+ {
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_OPEN_DISK),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F9),
+ HMainCommandOpenDisk
+ },
+ {
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_OPEN_MEMORY),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F10),
+ HMainCommandOpenMemory
+ },
+
+ {
+ 0,
+ 0,
+ NULL
+ }
+};
+
+
+EFI_STATUS
+HMainEditorInit (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Init function for MainEditor
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_LOAD_ERROR
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+ UINTN Index;
+
+ //
+ // basic initialization
+ //
+ CopyMem (&HMainEditor, &HMainEditorConst, sizeof (HMainEditor));
+
+ //
+ // set screen attributes
+ //
+ HMainEditor.ColorAttributes.Colors.Foreground = gST->ConOut->Mode->Attribute & 0x000000ff;
+
+ HMainEditor.ColorAttributes.Colors.Background = (UINT8) (gST->ConOut->Mode->Attribute >> 4);
+
+ HOriginalColors = HMainEditor.ColorAttributes.Colors;
+
+ HOriginalMode = gST->ConOut->Mode->Mode;
+
+ //
+ // query screen size
+ //
+ gST->ConOut->QueryMode (
+ gST->ConOut,
+ gST->ConOut->Mode->Mode,
+ &(HMainEditor.ScreenSize.Column),
+ &(HMainEditor.ScreenSize.Row)
+ );
+
+ //
+ // Find mouse in System Table ConsoleInHandle
+ //
+ Status = gBS->HandleProtocol (
+ gST->ConIn,
+ &gEfiSimplePointerProtocolGuid,
+ (VOID**)&HMainEditor.MouseInterface
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // If there is no Simple Pointer Protocol on System Table
+ //
+ HandleBuffer = NULL;
+ HMainEditor.MouseInterface = NULL;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSimplePointerProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (!EFI_ERROR (Status) && HandleCount > 0) {
+ //
+ // Try to find the first available mouse device
+ //
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiSimplePointerProtocolGuid,
+ (VOID**)&HMainEditor.MouseInterface
+ );
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ }
+ }
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+ }
+
+ if (!EFI_ERROR (Status) && HMainEditor.MouseInterface != NULL) {
+ HMainEditor.MouseAccumulatorX = 0;
+ HMainEditor.MouseAccumulatorY = 0;
+ HMainEditor.MouseSupported = TRUE;
+ }
+
+ //
+ // below will call the five components' init function
+ //
+ Status = MainTitleBarInit (NULL);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_TITLE), gShellDebug1HiiHandle);
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = MenuBarInit (HexEditorMenuItems);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_MAINMENU), gShellDebug1HiiHandle);
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = StatusBarInit ();
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_STATUS), gShellDebug1HiiHandle);
+ return EFI_LOAD_ERROR;
+ }
+
+ InputBarInit ();
+
+ Status = HBufferImageInit ();
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_BUFFERIMAGE), gShellDebug1HiiHandle);
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = HClipBoardInit ();
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_CLIPBOARD), gShellDebug1HiiHandle);
+ return EFI_LOAD_ERROR;
+ }
+ //
+ // clear whole screen and enable cursor
+ //
+ gST->ConOut->ClearScreen (gST->ConOut);
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+
+ //
+ // initialize EditorFirst and EditorExit
+ //
+ HEditorFirst = TRUE;
+ HEditorExit = FALSE;
+ HEditorMouseAction = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HMainEditorCleanup (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ cleanup function for MainEditor
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_LOAD_ERROR
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // call the five components' cleanup function
+ //
+ MainTitleBarCleanup ();
+
+ MenuBarCleanup ();
+
+ StatusBarCleanup ();
+
+ InputBarCleanup ();
+
+ Status = HBufferImageCleanup ();
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_BUFFERIMAGE_CLEAN), gShellDebug1HiiHandle);
+ }
+
+ Status = HClipBoardCleanup ();
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_CLIPBOARD_CLEAN), gShellDebug1HiiHandle);
+ }
+ //
+ // restore old mode
+ //
+ if (HOriginalMode != gST->ConOut->Mode->Mode) {
+ gST->ConOut->SetMode (gST->ConOut, HOriginalMode);
+ }
+
+ gST->ConOut->SetAttribute (
+ gST->ConOut,
+ EFI_TEXT_ATTR (HOriginalColors.Foreground, HOriginalColors.Background)
+ );
+ gST->ConOut->ClearScreen (gST->ConOut);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HMainEditorRefresh (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Refresh function for MainEditor
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ //
+ // to aVOID screen flicker
+ // the stall value is from experience
+ //
+ gBS->Stall (50);
+
+ //
+ // call the four components refresh function
+ //
+ MainTitleBarRefresh (
+ HMainEditor.BufferImage->BufferType == FileTypeFileBuffer?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Name:NULL,
+ HMainEditor.BufferImage->BufferType,
+ HMainEditor.BufferImage->FileImage->ReadOnly,
+ HMainEditor.BufferImage->Modified,
+ HMainEditor.ScreenSize.Column,
+ HMainEditor.ScreenSize.Row
+ );
+ HBufferImageRefresh ();
+ StatusBarRefresh (
+ HEditorFirst,
+ HMainEditor.ScreenSize.Row,
+ HMainEditor.ScreenSize.Column,
+ 0,
+ 0,
+ TRUE
+ );
+ MenuBarRefresh (
+ HMainEditor.ScreenSize.Row,
+ HMainEditor.ScreenSize.Column);
+
+ //
+ // EditorFirst is now set to FALSE
+ //
+ HEditorFirst = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+HMainEditorHandleMouseInput (
+ IN EFI_SIMPLE_POINTER_STATE MouseState,
+ OUT BOOLEAN *BeforeLeftButtonDown
+ )
+{
+
+ INT32 TextX;
+ INT32 TextY;
+ UINTN FRow;
+ UINTN FCol;
+ BOOLEAN HighBits;
+ LIST_ENTRY *Link;
+ HEFI_EDITOR_LINE *Line;
+ UINTN Index;
+ BOOLEAN Action;
+
+ Action = FALSE;
+
+ //
+ // have mouse movement
+ //
+ if (MouseState.RelativeMovementX || MouseState.RelativeMovementY) {
+ //
+ // handle
+ //
+ TextX = HGetTextX (MouseState.RelativeMovementX);
+ TextY = HGetTextY (MouseState.RelativeMovementY);
+
+ HBufferImageAdjustMousePosition (TextX, TextY);
+
+ Action = TRUE;
+
+ }
+
+ if (MouseState.LeftButton) {
+ HighBits = HBufferImageIsAtHighBits (
+ HMainEditor.BufferImage->MousePosition.Column,
+ &FCol
+ );
+
+ //
+ // not at an movable place
+ //
+ if (FCol == 0) {
+ //
+ // now just move mouse pointer to legal position
+ //
+ //
+ // move mouse position to legal position
+ //
+ HMainEditor.BufferImage->MousePosition.Column -= 10;
+ if (HMainEditor.BufferImage->MousePosition.Column > 24) {
+ HMainEditor.BufferImage->MousePosition.Column--;
+ FCol = HMainEditor.BufferImage->MousePosition.Column / 3 + 1 + 1;
+ } else {
+ if (HMainEditor.BufferImage->MousePosition.Column < 24) {
+ FCol = HMainEditor.BufferImage->MousePosition.Column / 3 + 1 + 1;
+ } else {
+ //
+ // == 24
+ //
+ FCol = 9;
+ }
+ }
+
+ HighBits = TRUE;
+
+ }
+
+ FRow = HMainEditor.BufferImage->BufferPosition.Row +
+ HMainEditor.BufferImage->MousePosition.Row -
+ HMainEditor.BufferImage->DisplayPosition.Row;
+
+ if (HMainEditor.BufferImage->NumLines < FRow) {
+ //
+ // dragging
+ //
+ //
+ // now just move mouse pointer to legal position
+ //
+ FRow = HMainEditor.BufferImage->NumLines;
+ HighBits = TRUE;
+ }
+
+ Link = HMainEditor.BufferImage->ListHead->ForwardLink;
+ for (Index = 0; Index < FRow - 1; Index++) {
+ Link = Link->ForwardLink;
+ }
+
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+
+ //
+ // dragging
+ //
+ //
+ // now just move mouse pointer to legal position
+ //
+ if (FCol > Line->Size) {
+ if (*BeforeLeftButtonDown) {
+ HighBits = FALSE;
+
+ if (Line->Size == 0) {
+ if (FRow > 1) {
+ FRow--;
+ FCol = 16;
+ } else {
+ FRow = 1;
+ FCol = 1;
+ }
+
+ } else {
+ FCol = Line->Size;
+ }
+ } else {
+ FCol = Line->Size + 1;
+ HighBits = TRUE;
+ }
+ }
+
+ HBufferImageMovePosition (FRow, FCol, HighBits);
+
+ HMainEditor.BufferImage->MousePosition.Row = HMainEditor.BufferImage->DisplayPosition.Row;
+
+ HMainEditor.BufferImage->MousePosition.Column = HMainEditor.BufferImage->DisplayPosition.Column;
+
+ *BeforeLeftButtonDown = TRUE;
+
+ Action = TRUE;
+ } else {
+ //
+ // else of if LButton
+ //
+ // release LButton
+ //
+ if (*BeforeLeftButtonDown == TRUE) {
+ Action = TRUE;
+ }
+ //
+ // mouse up
+ //
+ *BeforeLeftButtonDown = FALSE;
+ }
+
+ if (Action) {
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+HMainEditorKeyInput (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Handle user key input. will route it to other components handle function
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_LOAD_ERROR
+ EFI_OUT_OF_RESOURCES
+
+--*/
+{
+ EFI_INPUT_KEY Key;
+ EFI_STATUS Status;
+ EFI_SIMPLE_POINTER_STATE MouseState;
+ BOOLEAN LengthChange;
+ UINTN Size;
+ UINTN OldSize;
+ BOOLEAN BeforeMouseIsDown;
+ BOOLEAN MouseIsDown;
+ BOOLEAN FirstDown;
+ BOOLEAN MouseDrag;
+ UINTN FRow;
+ UINTN FCol;
+ UINTN SelectStartBackup;
+ UINTN SelectEndBackup;
+
+ //
+ // variable initialization
+ //
+ OldSize = 0;
+ FRow = 0;
+ FCol = 0;
+ LengthChange = FALSE;
+
+ MouseIsDown = FALSE;
+ FirstDown = FALSE;
+ MouseDrag = FALSE;
+
+ do {
+
+ Status = EFI_SUCCESS;
+
+ HEditorMouseAction = FALSE;
+
+ //
+ // backup some key elements, so that can aVOID some refresh work
+ //
+ HMainEditorBackup ();
+
+ //
+ // wait for user key input
+ //
+ //
+ // change priority of checking mouse/keyboard activity dynamically
+ // so prevent starvation of keyboard.
+ // if last time, mouse moves then this time check keyboard
+ //
+ if (HMainEditor.MouseSupported) {
+ Status = HMainEditor.MouseInterface->GetState (
+ HMainEditor.MouseInterface,
+ &MouseState
+ );
+ if (!EFI_ERROR (Status)) {
+
+ BeforeMouseIsDown = MouseIsDown;
+
+ Status = HMainEditorHandleMouseInput (MouseState, &MouseIsDown);
+
+ if (!EFI_ERROR (Status)) {
+ if (BeforeMouseIsDown == FALSE) {
+ //
+ // mouse down
+ //
+ if (MouseIsDown == TRUE) {
+ FRow = HBufferImage.BufferPosition.Row;
+ FCol = HBufferImage.BufferPosition.Column;
+ SelectStartBackup = HMainEditor.SelectStart;
+ SelectEndBackup = HMainEditor.SelectEnd;
+
+ FirstDown = TRUE;
+ }
+ } else {
+
+ SelectStartBackup = HMainEditor.SelectStart;
+ SelectEndBackup = HMainEditor.SelectEnd;
+
+ //
+ // begin to drag
+ //
+ if (MouseIsDown == TRUE) {
+ if (FirstDown == TRUE) {
+ if (MouseState.RelativeMovementX || MouseState.RelativeMovementY) {
+ HMainEditor.SelectStart = 0;
+ HMainEditor.SelectEnd = 0;
+ HMainEditor.SelectStart = (FRow - 1) * 0x10 + FCol;
+
+ MouseDrag = TRUE;
+ FirstDown = FALSE;
+ }
+ } else {
+ if ((
+ (HBufferImage.BufferPosition.Row - 1) *
+ 0x10 +
+ HBufferImage.BufferPosition.Column
+ ) >= HMainEditor.SelectStart
+ ) {
+ HMainEditor.SelectEnd = (HBufferImage.BufferPosition.Row - 1) *
+ 0x10 +
+ HBufferImage.BufferPosition.Column;
+ } else {
+ HMainEditor.SelectEnd = 0;
+ }
+ }
+ //
+ // end of if RelativeX/Y
+ //
+ } else {
+ //
+ // mouse is up
+ //
+ if (MouseDrag) {
+ if (HBufferImageGetTotalSize () == 0) {
+ HMainEditor.SelectStart = 0;
+ HMainEditor.SelectEnd = 0;
+ FirstDown = FALSE;
+ MouseDrag = FALSE;
+ }
+
+ if ((
+ (HBufferImage.BufferPosition.Row - 1) *
+ 0x10 +
+ HBufferImage.BufferPosition.Column
+ ) >= HMainEditor.SelectStart
+ ) {
+ HMainEditor.SelectEnd = (HBufferImage.BufferPosition.Row - 1) *
+ 0x10 +
+ HBufferImage.BufferPosition.Column;
+ } else {
+ HMainEditor.SelectEnd = 0;
+ }
+
+ if (HMainEditor.SelectEnd == 0) {
+ HMainEditor.SelectStart = 0;
+ }
+ }
+
+ FirstDown = FALSE;
+ MouseDrag = FALSE;
+ }
+
+ if (SelectStartBackup != HMainEditor.SelectStart || SelectEndBackup != HMainEditor.SelectEnd) {
+ if ((SelectStartBackup - 1) / 0x10 != (HMainEditor.SelectStart - 1) / 0x10) {
+ HBufferImageNeedRefresh = TRUE;
+ } else {
+ if ((SelectEndBackup - 1) / 0x10 != (HMainEditor.SelectEnd - 1) / 0x10) {
+ HBufferImageNeedRefresh = TRUE;
+ } else {
+ HBufferImageOnlyLineNeedRefresh = TRUE;
+ }
+ }
+ }
+ }
+
+ HEditorMouseAction = TRUE;
+ HBufferImageMouseNeedRefresh = TRUE;
+
+ } else if (Status == EFI_LOAD_ERROR) {
+ StatusBarSetStatusString (L"Invalid Mouse Movement ");
+ }
+ }
+ }
+
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ if (!EFI_ERROR (Status)) {
+ //
+ // dispatch to different components' key handling function
+ // so not everywhere has to set this variable
+ //
+ HBufferImageMouseNeedRefresh = TRUE;
+
+ //
+ // clear previous status string
+ //
+ StatusBarSetRefresh();
+
+ if (Key.ScanCode == SCAN_NULL) {
+ Status = HBufferImageHandleInput (&Key);
+ } else if (((Key.ScanCode >= SCAN_UP) && (Key.ScanCode <= SCAN_PAGE_DOWN))) {
+ Status = HBufferImageHandleInput (&Key);
+ } else if (((Key.ScanCode >= SCAN_F1) && Key.ScanCode <= (SCAN_F12))) {
+ Status = MenuBarDispatchFunctionKey (&Key);
+ } else {
+ StatusBarSetStatusString (L"Unknown Command");
+
+ HBufferImageMouseNeedRefresh = FALSE;
+ }
+
+ if (Status != EFI_SUCCESS && Status != EFI_OUT_OF_RESOURCES) {
+ //
+ // not already has some error status
+ //
+ if (StrCmp (L"", StatusBarGetString()) == 0) {
+ StatusBarSetStatusString (L"Disk Error. Try Again");
+ }
+ }
+ }
+ //
+ // decide if has to set length warning
+ //
+ if (HBufferImage.BufferType != HBufferImageBackupVar.BufferType) {
+ LengthChange = FALSE;
+ } else {
+ //
+ // still the old buffer
+ //
+ if (HBufferImage.BufferType != FileTypeFileBuffer) {
+ Size = HBufferImageGetTotalSize ();
+
+ switch (HBufferImage.BufferType) {
+ case FileTypeDiskBuffer:
+ OldSize = HBufferImage.DiskImage->Size * HBufferImage.DiskImage->BlockSize;
+ break;
+
+ case FileTypeMemBuffer:
+ OldSize = HBufferImage.MemImage->Size;
+ break;
+ }
+
+ if (LengthChange == FALSE) {
+ if (OldSize != Size) {
+ StatusBarSetStatusString (L"Disk/Mem Buffer Length should not be changed");
+ }
+ }
+
+ if (OldSize != Size) {
+ LengthChange = TRUE;
+ } else {
+ LengthChange = FALSE;
+ }
+ }
+ }
+ //
+ // after handling, refresh editor
+ //
+ HMainEditorRefresh ();
+
+ } while (Status != EFI_OUT_OF_RESOURCES && !HEditorExit);
+
+ return Status;
+}
+
+/**
+ Backup function for MainEditor.
+**/
+VOID
+EFIAPI
+HMainEditorBackup (
+ VOID
+ )
+{
+ HMainEditorBackupVar.SelectStart = HMainEditor.SelectStart;
+ HMainEditorBackupVar.SelectEnd = HMainEditor.SelectEnd;
+ HBufferImageBackup ();
+}
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.h b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.h
new file mode 100644
index 0000000000..c4f2ea6382
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.h
@@ -0,0 +1,48 @@
+/** @file
+ Defines the Main Editor data type -
+ - Global variables
+ - Instances of the other objects of the editor
+ - Main Interfaces
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LIB_EDITOR_H_
+#define _LIB_EDITOR_H_
+
+#include "HexEditor.h"
+
+EFI_STATUS
+HMainEditorInit (
+ VOID
+ );
+EFI_STATUS
+HMainEditorCleanup (
+ VOID
+ );
+EFI_STATUS
+HMainEditorRefresh (
+ VOID
+ );
+EFI_STATUS
+HMainEditorKeyInput (
+ VOID
+ );
+
+/**
+ Backup function for MainEditor.
+**/
+VOID
+EFIAPI
+HMainEditorBackup (
+ VOID
+ );
+#endif
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.c b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.c
new file mode 100644
index 0000000000..73464906b4
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.c
@@ -0,0 +1,412 @@
+/** @file
+ Functions to deal with Mem buffer
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HexEditor.h"
+
+extern EFI_HANDLE HImageHandleBackup;
+
+extern HEFI_EDITOR_BUFFER_IMAGE HBufferImage;
+
+extern BOOLEAN HBufferImageNeedRefresh;
+extern BOOLEAN HBufferImageOnlyLineNeedRefresh;
+extern BOOLEAN HBufferImageMouseNeedRefresh;
+
+extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;
+
+HEFI_EDITOR_MEM_IMAGE HMemImage;
+HEFI_EDITOR_MEM_IMAGE HMemImageBackupVar;
+
+EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL DummyPciRootBridgeIo;
+
+//
+// for basic initialization of HDiskImage
+//
+HEFI_EDITOR_MEM_IMAGE HMemImageConst = {
+ NULL,
+ 0,
+ 0
+};
+
+EFI_STATUS
+DummyMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+DummyMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+HMemImageInit (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initialization function for HDiskImage
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_LOAD_ERROR
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // basically initialize the HMemImage
+ //
+ CopyMem (&HMemImage, &HMemImageConst, sizeof (HMemImage));
+
+ Status = gBS->LocateProtocol (
+ &gEfiPciRootBridgeIoProtocolGuid,
+ NULL,
+ (VOID**)&HMemImage.IoFncs
+ );
+ if (Status == EFI_NOT_FOUND) {
+ //
+ // For NT32, no EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL is available
+ // Use Dummy PciRootBridgeIo for memory access
+ //
+ ZeroMem (&DummyPciRootBridgeIo, sizeof (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL));
+ DummyPciRootBridgeIo.Mem.Read = DummyMemRead;
+ DummyPciRootBridgeIo.Mem.Write = DummyMemWrite;
+ HMemImage.IoFncs = &DummyPciRootBridgeIo;
+ Status = EFI_SUCCESS;
+ }
+ if (!EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_LOAD_ERROR;
+ }
+}
+
+EFI_STATUS
+HMemImageBackup (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Backup function for HDiskImage
+ Only a few fields need to be backup.
+ This is for making the Disk buffer refresh
+ as few as possible.
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ HMemImageBackupVar.Offset = HMemImage.Offset;
+ HMemImageBackupVar.Size = HMemImage.Size;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HMemImageCleanup (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Cleanup function for HDiskImage
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HMemImageSetMemOffsetSize (
+ IN UINTN Offset,
+ IN UINTN Size
+ )
+/*++
+
+Routine Description:
+
+ Set FileName field in HFileImage
+
+Arguments:
+
+ Offset - The offset
+ Size - The size
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_OUT_OF_RESOURCES
+
+--*/
+{
+
+ HMemImage.Offset = Offset;
+ HMemImage.Size = Size;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HMemImageRead (
+ IN UINTN Offset,
+ IN UINTN Size,
+ BOOLEAN Recover
+ )
+/*++
+
+Routine Description:
+
+ Read a disk from disk into HBufferImage
+
+Arguments:
+
+ Offset - The offset
+ Size - The size
+ Recover - if is for recover, no information print
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_LOAD_ERROR
+ EFI_OUT_OF_RESOURCES
+
+--*/
+{
+
+ EFI_STATUS Status;
+ void *Buffer;
+ CHAR16 *Str;
+ HEFI_EDITOR_LINE *Line;
+
+ EDIT_FILE_TYPE BufferTypeBackup;
+
+ BufferTypeBackup = HBufferImage.BufferType;
+ HBufferImage.BufferType = FileTypeMemBuffer;
+
+ Buffer = AllocateZeroPool (Size);
+ if (Buffer == NULL) {
+ StatusBarSetStatusString (L"Read Memory Failed");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = HMemImage.IoFncs->Mem.Read (
+ HMemImage.IoFncs,
+ EfiPciWidthUint8,
+ Offset,
+ Size,
+ Buffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ StatusBarSetStatusString (L"Memory Specified Not Accessible");
+ return EFI_LOAD_ERROR;
+ }
+
+ HBufferImageFree ();
+
+ Status = HBufferImageBufferToList (Buffer, Size);
+ FreePool (Buffer);
+
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Read Memory Failed");
+ return Status;
+ }
+
+ Status = HMemImageSetMemOffsetSize (Offset, Size);
+
+ HBufferImage.DisplayPosition.Row = 2;
+ HBufferImage.DisplayPosition.Column = 10;
+
+ HBufferImage.MousePosition.Row = 2;
+ HBufferImage.MousePosition.Column = 10;
+
+ HBufferImage.LowVisibleRow = 1;
+ HBufferImage.HighBits = TRUE;
+
+ HBufferImage.BufferPosition.Row = 1;
+ HBufferImage.BufferPosition.Column = 1;
+
+ if (!Recover) {
+ Str = CatSPrint(NULL, L"%d Lines Read", HBufferImage.NumLines);
+ if (Str == NULL) {
+ StatusBarSetStatusString (L"Read Memory Failed");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StatusBarSetStatusString (Str);
+ SHELL_FREE_NON_NULL (Str);
+
+ HMainEditor.SelectStart = 0;
+ HMainEditor.SelectEnd = 0;
+
+ }
+
+ //
+ // has line
+ //
+ if (HBufferImage.Lines != NULL) {
+ HBufferImage.CurrentLine = CR (HBufferImage.ListHead->ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+ } else {
+ //
+ // create a dummy line
+ //
+ Line = HBufferImageCreateLine ();
+ if (Line == NULL) {
+ StatusBarSetStatusString (L"Read Memory Failed");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ HBufferImage.CurrentLine = Line;
+ }
+
+ HBufferImage.Modified = FALSE;
+ HBufferImageNeedRefresh = TRUE;
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+ HBufferImageMouseNeedRefresh = TRUE;
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+HMemImageSave (
+ IN UINTN Offset,
+ IN UINTN Size
+ )
+/*++
+
+Routine Description:
+
+ Save lines in HBufferImage to disk
+
+Arguments:
+
+ Offset - The offset
+ Size - The size
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_LOAD_ERROR
+ EFI_OUT_OF_RESOURCES
+
+--*/
+{
+
+ EFI_STATUS Status;
+ VOID *Buffer;
+
+ EDIT_FILE_TYPE BufferTypeBackup;
+
+ //
+ // not modified, so directly return
+ //
+ if (HBufferImage.Modified == FALSE) {
+ return EFI_SUCCESS;
+ }
+
+ BufferTypeBackup = HBufferImage.BufferType;
+ HBufferImage.BufferType = FileTypeMemBuffer;
+
+ Buffer = AllocateZeroPool (Size);
+
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = HBufferImageListToBuffer (Buffer, Size);
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return Status;
+ }
+ //
+ // write back to memory
+ //
+ Status = HMemImage.IoFncs->Mem.Write (
+ HMemImage.IoFncs,
+ EfiPciWidthUint8,
+ Offset,
+ Size,
+ Buffer
+ );
+
+ FreePool (Buffer);
+
+ if (EFI_ERROR (Status)) {
+ return EFI_LOAD_ERROR;
+ }
+ //
+ // now not modified
+ //
+ HBufferImage.Modified = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DummyMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+DummyMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.h b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.h
new file mode 100644
index 0000000000..8805c0d75d
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.h
@@ -0,0 +1,52 @@
+/** @file
+ Defines MemImage - the view of the file that is visible at any point,
+ as well as the event handlers for editing the file
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LIB_MEM_IMAGE_H_
+#define _LIB_MEM_IMAGE_H_
+
+#include "HexEditor.h"
+
+EFI_STATUS
+HMemImageInit (
+ VOID
+ );
+EFI_STATUS
+HMemImageCleanup (
+ VOID
+ );
+EFI_STATUS
+HMemImageBackup (
+ VOID
+ );
+
+EFI_STATUS
+HMemImageSetMemOffsetSize (
+ IN UINTN,
+ IN UINTN
+ );
+
+EFI_STATUS
+HMemImageRead (
+ IN UINTN,
+ IN UINTN,
+ IN BOOLEAN
+ );
+EFI_STATUS
+HMemImageSave (
+ IN UINTN,
+ IN UINTN
+ );
+
+#endif
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.c b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.c
new file mode 100644
index 0000000000..8ae21450c4
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.c
@@ -0,0 +1,541 @@
+/** @file
+ Implementation of various string and line routines
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HexEditor.h"
+
+extern BOOLEAN HEditorMouseAction;
+
+VOID
+HEditorClearLine (
+ IN UINTN Row
+ )
+/*++
+
+Routine Description:
+
+ Clear line at Row
+
+Arguments:
+
+ Row -- row number to be cleared ( start from 1 )
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ CHAR16 Line[200];
+ UINTN Index;
+ UINTN Limit;
+ UINTN StartCol;
+
+ if (HEditorMouseAction) {
+ Limit = 3 * 0x10;
+ StartCol = 10;
+ } else {
+ Limit = HMainEditor.ScreenSize.Column;
+ StartCol = 1;
+ }
+ //
+ // prepare a blank line
+ //
+ for (Index = 0; Index < Limit; Index++) {
+ Line[Index] = ' ';
+ }
+
+ if (Row == HMainEditor.ScreenSize.Row && Limit == HMainEditor.ScreenSize.Column) {
+ //
+ // if '\0' is still at position 80, it will cause first line error
+ //
+ Line[Limit - 1] = '\0';
+ } else {
+ Line[Limit] = '\0';
+ }
+ //
+ // print out the blank line
+ //
+ ShellPrintEx ((INT32)StartCol - 1, (INT32)Row - 1, Line);
+}
+
+HEFI_EDITOR_LINE *
+HLineDup (
+ IN HEFI_EDITOR_LINE *Src
+ )
+/*++
+
+Routine Description:
+
+ Duplicate a line
+
+Arguments:
+
+ Src -- line to be duplicated
+
+Returns:
+
+ NULL -- wrong
+ Not NULL -- line created
+
+--*/
+{
+ HEFI_EDITOR_LINE *Dest;
+
+ //
+ // allocate for the line structure
+ //
+ Dest = AllocateZeroPool (sizeof (HEFI_EDITOR_LINE));
+ if (Dest == NULL) {
+ return NULL;
+ }
+
+ Dest->Signature = EFI_EDITOR_LINE_LIST;
+ Dest->Size = Src->Size;
+
+ CopyMem (Dest->Buffer, Src->Buffer, 0x10);
+
+ Dest->Link = Src->Link;
+
+ return Dest;
+}
+
+VOID
+HLineFree (
+ IN HEFI_EDITOR_LINE *Src
+ )
+/*++
+
+Routine Description:
+
+ Free a line and it's internal buffer
+
+Arguments:
+
+ Src -- line to be freed
+
+Returns:
+
+ None
+
+--*/
+{
+ if (Src == NULL) {
+ return ;
+ }
+
+ SHELL_FREE_NON_NULL (Src);
+
+}
+
+HEFI_EDITOR_LINE *
+_HLineAdvance (
+ IN UINTN Count
+ )
+/*++
+
+Routine Description:
+
+ Advance to the next Count lines
+
+Arguments:
+
+ Count -- line number to advance
+
+Returns:
+
+ NULL -- wrong
+ Not NULL -- line after advance
+
+--*/
+{
+ UINTN Index;
+ HEFI_EDITOR_LINE *Line;
+
+ Line = HMainEditor.BufferImage->CurrentLine;
+ if (Line == NULL) {
+ return NULL;
+ }
+
+ for (Index = 0; Index < Count; Index++) {
+ //
+ // if already last line
+ //
+ if (Line->Link.ForwardLink == HMainEditor.BufferImage->ListHead) {
+ return NULL;
+ }
+
+ Line = CR (Line->Link.ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+ }
+
+ return Line;
+}
+
+HEFI_EDITOR_LINE *
+_HLineRetreat (
+ IN UINTN Count
+ )
+/*++
+
+Routine Description:
+
+ Retreat to the previous Count lines
+
+Arguments:
+
+ Count -- line number to retreat
+
+Returns:
+
+ NULL -- wrong
+ Not NULL -- line after retreat
+
+--*/
+{
+ UINTN Index;
+ HEFI_EDITOR_LINE *Line;
+
+ Line = HMainEditor.BufferImage->CurrentLine;
+ if (Line == NULL) {
+ return NULL;
+ }
+
+ for (Index = 0; Index < Count; Index++) {
+ //
+ // already the first line
+ //
+ if (Line->Link.BackLink == HMainEditor.BufferImage->ListHead) {
+ return NULL;
+ }
+
+ Line = CR (Line->Link.BackLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+ }
+
+ return Line;
+}
+
+HEFI_EDITOR_LINE *
+HMoveLine (
+ IN INTN Count
+ )
+/*++
+
+Routine Description:
+
+ Advance/Retreat lines
+
+Arguments:
+
+ Count -- line number to advance/retreat
+ >0 : advance
+ <0: retreat
+
+Returns:
+
+ NULL -- wrong
+ Not NULL -- line after advance
+
+--*/
+{
+ HEFI_EDITOR_LINE *Line;
+ UINTN AbsCount;
+
+ //
+ // difference with MoveCurrentLine
+ // just return Line
+ // do not set currentline to Line
+ //
+ if (Count <= 0) {
+ AbsCount = -Count;
+ Line = _HLineRetreat (AbsCount);
+ } else {
+ Line = _HLineAdvance (Count);
+ }
+
+ return Line;
+}
+
+HEFI_EDITOR_LINE *
+HMoveCurrentLine (
+ IN INTN Count
+ )
+/*++
+
+Routine Description:
+
+ Advance/Retreat lines and set CurrentLine in BufferImage to it
+
+Arguments:
+
+ Count -- line number to advance/retreat
+ >0 : advance
+ <0: retreat
+
+Returns:
+
+ NULL -- wrong
+ Not NULL -- line after advance
+
+
+--*/
+{
+ HEFI_EDITOR_LINE *Line;
+ UINTN AbsCount;
+
+ //
+ // <0: retreat
+ // >0: advance
+ //
+ if (Count <= 0) {
+ AbsCount = -Count;
+ Line = _HLineRetreat (AbsCount);
+ } else {
+ Line = _HLineAdvance (Count);
+ }
+
+ if (Line == NULL) {
+ return NULL;
+ }
+
+ HMainEditor.BufferImage->CurrentLine = Line;
+
+ return Line;
+}
+
+
+EFI_STATUS
+HFreeLines (
+ IN LIST_ENTRY *ListHead,
+ IN HEFI_EDITOR_LINE *Lines
+ )
+/*++
+
+Routine Description:
+
+ Free all the lines in HBufferImage
+ Fields affected:
+ Lines
+ CurrentLine
+ NumLines
+ ListHead
+
+Arguments:
+
+ ListHead - The list head
+ Lines - The lines
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ LIST_ENTRY *Link;
+ HEFI_EDITOR_LINE *Line;
+
+ //
+ // release all the lines
+ //
+ if (Lines != NULL) {
+
+ Line = Lines;
+ Link = &(Line->Link);
+ do {
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+ Link = Link->ForwardLink;
+ HLineFree (Line);
+ } while (Link != ListHead);
+ }
+
+ ListHead->ForwardLink = ListHead;
+ ListHead->BackLink = ListHead;
+
+ return EFI_SUCCESS;
+}
+
+UINTN
+HStrStr (
+ IN CHAR16 *Str,
+ IN CHAR16 *Pat
+ )
+/*++
+
+Routine Description:
+
+ Search Pat in Str
+
+Arguments:
+
+ Str -- mother string
+ Pat -- search pattern
+
+
+Returns:
+
+ 0 : not found
+ >= 1 : found position + 1
+
+--*/
+{
+ INTN *Failure;
+ INTN i;
+ INTN j;
+ INTN Lenp;
+ INTN Lens;
+
+ //
+ // this function copies from some lib
+ //
+ Lenp = StrLen (Pat);
+ Lens = StrLen (Str);
+
+ Failure = AllocateZeroPool (Lenp * sizeof (INTN));
+ Failure[0] = -1;
+ for (j = 1; j < Lenp; j++) {
+ i = Failure[j - 1];
+ while ((Pat[j] != Pat[i + 1]) && (i >= 0)) {
+ i = Failure[i];
+ }
+
+ if (Pat[j] == Pat[i + 1]) {
+ Failure[j] = i + 1;
+ } else {
+ Failure[j] = -1;
+ }
+ }
+
+ i = 0;
+ j = 0;
+ while (i < Lens && j < Lenp) {
+ if (Str[i] == Pat[j]) {
+ i++;
+ j++;
+ } else if (j == 0) {
+ i++;
+ } else {
+ j = Failure[j - 1] + 1;
+ }
+ }
+
+ FreePool (Failure);
+
+ //
+ // 0: not found
+ // >=1 : found position + 1
+ //
+ return ((j == Lenp) ? (i - Lenp) : -1) + 1;
+
+}
+
+INT32
+HGetTextX (
+ IN INT32 GuidX
+ )
+{
+ INT32 Gap;
+
+ HMainEditor.MouseAccumulatorX += GuidX;
+ Gap = (HMainEditor.MouseAccumulatorX * (INT32) HMainEditor.ScreenSize.Column) / (INT32) (50 * (INT32) HMainEditor.MouseInterface->Mode->ResolutionX);
+ HMainEditor.MouseAccumulatorX = (HMainEditor.MouseAccumulatorX * (INT32) HMainEditor.ScreenSize.Column) % (INT32) (50 * (INT32) HMainEditor.MouseInterface->Mode->ResolutionX);
+ HMainEditor.MouseAccumulatorX = HMainEditor.MouseAccumulatorX / (INT32) HMainEditor.ScreenSize.Column;
+ return Gap;
+}
+
+INT32
+HGetTextY (
+ IN INT32 GuidY
+ )
+{
+ INT32 Gap;
+
+ HMainEditor.MouseAccumulatorY += GuidY;
+ Gap = (HMainEditor.MouseAccumulatorY * (INT32) HMainEditor.ScreenSize.Row) / (INT32) (50 * (INT32) HMainEditor.MouseInterface->Mode->ResolutionY);
+ HMainEditor.MouseAccumulatorY = (HMainEditor.MouseAccumulatorY * (INT32) HMainEditor.ScreenSize.Row) % (INT32) (50 * (INT32) HMainEditor.MouseInterface->Mode->ResolutionY);
+ HMainEditor.MouseAccumulatorY = HMainEditor.MouseAccumulatorY / (INT32) HMainEditor.ScreenSize.Row;
+
+ return Gap;
+}
+
+EFI_STATUS
+HXtoi (
+ IN CHAR16 *Str,
+ OUT UINTN *Value
+ )
+/*++
+Routine Description:
+
+ convert hex string to uint
+
+Arguments:
+
+ Str - The string
+ Value - The value
+
+Returns:
+
+
+--*/
+{
+ UINT64 u;
+ CHAR16 c;
+ UINTN Size;
+
+ Size = sizeof (UINTN);
+
+ //
+ // skip leading white space
+ //
+ while (*Str && *Str == ' ') {
+ Str += 1;
+ }
+
+ if (StrLen (Str) > Size * 2) {
+ return EFI_LOAD_ERROR;
+ }
+ //
+ // convert hex digits
+ //
+ u = 0;
+ c = *Str;
+ while (c) {
+ c = *Str;
+ Str++;
+
+ if (c == 0) {
+ break;
+ }
+ //
+ // not valid char
+ //
+ if (!((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || (c >= '0' && c <= '9') || (c == '\0'))) {
+ return EFI_LOAD_ERROR;
+ }
+
+ if (c >= 'a' && c <= 'f') {
+ c -= 'a' - 'A';
+ }
+
+ if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
+ u = LShiftU64 (u, 4) + (c - (c >= 'A' ? 'A' - 10 : '0'));
+ } else {
+ //
+ // '\0'
+ //
+ break;
+ }
+ }
+
+ *Value = (UINTN) u;
+
+ return EFI_SUCCESS;
+}
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.h b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.h
new file mode 100644
index 0000000000..a9b59ff514
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.h
@@ -0,0 +1,96 @@
+/** @file
+ Definitions for various line and string routines
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LIB_MISC_H_
+#define _LIB_MISC_H_
+
+#include "HexEditor.h"
+
+VOID
+HEditorClearLine (
+ UINTN
+ );
+HEFI_EDITOR_LINE *
+HLineDup (
+ HEFI_EDITOR_LINE *
+ );
+VOID
+HLineFree (
+ HEFI_EDITOR_LINE *
+ );
+
+HEFI_EDITOR_LINE *
+HMoveLine (
+ INTN
+ );
+HEFI_EDITOR_LINE *
+HMoveCurrentLine (
+ INTN
+ );
+
+UINTN
+HLineStrInsert (
+ HEFI_EDITOR_LINE *,
+ CHAR16,
+ UINTN,
+ UINTN
+ );
+
+VOID
+HLineCat (
+ HEFI_EDITOR_LINE *,
+ HEFI_EDITOR_LINE *
+ );
+
+VOID
+HLineDeleteAt (
+ HEFI_EDITOR_LINE *,
+ UINTN
+ );
+
+UINTN
+HUnicodeToAscii (
+ CHAR16 *,
+ UINTN,
+ CHAR8 *
+ );
+
+UINTN
+HStrStr (
+ CHAR16 *,
+ CHAR16 *
+ );
+
+EFI_STATUS
+HFreeLines (
+ LIST_ENTRY *,
+ HEFI_EDITOR_LINE *
+ );
+
+INT32
+HGetTextX (
+ INT32
+ ) ;
+INT32
+HGetTextY (
+ INT32
+ ) ;
+
+EFI_STATUS
+HXtoi (
+ CHAR16 *,
+ UINTN *
+ );
+
+#endif