diff options
author | darylm503 <darylm503@6f19259b-4bc3-4df7-8a09-765794883524> | 2012-12-11 21:19:14 +0000 |
---|---|---|
committer | darylm503 <darylm503@6f19259b-4bc3-4df7-8a09-765794883524> | 2012-12-11 21:19:14 +0000 |
commit | 6c6c850ad62d6fdc73828057339be1dc7df37c8e (patch) | |
tree | a61c6d2725dd186f3affcb9b00b8d4caf2ea1ee6 /StdLib/LibC | |
parent | e575c101d866bb895ac2fab538bc2ed074163af3 (diff) | |
download | edk2-platforms-6c6c850ad62d6fdc73828057339be1dc7df37c8e.tar.xz |
StdLib: Add terminal type line editing (Interactive IO) for console devices.
Adds a subset of the terminal I/O capabilities described in the Single Unix Specification, V4.
Supports:
Erase previous character. Default is Backspace or ^H
Erase line. Default is ^U
TAB characters are supported and, by default, are rendered as 8 spaces. They will still be read as a single TAB character.
Both Canonical and Non-Canonical modes are supported.
If a terminal device is opened with O_TTY_INIT in the mode, the device will be initialized to "sane" values for interactive use. It will be in Canonical mode, Enter will be translated to NewLine and on output, a NewLine is translated to CRLF. Echoing will be on, control characters are output as ^X, and TABs are expanded.
See the new <sys/termios.h> file for more information.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: daryl.mcdaniel@intel.com
Reviewed-by: erik.c.bjorge@intel.com
Reviewed-by: leroy.p.leahy@intel.com
Reviewed-by: lee.g.rosenbaum@intel.com
Reviewed-by: jaben.carsey@intel.com
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13989 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'StdLib/LibC')
-rw-r--r-- | StdLib/LibC/Containers/Common/ModuloUtil.c | 149 | ||||
-rw-r--r-- | StdLib/LibC/Containers/ContainerLib.inf | 46 | ||||
-rw-r--r-- | StdLib/LibC/Containers/Queues/Fifo.c | 526 | ||||
-rw-r--r-- | StdLib/LibC/Main/Main.c | 4 | ||||
-rw-r--r-- | StdLib/LibC/Uefi/Devices/Console/daConsole.c | 316 | ||||
-rw-r--r-- | StdLib/LibC/Uefi/Devices/Utility/DevGenisis.c | 32 | ||||
-rw-r--r-- | StdLib/LibC/Uefi/Devices/daConsole.inf | 7 | ||||
-rw-r--r-- | StdLib/LibC/Uefi/InteractiveIO/CanonRead.c | 161 | ||||
-rw-r--r-- | StdLib/LibC/Uefi/InteractiveIO/IIO.c | 373 | ||||
-rw-r--r-- | StdLib/LibC/Uefi/InteractiveIO/IIO.inf | 51 | ||||
-rw-r--r-- | StdLib/LibC/Uefi/InteractiveIO/IIOecho.c | 141 | ||||
-rw-r--r-- | StdLib/LibC/Uefi/InteractiveIO/IIOechoCtrl.h | 33 | ||||
-rw-r--r-- | StdLib/LibC/Uefi/InteractiveIO/IIOutilities.c | 288 | ||||
-rw-r--r-- | StdLib/LibC/Uefi/InteractiveIO/IIOutilities.h | 129 | ||||
-rw-r--r-- | StdLib/LibC/Uefi/InteractiveIO/IIOwrite.c | 210 | ||||
-rw-r--r-- | StdLib/LibC/Uefi/InteractiveIO/NonCanonRead.c | 89 | ||||
-rw-r--r-- | StdLib/LibC/Uefi/InteractiveIO/TerminalFunctions.c | 285 | ||||
-rw-r--r-- | StdLib/LibC/Uefi/SysCalls.c | 313 |
18 files changed, 2934 insertions, 219 deletions
diff --git a/StdLib/LibC/Containers/Common/ModuloUtil.c b/StdLib/LibC/Containers/Common/ModuloUtil.c new file mode 100644 index 0000000000..5f75698bd6 --- /dev/null +++ b/StdLib/LibC/Containers/Common/ModuloUtil.c @@ -0,0 +1,149 @@ +/** @file
+ Utility functions for performing basic math operations constrained within a
+ modulus.
+
+ These functions are intended to simplify small changes to a value which much
+ remain within a specified modulus.
+
+ NOTE: Changes must be less than or equal to the modulus specified by MaxVal.
+
+ Copyright (c) 2012, 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 <Uefi.h>
+#include <LibConfig.h>
+#include <assert.h>
+
+/** Counter = (Counter + 1) % MaxVal;
+
+ Counter is always expected to be LESS THAN MaxVal.
+ 0 <= Counter < MaxVal
+
+ @param[in] Counter The value to be incremented.
+ @param[in] MaxVal Modulus of the operation.
+
+ @return Returns the result of incrementing Counter, modulus MaxVal.
+ If Counter >= MaxVal, returns -1.
+**/
+INT32
+EFIAPI
+ModuloIncrement(
+ UINT32 Counter,
+ UINT32 MaxVal
+ )
+{
+ INT32 Temp;
+
+ if(Counter < MaxVal) {
+ Temp = (INT32)(Counter + 1);
+ if(Temp >= (INT32)MaxVal) {
+ Temp = 0;
+ }
+ }
+ else {
+ Temp = -1;
+ }
+ return Temp;
+}
+
+/** Counter = (Counter - 1) % MaxVal;
+
+ Counter is always expected to be LESS THAN MaxVal.
+ 0 <= Counter < MaxVal
+
+ @param[in] Counter The value to be decremented.
+ @param[in] MaxVal Modulus of the operation.
+
+ @return Returns the result of decrementing Counter, modulus MaxVal.
+ If Counter >= MaxVal, returns -1.
+**/
+INT32
+EFIAPI
+ModuloDecrement(
+ UINT32 Counter,
+ UINT32 MaxVal
+ )
+{
+ INT32 Temp;
+
+ if(Counter < MaxVal) {
+ Temp = (INT32)Counter - 1;
+ // If Counter is zero, Temp will become -1.
+ if(Temp < 0) {
+ Temp = (INT32)MaxVal - 1;
+ }
+ }
+ else {
+ Temp = -1;
+ }
+
+ return Temp;
+}
+
+/** Decrement Counter but don't decrement past zero.
+
+ @param[in] Counter The value to be decremented.
+
+ @return Returns the result of decrementing Counter.
+**/
+UINT32
+EFIAPI
+BoundDecrement(
+ UINT32 Counter
+ )
+{
+ return ((Counter > 0) ? (Counter - 1) : 0);
+}
+
+/** Increment Counter but don't increment past MaxVal.
+ Counter should be maintained in the range (0 <= Counter < MaxVal).
+
+ @param[in] Counter The value to be decremented.
+ @param[in] MaxVal The upper bound for Counter.
+
+ @return Returns the result of incrementing Counter.
+**/
+UINT32
+EFIAPI
+BoundIncrement(
+ UINT32 Counter,
+ UINT32 MaxVal
+ )
+{
+ return ((Counter < (MaxVal - 1)) ? (Counter + 1) : (MaxVal - 1));
+}
+
+/** Counter = (Counter + Increment) % MaxVal;
+
+ @param[in] Counter The value to be incremented.
+ @param[in] Increment The value to add to Counter.
+ @param[in] MaxVal Modulus of the operation.
+
+ @return Returns the result of adding Increment to Counter, modulus MaxVal,
+ or -1 if Increment is larger than MaxVal.
+**/
+INT32
+EFIAPI
+ModuloAdd (
+ UINT32 Counter,
+ UINT32 Increment,
+ UINT32 MaxVal
+ )
+{
+ UINT32 Temp;
+
+ if(Increment > MaxVal) {
+ return -1;
+ }
+ Temp = (Counter + Increment);
+ while(Temp >= MaxVal) {
+ Temp -= MaxVal;
+ }
+ return Temp;
+}
diff --git a/StdLib/LibC/Containers/ContainerLib.inf b/StdLib/LibC/Containers/ContainerLib.inf new file mode 100644 index 0000000000..4ca6690c4d --- /dev/null +++ b/StdLib/LibC/Containers/ContainerLib.inf @@ -0,0 +1,46 @@ +## @file
+# INF file for building the Container library.
+#
+# Various types of containers are implemented within this library.
+# Types of containers may be Queues (FIFO, LIFO, etc.), hash tables, etc.
+#
+# Copyright (c) 2012, 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
+#
+# THIS 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 = 0x00010005
+ BASE_NAME = LibContainer
+ FILE_GUID = 92f7436e-7395-4da1-a7be-f352f0bcd79c
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = LibContainer
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ Queues/Fifo.c
+ Common/ModuloUtil.c
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ LibC
+ LibWchar
+
+[Packages]
+ MdePkg/MdePkg.dec
+ StdLib/StdLib.dec
+ StdLibPrivateInternalFiles/DoNotUse.dec
diff --git a/StdLib/LibC/Containers/Queues/Fifo.c b/StdLib/LibC/Containers/Queues/Fifo.c new file mode 100644 index 0000000000..347ac02fd2 --- /dev/null +++ b/StdLib/LibC/Containers/Queues/Fifo.c @@ -0,0 +1,526 @@ +/** @file
+ Class for arbitrary sized FIFO queues.
+
+ The FIFO is empty if both the Read and Write indexes are equal.
+ The FIFO is full if the next write would make the Read and Write indexes equal.
+
+ Member variable NumElements is the maximum number of elements that can be
+ contained in the FIFO.
+ If NumElements is ZERO, there is an error.
+ NumElements should be in the range 1:N.
+
+ Members WriteIndex and ReadIndex are indexes into the array implementing the
+ FIFO. They should be in the range 0:(NumElements - 1).
+
+ One element of the FIFO is always reserved as the "terminator" element. Thus,
+ the capacity of a FIFO is actually NumElements-1.
+
+ Copyright (c) 2012, 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 <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <LibConfig.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <wchar.h>
+#include <Containers/Fifo.h>
+
+/** Determine number of items available to read from the FIFO.
+
+ The number of items are either the number of bytes, or the number of elements
+ depending upon the value of the As enumerator.
+
+ @param[in] Self Pointer to the FIFO instance.
+ @param[in] As An enumeration variable whose value determines whether the
+ returned value is the number of bytes or the number of elements
+ currently contained by the FIFO.
+
+ @retval 0 The FIFO is empty.
+ @retval >=0 The number of items contained by the FIFO.
+**/
+static
+size_t
+EFIAPI
+FIFO_NumInQueue (
+ cFIFO *Self,
+ FIFO_ElemBytes As
+)
+{
+ size_t Count;
+
+ if(Self->ReadIndex <= Self->WriteIndex) {
+ Count = Self->WriteIndex - Self->ReadIndex;
+ }
+ else {
+ Count = Self->NumElements - (Self->ReadIndex - Self->WriteIndex);
+ }
+ if(As == AsBytes) {
+ Count *= Self->ElementSize;
+ }
+ return Count;
+}
+
+/** Determine amount of free space in the FIFO that can be written into.
+
+ The number of items are either the number of bytes, or the number of elements
+ depending upon the value of the As enumerator.
+
+ @param[in] Self Pointer to the FIFO instance.
+ @param[in] As An enumeration variable whose value determines whether the
+ returned value is the number of bytes or the number of elements
+ currently available in the FIFO.
+
+ @retval 0 The FIFO is full.
+ @retval >=0 The number of items which can be accepted by the FIFO.
+**/
+static
+size_t
+EFIAPI
+FIFO_FreeSpace (
+ cFIFO *Self,
+ FIFO_ElemBytes As
+)
+{
+ size_t Count;
+ UINT32 RDex;
+ UINT32 WDex;
+
+ RDex = Self->ReadIndex;
+ WDex = Self->WriteIndex;
+
+ if(RDex <= WDex) {
+ Count = Self->NumElements - ((WDex - RDex) - 1);
+ }
+ else {
+ Count = (RDex - WDex);
+ }
+ if(As == AsBytes) {
+ Count *= Self->ElementSize;
+ }
+ return Count;
+}
+
+/** Reduce the FIFO contents by NumElem elements.
+
+ @param[in] Self Pointer to the FIFO instance.
+ @param[in] NumElem Number of elements to delete from the FIFO.
+
+ @retval 0 FIFO is now empty.
+ @retval N>0 There are still N elements in the FIFO.
+ @retval -1 There are fewer than NumElem elements in the FIFO.
+**/
+static
+ssize_t
+FIFO_Reduce (
+ cFIFO *Self,
+ size_t NumElem
+ )
+{
+ size_t QCount;
+ ssize_t RetVal;
+
+ assert(Self != NULL);
+
+ QCount = FIFO_NumInQueue(Self, AsElements);
+ if(NumElem > QCount) {
+ RetVal = -1;
+ errno = EINVAL;
+ }
+ else {
+ RetVal = (ssize_t)ModuloAdd(Self->ReadIndex, (UINT32)NumElem, Self->NumElements);
+ Self->ReadIndex = (UINT32)RetVal;
+
+ RetVal = (ssize_t)(QCount - NumElem);
+ }
+ return RetVal;
+}
+
+/** Test whether the FIFO is empty.
+
+ @param[in] Self Pointer to the FIFO instance.
+
+ @retval TRUE The FIFO is empty.
+ @retval FALSE There is data in the FIFO.
+**/
+static
+BOOLEAN
+EFIAPI
+FIFO_IsEmpty (
+ cFIFO *Self
+ )
+{
+ assert(Self != NULL);
+
+ return (BOOLEAN)(Self->WriteIndex == Self->ReadIndex);
+}
+
+/** Test whether the FIFO is full.
+
+ @param[in] Self Pointer to the FIFO instance.
+
+ @retval TRUE The FIFO is full.
+ @retval FALSE There is free space in the FIFO.
+**/
+static
+BOOLEAN
+EFIAPI
+FIFO_IsFull (
+ cFIFO *Self
+ )
+{
+ assert(Self != NULL);
+
+ return (BOOLEAN)(ModuloIncrement(Self->WriteIndex, Self->NumElements) == (INT32)Self->ReadIndex);
+}
+
+/** Add one or more elements to the FIFO.
+
+ This function allows one to add one or more elements, as specified by Count,
+ to the FIFO. Each element is of the size specified when the FIFO object
+ was instantiated (FIFO.ElementSize).
+
+ pElement points to the first byte of the first element to be added.
+ If multiple elements are to be added, the elements are expected to be
+ organized as a packed array.
+
+ @param[in] Self Pointer to the FIFO instance.
+ @param[in] pElement Pointer to the element(s) to enqueue (add).
+ @param[in] Count Number of elements to add.
+
+ @retval 0 The FIFO is full.
+ @retval >=0 The number of elements added to the FIFO.
+**/
+static
+size_t
+EFIAPI
+FIFO_Enqueue (
+ cFIFO *Self,
+ const void *pElement,
+ size_t Count
+ )
+{
+ uintptr_t ElemPtr;
+ uintptr_t QPtr;
+ size_t i;
+ UINT32 SizeOfElement;
+ UINT32 Windex;
+
+ assert(Self != NULL);
+ assert(pElement != NULL);
+ assert(Count >= 0);
+
+ if(FIFO_IsFull(Self)) {
+ Count = 0;
+ }
+ else {
+ Count = MIN(Count, Self->FreeSpace(Self, AsElements));
+ SizeOfElement = Self->ElementSize;
+ Windex = Self->WriteIndex;
+
+ ElemPtr = (uintptr_t)pElement;
+
+ QPtr = (uintptr_t)Self->Queue + (SizeOfElement * Windex);
+ for(i = 0; i < Count; ++i) {
+ (void)CopyMem((void *)QPtr, (const void *)ElemPtr, SizeOfElement);
+ Windex = (UINT32)ModuloIncrement(Windex, Self->NumElements);
+ if(Windex == 0) { // If the index wrapped
+ QPtr = (uintptr_t)Self->Queue;
+ }
+ else {
+ QPtr += SizeOfElement;
+ }
+ ElemPtr += SizeOfElement;
+ }
+ (void)ZeroMem((void*)QPtr, SizeOfElement);
+ Self->WriteIndex = Windex;
+ }
+ return Count;
+}
+
+/** Read or copy elements from the FIFO.
+
+ This function allows one to read one or more elements, as specified by Count,
+ from the FIFO. Each element is of the size specified when the FIFO object
+ was instantiated (FIFO.ElementSize).
+
+ pElement points to the destination of the first byte of the first element
+ to be read. If multiple elements are to be read, the elements are expected
+ to be organized as a packed array.
+
+ @param[in] Self Pointer to the FIFO instance.
+ @param[out] pElement Pointer to where to store the element(s) read from the FIFO.
+ @param[in] Count Number of elements to dequeue.
+ @param[in] Consume If TRUE, consume read elements. Otherwise, preserve.
+
+ @retval 0 The FIFO is empty.
+ @retval >=0 The number of elements read from the FIFO.
+**/
+static
+size_t
+EFIAPI
+FIFO_Dequeue (
+ cFIFO *Self,
+ void *pElement,
+ size_t Count,
+ BOOLEAN Consume
+ )
+{
+ UINTN ElemPtr;
+ UINTN QPtr;
+ UINT32 RDex;
+ UINT32 SizeOfElement;
+ UINT32 i;
+
+ assert(Self != NULL);
+ assert(pElement != NULL);
+ assert(Count != 0);
+
+ if(FIFO_IsEmpty(Self)) {
+ Count = 0;
+ }
+ else {
+ RDex = Self->ReadIndex;
+ SizeOfElement = Self->ElementSize;
+ ElemPtr = (UINTN)pElement;
+ Count = MIN(Count, Self->Count(Self, AsElements));
+
+ QPtr = (UINTN)Self->Queue + (RDex * Self->ElementSize);
+ for(i = 0; i < Count; ++i) {
+ (void)CopyMem((void *)ElemPtr, (const void *)QPtr, Self->ElementSize);
+ RDex = (UINT32)ModuloIncrement(RDex, Self->NumElements);
+ if(RDex == 0) { // If the index wrapped
+ QPtr = (UINTN)Self->Queue;
+ }
+ else {
+ QPtr += Self->ElementSize;
+ }
+ ElemPtr += Self->ElementSize;
+ }
+ if(Consume) {
+ Self->ReadIndex = RDex;
+ }
+ }
+ return Count;
+}
+
+/** Read elements from the FIFO.
+
+ @param[in] Self Pointer to the FIFO instance.
+ @param[out] pElement Pointer to where to store the element read from the FIFO.
+ @param[in] Count Number of elements to dequeue.
+
+ @retval 0 The FIFO is empty.
+ @retval >=0 The number of elements read from the FIFO.
+**/
+static
+size_t
+EFIAPI
+FIFO_Read (
+ cFIFO *Self,
+ void *pElement,
+ size_t Count
+ )
+{
+ return FIFO_Dequeue(Self, pElement, Count, TRUE);
+}
+
+/** Make a copy of the FIFO's data.
+ The contents of the FIFO is copied out and linearized without affecting the
+ FIFO contents.
+
+ @param[in] Self Pointer to the FIFO instance.
+ @param[out] pElement Pointer to where to store the elements copied from the FIFO.
+ @param[in] Count Number of elements to copy.
+
+ @retval 0 The FIFO is empty.
+ @retval >=0 The number of elements copied from the FIFO.
+**/
+static
+size_t
+EFIAPI
+FIFO_Copy (
+ cFIFO *Self,
+ void *pElement,
+ size_t Count
+ )
+{
+ return FIFO_Dequeue(Self, pElement, Count, FALSE);
+}
+
+/** Get the FIFO's current Read Index.
+
+ @param[in] Self Pointer to the FIFO instance.
+**/
+static
+UINT32
+EFIAPI
+FIFO_GetRDex (
+ cFIFO *Self
+)
+{
+ assert(Self != NULL);
+
+ return Self->ReadIndex;
+}
+
+/** Get the FIFO's current Write Index.
+
+ @param[in] Self Pointer to the FIFO instance.
+
+ @return The current value of the FIFO's WriteIndex member is returned.
+**/
+static
+UINT32
+EFIAPI
+FIFO_GetWDex (
+ cFIFO *Self
+)
+{
+ assert(Self != NULL);
+
+ return Self->WriteIndex;
+}
+
+/** Cleanly delete a FIFO instance.
+
+ @param[in] Self Pointer to the FIFO instance.
+**/
+static
+void
+EFIAPI
+FIFO_Delete (
+ cFIFO *Self
+ )
+{
+ assert(Self != NULL);
+
+ if(Self->Queue != NULL) {
+ FreePool(Self->Queue);
+ Self->Queue = NULL; // Zombie catcher
+ }
+ FreePool(Self);
+}
+
+/** Empty the FIFO, discarding up to NumToFlush elements.
+
+ @param[in] Self Pointer to the FIFO instance.
+ @param[in] NumToFlush Number of elements to flush from the FIFO.
+ If larger than the number of elements in the
+ FIFO, the FIFO is emptied.
+
+ @return Returns the number of elements remaining in the FIFO after the flush.
+**/
+static
+size_t
+EFIAPI
+FIFO_Flush (
+ cFIFO *Self,
+ size_t NumToFlush
+ )
+{
+ size_t NumInQ;
+ size_t Remainder;
+
+ assert(Self != NULL);
+
+ NumInQ = FIFO_FreeSpace(Self, AsElements);
+ if(NumToFlush >= NumInQ) {
+ Self->ReadIndex = 0;
+ Self->WriteIndex = 0;
+ Remainder = 0;
+ }
+ else {
+ Remainder = FIFO_Reduce(Self, NumToFlush);
+ }
+ return Remainder;
+}
+
+/** Remove the most recently added element from the FIFO.
+
+ @param[in] Self Pointer to the FIFO instance.
+
+ @return Returns the number of elements remaining in the FIFO.
+**/
+static
+size_t
+EFIAPI
+FIFO_Truncate (
+ cFIFO *Self
+ )
+{
+ size_t Remainder;
+
+ assert(Self != NULL);
+
+ Remainder = Self->Count(Self, AsElements);
+ if(Remainder > 0) {
+ Self->WriteIndex = (UINT32)ModuloDecrement(Self->WriteIndex, Self->NumElements);
+ --Remainder;
+ }
+ return Remainder;
+}
+
+/** Construct a new instance of a FIFO Queue.
+
+ @param[in] NumElements Number of elements to be contained in the new FIFO.
+ @param[in] ElementSize Size, in bytes, of an element.
+
+ @retval NULL Unable to create the instance.
+ @retval NonNULL Pointer to the new FIFO instance.
+**/
+cFIFO *
+EFIAPI
+New_cFIFO(
+ UINT32 NumElements,
+ size_t ElementSize
+ )
+{
+ cFIFO *FIFO;
+ UINT8 *Queue;
+
+ FIFO = NULL;
+ if((NumElements > 2) && (ElementSize > 0)) {
+ FIFO = (cFIFO *)AllocatePool(sizeof(cFIFO));
+ if(FIFO != NULL) {
+ Queue = (UINT8 *)AllocateZeroPool(NumElements * ElementSize);
+ if(Queue != NULL) {
+ FIFO->Write = FIFO_Enqueue;
+ FIFO->Read = FIFO_Read;
+ FIFO->Copy = FIFO_Copy;
+ FIFO->IsEmpty = FIFO_IsEmpty;
+ FIFO->IsFull = FIFO_IsFull;
+ FIFO->Count = FIFO_NumInQueue;
+ FIFO->FreeSpace = FIFO_FreeSpace;
+ FIFO->Flush = FIFO_Flush;
+ FIFO->Truncate = FIFO_Truncate;
+ FIFO->Delete = FIFO_Delete;
+ FIFO->GetRDex = FIFO_GetRDex;
+ FIFO->GetWDex = FIFO_GetWDex;
+
+ FIFO->Queue = Queue;
+ FIFO->ElementSize = (UINT32)ElementSize;
+ FIFO->NumElements = (UINT32)NumElements;
+ FIFO->ReadIndex = 0;
+ FIFO->WriteIndex = 0;
+ }
+ else {
+ FreePool(FIFO);
+ FIFO = NULL;
+ }
+ }
+ }
+ return FIFO;
+}
diff --git a/StdLib/LibC/Main/Main.c b/StdLib/LibC/Main/Main.c index 5736428db5..0c84c160e0 100644 --- a/StdLib/LibC/Main/Main.c +++ b/StdLib/LibC/Main/Main.c @@ -158,9 +158,9 @@ ShellAppMain ( mfd[i].MyFD = (UINT16)i;
}
- i = open("stdin:", O_RDONLY, 0444);
+ i = open("stdin:", (O_RDONLY | O_TTY_INIT), 0444);
if(i == 0) {
- i = open("stdout:", O_WRONLY, 0222);
+ i = open("stdout:", (O_WRONLY | O_TTY_INIT), 0222);
if(i == 1) {
i = open("stderr:", O_WRONLY, 0222);
}
diff --git a/StdLib/LibC/Uefi/Devices/Console/daConsole.c b/StdLib/LibC/Uefi/Devices/Console/daConsole.c index 4897a2e56e..927ec944ea 100644 --- a/StdLib/LibC/Uefi/Devices/Console/daConsole.c +++ b/StdLib/LibC/Uefi/Devices/Console/daConsole.c @@ -3,6 +3,13 @@ Manipulates abstractions for stdin, stdout, stderr.
+ This device is a WIDE device and this driver returns WIDE
+ characters. It this the responsibility of the caller to convert between
+ narrow and wide characters in order to perform the desired operations.
+
+ The devices status as a wide device is indicatd by _S_IWTTY being set in
+ f_iflags.
+
Copyright (c) 2010 - 2012, 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 that accompanies this distribution.
@@ -30,6 +37,7 @@ #include <unistd.h>
#include <kfile.h>
#include <Device/Device.h>
+#include <Device/IIO.h>
#include <MainData.h>
static const CHAR16* const
@@ -46,7 +54,7 @@ static const int stdioFlags[NUM_SPECIAL] = { static DeviceNode *ConNode[NUM_SPECIAL];
static ConInstance *ConInstanceList;
-static wchar_t *ConReadBuf;
+static cIIO *IIO;
/* Flags settable by Ioctl */
static BOOLEAN TtyCooked;
@@ -58,10 +66,10 @@ static BOOLEAN TtyEcho; large enough to hold the converted results. It is guaranteed
that there will be fewer than n characters placed in dest.
- @param dest WCS buffer to receive the converted string.
- @param buf MBCS string to convert to WCS.
- @param n Number of BYTES contained in buf.
- @param Cs Pointer to the character state object for this stream
+ @param[out] dest WCS buffer to receive the converted string.
+ @param[in] buf MBCS string to convert to WCS.
+ @param[in] n Number of BYTES contained in buf.
+ @param[in,out] Cs Pointer to the character state object for this stream
@return The number of BYTES consumed from buf.
**/
@@ -94,6 +102,13 @@ WideTtyCvt( CHAR16 *dest, const char *buf, ssize_t n, mbstate_t *Cs) return i;
}
+/** Close an open file.
+
+ @param[in] filp Pointer to the file descriptor structure for this file.
+
+ @retval 0 The file has been successfully closed.
+ @retval -1 filp does not point to a valid console descriptor.
+**/
static
int
EFIAPI
@@ -106,13 +121,25 @@ da_ConClose( Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
// Quick check to see if Stream looks reasonable
if(Stream->Cookie != CON_COOKIE) { // Cookie == 'IoAb'
+ errno = EINVAL;
EFIerrno = RETURN_INVALID_PARAMETER;
return -1; // Looks like a bad File Descriptor pointer
}
gMD->StdIo[Stream->InstanceNum] = NULL; // Mark the stream as closed
- return RETURN_SUCCESS;
+ return 0;
}
+/** Position the console cursor to the coordinates specified by Position.
+
+ @param[in] filp Pointer to the file descriptor structure for this file.
+ @param[in] Position A value containing the target X and Y coordinates.
+ @param[in] whence Ignored by the Console device.
+
+ @retval Position Success. Returns a copy of the Position argument.
+ @retval -1 filp is not associated with a valid console stream.
+ @retval -1 This console stream is attached to stdin.
+ @retval -1 The SetCursorPosition operation failed.
+**/
static
off_t
EFIAPI
@@ -155,11 +182,14 @@ da_ConSeek( /* Write a NULL terminated WCS to the EFI console.
- @param[in,out] BufferSize Number of bytes in Buffer. Set to zero if
- the string couldn't be displayed.
+ NOTE: The UEFI Console is a wide device, _S_IWTTY, so characters received
+ by da_ConWrite are WIDE characters. It is the responsibility of the
+ higher-level function(s) to perform any necessary conversions.
+
+ @param[in,out] BufferSize Number of characters in Buffer.
@param[in] Buffer The WCS string to be displayed
- @return The number of BYTES written. Because of MBCS, this may be more than number of characters.
+ @return The number of Characters written.
*/
static
ssize_t
@@ -174,8 +204,10 @@ da_ConWrite( EFI_STATUS Status;
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Proto;
ConInstance *Stream;
- ssize_t NumBytes;
+ ssize_t NumChar;
+ XY_OFFSET CursorPos;
+ NumChar = -1;
Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
// Quick check to see if Stream looks reasonable
if(Stream->Cookie != CON_COOKIE) { // Cookie == 'IoAb'
@@ -190,35 +222,45 @@ da_ConWrite( // Everything is OK to do the write.
Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)Stream->Dev;
- // Convert string from MBCS to WCS and translate \n to \r\n.
- NumBytes = WideTtyCvt(gMD->UString, (const char *)Buffer, (ssize_t)BufferSize, &Stream->CharState);
- BufferSize = NumBytes;
+ Status = EFI_SUCCESS;
+ if(Position != NULL) {
+ CursorPos.Offset = *Position;
+ Status = Proto->SetCursorPosition(Proto,
+ (INTN)CursorPos.XYpos.Column,
+ (INTN)CursorPos.XYpos.Row);
+ }
+ if(!RETURN_ERROR(Status)) {
// Send the Unicode buffer to the console
- Status = Proto->OutputString( Proto, gMD->UString);
- // Depending on status, update BufferSize and return
- if(RETURN_ERROR(Status)) {
- BufferSize = 0; // We don't really know how many characters made it out
+ Status = Proto->OutputString( Proto, (CHAR16 *)Buffer);
}
- else {
- //BufferSize = NumBytes;
- Stream->NumWritten += NumBytes;
+
+ // Depending on status, update BufferSize and return
+ if(!RETURN_ERROR(Status)) {
+ //BufferSize = NumChar;
+ NumChar = BufferSize;
+ Stream->NumWritten += NumChar;
}
EFIerrno = Status; // Make error reason available to caller
- return BufferSize;
+ return NumChar;
}
-/** Read characters from the console input device.
+/** Read a wide character from the console input device.
+
+ NOTE: The UEFI Console is a wide device, _S_IWTTY, so characters returned
+ by da_ConRead are WIDE characters. It is the responsibility of the
+ higher-level function(s) to perform any necessary conversions.
- @param[in,out] filp Pointer to file descriptor for this file.
- @param[in,out] offset Ignored.
+ @param[in,out] BufferSize Number of characters in Buffer.
+ @param[in] filp Pointer to file descriptor for this file.
+ @param[in] offset Ignored.
@param[in] BufferSize Buffer size, in bytes.
@param[out] Buffer Buffer in which to place the read characters.
- @return Number of bytes actually placed into Buffer.
-
- @todo Handle encodings other than ASCII-7 and UEFI.
+ @retval -1 An error has occurred. Reason in errno and EFIerrno.
+ @retval -1 No data is available. errno is set to EAGAIN
+ @retval 1 One wide character has been placed in Buffer
**/
static
ssize_t
@@ -232,84 +274,80 @@ da_ConRead( {
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *Proto;
ConInstance *Stream;
- wchar_t *OutPtr;
- EFI_INPUT_KEY Key;
- UINTN NumChar;
- UINTN Edex;
+ cIIO *Self;
+ EFI_INPUT_KEY Key = {0,0};
EFI_STATUS Status = RETURN_SUCCESS;
- UINTN i;
- char EchoBuff[MB_CUR_MAX + 1];
- int NumEcho;
+ UINTN Edex;
+ ssize_t NumRead;
+ int Flags;
+ wchar_t RetChar; // Default to No Data
- Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
- // Quick check to see if Stream looks reasonable
- if(Stream->Cookie != CON_COOKIE) { // Cookie == 'IoAb'
- EFIerrno = RETURN_INVALID_PARAMETER;
- return -1; // Looks like a bad This pointer
- }
- if(Stream->InstanceNum != STDIN_FILENO) {
- // Read only valid for stdin
- EFIerrno = RETURN_UNSUPPORTED;
- return -1;
+ NumRead = -1;
+ if(BufferSize < sizeof(wchar_t)) {
+ errno = EINVAL; // Buffer is too small to hold one character
}
- // It looks like things are OK for trying to read
- // We will accumulate *BufferSize characters or until we encounter
- // an "activation" character. Currently any control character.
+ else {
+ Self = (cIIO *)filp->devdata;
+ Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
Proto = (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)Stream->Dev;
- OutPtr = ConReadBuf;
- NumChar = (BufferSize > MAX_INPUT)? MAX_INPUT : BufferSize;
- i = 0;
- do {
+ Flags = filp->Oflags;
if((Stream->UnGetKey.UnicodeChar == CHAR_NULL) && (Stream->UnGetKey.ScanCode == SCAN_NULL)) {
+ // No data pending in the Un-get buffer. Get a char from the hardware.
+ if((Flags & O_NONBLOCK) == 0) {
+ // Read a byte in Blocking mode
Status = gBS->WaitForEvent( 1, &Proto->WaitForKey, &Edex);
- if(Status != RETURN_SUCCESS) {
- break;
+ EFIerrno = Status;
+ if(Status != EFI_SUCCESS) {
+ errno = EINVAL;
}
+ else {
Status = Proto->ReadKeyStroke(Proto, &Key);
- if(Status != RETURN_SUCCESS) {
- break;
+ if(Status == EFI_SUCCESS) {
+ NumRead = 1; // Indicate that Key holds the data
+ }
+ else {
+ errno = EIO;
+ }
+ }
+ }
+ else {
+ // Read a byte in Non-Blocking mode
+ Status = Proto->ReadKeyStroke(Proto, &Key);
+ EFIerrno = Status;
+ if(Status == EFI_SUCCESS) {
+ // Got a keystroke.
+ NumRead = 1; // Indicate that Key holds the data
+ }
+ else if(Status == EFI_NOT_READY) {
+ // Keystroke data is not available
+ errno = EAGAIN;
+ }
+ else {
+ // Hardware error
+ errno = EIO;
+ }
}
}
else {
+ // Use the data in the Un-get buffer
Key.ScanCode = Stream->UnGetKey.ScanCode;
Key.UnicodeChar = Stream->UnGetKey.UnicodeChar;
Stream->UnGetKey.ScanCode = SCAN_NULL;
Stream->UnGetKey.UnicodeChar = CHAR_NULL;
+ NumRead = 1; // Indicate that Key holds the data
}
- if(Key.ScanCode == SCAN_NULL) {
- NumEcho = 0;
- if(TtyCooked && (Key.UnicodeChar == CHAR_CARRIAGE_RETURN)) {
- *OutPtr++ = CHAR_LINEFEED;
- NumEcho = wctomb(EchoBuff, CHAR_LINEFEED);
- }
- else {
- *OutPtr++ = Key.UnicodeChar;
- NumEcho = wctomb(EchoBuff, Key.UnicodeChar);
+ // If we have data, prepare it for return.
+ if(NumRead == 1) {
+ RetChar = Key.UnicodeChar;
+ if((RetChar == 0) && ((Self->Termio.c_iflag & IGNSPEC) == 0)) {
+ // Must be a control, function, or other non-printable key.
+ // Map it into the Platform portion of the Unicode private use area
+ RetChar = (Key.ScanCode == 0) ? 0 : 0xF900U - Key.ScanCode;
}
- ++i;
- EchoBuff[NumEcho] = 0; /* Terminate the Echo buffer */
- if(TtyEcho) {
- /* Echo the character just input */
- da_ConWrite(&gMD->fdarray[STDOUT_FILENO], NULL, 2, EchoBuff);
+ *((wchar_t *)Buffer) = RetChar;
}
}
- if(iswcntrl(Key.UnicodeChar)) { // If a control character, or a scan code
- break;
- }
- } while(i < NumChar);
-
- *OutPtr = L'\0'; // Terminate the input buffer
-
- /* Convert the input buffer and place in Buffer.
- If the fully converted input buffer won't fit, write what will and
- leave the rest in ConReadBuf with ConReadLeft indicating how many
- unconverted characters remain in ConReadBuf.
- */
- NumEcho = (int)wcstombs(Buffer, ConReadBuf, BufferSize); /* Re-use NumEcho to hold number of bytes in Buffer */
- /* More work needs to be done before locales other than C can be supported. */
-
- EFIerrno = Status;
- return (ssize_t)NumEcho; // Will be 0 if we didn't get a key
+ return NumRead;
}
/** Console-specific helper function for the fstat() function.
@@ -320,6 +358,14 @@ da_ConRead( st_blksize Set to 1 since this is a character device
All other members of the stat structure are left unchanged.
+
+ @param[in] filp Pointer to file descriptor for this file.
+ @param[out] Buffer Pointer to a stat structure to receive the information.
+ @param[in,out] Something Ignored.
+
+ @retval 0 Successful completion.
+ @retval -1 Either filp is not associated with a console stream, or
+ Buffer is NULL. errno is set to EINVAL.
**/
static
int
@@ -343,6 +389,7 @@ da_ConStat( if ((Stream->Cookie != CON_COOKIE) || // Cookie == 'IoAb'
(Buffer == NULL))
{
+ errno = EINVAL;
EFIerrno = RETURN_INVALID_PARAMETER;
return -1;
}
@@ -378,6 +425,14 @@ da_ConStat( return 0;
}
+/** Console-specific helper for the ioctl system call.
+
+ The console device does not directly participate in ioctl operations.
+ This function completes the device abstraction and returns an error value
+ to indicate that the function is not supported for this device.
+
+ @retval -1 Function is not supported for this device.
+**/
static
int
EFIAPI
@@ -387,10 +442,21 @@ da_ConIoctl( va_list argp
)
{
- return -EPERM;
+ errno = ENODEV;
+ return -1;
}
/** Open an abstract Console Device.
+
+ @param[in] DevNode Pointer to the Device control structure for this stream.
+ @param[in] filp Pointer to the new file control structure for this stream.
+ @param[in] DevInstance Not used for the console device.
+ @param[in] Path Not used for the console device.
+ @param[in] MPath Not used for the console device.
+
+ @retval 0 This console stream has been successfully opened.
+ @retval -1 The DevNode or filp pointer is NULL.
+ @retval -1 DevNode does not point to a valid console stream device.
**/
int
EFIAPI
@@ -403,36 +469,57 @@ da_ConOpen( )
{
ConInstance *Stream;
+ UINT32 Instance;
+ int RetVal = -1;
- if((filp == NULL) ||
- (DevNode == NULL))
+ if((filp != NULL) &&
+ (DevNode != NULL))
{
- EFIerrno = RETURN_INVALID_PARAMETER;
- errno = EINVAL;
- return -1;
- }
Stream = (ConInstance *)DevNode->InstanceList;
// Quick check to see if Stream looks reasonable
- if(Stream->Cookie != CON_COOKIE) { // Cookie == 'IoAb'
+ if(Stream->Cookie == CON_COOKIE)
+ {
+ Instance = Stream->InstanceNum;
+ if(Instance < NUM_SPECIAL) {
+ gMD->StdIo[Instance] = Stream;
+ filp->f_iflags |= (_S_IFCHR | _S_ITTY | _S_IWTTY | _S_ICONSOLE);
+ filp->f_offset = 0;
+ filp->f_ops = &Stream->Abstraction;
+ filp->devdata = (void *)IIO;
+ RetVal = 0;
+ }
+ }
+ }
+ if (RetVal < 0) {
EFIerrno = RETURN_INVALID_PARAMETER;
errno = EINVAL;
- return -1; // Looks like a bad This pointer
}
- gMD->StdIo[Stream->InstanceNum] = Stream;
- filp->f_iflags |= (S_IFREG | _S_IFCHR | _S_ICONSOLE);
- filp->f_offset = 0;
- filp->f_ops = &Stream->Abstraction;
+ return RetVal;
- return 0;
}
#include <sys/poll.h>
/* Returns a bit mask describing which operations could be completed immediately.
+ Testable Events for this device are:
(POLLIN | POLLRDNORM) A Unicode character is available to read
(POLLIN) A ScanCode is ready.
(POLLOUT) The device is ready for output - always set on stdout and stderr.
+ Non-testable Events which are only valid in return values are:
+ POLLERR The specified device is not one of stdin, stdout, or stderr.
+ POLLHUP The specified stream has been disconnected
+ POLLNVAL da_ConPoll was called with an invalid parameter.
+
+ NOTE: The "Events" handled by this function are not UEFI events.
+
+ @param[in] filp Pointer to the file control structure for this stream.
+ @param[in] events A bit mask identifying the events to be examined
+ for this device.
+
+ @return Returns a bit mask comprised of both testable and non-testable
+ event codes indicating both the state of the operation and the
+ status of the device.
*/
static
short
@@ -450,6 +537,7 @@ da_ConPoll( Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
// Quick check to see if Stream looks reasonable
if(Stream->Cookie != CON_COOKIE) { // Cookie == 'IoAb'
+ errno = EINVAL;
EFIerrno = RETURN_INVALID_PARAMETER;
return POLLNVAL; // Looks like a bad filp pointer
}
@@ -495,15 +583,18 @@ __Cons_construct( )
{
ConInstance *Stream;
- RETURN_STATUS Status = RETURN_SUCCESS;
+ RETURN_STATUS Status;
int i;
+ Status = RETURN_OUT_OF_RESOURCES;
ConInstanceList = (ConInstance *)AllocateZeroPool(NUM_SPECIAL * sizeof(ConInstance));
- ConReadBuf = (wchar_t *)AllocateZeroPool((MAX_INPUT + 1) * sizeof(wchar_t));
- if((ConInstanceList == NULL) || (ConReadBuf == NULL)) {
- return RETURN_OUT_OF_RESOURCES;
+ if(ConInstanceList != NULL) {
+ IIO = New_cIIO();
+ if(IIO == NULL) {
+ FreePool(ConInstanceList);
}
-
+ else {
+ Status = RETURN_SUCCESS;
for( i = 0; i < NUM_SPECIAL; ++i) {
// Get pointer to instance.
Stream = &ConInstanceList[i];
@@ -553,9 +644,10 @@ __Cons_construct( if(Stream->Dev == NULL) {
continue; // No device for this stream.
}
- ConNode[i] = __DevRegister(stdioNames[i], NULL, &da_ConOpen, Stream, 1, sizeof(ConInstance), stdioFlags[i]);
+ ConNode[i] = __DevRegister(stdioNames[i], NULL, &da_ConOpen, Stream,
+ 1, sizeof(ConInstance), stdioFlags[i]);
if(ConNode[i] == NULL) {
- Status = EFIerrno;
+ Status = EFIerrno; // Grab error code that DevRegister produced.
break;
}
Stream->Parent = ConNode[i];
@@ -563,7 +655,8 @@ __Cons_construct( /* Initialize Ioctl flags until Ioctl is really implemented. */
TtyCooked = TRUE;
TtyEcho = TRUE;
-
+ }
+ }
return Status;
}
@@ -584,15 +677,16 @@ __Cons_deconstruct( if(ConInstanceList != NULL) {
FreePool(ConInstanceList);
}
- if(ConReadBuf != NULL) {
- FreePool(ConReadBuf);
+ if(IIO != NULL) {
+ IIO->Delete(IIO);
+ IIO = NULL;
}
return RETURN_SUCCESS;
}
/* ######################################################################### */
-#if 0 /* Not implemented for Console */
+#if 0 /* Not implemented (yet?) for Console */
static
int
diff --git a/StdLib/LibC/Uefi/Devices/Utility/DevGenisis.c b/StdLib/LibC/Uefi/Devices/Utility/DevGenisis.c index f6d375e6db..8d95fbad5e 100644 --- a/StdLib/LibC/Uefi/Devices/Utility/DevGenisis.c +++ b/StdLib/LibC/Uefi/Devices/Utility/DevGenisis.c @@ -1,7 +1,7 @@ /** @file
Device Abstraction: device creation utility functions.
- Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2011 - 2012, 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 that accompanies this distribution.
The full text of the license may be found at
@@ -44,22 +44,40 @@ int EFIAPI fnullop_flush (struct __filedes *filp) { return 0; }
int EFIAPI fbadop_stat (struct __filedes *filp, struct stat *StatBuf, void *Buf)
-{ return -EPERM; }
+{
+ errno = EPERM;
+ return -1;
+}
int EFIAPI fbadop_ioctl (struct __filedes *filp, ULONGN Cmd, va_list argp)
-{ return -EPERM; }
+{
+ errno = EPERM;
+ return -1;
+}
int EFIAPI fbadop_delete (struct __filedes *filp)
-{ return -EPERM; }
+{
+ errno = EPERM;
+ return -1;
+}
int EFIAPI fbadop_mkdir (const char *path, __mode_t perms)
-{ return -EPERM; }
+{
+ errno = EPERM;
+ return -1;
+}
int EFIAPI fbadop_rename (const char *from, const char *to)
-{ return -EPERM; }
+{
+ errno = EPERM;
+ return -1;
+}
int EFIAPI fbadop_rmdir (struct __filedes *filp)
-{ return -EPERM; }
+{
+ errno = EPERM;
+ return -1;
+}
/** Add a new device to the device list.
If both DevName and DevProto are NULL, register this as the Default device.
diff --git a/StdLib/LibC/Uefi/Devices/daConsole.inf b/StdLib/LibC/Uefi/Devices/daConsole.inf index 802c6eb13c..e23193f4e2 100644 --- a/StdLib/LibC/Uefi/Devices/daConsole.inf +++ b/StdLib/LibC/Uefi/Devices/daConsole.inf @@ -1,7 +1,7 @@ ## @file
# Standard C library: Console Device Abstraction.
#
-# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2011 - 2012, 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
@@ -44,8 +44,9 @@ LibC
LibWchar
LibUefi
+ LibIIO
DevUtility
[Protocols]
- gEfiSimpleTextInProtocolGuid
- gEfiSimpleTextOutProtocolGuid
+ gEfiSimpleTextInProtocolGuid ## CONSUMED
+ gEfiSimpleTextOutProtocolGuid ## CONSUMED
diff --git a/StdLib/LibC/Uefi/InteractiveIO/CanonRead.c b/StdLib/LibC/Uefi/InteractiveIO/CanonRead.c new file mode 100644 index 0000000000..db6af6e4bf --- /dev/null +++ b/StdLib/LibC/Uefi/InteractiveIO/CanonRead.c @@ -0,0 +1,161 @@ +/** @file
+ Canonical Interactive Input Function.
+
+ The functions assume that isatty() is TRUE at the time they are called.
+
+ Copyright (c) 2012, 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 <Uefi.h>
+
+#include <LibConfig.h>
+
+#include <errno.h>
+#include <sys/syslimits.h>
+#include <sys/termios.h>
+#include <Device/IIO.h>
+#include <MainData.h>
+#include "IIOutilities.h"
+#include "IIOechoCtrl.h"
+
+/** Read a line from the input file in canonical mode.
+ Perform echoing and input processing as directed by the termios flags.
+
+ @param[in] filp A pointer to a file descriptor structure.
+
+ @return The number of characters in the input buffer, or -1 if there
+ was an error.
+**/
+ssize_t
+IIO_CanonRead (
+ struct __filedes *filp
+ )
+{
+ cIIO *This;
+ cFIFO *InBuf;
+ struct termios *Termio;
+ struct __filedes *fpOut;
+ size_t NumRead;
+ wint_t InChar;
+ tcflag_t IFlag;
+ tcflag_t LFlag;
+ BOOLEAN EchoIsOK;
+ BOOLEAN Activate;
+ BOOLEAN FirstRead;
+ int OutMode;
+ UINTN MaxColumn;
+ UINTN MaxRow;
+
+ NumRead = MAX_INPUT; // Workaround "potentially uninitialized" warning
+ EchoIsOK = FALSE;
+ FirstRead = TRUE;
+ This = filp->devdata;
+ Termio = &This->Termio;
+ InBuf = This->InBuf;
+
+ // Get a copy of the flags we are going to use
+ IFlag = Termio->c_iflag;
+ LFlag = Termio->c_lflag;
+
+ /* Determine what the current screen size is. Also validates the output device. */
+ OutMode = IIO_GetOutputSize(STDOUT_FILENO, &MaxColumn, &MaxRow);
+ if(OutMode >= 0) {
+ /* Set the maximum screen dimensions. */
+ This->MaxColumn = MaxColumn;
+ This->MaxRow = MaxRow;
+
+ /* Record where the cursor is at the beginning of this Input operation.
+ The currently set stdout device is used to determine this. If there is
+ no stdout, or stdout is not an interactive device, nothing is recorded.
+ */
+ if (IIO_GetCursorPosition(STDOUT_FILENO, &This->InitialXY.Column, &This->InitialXY.Row) >= 0) {
+ This->CurrentXY.Column = This->InitialXY.Column;
+ This->CurrentXY.Row = This->InitialXY.Row;
+ EchoIsOK = TRUE; // Can only echo to stdout
+ }
+ }
+
+ // For now, we only echo to stdout.
+ fpOut = &gMD->fdarray[STDOUT_FILENO];
+
+ // Input and process characters until BufferSize is exhausted.
+ do {
+ InChar = IIO_GetInChar(filp, FirstRead);
+ FirstRead = FALSE;
+ Activate = TRUE;
+ if(InChar == CHAR_CARRIAGE_RETURN) {
+ if((IFlag & IGNCR) != 0) {
+ continue; // Restart the do loop, discarding the CR
+ }
+ else if((IFlag & ICRNL) != 0) {
+ InChar = L'\n';
+ }
+ }
+ else if(InChar == CHAR_LINEFEED) {
+ if((IFlag & INLCR) != 0) {
+ InChar = L'\r';
+ }
+ }
+ else if(CCEQ(Termio->c_cc[VINTR], InChar)) {
+ if((LFlag & ISIG) != 0) {
+ // Raise Signal
+ // Flush Input Buffer
+ // Return to caller
+ InChar = IIO_ECHO_DISCARD;
+ errno = EINTR;
+ }
+ else {
+ Activate = FALSE;
+ }
+ }
+ else if(CCEQ(Termio->c_cc[VQUIT], InChar)) {
+ if((LFlag & ISIG) != 0) {
+ // Raise Signal
+ // Flush Input Buffer
+ // Return to caller
+ InChar = IIO_ECHO_DISCARD;
+ errno = EINTR;
+ }
+ else {
+ Activate = FALSE;
+ }
+ }
+ else if(CCEQ(Termio->c_cc[VEOF], InChar)) {
+ InChar = WEOF;
+ }
+ else if(CCEQ(Termio->c_cc[VEOL], InChar)) {
+ EchoIsOK = FALSE; // Buffer, but don't echo this character
+ }
+ else if(CCEQ(Termio->c_cc[VERASE], InChar)) {
+ InChar = IIO_ECHO_ERASE;
+ Activate = FALSE;
+ }
+ else if(CCEQ(Termio->c_cc[VKILL], InChar)) {
+ InChar = IIO_ECHO_KILL;
+ Activate = FALSE;
+ }
+ else {
+ if((InChar < TtySpecKeyMin) || (InChar >= TtyFunKeyMax)) {
+ Activate = FALSE;
+ }
+ }
+ /** The Echo function is responsible for:
+ * Adding the character to the input buffer, if appropriate.
+ * Removing characters from the input buffer for ERASE and KILL processing.
+ * Visually removing characters from the screen if ECHOE is set.
+ * Ensuring one can not backspace beyond the beginning of the input text.
+ * Sending final echo strings to output.
+ **/
+ (void)This->Echo(fpOut, (wchar_t)InChar, EchoIsOK);
+ NumRead = InBuf->Count(InBuf, AsElements);
+ } while((NumRead < MAX_INPUT) &&
+ (Activate == FALSE));
+
+ return (ssize_t)NumRead;
+}
diff --git a/StdLib/LibC/Uefi/InteractiveIO/IIO.c b/StdLib/LibC/Uefi/InteractiveIO/IIO.c new file mode 100644 index 0000000000..65b61d9bcc --- /dev/null +++ b/StdLib/LibC/Uefi/InteractiveIO/IIO.c @@ -0,0 +1,373 @@ +/** @file
+ Definitions for the Interactive IO library.
+
+ The functions assume that isatty() is TRUE at the time they are called.
+
+ Copyright (c) 2012, 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 <Uefi.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <LibConfig.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <sys/syslimits.h>
+#include <sys/termios.h>
+#include <Device/IIO.h>
+#include <MainData.h>
+#include "IIOutilities.h"
+#include "IIOechoCtrl.h"
+
+/** Read from an Interactive IO device.
+
+ NOTE: If _S_IWTTY is set, the internal buffer contains WIDE characters.
+ They will need to be converted to MBCS when returned.
+
+ Input is line buffered if ICANON is set,
+ otherwise MIN determines how many characters to input.
+ Currently MIN is always zero, meaning 0 or 1 character is input in
+ noncanonical mode.
+
+ @param[in] filp Pointer to the descriptor of the device (file) to be read.
+ @param[in] BufferSize Maximum number of bytes to be returned to the caller.
+ @param[out] Buffer Pointer to the buffer where the input is to be stored.
+
+ @retval -1 An error occurred. No data is available.
+ @retval 0 No data was available. Try again later.
+ @retval >0 The number of bytes consumed by the returned data.
+**/
+static
+ssize_t
+EFIAPI
+IIO_Read(
+ struct __filedes *filp,
+ size_t BufferSize,
+ VOID *Buffer
+ )
+{
+ cIIO *This;
+ ssize_t NumRead;
+ tcflag_t Flags;
+ size_t XlateSz;
+ size_t Needed;
+
+ NumRead = -1;
+ This = filp->devdata;
+ if(This != NULL) {
+ Flags = This->Termio.c_lflag;
+ if(Flags & ICANON) {
+ NumRead = IIO_CanonRead(filp);
+ }
+ else {
+ NumRead = IIO_NonCanonRead(filp);
+ }
+ // At this point, the input has been accumulated in the input buffer.
+ if(filp->f_iflags & _S_IWTTY) {
+ // Data in InBuf is wide characters. Convert to MBCS
+ // First, convert into a linear buffer
+ NumRead = This->InBuf->Copy(This->InBuf, gMD->UString2, (INT32)UNICODE_STRING_MAX-1);
+ gMD->UString2[NumRead] = 0; // Ensure that the buffer is terminated
+ // Determine the needed space
+ XlateSz = EstimateWtoM((const wchar_t *)gMD->UString2, BufferSize, &Needed);
+
+ // Now translate this into MBCS in Buffer
+ NumRead = wcstombs((char *)Buffer, (const wchar_t *)gMD->UString2, XlateSz);
+
+ // Consume the translated characters
+ (void)This->InBuf->Flush(This->InBuf, Needed);
+ }
+ else {
+ // Data in InBuf is narrow characters. Use verbatim.
+ NumRead = This->InBuf->Read(This->InBuf, Buffer, (INT32)BufferSize);
+ }
+ }
+ return NumRead;
+}
+
+/** Process characters from buffer buf and write them to the output device
+ specified by filp.
+
+ @param[in] filp Pointer to a file descriptor structure.
+ @param[in] buf Pointer to the MBCS string to be output.
+ @param[in] N Number of bytes in buf.
+
+ @retval >=0 Number of bytes sent to the output device.
+**/
+static
+ssize_t
+EFIAPI
+IIO_Write(
+ struct __filedes *filp,
+ const char *buf,
+ ssize_t N
+ )
+{
+ cIIO *This;
+ cFIFO *OutBuf;
+ mbstate_t *OutState;
+ char *MbcsPtr;
+ ssize_t NumWritten;
+ ssize_t NumProc;
+ size_t CharLen;
+ UINTN MaxColumn;
+ UINTN MaxRow;
+ wchar_t OutChar[2]; // Just in case we run into 4-byte MBCS character
+ int OutMode;
+
+ errno = 0; // indicate no error as default
+ NumWritten = -1;
+
+ /* Determine what the current screen size is. Also validates the output device. */
+ OutMode = IIO_GetOutputSize(filp->MyFD, &MaxColumn, &MaxRow);
+
+ This = filp->devdata;
+ if((This != NULL) && (OutMode >= 0)) {
+ if(filp->MyFD == STDERR_FILENO) {
+ OutBuf = This->ErrBuf;
+ OutState = &This->ErrState;
+ }
+ else {
+ OutBuf = This->OutBuf;
+ OutState = &This->OutState;
+ }
+
+ /* Set the maximum screen dimensions. */
+ This->MaxColumn = MaxColumn;
+ This->MaxRow = MaxRow;
+
+ /* Record where the cursor is at the beginning of the Output operation. */
+ (void)IIO_GetCursorPosition(filp->MyFD, &This->InitialXY.Column, &This->InitialXY.Row);
+ This->CurrentXY.Column = This->InitialXY.Column;
+ This->CurrentXY.Row = This->InitialXY.Row;
+
+
+ NumWritten = 0;
+ OutChar[0] = (wchar_t)buf[0];
+ while((OutChar[0] != 0) && (NumWritten < N)) {
+ CharLen = mbrtowc(OutChar, (const char *)&buf[NumWritten], MB_CUR_MAX, OutState);
+ NumProc = IIO_WriteOne(filp, OutBuf, OutChar[0]);
+ if(NumProc > 0) {
+ // Successfully processed and buffered one character
+ NumWritten += CharLen; // Index of start of next character
+ }
+ else if(NumProc == -1) {
+ // Encoding Error
+ (void)mbrtowc(NULL, NULL, 1, OutState); // Re-Initialize the conversion state
+ errno = EILSEQ;
+ break;
+ }
+ else {
+ // Last character was incomplete
+ break;
+ }
+ }
+ // At this point, the characters to write are in OutBuf
+ // First, linearize the buffer
+ NumWritten = OutBuf->Copy(OutBuf, gMD->UString, UNICODE_STRING_MAX-1);
+ gMD->UString[NumWritten] = 0; // Ensure that the buffer is terminated
+
+ if(filp->f_iflags & _S_IWTTY) {
+ // Output device expects wide characters, Output what we have
+ NumWritten = filp->f_ops->fo_write(filp, NULL, NumWritten, gMD->UString);
+ }
+ else {
+ // Output device expects narrow characters, convert to MBCS
+ MbcsPtr = (char *)gMD->UString2;
+ // Determine the needed space
+ NumProc = (ssize_t)EstimateWtoM((const wchar_t *)gMD->UString, UNICODE_STRING_MAX * sizeof(wchar_t), &CharLen);
+
+ // Now translate this into MBCS in Buffer
+ NumWritten = wcstombs(MbcsPtr, (const wchar_t *)gMD->UString, NumProc);
+ MbcsPtr[NumWritten] = 0; // Ensure the buffer is terminated
+
+ // Send the MBCS buffer to Output
+ NumWritten = filp->f_ops->fo_write(filp, NULL, NumWritten, MbcsPtr);
+ }
+ // Consume the translated characters
+ (void)OutBuf->Flush(OutBuf, NumWritten);
+ }
+ else {
+ if(This == NULL) {
+ errno = EINVAL;
+ }
+ // Otherwise, errno is already set.
+ }
+ return NumWritten;
+}
+
+/** Echo a character to an output device.
+ Performs translation and edit processing depending upon termios flags.
+
+ @param[in] filp A pointer to a file descriptor structure.
+ @param[in] EChar The character to echo.
+ @param[in] EchoIsOK TRUE if the caller has determined that characters
+ should be echoed. Otherwise, just buffer.
+
+ @return Returns the number of characters actually output.
+**/
+static
+ssize_t
+EFIAPI
+IIO_Echo(
+ struct __filedes *filp,
+ wchar_t EChar,
+ BOOLEAN EchoIsOK
+ )
+{
+ cIIO *This;
+ ssize_t NumWritten;
+ cFIFO *OutBuf;
+ char *MbcsPtr;
+ ssize_t NumProc;
+ tcflag_t LFlags;
+
+ NumWritten = -1;
+ This = filp->devdata;
+ if(This != NULL) {
+ OutBuf = This->OutBuf;
+ LFlags = This->Termio.c_lflag & (ECHOK | ECHOE);
+
+ if((EChar >= TtyFunKeyMin) && (EChar < TtyFunKeyMax)) {
+ // A special function key was pressed, buffer it, don't echo, and activate.
+ // Process and buffer the character. May produce multiple characters.
+ NumProc = IIO_EchoOne(filp, EChar, FALSE); // Don't echo this character
+ EChar = CHAR_LINEFEED; // Every line must end with '\n' (legacy)
+ }
+ // Process and buffer the character. May produce multiple characters.
+ NumProc = IIO_EchoOne(filp, EChar, EchoIsOK);
+
+ // At this point, the character(s) to write are in OutBuf
+ // First, linearize the buffer
+ NumWritten = OutBuf->Copy(OutBuf, gMD->UString, UNICODE_STRING_MAX-1);
+ gMD->UString[NumWritten] = 0; // Ensure that the buffer is terminated
+
+ if((EChar == IIO_ECHO_KILL) && (LFlags & ECHOE) && EchoIsOK) {
+ // Position the cursor to the start of input.
+ (void)IIO_SetCursorPosition(filp, &This->InitialXY);
+ }
+ // Output the buffer
+ if(filp->f_iflags & _S_IWTTY) {
+ // Output device expects wide characters, Output what we have
+ NumWritten = filp->f_ops->fo_write(filp, NULL, NumWritten, gMD->UString);
+ }
+ else {
+ // Output device expects narrow characters, convert to MBCS
+ MbcsPtr = (char *)gMD->UString2;
+ // Determine the needed space
+ NumProc = (ssize_t)EstimateWtoM((const wchar_t *)gMD->UString, UNICODE_STRING_MAX * sizeof(wchar_t), NULL);
+
+ // Now translate this into MBCS in Buffer
+ NumWritten = wcstombs(MbcsPtr, (const wchar_t *)gMD->UString, NumProc);
+ MbcsPtr[NumWritten] = 0; // Ensure the buffer is terminated
+
+ // Send the MBCS buffer to Output
+ NumWritten = filp->f_ops->fo_write(filp, NULL, NumWritten, MbcsPtr);
+ }
+ // Consume the echoed characters
+ (void)OutBuf->Flush(OutBuf, NumWritten);
+
+ if(EChar == IIO_ECHO_KILL) {
+ if(LFlags == ECHOK) {
+ NumWritten = IIO_WriteOne(filp, OutBuf, CHAR_LINEFEED);
+ }
+ else if((LFlags & ECHOE) && EchoIsOK) {
+ // Position the cursor to the start of input.
+ (void)IIO_SetCursorPosition(filp, &This->InitialXY);
+ }
+ NumWritten = 0;
+ }
+ }
+ else {
+ errno = EINVAL;
+ }
+
+ return NumWritten;
+}
+
+static
+void
+FifoDelete(cFIFO *Member)
+{
+ if(Member != NULL) {
+ Member->Delete(Member);
+ }
+}
+
+/** Destructor for an IIO instance.
+
+ Releases all resources used by a particular IIO instance.
+**/
+static
+void
+EFIAPI
+IIO_Delete(
+ cIIO *Self
+ )
+{
+ if(Self != NULL) {
+ FifoDelete(Self->ErrBuf);
+ FifoDelete(Self->OutBuf);
+ FifoDelete(Self->InBuf);
+ if(Self->AttrBuf != NULL) {
+ FreePool(Self->AttrBuf);
+ }
+ FreePool(Self);
+ }
+}
+
+/** Constructor for new IIO instances.
+
+ @return Returns NULL or a pointer to a new IIO instance.
+**/
+cIIO *
+EFIAPI
+New_cIIO(void)
+{
+ cIIO *IIO;
+ cc_t *TempBuf;
+ int i;
+
+ IIO = (cIIO *)AllocateZeroPool(sizeof(cIIO));
+ if(IIO != NULL) {
+ IIO->InBuf = New_cFIFO(MAX_INPUT, sizeof(wchar_t));
+ IIO->OutBuf = New_cFIFO(MAX_OUTPUT, sizeof(wchar_t));
+ IIO->ErrBuf = New_cFIFO(MAX_OUTPUT, sizeof(wchar_t));
+ IIO->AttrBuf = (UINT8 *)AllocateZeroPool(MAX_OUTPUT);
+
+ if((IIO->InBuf == NULL) || (IIO->OutBuf == NULL) ||
+ (IIO->ErrBuf == NULL) || (IIO->AttrBuf == NULL))
+ {
+ IIO_Delete(IIO);
+ IIO = NULL;
+ }
+ else {
+ IIO->Delete = IIO_Delete;
+ IIO->Read = IIO_Read;
+ IIO->Write = IIO_Write;
+ IIO->Echo = IIO_Echo;
+ }
+ // Initialize Termio member
+ TempBuf = &IIO->Termio.c_cc[0];
+ TempBuf[0] = 8; // Default length for TABs
+ for(i=1; i < NCCS; ++i) {
+ TempBuf[i] = _POSIX_VDISABLE;
+ }
+ TempBuf[VMIN] = 0;
+ TempBuf[VTIME] = 0;
+ IIO->Termio.c_ispeed = B115200;
+ IIO->Termio.c_ospeed = B115200;
+ IIO->Termio.c_iflag = ICRNL;
+ IIO->Termio.c_oflag = OPOST | ONLCR | ONOCR | ONLRET;
+ IIO->Termio.c_cflag = 0;
+ IIO->Termio.c_lflag = ECHO | ECHONL;
+ }
+ return IIO;
+}
diff --git a/StdLib/LibC/Uefi/InteractiveIO/IIO.inf b/StdLib/LibC/Uefi/InteractiveIO/IIO.inf new file mode 100644 index 0000000000..dd21e85b13 --- /dev/null +++ b/StdLib/LibC/Uefi/InteractiveIO/IIO.inf @@ -0,0 +1,51 @@ +## @file
+# Interactive I/O Library.
+#
+# Copyright (c) 2012, 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.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = LibIIO
+ FILE_GUID = c1e9fffb-5557-4cb5-a5f5-1fbd902a74ed
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = LibIIO
+
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ IIO.c
+ NonCanonRead.c
+ CanonRead.c
+ TerminalFunctions.c
+ IIOutilities.c
+ IIOwrite.c
+ IIOecho.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ StdLib/StdLib.dec
+ StdLibPrivateInternalFiles/DoNotUse.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ LibC
+ LibWchar
+ LibContainer
+
+[Protocols]
+ gEfiSimpleTextInProtocolGuid ## CONSUMES
+ gEfiSimpleTextOutProtocolGuid ## CONSUMES
diff --git a/StdLib/LibC/Uefi/InteractiveIO/IIOecho.c b/StdLib/LibC/Uefi/InteractiveIO/IIOecho.c new file mode 100644 index 0000000000..14369de95b --- /dev/null +++ b/StdLib/LibC/Uefi/InteractiveIO/IIOecho.c @@ -0,0 +1,141 @@ +/** @file
+ Echo characters to an Interactive I/O Output device.
+
+ The functions assume that isatty() is TRUE at the time they are called.
+ Since the UEFI console is a WIDE character device, these functions do all
+ processing using wide characters.
+
+ It is the responsibility of the caller, or higher level function, to perform
+ any necessary translation between wide and narrow characters.
+
+ Copyright (c) 2012, 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 <Uefi.h>
+
+#include <LibConfig.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <sys/termios.h>
+#include <Device/IIO.h>
+#include "IIOutilities.h"
+#include "IIOechoCtrl.h"
+
+/** Echo one character to an IIO file.
+
+ If character InCh is a special "echo control" character, process it and output
+ the resultant character(s), if any. Otherwise pass the character on to the
+ IIO_WriteOne() function which performs generic output processing, if needed.
+
+ @param[in] filp Pointer to an open IIO file's file descriptor structure.
+ @param[in] InCh The wide character to be echoed.
+ @param[in] EchoIsOK A flag indicating whether echoing is appropriate for this
+ device or not.
+
+ @retval -1 The filp argument does not refer to an IIO device.
+ Global value errno is set to EINVAL.
+ @retval >=0 The number of characters actually output.
+
+ @sa IIO_WriteOne
+**/
+ssize_t
+IIO_EchoOne (
+ struct __filedes *filp,
+ wchar_t InCh,
+ BOOLEAN EchoIsOK
+ )
+{
+ cIIO *This;
+ cFIFO *OutBuf;
+ cFIFO *InBuf;
+ UINT8 *AttrBuf;
+ ssize_t NumEcho;
+ tcflag_t LFlags;
+ UINT32 AttrDex;
+ int i;
+
+ NumEcho = -1;
+ This = filp->devdata;
+
+ if(This != NULL) {
+ LFlags = This->Termio.c_lflag;
+ OutBuf = This->OutBuf;
+ InBuf = This->InBuf;
+ AttrBuf = This->AttrBuf;
+ AttrDex = InBuf->GetWDex(InBuf);
+
+ switch(InCh) {
+ case IIO_ECHO_DISCARD:
+ // Do not buffer or otherwise process
+ NumEcho = 0;
+ break;
+
+ case IIO_ECHO_ERASE:
+ // Delete last character from InBuf
+ if(!InBuf->IsEmpty(InBuf)) {
+ (void)InBuf->Truncate(InBuf);
+
+ // Erase screen character(s) based on Attrib value
+ if(LFlags & ECHO) {
+ AttrDex = (UINT32)ModuloDecrement(AttrDex, InBuf->NumElements);
+ NumEcho = AttrBuf[AttrDex];
+ for(i = 0; i < NumEcho; ++i) {
+ (void)IIO_WriteOne(filp, OutBuf, CHAR_BACKSPACE);
+ }
+ if(LFlags & ECHOE) {
+ for(i = 0; i < NumEcho; ++i) {
+ (void)IIO_WriteOne(filp, OutBuf, L' ');
+ }
+ for(i = 0; i < NumEcho; ++i) {
+ (void)IIO_WriteOne(filp, OutBuf, CHAR_BACKSPACE);
+ }
+ }
+ }
+ else {
+ NumEcho = 0;
+ }
+ }
+ break;
+
+ case IIO_ECHO_KILL:
+ // Flush contents of InBuf and OutBuf
+ InBuf->Flush(InBuf, (size_t)-1);
+ OutBuf->Flush(OutBuf, (size_t)-1);
+
+ // Erase characters from screen.
+ if(LFlags & ECHOE) {
+ NumEcho = IIO_CursorDelta(This, &This->InitialXY, &This->CurrentXY);
+ for(i = 0; i < NumEcho; ++i) {
+ (void)IIO_WriteOne(filp, OutBuf, L' ');
+ }
+ }
+ break;
+
+ default:
+ // Add character to input buffer
+ (void)InBuf->Write(InBuf, &InCh, 1);
+
+ NumEcho = 0; // In case echoing is not enabled or OK
+ // If echoing is OK and enabled, "echo" character using IIO_WriteOne
+ if( EchoIsOK &&
+ ( (LFlags & ECHO) ||
+ ((LFlags & ECHONL) && (InCh == CHAR_LINEFEED))))
+ {
+ NumEcho = IIO_WriteOne(filp, OutBuf, InCh);
+ }
+ AttrBuf[AttrDex] = (UINT8)NumEcho;
+ break;
+ }
+ }
+ else {
+ errno = EINVAL;
+ }
+ return NumEcho;
+}
diff --git a/StdLib/LibC/Uefi/InteractiveIO/IIOechoCtrl.h b/StdLib/LibC/Uefi/InteractiveIO/IIOechoCtrl.h new file mode 100644 index 0000000000..69d040af01 --- /dev/null +++ b/StdLib/LibC/Uefi/InteractiveIO/IIOechoCtrl.h @@ -0,0 +1,33 @@ +/** @file
+ Constants and declarations for the Echo function.
+
+ Copyright (c) 2012, 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 _IIO_ECHO_CTRL_H
+#define _IIO_ECHO_CTRL_H
+#include <sys/termios.h>
+
+__BEGIN_DECLS
+
+/* These constants are assigned values within the Unicode Private Use range.
+ The value of IIO_ECHO_MIN must be adjusted to ensure that IIO_ECHO_MAX
+ never exceeds the value of 0xF900.
+*/
+typedef enum {
+ IIO_ECHO_MIN = (TtyFunKeyMin - 3),
+ IIO_ECHO_DISCARD = IIO_ECHO_MIN, // Ignore this character completely
+ IIO_ECHO_ERASE, // Erase previous character
+ IIO_ECHO_KILL, // Kill the entire line
+ IIO_ECHO_MAX
+} IioEchoCtrl;
+
+__END_DECLS
+
+#endif /* _IIO_ECHO_CTRL_H */
diff --git a/StdLib/LibC/Uefi/InteractiveIO/IIOutilities.c b/StdLib/LibC/Uefi/InteractiveIO/IIOutilities.c new file mode 100644 index 0000000000..2da0628840 --- /dev/null +++ b/StdLib/LibC/Uefi/InteractiveIO/IIOutilities.c @@ -0,0 +1,288 @@ +/** @file
+ Utilities for Interactive I/O Functions.
+
+ The functions assume that isatty() is TRUE at the time they are called.
+
+ Copyright (c) 2012, 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 <Uefi.h>
+#include <Protocol/SimpleTextOut.h>
+
+#include <LibConfig.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <sys/syslimits.h>
+#include <sys/termios.h>
+#include <Device/IIO.h>
+#include <MainData.h>
+#include "IIOutilities.h"
+
+/** Get the low-level UEFI protocol associated with an open file.
+
+ @param[in] fd File descriptor for an open file.
+ @param[out] filp NULL, or a pointer to where a pointer to the file's
+ file descriptor structure is to be stored.
+
+ @return Returns NULL if fd is not a valid file descriptor, otherwise
+ a pointer to the file's associated UEFI protocol is returned.
+**/
+void *
+EFIAPI
+IIO_GetDeviceProto (
+ int fd,
+ struct __filedes **filp
+ )
+{
+ void *Proto;
+ ConInstance *Stream;
+ struct __filedes *pfil;
+
+ Proto = NULL;
+ if(ValidateFD( fd, VALID_OPEN)) {
+ pfil = &gMD->fdarray[fd];
+ Stream = BASE_CR(pfil->f_ops, ConInstance, Abstraction);
+ Proto = (void *)Stream->Dev;
+ if(filp != NULL) {
+ *filp = pfil;
+ }
+ }
+ return Proto;
+}
+
+/** Get a character either from the input buffer or from hardware.
+
+ @param[in] filp Pointer to a file descriptor structure.
+ @param[in] First Set to TRUE to identify the initial read.
+
+ @return Returns a character read from either the input buffer
+ or from the open file (device) identified by filp.
+ A return value of WEOF indicates an error has occurred.
+**/
+wint_t
+EFIAPI
+IIO_GetInChar (
+ struct __filedes *filp,
+ BOOLEAN First
+)
+{
+ cIIO *This;
+ cFIFO *InBuf;
+ EFI_STATUS Status;
+ ssize_t NumRead;
+ wint_t RetVal;
+ wchar_t InChar;
+
+ static size_t BufCnt;
+
+ This = filp->devdata;
+ InBuf = This->InBuf;
+
+ NumRead = -1;
+ InChar = 0;
+ if(First) {
+ BufCnt = InBuf->Count(InBuf, AsElements);
+ }
+ if(BufCnt > 0) {
+ Status = InBuf->Read(InBuf, &InChar, 1);
+ --BufCnt;
+ NumRead = 1;
+ }
+ else {
+ NumRead = filp->f_ops->fo_read(filp, &filp->f_offset, sizeof(wchar_t), &InChar);
+ }
+ if(NumRead <= 0) {
+ RetVal = WEOF;
+ }
+ else {
+ RetVal = (wint_t)InChar;
+ }
+ return InChar;
+}
+
+/** Get the current cursor position.
+
+ @param[in] fd File descriptor for an open file.
+ @param[out] Column Pointer to where the current cursor column is to be stored.
+ @param[out] Row Pointer to where the current cursor row is to be stored.
+
+ @retval -1 fd is not an IIO output device.
+ @retval 0 Cursor position retrieved, Cursor is Not Visible.
+ @retval 1 Cursor position retrieved, Cursor is Visible.
+**/
+int
+EFIAPI
+IIO_GetCursorPosition (
+ int fd,
+ UINT32 *Column,
+ UINT32 *Row
+ )
+{
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Proto;
+ struct __filedes *pStdOut;
+ int RetVal;
+
+ RetVal = -1;
+
+ Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)IIO_GetDeviceProto(fd, &pStdOut);
+ if(Proto != NULL) {
+ if(((pStdOut->f_iflags & _S_ITTY) != 0) && // file is a TTY
+ ((pStdOut->Oflags & O_ACCMODE) != 0)) // and it is open for output
+ {
+ // fd is for a TTY or "Interactive IO" device
+ *Column = Proto->Mode->CursorColumn;
+ *Row = Proto->Mode->CursorRow;
+ if(Proto->Mode->CursorVisible) {
+ RetVal = 1;
+ }
+ else {
+ RetVal = 0;
+ }
+ }
+ }
+ return RetVal;
+}
+
+/** Set the cursor position.
+
+ @param[in] filp Pointer to the output device's file descriptor structure.
+ @param[in] StartXY Pointer to a cursor coordinate (XY) structure indicating
+ the desired coordinate to move the cursor to.
+
+ @retval -1 fd is not an IIO output device
+ @retval 0 Cursor position set successfully.
+**/
+int
+EFIAPI
+IIO_SetCursorPosition (
+ struct __filedes *filp,
+ CURSOR_XY *CursorXY
+ )
+{
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Proto;
+ cIIO *This;
+ EFI_STATUS Status;
+ int RetVal;
+
+ RetVal = -1;
+
+ This = filp->devdata;
+ Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)IIO_GetDeviceProto(filp->MyFD, NULL);
+ if(Proto != NULL) {
+ if(((filp->f_iflags & _S_ITTY) != 0) && // file is a TTY
+ ((filp->Oflags & O_ACCMODE) != 0)) // and it is open for output
+ {
+ // fd is for a TTY or "Interactive IO" device
+ Status = Proto->SetCursorPosition(Proto, CursorXY->Column, CursorXY->Row);
+ if(Status == EFI_SUCCESS) {
+ This->CurrentXY.Column = CursorXY->Column;
+ This->CurrentXY.Row = CursorXY->Row;
+ RetVal = 0;
+ }
+ }
+ }
+ return RetVal;
+}
+
+/** Get Output screen size and mode.
+
+ @param[in] fd File descriptor of the output device.
+ @param[out] Col Pointer to where to store the MAX Column, or NULL.
+ @param[out] Row Pointer to where to store the MAX Row, or NULL.
+
+ @retval <0 An error occurred. The reason is in errno and EFIerrno.
+ * EIO UEFI QueryMode failed
+ * ENOTTY fd does not refer to an interactive output device
+ @retval >=0 Current output mode
+**/
+int
+EFIAPI
+IIO_GetOutputSize (
+ int fd,
+ UINTN *Col,
+ UINTN *Row
+)
+{
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Proto;
+ struct __filedes *pStdOut;
+ EFI_STATUS Status;
+ UINTN TempCol;
+ UINTN TempRow;
+ UINTN TempMode;
+ int RetVal;
+
+ RetVal = -1;
+
+ Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)IIO_GetDeviceProto(fd, &pStdOut);
+ if(Proto != NULL) {
+ if(((pStdOut->f_iflags & _S_ITTY) != 0) && // file is a TTY
+ ((pStdOut->Oflags & O_ACCMODE) != 0)) // and it is open for output
+ {
+ // fd is for a TTY or "Interactive IO" device
+ TempMode = Proto->Mode->Mode;
+ Status = Proto->QueryMode(Proto, TempMode, &TempCol, &TempRow);
+ if(EFI_ERROR(Status)) {
+ EFIerrno = Status;
+ errno = EIO;
+ }
+ else {
+ *Col = TempCol;
+ *Row = TempRow;
+ RetVal = (int)TempMode;
+ }
+ }
+ else {
+ errno = ENOTTY;
+ }
+ }
+ return RetVal;
+}
+
+/** Calculate the number of character positions between two X/Y coordinate pairs.
+
+ Using the current output device characteristics, calculate the number of
+ characters between two coordinates. It is assumed that EndXY points to
+ an output location that occurs after StartXY.
+
+ RowDelta is the computed difference between the ending and starting rows.
+ If RowDelta < 0, then EndXY is NOT after StartXY, so assert.
+
+ ColumnDelta is the computed number of character positions (columns) between
+ the starting position and the ending position. If ColumnDelta is < 0,
+ then EndXY is NOT after StartXY, so assert.
+
+ @param[in] This Pointer to the IIO instance to be examined.
+ @param[in] StartXY Pointer to the starting coordinate pair.
+ @param[in] EndXY Pointer to the ending coordinate pair.
+
+ @return Returns the difference between the starting and ending coordinates.
+**/
+UINT32
+EFIAPI
+IIO_CursorDelta (
+ cIIO *This,
+ CURSOR_XY *StartXY,
+ CURSOR_XY *EndXY
+)
+{
+ INT32 ColumnDelta;
+ INT32 RowDelta;
+
+ RowDelta = (int)EndXY->Row - (int)StartXY->Row;
+
+ assert(RowDelta >= 0); // assert if EndXY is NOT after StartXY
+
+ ColumnDelta = (INT32)((This->MaxColumn * RowDelta) + EndXY->Column);
+ ColumnDelta -= (INT32)StartXY->Column;
+
+ assert(ColumnDelta >= 0); // assert if EndXY is NOT after StartXY
+
+ return (UINT32)ColumnDelta;
+}
diff --git a/StdLib/LibC/Uefi/InteractiveIO/IIOutilities.h b/StdLib/LibC/Uefi/InteractiveIO/IIOutilities.h new file mode 100644 index 0000000000..778b612ea5 --- /dev/null +++ b/StdLib/LibC/Uefi/InteractiveIO/IIOutilities.h @@ -0,0 +1,129 @@ +/** @file
+ Utilities for Interactive I/O Functions.
+
+ The functions assume that isatty() is TRUE at the time they are called.
+
+ Copyright (c) 2012, 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 _IIO_UTILITIES_H
+#define _IIO_UTILITIES_H
+
+#include <sys/EfiSysCall.h>
+
+__BEGIN_DECLS
+
+/** Get the low-level UEFI protocol associated with an open file.
+
+ @param[in] fd File descriptor for an open file.
+ @param[out] filp NULL, or a pointer to where a pointer to the file's
+ file descriptor structure is to be stored.
+
+ @return Returns NULL if fd is not a valid file descriptor, otherwise
+ a pointer to the file's associated UEFI protocol is returned.
+**/
+void *
+EFIAPI
+IIO_GetDeviceProto (
+ int fd,
+ struct __filedes **filp // Optional - filp == NULL if unused
+ );
+
+/** Get a character either from the input buffer or from hardware.
+
+ @param[in] filp Pointer to a file descriptor structure.
+ @param[in] First Set to TRUE to identify the initial read.
+
+ @return Returns a character read from either the input buffer
+ or from the open file (device) identified by filp.
+ A return value of WEOF indicates an error has occurred.
+**/
+wint_t
+EFIAPI
+IIO_GetInChar (
+ struct __filedes *filp,
+ BOOLEAN First
+ );
+
+/** Get the current cursor position.
+
+ @param[in] fd File descriptor for an open file.
+ @param[out] Column Pointer to where the current cursor column is to be stored.
+ @param[out] Row Pointer to where the current cursor row is to be stored.
+
+ @retval -1 fd is not an IIO output device.
+ @retval 0 Cursor position retrieved, Cursor is Not Visible.
+ @retval 1 Cursor position retrieved, Cursor is Visible.
+**/
+int
+EFIAPI
+IIO_GetCursorPosition (
+ int fd,
+ UINT32 *Column,
+ UINT32 *Row
+ );
+
+/** Set the cursor position.
+
+ @param[in] filp Pointer to the output device's file descriptor structure.
+ @param[in] StartXY Pointer to a cursor coordinate (XY) structure indicating
+ the desired coordinate to move the cursor to.
+
+ @retval -1 fd is not an IIO output device
+ @retval 0 Cursor position set successfully.
+**/
+int
+EFIAPI
+IIO_SetCursorPosition (
+ struct __filedes *filp,
+ CURSOR_XY *StartXY
+ );
+
+/** Get Output screen size and mode.
+
+ @param[in] fd File descriptor of the output device.
+ @param[out] Col Pointer to where to store the MAX Column, or NULL.
+ @param[out] Row Pointer to where to store the MAX Row, or NULL.
+
+ @retval <0 An error occurred. The reason is in errno and EFIerrno.
+ * EIO UEFI QueryMode failed
+ * ENOTTY fd does not refer to an interactive output device
+ @retval >=0 Current output mode
+**/
+int
+EFIAPI
+IIO_GetOutputSize (
+ int fd,
+ UINTN *Col,
+ UINTN *Row
+);
+
+/** Calculate the number of character positions between two X/Y coordinate pairs.
+
+ Using the current output device characteristics, calculate the number of
+ characters between two coordinates.
+
+ @param[in] This Pointer to the IIO instance to be examined.
+ @param[in] StartXY Pointer to the starting coordinate pair.
+ @param[in] EndXY Pointer to the ending coordinate pair.
+
+ @return Returns the difference between the starting and ending coordinates.
+ The return value is positive if the coordinates contained in EndXY
+ are larger than StartXY, otherwise the return value is negative.
+**/
+int
+EFIAPI
+IIO_CursorDelta (
+ cIIO *This,
+ CURSOR_XY *StartXY,
+ CURSOR_XY *EndXY
+ );
+
+__END_DECLS
+#endif /* _IIO_UTILITIES_H */
diff --git a/StdLib/LibC/Uefi/InteractiveIO/IIOwrite.c b/StdLib/LibC/Uefi/InteractiveIO/IIOwrite.c new file mode 100644 index 0000000000..927f4f4ff3 --- /dev/null +++ b/StdLib/LibC/Uefi/InteractiveIO/IIOwrite.c @@ -0,0 +1,210 @@ +/** @file
+ Write to an Interactive I/O Output device.
+
+ The functions assume that isatty() is TRUE at the time they are called.
+ Since the UEFI console is a WIDE character device, these functions do all
+ processing using wide characters.
+
+ It is the responsibility of the caller, or higher level function, to perform
+ any necessary translation between wide and narrow characters.
+
+ Copyright (c) 2012, 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 <Uefi.h>
+
+#include <LibConfig.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <sys/termios.h>
+#include <Device/IIO.h>
+
+static wchar_t Spaces[] = L" "; // Spaces for expanding TABs
+
+#define MAX_TAB_WIDTH ((int)(sizeof(Spaces) / sizeof(wchar_t)) - 1)
+
+#define MAX_EXPANSION 3
+
+/** Process and buffer one character for output.
+
+ @param[in] filp Pointer to a file descriptor structure.
+ @param[out] OBuf Pointer to the Output Buffer FIFO.
+ @param[in] InCh The wide character to process.
+
+ @retval <0 An error occurred. Reason is in errno.
+ * EINVAL The pointer to the IIO object is NULL.
+ * ENOSPC The OBuf FIFO is full.
+
+ @retval 0 A character was input but not placed in the output buffer.
+
+ @retval >0 The number of characters buffered. Normally 1, or 2.
+ If a character is discarded because of flag settings, a
+ 1 will be returned.
+**/
+ssize_t
+IIO_WriteOne(struct __filedes *filp, cFIFO *OBuf, wchar_t InCh)
+{
+ cIIO *This;
+ struct termios *Termio;
+ tcflag_t OFlag;
+ ssize_t RetVal;
+ wchar_t wc[MAX_EXPANSION]; // Sub-buffer for conversions
+ wchar_t *wcb; // Pointer to either wc or spaces
+ int numW = 0; // Wide characters placed in OBuf
+ INT32 TabWidth; // Each TAB expands into this number of spaces
+ UINT32 CurColumn; // Current cursor column on the screen
+ UINT32 CurRow; // Current cursor row on the screen
+ UINT32 PrevColumn; // Previous column. Used to detect wrapping.
+ UINT32 AdjColumn; // Current cursor column on the screen
+ UINT32 AdjRow; // Current cursor row on the screen
+
+ RetVal = -1;
+ wcb = wc;
+ This = filp->devdata;
+ if((This != NULL) && (OBuf->FreeSpace(OBuf, AsElements) >= MAX_EXPANSION)) {
+ Termio = &This->Termio;
+ OFlag = Termio->c_oflag;
+ TabWidth = (INT32)This->Termio.c_cc[VTABLEN];
+ if(TabWidth > MAX_TAB_WIDTH) {
+ TabWidth = MAX_TAB_WIDTH;
+ }
+ CurColumn = This->CurrentXY.Column;
+ CurRow = This->CurrentXY.Row;
+
+ numW = 1; // The majority of characters buffer one character
+ AdjRow = 0; // Most characters just cause horizontal movement
+ AdjColumn = 0;
+ if(OFlag & OPOST) {
+ /* Perform output processing */
+ switch(InCh) {
+ case CHAR_TAB: //{{
+ if(OFlag & OXTABS) {
+ if(TabWidth > 0) {
+ int SpaceIndex;
+
+ SpaceIndex = CurColumn % TabWidth; // Number of spaces after a Tab Stop
+ numW = TabWidth - SpaceIndex; // Number of spaces to the next Tab Stop
+ SpaceIndex = MAX_TAB_WIDTH - numW; // Index into the Spaces array
+ wcb = &Spaces[SpaceIndex]; // Point to the appropriate number of spaces
+ }
+ else {
+ wc[0] = L' ';
+ }
+ AdjColumn = numW;
+ }
+ else {
+ wc[0] = InCh; // Send the TAB itself - assumes that it does not move cursor.
+ }
+ break; //}}
+
+ case CHAR_CARRIAGE_RETURN: //{{
+ if((OFlag & OCRNL) == 0) {
+ if((OFlag & ONLRET) == 0) {
+ numW = 0; /* Discard the CR */
+ // Cursor doesn't move
+ }
+ else {
+ wc[0] = CHAR_CARRIAGE_RETURN;
+ CurColumn = 0;
+ }
+ break;
+ }
+ else {
+ InCh = CHAR_LINEFEED;
+ } //}}
+ // Fall through to the NL case
+ case CHAR_LINEFEED: //{{
+ if(OFlag & ONLCR) {
+ wc[0] = CHAR_CARRIAGE_RETURN;
+ wc[1] = CHAR_LINEFEED;
+ numW = 2;
+ CurColumn = 0;
+ }
+ AdjRow = 1;
+ break; //}}
+
+ case CHAR_BACKSPACE: //{{
+ if(CurColumn > 0) {
+ wc[0] = CHAR_BACKSPACE;
+ CurColumn = (UINT32)ModuloDecrement(CurColumn, (UINT32)This->MaxColumn);
+ }
+ else {
+ numW = 0; // Discard the backspace if in column 0
+ }
+ break; //}}
+
+ case CHAR_EOT: //{{
+ if(OFlag & ONOEOT) {
+ numW = 0; // Discard the EOT character
+ // Cursor doesn't move
+ break;
+ } //}}
+ // Fall through to default in order to potentially output "^D"
+ default: //{{
+ if((InCh >= 0) && (InCh < L' ')) {
+ // InCh contains a control character
+ if(OFlag & OCTRL) {
+ wc[1] = InCh + L'@';
+ wc[0] = L'^';
+ numW = 2;
+ AdjColumn = 2;
+ }
+ else {
+ numW = 0; // Discard. Not a UEFI supported control character.
+ }
+ }
+ else {
+ // Regular printing character
+ wc[0] = InCh;
+ AdjColumn = 1;
+ }
+ break; //}}
+ }
+ if(numW < MAX_EXPANSION) {
+ wc[numW] = 0; // Terminate the sub-buffer
+ }
+ if(AdjColumn != 0) {
+ // Adjust the cursor position
+ PrevColumn = CurColumn;
+ CurColumn = ModuloAdd(PrevColumn, AdjColumn, (UINT32)This->MaxColumn);
+ if(CurColumn < PrevColumn) {
+ // We must have wrapped, so we are on the next Row
+ ++CurRow;
+ if(CurRow >= This->MaxRow) {
+ // The screen has scrolled so need to adjust Initial location.
+ --This->InitialXY.Row; // Initial row has moved up one
+ CurRow = (UINT32)(This->MaxRow - 1); // We stay on the bottom row
+ }
+ }
+ }
+ This->CurrentXY.Column = CurColumn;
+ This->CurrentXY.Row = CurRow;
+ }
+ else {
+ // Output processing disabled -- RAW output mode
+ wc[0] = InCh;
+ wc[1] = 0;
+ }
+ // Put the character(s) into the output buffer
+ if(numW > 0) {
+ (void)OBuf->Write(OBuf, (const void *)wcb, (size_t)numW);
+ }
+ RetVal = numW;
+ }
+ else {
+ if(This == NULL) {
+ errno = EINVAL;
+ }
+ else {
+ errno = ENOSPC;
+ }
+ }
+ return RetVal;
+}
diff --git a/StdLib/LibC/Uefi/InteractiveIO/NonCanonRead.c b/StdLib/LibC/Uefi/InteractiveIO/NonCanonRead.c new file mode 100644 index 0000000000..15bf43e260 --- /dev/null +++ b/StdLib/LibC/Uefi/InteractiveIO/NonCanonRead.c @@ -0,0 +1,89 @@ +/** @file
+ NonCanonical Interactive Input Function.
+
+ The functions assume that isatty() is TRUE at the time they are called.
+ If _S_IWTTY is set, the device returns WIDE characters.
+
+ Copyright (c) 2012, 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 <LibConfig.h>
+
+#include <sys/syslimits.h>
+#include <sys/termios.h>
+#include <Device/IIO.h>
+#include <Containers/Fifo.h>
+
+/** Perform a noncanonical read of input.
+
+ @param[in] filp Pointer to a file descriptor structure.
+ @param[in] BufferSize Maximum number of bytes to return.
+
+ @retval -1 An error has occurred. Reason in errno.
+ @retval -1 No data returned. None was ready.
+ @retval >0 The number of elements returned
+**/
+ssize_t
+IIO_NonCanonRead (
+ struct __filedes *filp
+ )
+{
+ cIIO *This;
+ cFIFO *InBuf;
+ struct termios *Termio;
+ EFI_STATUS Status;
+ ssize_t NumRead;
+ cc_t tioMin;
+ cc_t tioTime;
+ UINT32 InputType;
+ wchar_t InChar; // Intermediate character buffer
+
+ NumRead = -1;
+ InChar = 0; // Initialize so compilers don't complain.
+ This = filp->devdata;
+ Termio = &This->Termio;
+ InBuf = This->InBuf;
+ tioMin = Termio->c_cc[VMIN];
+ tioTime = Termio->c_cc[VTIME];
+
+ if(tioMin >= MAX_INPUT) {
+ tioMin = MAX_INPUT;
+ }
+ /* There are four types of processing that may be done, based on
+ the values of tioMin and tioTime.
+ Min Time Type
+ --- ---- ----
+ 0 0 0 Return buffer contents or 1 new char
+ 0 >0 1 Return 0 or 1 character depending on timeout
+ >0 0 2 Buffer Min chars. Return BufferSize chars.
+ >0 >0 3 Return up to Min chars. Unless the inter-byte timer expires.
+
+ Currently, only type 0 is implemented.
+ */
+ InputType = 0;
+ if(tioMin != 0) InputType = 2;
+ if(tioTime != 0) ++InputType;
+ //switch(InputType) {
+ // case 0:
+ if(InBuf->IsEmpty(InBuf)) {
+ NumRead = filp->f_ops->fo_read(filp, &filp->f_offset, sizeof(wchar_t), &InChar);
+ if(NumRead > 0) {
+ Status = InBuf->Write(InBuf, &InChar, 1); // Buffer the character
+ }
+ }
+ // break;
+ // case 1:
+ // break;
+ // case 2:
+ // break;
+ // case 3:
+ // break;
+ //}
+ return NumRead;
+}
diff --git a/StdLib/LibC/Uefi/InteractiveIO/TerminalFunctions.c b/StdLib/LibC/Uefi/InteractiveIO/TerminalFunctions.c new file mode 100644 index 0000000000..807ab1fd4c --- /dev/null +++ b/StdLib/LibC/Uefi/InteractiveIO/TerminalFunctions.c @@ -0,0 +1,285 @@ +/** @file
+ "Terminal" Control functions for Interactive IO.
+
+ Copyright (c) 2012, 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 that accompanies this distribution.
+ The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.
+
+ 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 <Uefi.h>
+#include <Library/BaseMemoryLib.h>
+
+#include <LibConfig.h>
+
+#include <errno.h>
+#include <sys/termios.h>
+#include <Device/IIO.h>
+#include <MainData.h>
+
+/** Get input baud rate.
+
+ Extracts the input baud rate from the termios structure pointed to by the
+ pTermios argument.
+
+ @param[in] pTermios A pointer to the termios structure from which to extract
+ the input baud rate.
+
+ @return The value of the input speed is returned exactly as it is contained
+ in the termios structure, without interpretation.
+**/
+speed_t
+cfgetispeed (
+ const struct termios *pTermios
+ )
+{
+ return pTermios->c_ispeed;
+}
+
+/** Get output baud rate.
+
+ Extracts the output baud rate from the termios structure pointed to by the
+ pTermios argument.
+
+ @param[in] pTermios A pointer to the termios structure from which to extract
+ the output baud rate.
+
+ @return The value of the output speed is returned exactly as it is contained
+ in the termios structure, without interpretation.
+**/
+speed_t
+cfgetospeed (
+ const struct termios *pTermios
+ )
+{
+ return pTermios->c_ospeed;
+}
+
+/** Set input baud rate.
+
+ Replaces the input baud rate, in the termios structure pointed to by the
+ pTermios argument, with the value of NewSpeed.
+
+ @param[out] pTermios A pointer to the termios structure into which to set
+ the input baud rate.
+ @param[in] NewSpeed The new input baud rate.
+
+ @retval 0 The operation completed successfully.
+ @retval -1 An error occured and errno is set to indicate the error.
+ * EINVAL - The value of NewSpeed is outside the range of
+ possible speed values as specified in <sys/termios.h>.
+**/
+int
+cfsetispeed (
+ struct termios *pTermios,
+ speed_t NewSpeed
+ )
+{
+ int RetVal;
+
+ if(NewSpeed < B921600) {
+ pTermios->c_ispeed = NewSpeed;
+ RetVal = 0;
+ }
+ else {
+ RetVal = -1;
+ errno = EINVAL;
+ }
+ return RetVal;
+}
+
+/** Set output baud rate.
+
+ Replaces the output baud rate, in the termios structure pointed to by the
+ pTermios argument, with the value of NewSpeed.
+
+ @param[out] pTermios A pointer to the termios structure into which to set
+ the output baud rate.
+ @param[in] NewSpeed The new output baud rate.
+
+ @retval 0 The operation completed successfully.
+ @retval -1 An error occured and errno is set to indicate the error.
+ * EINVAL - The value of NewSpeed is outside the range of
+ possible speed values as specified in <sys/termios.h>.
+**/
+int
+cfsetospeed (
+ struct termios *pTermios,
+ speed_t NewSpeed
+ )
+{
+ int RetVal;
+
+ if(NewSpeed < B921600) {
+ pTermios->c_ospeed = NewSpeed;
+ RetVal = 0;
+ }
+ else {
+ RetVal = -1;
+ errno = EINVAL;
+ }
+ return RetVal;
+}
+
+/** Get the parameters associated with an interactive IO device.
+
+ Get the parameters associated with the device referred to by
+ fd and store them into the termios structure referenced by pTermios.
+
+ @param[in] fd The file descriptor for an open interactive IO device.
+ @param[out] pTermios A pointer to a termios structure into which to store
+ attributes of the interactive IO device.
+
+ @retval 0 The operation completed successfully.
+ @retval -1 An error occured and errno is set to indicate the error.
+ * EBADF - The fd argument is not a valid file descriptor.
+ * ENOTTY - The file associated with fd is not an interactive IO device.
+**/
+int
+tcgetattr (
+ int fd,
+ struct termios *pTermios
+ )
+{
+ cIIO *IIO;
+ int RetVal;
+ struct __filedes *filp;
+ struct termios *Termio;
+
+ RetVal = 0;
+ if(ValidateFD( fd, VALID_OPEN)) {
+ filp = &gMD->fdarray[fd];
+
+ if((filp->f_iflags & _S_ITTY) != 0) {
+ // fd is for a TTY or "Interactive IO" device
+ IIO = (cIIO *)filp->devdata;
+ Termio = &IIO->Termio;
+ (void)CopyMem((void *)pTermios, (const void *)Termio, sizeof(struct termios));
+ }
+ else {
+ errno = ENOTTY;
+ RetVal = -1;
+ }
+ }
+ else {
+ errno = EBADF;
+ RetVal = -1;
+ }
+ return RetVal;
+}
+
+/** Set the parameters associated with an interactive IO device.
+
+ Set the parameters associated with the device referred to by
+ fd to the values in the termios structure referenced by pTermios.
+
+ Behavior is modified by the value of the OptAct parameter:
+ * TCSANOW: The change shall occur immediately.
+ * TCSADRAIN: The change shall occur after all output written to fd is
+ transmitted. This action should be used when changing parameters which
+ affect output.
+ * TCSAFLUSH: The change shall occur after all output written to fd is
+ transmitted, and all input so far received but not read shall be
+ discarded before the change is made.
+
+ @param[in] fd The file descriptor for an open interactive IO device.
+ @param[in] OptAct Currently has no effect.
+ @param[in] pTermios A pointer to a termios structure into which to retrieve
+ attributes to set in the interactive IO device.
+
+ @retval 0 The operation completed successfully.
+ @retval -1 An error occured and errno is set to indicate the error.
+ * EBADF - The fd argument is not a valid file descriptor.
+ * ENOTTY - The file associated with fd is not an interactive IO device.
+**/
+int
+tcsetattr (
+ int fd,
+ int OptAct, // Currently ignored
+ const struct termios *pTermios
+ )
+{
+ cIIO *IIO;
+ int RetVal;
+ struct __filedes *filp;
+ struct termios *Termio;
+
+ RetVal = 0;
+ if(ValidateFD( fd, VALID_OPEN)) {
+ filp = &gMD->fdarray[fd];
+
+ if((filp->f_iflags & _S_ITTY) != 0) {
+ // fd is for a TTY or "Interactive IO" device
+ IIO = (cIIO *)filp->devdata;
+ Termio = &IIO->Termio;
+ (void)CopyMem((void *)Termio, (const void *)pTermios, sizeof(struct termios));
+ }
+ else {
+ errno = ENOTTY;
+ RetVal = -1;
+ }
+ }
+ else {
+ errno = EBADF;
+ RetVal = -1;
+ }
+ return RetVal;
+}
+
+/** Transmit pending output.
+
+ Function is not yet implemented for UEFI.
+
+ @param[in] fd Ignored
+
+ @retval -1 This function is not yet supported. errno is set to ENOTSUP.
+**/
+int
+tcdrain (int fd)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+/** Suspend or restart the transmission or reception of data.
+
+ This function will suspend or resume transmission or reception of data on
+ the file referred to by fd, depending on the value of Action.
+
+ Function is not yet implemented for UEFI.
+
+ @param[in] fd Ignored
+ @param[in] Action Ignored
+
+ @retval -1 This function is not yet supported. errno is set to ENOTSUP.
+**/
+int
+tcflow (
+ int fd,
+ int Action)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+/** Discard non-transmitted output data, non-read input data, or both.
+
+ Function is not yet implemented for UEFI.
+
+ @param[in] fd Ignored
+ @param[in] QueueSelector Ignored
+
+ @retval -1 This function is not yet supported. errno is set to ENOTSUP.
+**/
+int
+tcflush (
+ int fd,
+ int QueueSelector)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
diff --git a/StdLib/LibC/Uefi/SysCalls.c b/StdLib/LibC/Uefi/SysCalls.c index 5576938f8e..c3b210120b 100644 --- a/StdLib/LibC/Uefi/SysCalls.c +++ b/StdLib/LibC/Uefi/SysCalls.c @@ -36,6 +36,7 @@ #include <unistd.h>
#include <kfile.h>
#include <Device/Device.h>
+#include <Device/IIO.h>
#include <MainData.h>
#include <extern.h>
@@ -114,12 +115,14 @@ DeleteOnClose(int fd) return retval;
}
-/** The isatty() function tests whether fildes, an open file descriptor,
+/** The isatty() function tests whether fd, an open file descriptor,
is associated with a terminal device.
- @retval 1 fildes is associated with a terminal.
- @retval 0 fildes is not associated with a terminal. errno is set to
- EBADF if fildes is not a valid open FD.
+ @param[in] fd File Descriptor for the file to be examined.
+
+ @retval 1 fd is associated with a terminal.
+ @retval 0 fd is not associated with a terminal. errno is set to
+ EBADF if fd is not a valid open FD.
**/
int
isatty (int fd)
@@ -129,7 +132,7 @@ isatty (int fd) if(ValidateFD( fd, VALID_OPEN)) {
Fp = &gMD->fdarray[fd];
- retval = Fp->f_iflags & _S_ITTY;
+ retval = (Fp->f_iflags & _S_ITTY) ? 1 : 0;
}
else {
errno = EBADF;
@@ -169,13 +172,14 @@ IsDupFd( int fd) return Ret;
}
-/** Close a file and set its fd to the specified state.
+/** Worker function to Close a file and set its fd to the specified state.
@param[in] fd The file descriptor to close.
@param[in] NewState State to set the fd to after the file is closed.
@retval 0 The operation completed successfully.
@retval -1 The operation failed. Further information is in errno.
+ * EBADF fd is not a valid or open file descriptor.
**/
static int
_closeX (int fd, int NewState)
@@ -221,6 +225,8 @@ _closeX (int fd, int NewState) descriptors. All outstanding record locks owned by the process on the file
associated with the file descriptor are removed (that is, unlocked).
+ @param[in] fd Descriptor for the File to close.
+
@retval 0 Successful completion.
@retval -1 An error occurred and errno is set to identify the error.
**/
@@ -230,7 +236,14 @@ close (int fd) return _closeX(fd, 0);
}
-/**
+/** Delete the file specified by path.
+
+ @param[in] path The MBCS path of the file to delete.
+
+ @retval -1 Unable to open the file specified by path.
+ @retval -1 If (errno == EPERM), unlink is not permited for this file.
+ @retval -1 Low-level delete filed. Reason is in errno.
+ @retval 0 The file was successfully deleted.
**/
int
unlink (const char *path)
@@ -315,6 +328,10 @@ unlink (const char *path) descriptors greater than or equal to arg are available.
[EOVERFLOW] One of the values to be returned cannot be represented correctly.
+ @param[in] fildes Descriptor for the file to be controlled.
+ @param[in] cmd Command to be acted upon.
+ @param[in,out] ... Optional additional parameters as required by cmd.
+
@return Upon successful completion, the value returned shall depend on
cmd as follows:
- F_DUPFD - A new file descriptor.
@@ -407,6 +424,8 @@ fcntl (int fildes, int cmd, ...) shall be equivalent to:
- fid = fcntl(fildes, F_DUPFD, 0);
+ @param[in] fildes Descriptor for the file to be examined.
+
@return Upon successful completion a non-negative integer, namely the
file descriptor, shall be returned; otherwise, -1 shall be
returned and errno set to indicate the error.
@@ -417,7 +436,9 @@ dup (int fildes) return fcntl(fildes, F_DUPFD, 0);
}
-/** The dup2() function provides an alternative interface to the
+/** Make fildes2 refer to a duplicate of fildes.
+
+ The dup2() function provides an alternative interface to the
service provided by fcntl() using the F_DUPFD command. The call:
- fid = dup2(fildes, fildes2);
shall be equivalent to:
@@ -433,6 +454,9 @@ dup (int fildes) - The value returned shall be equal to the value of fildes2 upon
successful completion, or -1 upon failure.
+ @param[in] fildes File Descriptor to be duplicated.
+ @param[in] fildes2 File Descriptor to be made a duplicate of fildes.
+
@return Upon successful completion a non-negative integer, namely
fildes2, shall be returned; otherwise, -1 shall be
returned and errno set to EBADF indicate the error.
@@ -470,13 +494,13 @@ dup2 (int fildes, int fildes2) fildes must be an open file descriptor. lseek() repositions the file
pointer fildes as follows:
- If how is SEEK_SET, the offset is set to offset bytes.
+ - If how is SEEK_SET, the offset is set to offset bytes.
- If how is SEEK_CUR, the offset is set to its current location
- plus offset bytes.
+ - If how is SEEK_CUR, the offset is set to its current location
+ plus offset bytes.
- If how is SEEK_END, the offset is set to the size of the file
- plus offset bytes.
+ - If how is SEEK_END, the offset is set to the size of the file
+ plus offset bytes.
The lseek() function allows the file offset to be set beyond the end of
the existing end-of-file of the file. If data is later written at this
@@ -486,6 +510,10 @@ dup2 (int fildes, int fildes2) Some devices are incapable of seeking. The value of the pointer associ-
ated with such a device is undefined.
+ @param[in] fd Descriptor for the File to be affected.
+ @param[in] offset Value to adjust the file position by.
+ @param[in] how How the file position is to be adjusted.
+
@return Upon successful completion, lseek() returns the resulting offset
location as measured in bytes from the beginning of the file.
Otherwise, a value of -1 is returned and errno is set to
@@ -524,6 +552,9 @@ lseek (int fd, __off_t offset, int how) The directory is closed after it is created.
+ @param[in] path The path to a directory to create.
+ @param[in] perms Permissions as defined in <sys/stat.h>
+
@retval 0 The directory was created successfully.
@retval -1 An error occurred and error codes are stored in errno and EFIerrno.
**/
@@ -606,19 +637,19 @@ mkdir (const char *path, __mode_t perms) @param[in] oflags File status flags and file access modes of the
open file description.
@param[in] mode File access permission bits as defined in
- <sys/stat.h>.
+ <sys/stat.h>. Only used if a file is created
+ as a result of the open.
@return Upon successful completion, open() opens the file and returns
a non-negative integer representing the lowest numbered
unused file descriptor. Otherwise, open returns -1 and sets
errno to indicate the error. If a negative value is
returned, no files are created or modified.
-
- @retval EMFILE No file descriptors available -- Max number already open.
- @retval EINVAL Bad value specified for oflags or mode.
- @retval ENOMEM Failure allocating memory for internal buffers.
- @retval EEXIST File exists and open attempted with (O_EXCL | O_CREAT) set.
- @retval EIO UEFI failure. Check value in EFIerrno.
+ - EMFILE - No file descriptors available -- Max number already open.
+ - EINVAL - Bad value specified for oflags or mode.
+ - ENOMEM - Failure allocating memory for internal buffers.
+ - EEXIST - File exists and open attempted with (O_EXCL | O_CREAT) set.
+ - EIO - UEFI failure. Check value in EFIerrno.
**/
int
open(
@@ -631,18 +662,20 @@ open( wchar_t *MPath;
DeviceNode *Node;
struct __filedes *filp;
+ struct termios *Termio;
int Instance = 0;
RETURN_STATUS Status;
- UINT64 OpenMode;
+ UINT32 OpenMode;
int fd = -1;
int doresult;
Status = ParsePath(path, &NewPath, &Node, &Instance, &MPath);
if(Status == RETURN_SUCCESS) {
if((Node == NULL) ||
- (Node->InstanceList == NULL)) {
+ (Node->InstanceList == NULL))
+ {
errno = EPERM;
- }
+ }
else {
// Could add a test to see if the file name begins with a period.
// If it does, then add the HIDDEN flag to Attributes.
@@ -666,23 +699,31 @@ open( fd = -1; // Indicate an error
}
else {
- // Re-use OpenMode in order to build our final f_iflags value
+ // Build our final f_iflags value
OpenMode = ( mode & S_ACC_READ ) ? S_ACC_READ : 0;
OpenMode |= ( mode & S_ACC_WRITE ) ? S_ACC_WRITE : 0;
- filp->f_iflags |= (UINT32)OpenMode;
+ filp->f_iflags |= OpenMode;
+
+ if((oflags & O_TTY_INIT) && (filp->f_iflags & _S_ITTY) && (filp->devdata != NULL)) {
+ // Initialize the device's termios flags to a "sane" value
+ Termio = &((cIIO *)filp->devdata)->Termio;
+ Termio->c_iflag = ICRNL;
+ Termio->c_oflag = OPOST | ONLCR | OXTABS | ONOEOT | ONOCR | ONLRET | OCTRL;
+ Termio->c_lflag = ECHO | ECHOE | ECHONL | ICANON;
+ Termio->c_cc[VERASE] = 0x08; // ^H Backspace
+ Termio->c_cc[VKILL] = 0x15; // ^U
+ Termio->c_cc[VINTR] = 0x03; // ^C Interrupt character
+ }
++filp->RefCount;
FILE_SET_MATURE(filp);
}
}
}
- if(NewPath != NULL) {
free(NewPath);
}
- }
- if(MPath != NULL) {
free(MPath); // We don't need this any more.
- }
+
// return the fd of our now open file
return fd;
}
@@ -699,11 +740,11 @@ open( <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html">POSIX</a>
documentation is available online.
- @param [in] pfd Address of an array of pollfd structures.
+ @param[in] pfd Address of an array of pollfd structures.
- @param [in] nfds Number of elements in the array of pollfd structures.
+ @param[in] nfds Number of elements in the array of pollfd structures.
- @param [in] timeout Length of time in milliseconds to wait for the event
+ @param[in] timeout Length of time in milliseconds to wait for the event
@return The number of file descriptors with detected events. Zero
indicates that the call timed out and -1 indicates an error.
@@ -841,38 +882,44 @@ poll ( /** The rename() function changes the name of a file.
- The old argument points to the pathname of the file to be renamed. The new
+ The From argument points to the pathname of the file to be renamed. The To
argument points to the new pathname of the file.
- If the old argument points to the pathname of a file that is not a
- directory, the new argument shall not point to the pathname of a
- directory. If the file named by the new argument exists, it shall be
- removed and old renamed to new. Write access permission is required for
- both the directory containing old and the directory containing new.
+ If the From argument points to the pathname of a file that is not a
+ directory, the To argument shall not point to the pathname of a
+ directory. If the file named by the To argument exists, it shall be
+ removed and From renamed to To. Write access permission is required for
+ both the directory containing old and the directory containing To.
- If the old argument points to the pathname of a directory, the new
+ If the From argument points to the pathname of a directory, the To
argument shall not point to the pathname of a file that is not a
- directory. If the directory named by the new argument exists, it shall be
- removed and old renamed to new.
+ directory. If the directory named by the To argument exists, it shall be
+ removed and From renamed to To.
- The new pathname shall not contain a path prefix that names old. Write
- access permission is required for the directory containing old and the
- directory containing new. If the old argument points to the pathname of a
+ The To pathname shall not contain a path prefix that names From. Write
+ access permission is required for the directory containing From and the
+ directory containing To. If the From argument points to the pathname of a
directory, write access permission may be required for the directory named
- by old, and, if it exists, the directory named by new.
+ by From, and, if it exists, the directory named by To.
If the rename() function fails for any reason other than [EIO], any file
- named by new shall be unaffected.
+ named by To shall be unaffected.
- @return Upon successful completion, rename() shall return 0; otherwise,
- -1 shall be returned, errno shall be set to indicate the error,
- and neither the file named by old nor the file named by new
- shall be changed or created.
+ @param[in] From Path to the file to be renamed.
+ @param[in] To The new name of From.
+
+ @retval 0 Successful completion.
+ @retval -1 An error has occured and errno has been set to further specify the error.
+ Neither the file named by From nor the file named by To are
+ changed or created.
+ - ENXIO: Path specified is not supported by any loaded driver.
+ - ENOMEM: Insufficient memory to calloc a MapName buffer.
+ - EINVAL: The path parameter is not valid.
**/
int
rename(
- const char *from,
- const char *to
+ const char *From,
+ const char *To
)
{
wchar_t *FromPath;
@@ -882,7 +929,7 @@ rename( RETURN_STATUS Status;
int retval = -1;
- Status = ParsePath(from, &FromPath, &FromNode, &Instance, NULL);
+ Status = ParsePath(From, &FromPath, &FromNode, &Instance, NULL);
if(Status == RETURN_SUCCESS) {
GenI = FromNode->InstanceList;
if(GenI == NULL) {
@@ -891,14 +938,19 @@ rename( }
else {
//GenI += (Instance * FromNode->InstanceSize);
- retval = ((GenericInstance *)GenI)->Abstraction.fo_rename( from, to);
+ retval = ((GenericInstance *)GenI)->Abstraction.fo_rename( From, To);
}
free(FromPath);
}
return retval;
}
-/**
+/** Delete a specified directory.
+
+ @param[in] path Path to the directory to delete.
+
+ @retval -1 The directory couldn't be opened (doesn't exist).
+ @retval -1 The directory wasn't empty or an IO error occured.
**/
int
rmdir(
@@ -921,10 +973,10 @@ rmdir( }
/** The fstat() function obtains information about an open file associated
- with the file descriptor fildes, and shall write it to the area pointed to
- by buf.
+ with the file descriptor fd, and writes it to the area pointed to
+ by statbuf.
- The buf argument is a pointer to a stat structure, as defined
+ The statbuf argument is a pointer to a stat structure, as defined
in <sys/stat.h>, into which information is placed concerning the file.
The structure members st_mode, st_ino, st_dev, st_uid, st_gid, st_atime,
@@ -939,7 +991,7 @@ rmdir( The stat structure members which don't have direct analogs to EFI file
information are filled in as follows:
- - st_mode Populated with information from fildes
+ - st_mode Populated with information from fd
- st_ino Set to zero. (inode)
- st_dev Set to zero.
- st_uid Set to zero.
@@ -974,6 +1026,9 @@ fstat (int fd, struct stat *statbuf) Opens the file pointed to by path, calls _EFI_FileInfo with the file's handle,
then closes the file.
+ @param[in] path Path to the file to obtain information about.
+ @param[out] statbuf Buffer in which the file status is put.
+
@retval 0 Successful Completion.
@retval -1 An error has occurred and errno has been set to
identify the error.
@@ -994,7 +1049,15 @@ stat (const char *path, struct stat *statbuf) return retval;
}
-/** Same as stat since EFI doesn't have symbolic links. **/
+/** Same as stat since EFI doesn't have symbolic links.
+
+ @param[in] path Path to the file to obtain information about.
+ @param[out] statbuf Buffer in which the file status is put.
+
+ @retval 0 Successful Completion.
+ @retval -1 An error has occurred and errno has been set to
+ identify the error.
+**/
int
lstat (const char *path, struct stat *statbuf)
{
@@ -1002,6 +1065,13 @@ lstat (const char *path, struct stat *statbuf) }
/** Control a device.
+
+ @param[in] fd Descriptor for the file to be acted upon.
+ @param[in] request Specifies the operation to perform.
+ @param[in,out] ... Zero or more parameters as required for request.
+
+ @retval >=0 The operation completed successfully.
+ @retval -1 An error occured. More information is in errno.
**/
int
ioctl(
@@ -1098,6 +1168,10 @@ ioctl( directory entries, the read returns a zero-length buffer.
EFI_FILE_INFO is the structure returned as the directory entry.
+ @param[in] fildes Descriptor of the file to be read.
+ @param[out] buf Pointer to location in which to store the read data.
+ @param[in] nbyte Maximum number of bytes to be read.
+
@return Upon successful completion, read() returns a non-negative integer
indicating the number of bytes actually read. Otherwise, the
functions return a negative value and sets errno to indicate the
@@ -1109,62 +1183,91 @@ ssize_t read (int fildes, void *buf, size_t nbyte)
{
struct __filedes *filp;
+ cIIO *IIO;
ssize_t BufSize;
BufSize = (ssize_t)nbyte;
- if(ValidateFD( fildes, VALID_OPEN)) {
- filp = &gMD->fdarray[fildes];
+ if(BufSize > 0) {
+ if(ValidateFD( fildes, VALID_OPEN)) {
+ filp = &gMD->fdarray[fildes];
- BufSize = filp->f_ops->fo_read(filp, &filp->f_offset, nbyte, buf);
- }
- else {
- errno = EBADF;
- BufSize = -EBADF;
+ IIO = filp->devdata;
+ if(isatty(fildes) && (IIO != NULL)) {
+ BufSize = IIO->Read(filp, nbyte, buf);
+ }
+ else {
+ BufSize = filp->f_ops->fo_read(filp, &filp->f_offset, nbyte, buf);
+ }
+ }
+ else {
+ errno = EBADF;
+ BufSize = -1;
+ }
}
return BufSize;
}
/** Write data to a file.
- This function writes the specified number of bytes to the file at the current
- file position. The current file position is advanced the actual number of bytes
- written, which is returned in BufferSize. Partial writes only occur when there
- has been a data error during the write attempt (such as "volume space full").
- The file is automatically grown to hold the data if required. Direct writes to
- opened directories are not supported.
-
- If fildes refers to a terminal device, isatty() returns TRUE, a partial write
- will occur if a NULL or EOF character is encountered before n characters have
- been written. Characters inserted due to line-end translations will not be
- counted. Unconvertable characters are translated into the UEFI character
- BLOCKELEMENT_LIGHT_SHADE.
-
- Since the UEFI console device works on wide characters, the buffer is assumed
- to contain a single-byte character stream which is then translated to wide
- characters using the btowc() functions. The resulting wide character stream
- is what is actually sent to the UEFI console.
-
- QUESTION: Should writes to stdout or stderr always succeed?
+ This function writes the specified number of bytes to the file at the current
+ file position. The current file position is advanced the actual number of bytes
+ written, which is returned in BufferSize. Partial writes only occur when there
+ has been a data error during the write attempt (such as "volume space full").
+ The file is automatically grown to hold the data if required. Direct writes to
+ opened directories are not supported.
+
+ If fildes refers to a terminal device, isatty() returns TRUE, a partial write
+ will occur if a NULL or EOF character is encountered before n characters have
+ been written. Characters inserted due to line-end translations will not be
+ counted. Unconvertable characters are translated into the UEFI character
+ BLOCKELEMENT_LIGHT_SHADE.
+
+ Since the UEFI console device works on wide characters, the buffer is assumed
+ to contain a single-byte character stream which is then translated to wide
+ characters using the mbtowc() functions. The resulting wide character stream
+ is what is actually sent to the UEFI console.
+
+ @param[in] fd Descriptor of file to be written to.
+ @param[in] buf Pointer to data to write to the file.
+ @param[in] nbyte Number of bytes to be written to the file.
+
+ @retval >=0 Number of bytes actually written to the file.
+ @retval <0 An error occurred. More data is provided by errno.
**/
ssize_t
write (int fd, const void *buf, size_t nbyte)
{
struct __filedes *filp;
+ cIIO *IIO;
ssize_t BufSize;
-// EFI_FILE_HANDLE FileHandle;
-// RETURN_STATUS Status = RETURN_SUCCESS;
BufSize = (ssize_t)nbyte;
if(ValidateFD( fd, VALID_OPEN)) {
filp = &gMD->fdarray[fd];
-
- BufSize = filp->f_ops->fo_write(filp, &filp->f_offset, nbyte, buf);
+ if ((filp->Oflags & O_ACCMODE) != 0) {
+ // File is open for writing
+ IIO = filp->devdata;
+ if(isatty(fd) && (IIO != NULL)) {
+ // Output to an Interactive I/O device
+ BufSize = IIO->Write(filp, buf, nbyte);
+ }
+ else {
+ // Output to a file, socket, pipe, etc.
+ BufSize = filp->f_ops->fo_write(filp, &filp->f_offset, nbyte, buf);
+ }
}
else {
+ // File is NOT open for writing
+ errno = EINVAL;
+ BufSize = -1;
+ }
+ }
+ else {
+ // fd is not for a valid open file
errno = EBADF;
- BufSize = -EBADF;
- }
+ BufSize = -1;
+ }
return BufSize;
}
@@ -1260,11 +1363,29 @@ chdir (const char *path) return -1;
}
+/** Get the foreground process group ID associated with a terminal.
+
+ Just returns the Image Handle for the requestor since UEFI does not have
+ a concept of processes or groups.
+
+ @param[in] x Ignored.
+
+ @return Returns the Image Handle of the application or driver which
+ called this function.
+**/
pid_t tcgetpgrp (int x)
{
return ((pid_t)(UINTN)(gImageHandle));
}
+/** Get the process group ID of the calling process.
+
+ Just returns the Image Handle for the requestor since UEFI does not have
+ a concept of processes or groups.
+
+ @return Returns the Image Handle of the application or driver which
+ called this function.
+**/
pid_t getpgrp(void)
{
return ((pid_t)(UINTN)(gImageHandle));
@@ -1300,10 +1421,11 @@ va_Utimes( /** Set file access and modification times.
- @param[in] path
- @param[in] times
+ @param[in] path Path to the file to be modified.
+ @param[in] times Pointer to an array of two timeval structures
- @return
+ @retval 0 File times successfully set.
+ @retval -1 An error occured. Error type in errno.
**/
int
utimes(
@@ -1313,4 +1435,3 @@ utimes( {
return va_Utimes(path, times);
}
-
|