summaryrefslogtreecommitdiff
path: root/ShellPkg/Library
diff options
context:
space:
mode:
authorjcarsey <jcarsey@6f19259b-4bc3-4df7-8a09-765794883524>2009-06-16 00:23:19 +0000
committerjcarsey <jcarsey@6f19259b-4bc3-4df7-8a09-765794883524>2009-06-16 00:23:19 +0000
commitb1f95a06ca1a66ad15b3d8843fb4c7563c5350d2 (patch)
treecf88e0c20fe3952951914456198608b58c471aa1 /ShellPkg/Library
parent14e96c2996a138b22f544da4d7921782ef85e51e (diff)
downloadedk2-b1f95a06ca1a66ad15b3d8843fb4c7563c5350d2.tar.gz
Updating with new functions and adding "C" style entrypoint library with example application.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8564 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'ShellPkg/Library')
-rw-r--r--ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.c304
-rw-r--r--ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.c82
-rw-r--r--ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf47
-rw-r--r--ShellPkg/Library/UefiShellLib/UefiShellLib.c145
-rw-r--r--ShellPkg/Library/UefiShellLib/UefiShellLib.inf3
5 files changed, 544 insertions, 37 deletions
diff --git a/ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.c b/ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.c
index 87b577248..023210e8e 100644
--- a/ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.c
+++ b/ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.c
@@ -14,11 +14,14 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Uefi.h>
-#include <Library/ShellLib.h>
+#include <Protocol/SimpleFileSystem.h>
+
+#include <Guid/FileInfo.h>
+
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
-
-#include <Protocol/SimpleFileSystem.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
#define MAX_FILE_NAME_LEN 522 // (20 * (6+5+2))+1) unicode characters from EFI FAT spec (doubled for bytes)
#define FIND_XXXXX_FILE_BUFFER_SIZE (SIZE_OF_EFI_FILE_INFO + MAX_FILE_NAME_LEN)
@@ -620,4 +623,297 @@ FileHandleGetSize (
FreePool(FileInfo);
return (EFI_SUCCESS);
-} \ No newline at end of file
+}
+
+
+/**
+ Safely append (on the left) with automatic string resizing given length of Destination and
+ desired length of copy from Source.
+
+ append the first D characters of Source to the end of Destination, where D is
+ the lesser of Count and the StrLen() of Source. If appending those D characters
+ will fit within Destination (whose Size is given as CurrentSize) and
+ still leave room for a null terminator, then those characters are appended,
+ starting at the original terminating null of Destination, and a new terminating
+ null is appended.
+
+ If appending D characters onto Destination will result in a overflow of the size
+ given in CurrentSize the string will be grown such that the copy can be performed
+ and CurrentSize will be updated to the new size.
+
+ If Source is NULL, there is nothing to append, just return the current buffer in
+ Destination.
+
+ if Destination is NULL, then ASSERT()
+ if Destination's current length (including NULL terminator) is already more then
+ CurrentSize, then ASSERT()
+
+ @param[in][out] Destination The String to append onto
+ @param[in][out] CurrentSize on call the number of bytes in Destination. On
+ return possibly the new size (still in bytes). if NULL
+ then allocate whatever is needed.
+ @param[in] Source The String to append from
+ @param[in] Count Maximum number of characters to append. if 0 then
+ all are appended.
+
+ @return Destination return the resultant string.
+**/
+CHAR16*
+EFIAPI
+StrnCatGrowLeft (
+ IN OUT CHAR16 **Destination,
+ IN OUT UINTN *CurrentSize,
+ IN CONST CHAR16 *Source,
+ IN UINTN Count
+ ){
+ UINTN DestinationStartSize;
+ UINTN NewSize;
+
+ //
+ // ASSERTs
+ //
+ ASSERT(Destination != NULL);
+
+ //
+ // If there's nothing to do then just return Destination
+ //
+ if (Source == NULL) {
+ return (*Destination);
+ }
+
+ //
+ // allow for NULL pointers address as Destination
+ //
+ if (*Destination != NULL) {
+ ASSERT(CurrentSize != 0);
+ DestinationStartSize = StrSize(*Destination);
+ ASSERT(DestinationStartSize <= *CurrentSize);
+ } else {
+ DestinationStartSize = 0;
+// ASSERT(*CurrentSize == 0);
+ }
+
+ //
+ // Append all of Source?
+ //
+ if (Count == 0) {
+ Count = StrLen(Source);
+ }
+
+ //
+ // Test and grow if required
+ //
+ if (CurrentSize != NULL) {
+ NewSize = *CurrentSize;
+ while (NewSize < (DestinationStartSize + (Count*sizeof(CHAR16)))) {
+ NewSize += 2 * Count * sizeof(CHAR16);
+ }
+ *Destination = ReallocatePool(*CurrentSize, NewSize, *Destination);
+ *CurrentSize = NewSize;
+ } else {
+ *Destination = AllocateZeroPool((Count+1)*sizeof(CHAR16));
+ }
+
+ *Destination = CopyMem(*Destination+StrLen(Source), *Destination, StrSize(*Destination));
+ *Destination = CopyMem(*Destination, Source, StrLen(Source));
+ return (*Destination);
+}
+
+/**
+ Function to get a full filename given a EFI_FILE_HANDLE somewhere lower on the
+ directory 'stack'.
+
+ if Handle is NULL, return EFI_INVALID_PARAMETER
+
+ @param[in] Handle Handle to the Directory or File to create path to.
+ @param[out] FullFileName pointer to pointer to generated full file name. It
+ is the responsibility of the caller to free this memory
+ with a call to FreePool().
+ @retval EFI_SUCCESS the operation was sucessful and the FullFileName is valid.
+ @retval EFI_INVALID_PARAMETER Handle was NULL.
+ @retval EFI_INVALID_PARAMETER FullFileName was NULL.
+ @retval EFI_OUT_OF_RESOURCES a memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileHandleGetFileName (
+ IN CONST EFI_FILE_HANDLE Handle,
+ OUT CHAR16 **FullFileName
+ ){
+ EFI_STATUS Status;
+ UINTN Size;
+ EFI_FILE_HANDLE CurrentHandle;
+ EFI_FILE_HANDLE NextHigherHandle;
+ EFI_FILE_INFO *FileInfo;
+
+ Size = 0;
+ *FullFileName = NULL;
+
+ //
+ // Check our parameters
+ //
+ if (FullFileName == NULL || Handle == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ Status = Handle->Open(Handle, &CurrentHandle, L".", EFI_FILE_MODE_READ, 0);
+ if (!EFI_ERROR(Status)) {
+ //
+ // Reverse out the current directory on the device
+ //
+ for (;;) {
+ FileInfo = FileHandleGetInfo(CurrentHandle);
+ if (FileInfo == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ } else {
+ //
+ // We got info... do we have a name? if yes preceed the current path with it...
+ //
+ if (StrLen (FileInfo->FileName) == 0) {
+ *FullFileName = StrnCatGrowLeft(FullFileName, &Size, L"\\", 0);
+ FreePool(FileInfo);
+ break;
+ } else {
+ *FullFileName = StrnCatGrowLeft(FullFileName, &Size, FileInfo->FileName, 0);
+ *FullFileName = StrnCatGrowLeft(FullFileName, &Size, L"\\", 0);
+ FreePool(FileInfo);
+ }
+ }
+ //
+ // Move to the parent directory
+ //
+ Status = CurrentHandle->Open (CurrentHandle, &NextHigherHandle, L"..", EFI_FILE_MODE_READ, 0);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ FileHandleClose(CurrentHandle);
+ CurrentHandle = NextHigherHandle;
+ }
+ }
+
+ if (CurrentHandle != NULL) {
+ CurrentHandle->Close (CurrentHandle);
+ }
+
+ if (EFI_ERROR(Status) && *FullFileName != NULL) {
+ FreePool(FullFileName);
+ }
+
+ return (Status);
+}
+
+/**
+ Function to read a single line (up to but not including the \n) from a file.
+
+ @param[in] Handle FileHandle to read from
+ @param[in][out] Buffer pointer to buffer to read into
+ @param[in][out] Size pointer to number of bytes in buffer
+ @param[in[ Truncate if TRUE then allows for truncation of the line to fit.
+ if FALSE will reset the position to the begining of the
+ line if the buffer is not large enough.
+
+ @retval EFI_SUCCESS the operation was sucessful. the line is stored in
+ Buffer.
+ @retval EFI_INVALID_PARAMETER Handle was NULL.
+ @retval EFI_INVALID_PARAMETER Buffer was NULL.
+ @retval EFI_INVALID_PARAMETER Size was NULL.
+ @retval EFI_BUFFER_TOO_SMALL Size was not enough space to store the line.
+ Size was updated to minimum space required.
+ @sa FileHandleRead
+**/
+EFI_STATUS
+EFIAPI
+FileHandleReadLine(
+ IN EFI_FILE_HANDLE Handle,
+ IN OUT VOID *Buffer,
+ IN OUT UINTN *Size,
+ IN BOOLEAN Truncate
+ ){
+ EFI_STATUS Status;
+ CHAR16 CharBuffer;
+ UINTN CharSize;
+ UINTN CountSoFar;
+ UINT64 Position;
+
+
+ if (Handle == NULL
+ ||Buffer == NULL
+ ||Size == NULL
+ ){
+ return (EFI_INVALID_PARAMETER);
+ }
+ FileHandleGetPosition(Handle, &Position);
+
+ for (CountSoFar = 0;;CountSoFar++){
+ CharSize = sizeof(CharBuffer);
+ Status = FileHandleRead(Handle, &CharSize, &CharBuffer);
+ if ( EFI_ERROR(Status)
+ || CharSize == 0
+ || CharBuffer == '\n'
+ ){
+ break;
+ }
+ //
+ // if we have space save it...
+ //
+ if ((CountSoFar+1)*sizeof(CHAR16) < *Size){
+ ((CHAR16*)Buffer)[CountSoFar] = CharBuffer;
+ ((CHAR16*)Buffer)[CountSoFar+1] = '\0';
+ }
+ }
+
+ //
+ // if we ran out of space tell when...
+ //
+ if ((CountSoFar+1)*sizeof(CHAR16) > *Size){
+ *Size = (CountSoFar+1)*sizeof(CHAR16);
+ if (Truncate == FALSE) {
+ FileHandleSetPosition(Handle, Position);
+ } else {
+ DEBUG((DEBUG_WARN, "The line was truncated in ReadLine"));
+ }
+ return (EFI_BUFFER_TOO_SMALL);
+ }
+ *Size = (CountSoFar+1)*sizeof(CHAR16);
+ return (Status);
+}
+
+/**
+ function to write a line of unicode text to a file.
+
+ if Handle is NULL, ASSERT.
+ if Buffer is NULL, do nothing. (return SUCCESS)
+
+ @param[in] Handle FileHandle to write to
+ @param[in] Buffer Buffer to write
+
+ @retval EFI_SUCCESS the data was written.
+ @retval other failure.
+
+ @sa FileHandleWrite
+**/
+EFI_STATUS
+EFIAPI
+FileHandleWriteLine(
+ IN EFI_FILE_HANDLE Handle,
+ IN CHAR16 *Buffer
+ ){
+ EFI_STATUS Status;
+ UINTN Size;
+
+ ASSERT(Handle != NULL);
+
+ if (Buffer == NULL) {
+ return (EFI_SUCCESS);
+ }
+
+ Size = StrLen(Buffer);
+ Status = FileHandleWrite(Handle, &Size, Buffer);
+ if (EFI_ERROR(Status)) {
+ return (Status);
+ }
+ Size = StrLen(L"\r\n");
+ return FileHandleWrite(Handle, &Size, L"\r\n");
+}
diff --git a/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.c b/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.c
new file mode 100644
index 000000000..0ce5271f2
--- /dev/null
+++ b/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.c
@@ -0,0 +1,82 @@
+/** @file
+ Provides application point extension for "C" style main funciton
+
+Copyright (c) 2009, Intel Corporation
+All rights reserved. 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 <Base.h>
+
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/EfiShellInterface.h>
+#include <Protocol/EfiShellParameters.h>
+
+#include <Library/DebugLib.h>
+
+INT32
+EFIAPI
+main(
+ UINTN Argc,
+ CHAR16 **Argv
+);
+
+EFI_STATUS
+EFIAPI
+ShellCEntryLib(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ ){
+ INT32 ReturnFromMain;
+ EFI_SHELL_PARAMETERS_PROTOCOL *EfiShellParametersProtocol;
+ EFI_SHELL_INTERFACE *EfiShellInterface;
+ EFI_STATUS Status;
+
+ ReturnFromMain = -1;
+ EfiShellParametersProtocol = NULL;
+ EfiShellInterface = NULL;
+
+ Status = SystemTable->BootServices->OpenProtocol(ImageHandle,
+ &gEfiShellParametersProtocolGuid,
+ (VOID **)&EfiShellParametersProtocol,
+ ImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR(Status)) {
+ //
+ // use shell 2.0 interface
+ //
+ ReturnFromMain = main(EfiShellInterface->Argc, EfiShellInterface->Argv);
+ } else {
+ //
+ // try to get shell 1.0 interface instead.
+ //
+ Status = SystemTable->BootServices->OpenProtocol(ImageHandle,
+ &gEfiShellInterfaceGuid,
+ (VOID **)&EfiShellInterface,
+ ImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR(Status)) {
+ //
+ // use shell 1.0 interface
+ //
+ ReturnFromMain = main(EfiShellParametersProtocol->Argc, EfiShellParametersProtocol->Argv);
+ } else {
+ ASSERT(FALSE);
+ }
+ }
+ if (ReturnFromMain == 0) {
+ return (EFI_SUCCESS);
+ } else {
+ return (EFI_UNSUPPORTED);
+ }
+}
diff --git a/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf b/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
new file mode 100644
index 000000000..15a744ff8
--- /dev/null
+++ b/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
@@ -0,0 +1,47 @@
+#/** @file
+# Provides interface to shell functionality for shell commands and applications.
+#
+# Copyright (c) 2006 - 2009, Intel Corporation.
+#
+# All rights reserved. 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.
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = UefiShellCEntryLib
+ FILE_GUID = 0e205c8a-8586-4dec-9f5c-4f9e394aefe8
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ShellCEntryLib|UEFI_APPLICATION
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ UefiShellCEntryLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+
+[LibraryClasses]
+ UefiApplicationEntryPoint
+ DebugLib
+
+
+[Protocols]
+ gEfiShellParametersProtocolGuid # ALWAYS_CONSUMED
+ gEfiShellInterfaceGuid # SOMETIMES_CONSUMED
+
+[Guids]
+
+[Pcd.common]
+
diff --git a/ShellPkg/Library/UefiShellLib/UefiShellLib.c b/ShellPkg/Library/UefiShellLib/UefiShellLib.c
index 1ddff9a2a..7ac7765b4 100644
--- a/ShellPkg/Library/UefiShellLib/UefiShellLib.c
+++ b/ShellPkg/Library/UefiShellLib/UefiShellLib.c
@@ -22,13 +22,16 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Library/DevicePathLib.h>
#include <Library/PcdLib.h>
#include <Library/FileHandleLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiLib.h>
+
#include <Protocol/EfiShellEnvironment2.h>
#include <Protocol/EfiShellInterface.h>
#include <Protocol/EfiShell.h>
#include <Protocol/EfiShellParameters.h>
#include <Protocol/SimpleFileSystem.h>
-#include "BaseShellLib.h"
+#include "UefiShellLib.h"
#define MAX_FILE_NAME_LEN 522 // (20 * (6+5+2))+1) unicode characters from EFI FAT spec (doubled for bytes)
#define FIND_XXXXX_FILE_BUFFER_SIZE (SIZE_OF_EFI_FILE_INFO + MAX_FILE_NAME_LEN)
@@ -237,7 +240,6 @@ ShellLibConstructor (
mEfiShellInterface = NULL;
mEfiShellEnvironment2Handle = NULL;
- ///@todo make a worker constructor so initialize function works
//
// verify that auto initialize is not set false
//
@@ -455,7 +457,7 @@ ShellOpenFileByDevicePath(
}
Status = gBS->OpenProtocol(*DeviceHandle,
&gEfiSimpleFileSystemProtocolGuid,
- (VOID**) &EfiSimpleFileSystemProtocol,
+ (VOID**)&EfiSimpleFileSystemProtocol,
gImageHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
@@ -569,6 +571,8 @@ ShellOpenFileByName(
{
EFI_HANDLE DeviceHandle;
EFI_DEVICE_PATH_PROTOCOL *FilePath;
+ EFI_STATUS Status;
+ EFI_FILE_INFO *FileInfo;
//
// ASSERT if FileName is NULL
@@ -579,11 +583,16 @@ ShellOpenFileByName(
//
// Use UEFI Shell 2.0 method
//
- return (mEfiShellProtocol->OpenFileByName(FileName,
- FileHandle,
- OpenMode));
-
- ///@todo add the attributes
+ Status = mEfiShellProtocol->OpenFileByName(FileName,
+ FileHandle,
+ OpenMode);
+ if (!EFI_ERROR(Status)){
+ FileInfo = FileHandleGetInfo(*FileHandle);
+ ASSERT(FileInfo != NULL);
+ FileInfo->Attribute = Attributes;
+ Status = FileHandleSetInfo(*FileHandle, FileInfo);
+ }
+ return (Status);
}
//
// Using EFI Shell version
@@ -1602,29 +1611,6 @@ InternalCommandLineParse (
//
// do nothing for NULL argv
//
- } else if (GetItemValue == TRUE) {
- ASSERT(CurrentItemPackage != NULL);
- //
- // get the item VALUE for the previous flag
- //
- GetItemValue = FALSE;
- CurrentItemPackage->Value = AllocateZeroPool(StrSize(Argv[LoopCounter]));
- ASSERT(CurrentItemPackage->Value != NULL);
- StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]);
- InsertTailList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage);
- } else if (InternalIsFlag(Argv[LoopCounter]) == FALSE) {
- //
- // add this one as a non-flag
- //
- CurrentItemPackage = AllocatePool(sizeof(SHELL_PARAM_PACKAGE));
- ASSERT(CurrentItemPackage != NULL);
- CurrentItemPackage->Name = NULL;
- CurrentItemPackage->Type = TypePosition;
- CurrentItemPackage->Value = AllocatePool(StrSize(Argv[LoopCounter]));
- ASSERT(CurrentItemPackage->Value != NULL);
- StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]);
- CurrentItemPackage->OriginalPosition = Count++;
- InsertTailList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage);
} else if (InternalIsOnCheckList(Argv[LoopCounter], CheckList, &CurrentItemType) == TRUE) {
//
// this is a flag
@@ -1636,6 +1622,7 @@ InternalCommandLineParse (
StrCpy(CurrentItemPackage->Name, Argv[LoopCounter]);
CurrentItemPackage->Type = CurrentItemType;
CurrentItemPackage->OriginalPosition = (UINTN)(-1);
+ CurrentItemPackage->Value = NULL;
//
// Does this flag require a value
@@ -1649,9 +1636,31 @@ InternalCommandLineParse (
//
// this item has no value expected; we are done
//
- CurrentItemPackage->Value = NULL;
- InsertTailList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage);
+ InsertHeadList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage);
}
+ } else if (GetItemValue == TRUE && InternalIsFlag(Argv[LoopCounter]) == FALSE) {
+ ASSERT(CurrentItemPackage != NULL);
+ //
+ // get the item VALUE for the previous flag
+ //
+ GetItemValue = FALSE;
+ CurrentItemPackage->Value = AllocateZeroPool(StrSize(Argv[LoopCounter]));
+ ASSERT(CurrentItemPackage->Value != NULL);
+ StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]);
+ InsertHeadList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage);
+ } else if (InternalIsFlag(Argv[LoopCounter]) == FALSE) {
+ //
+ // add this one as a non-flag
+ //
+ CurrentItemPackage = AllocatePool(sizeof(SHELL_PARAM_PACKAGE));
+ ASSERT(CurrentItemPackage != NULL);
+ CurrentItemPackage->Name = NULL;
+ CurrentItemPackage->Type = TypePosition;
+ CurrentItemPackage->Value = AllocatePool(StrSize(Argv[LoopCounter]));
+ ASSERT(CurrentItemPackage->Value != NULL);
+ StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]);
+ CurrentItemPackage->OriginalPosition = Count++;
+ InsertHeadList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage);
} else if (ProblemParam) {
//
// this was a non-recognised flag... error!
@@ -1936,4 +1945,74 @@ ShellCommandLineGetRawValue (
}
}
return (NULL);
+}
+
+/**
+ Print at a specific location on the screen.
+
+ This function will move the cursor to a given screen location, print the specified string,
+ and return the cursor to the original locaiton.
+
+ If -1 is specified for either the Row or Col the current screen location for BOTH
+ will be used and the cursor's position will not be moved back to an original location.
+
+ if either Row or Col is out of range for the current console, then ASSERT
+ if Format is NULL, then ASSERT
+
+ In addition to the standard %-based flags as supported by UefiLib Print() this supports
+ the following additional flags:
+ %N - Set output attribute to normal
+ %H - Set output attribute to highlight
+ %E - Set output attribute to error
+ %B - Set output attribute to blue color
+ %V - Set output attribute to green color
+
+ Note: The background color is controlled by the shell command cls.
+
+ @param[in] Row the row to print at
+ @param[in] Col the column to print at
+ @param[in] Format the format string
+
+ @return the number of characters printed to the screen
+**/
+
+UINTN
+EFIAPI
+ShellPrintEx(
+ IN INT32 Col OPTIONAL,
+ IN INT32 Row OPTIONAL,
+ IN CONST CHAR16 *Format,
+ ...
+ ){
+ VA_LIST Marker;
+ UINTN BufferSize;
+ CHAR16 *Buffer;
+ UINTN Return;
+ INT32 CurrentCol;
+ INT32 CurrentRow;
+ EFI_STATUS Status;
+
+ BufferSize = (PcdGet32 (PcdUefiLibMaxPrintBufferSize) + 1) * sizeof (CHAR16);
+ Buffer = AllocateZeroPool (BufferSize);
+ ASSERT (Buffer != NULL);
+
+ VA_START (Marker, Format);
+ Return = UnicodeVSPrint (Buffer, BufferSize, Format, Marker);
+
+ if (Col != -1 && Row != -1) {
+ CurrentCol = gST->ConOut->Mode->CursorColumn;
+ CurrentRow = gST->ConOut->Mode->CursorRow;
+ Status = gST->ConOut->SetCursorPosition(gST->ConOut, Col, Row);
+ ASSERT_EFI_ERROR(Status);
+ Status = gST->ConOut->OutputString(gST->ConOut, Buffer);
+ ASSERT_EFI_ERROR(Status);
+ Status = gST->ConOut->SetCursorPosition(gST->ConOut, CurrentCol, CurrentRow);
+ ASSERT_EFI_ERROR(Status);
+ } else {
+ Status = gST->ConOut->OutputString(gST->ConOut, Buffer);
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ FreePool(Buffer);
+ return (Return);
} \ No newline at end of file
diff --git a/ShellPkg/Library/UefiShellLib/UefiShellLib.inf b/ShellPkg/Library/UefiShellLib/UefiShellLib.inf
index 5ed425947..c2f26cd52 100644
--- a/ShellPkg/Library/UefiShellLib/UefiShellLib.inf
+++ b/ShellPkg/Library/UefiShellLib/UefiShellLib.inf
@@ -43,6 +43,8 @@
BaseMemoryLib
DebugLib
FileHandleLib
+ PrintLib
+ UefiLib
[Protocols]
gEfiSimpleFileSystemProtocolGuid # ALWAYS_CONSUMED
@@ -61,3 +63,4 @@
[Pcd.common]
gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize # ALWAYS_CONSUMED
+ gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize # ALWAYS_CONSUMED