StdLib: Add multi-byte character support. The normal "narrow" character set is now UTF-8 instead of ASCII.
Add library classes which are required by StdLib, but not commonly defined in Platform DSC files, to StdLib.inc. Modify MB_LEN_MAX to be 4, the maximum length of UTF-8 characters. Adjust size of internal buffers to be multiples of MB_LEN_MAX instead of assuming 1-byte characters. Make the XYoffset object public and move its declaration into EfiSysCall.h. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: daryl.mcdaniel@intel.com Reviewed-by: erik.c.bjorge@intel.com Reviewed-by: lee.g.rosenbaum@intel.com Reviewed-by: leroy.p.leahy@intel.com git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13457 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
|
||||
Manipulates abstractions for stdin, stdout, stderr.
|
||||
|
||||
Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
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.
|
||||
The full text of the license may be found at
|
||||
@@ -52,27 +52,45 @@ static wchar_t *ConReadBuf;
|
||||
static BOOLEAN TtyCooked;
|
||||
static BOOLEAN TtyEcho;
|
||||
|
||||
ssize_t
|
||||
WideTtyCvt( CHAR16 *dest, const char *buf, size_t n)
|
||||
{
|
||||
UINTN i;
|
||||
wint_t wc;
|
||||
/** Convert string from MBCS to WCS and translate \n to \r\n.
|
||||
|
||||
for(i = 0; i < n; ++i) {
|
||||
wc = btowc(*buf++);
|
||||
if( wc == 0) {
|
||||
It is the caller's responsibility to ensure that dest is
|
||||
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
|
||||
|
||||
@return The number of BYTES consumed from buf.
|
||||
**/
|
||||
ssize_t
|
||||
WideTtyCvt( CHAR16 *dest, const char *buf, ssize_t n, mbstate_t *Cs)
|
||||
{
|
||||
ssize_t i = 0;
|
||||
int numB = 0;
|
||||
wchar_t wc[2];
|
||||
|
||||
while(n > 0) {
|
||||
numB = (int)mbrtowc(wc, buf, MIN(MB_LEN_MAX,n), Cs);
|
||||
if( numB == 0) {
|
||||
break;
|
||||
};
|
||||
if(wc < 0) {
|
||||
wc = BLOCKELEMENT_LIGHT_SHADE;
|
||||
if(numB < 0) {
|
||||
wc[0] = BLOCKELEMENT_LIGHT_SHADE;
|
||||
}
|
||||
if(wc == L'\n') {
|
||||
if(wc[0] == L'\n') {
|
||||
*dest++ = L'\r';
|
||||
++i;
|
||||
}
|
||||
*dest++ = (CHAR16)wc;
|
||||
*dest++ = (CHAR16)wc[0];
|
||||
i += numB;
|
||||
n -= numB;
|
||||
buf += numB;
|
||||
}
|
||||
*dest = 0;
|
||||
return (ssize_t)i;
|
||||
return i;
|
||||
}
|
||||
|
||||
static
|
||||
@@ -105,7 +123,7 @@ da_ConSeek(
|
||||
{
|
||||
ConInstance *Stream;
|
||||
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Proto;
|
||||
XYoffset CursorPos;
|
||||
XY_OFFSET CursorPos;
|
||||
|
||||
Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
|
||||
// Quick check to see if Stream looks reasonable
|
||||
@@ -140,7 +158,7 @@ da_ConSeek(
|
||||
the string couldn't be displayed.
|
||||
@param[in] Buffer The WCS string to be displayed
|
||||
|
||||
@return The number of characters written.
|
||||
@return The number of BYTES written. Because of MBCS, this may be more than number of characters.
|
||||
*/
|
||||
static
|
||||
ssize_t
|
||||
@@ -155,8 +173,7 @@ da_ConWrite(
|
||||
EFI_STATUS Status;
|
||||
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Proto;
|
||||
ConInstance *Stream;
|
||||
ssize_t NumChar;
|
||||
//XYoffset CursorPos;
|
||||
ssize_t NumBytes;
|
||||
|
||||
Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
|
||||
// Quick check to see if Stream looks reasonable
|
||||
@@ -173,34 +190,21 @@ da_ConWrite(
|
||||
Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)Stream->Dev;
|
||||
|
||||
// Convert string from MBCS to WCS and translate \n to \r\n.
|
||||
NumChar = WideTtyCvt(gMD->UString, (const char *)Buffer, BufferSize);
|
||||
//if(NumChar > 0) {
|
||||
// BufferSize = (size_t)(NumChar * sizeof(CHAR16));
|
||||
//}
|
||||
BufferSize = NumChar;
|
||||
NumBytes = WideTtyCvt(gMD->UString, (const char *)Buffer, (ssize_t)BufferSize, &Stream->CharState);
|
||||
BufferSize = NumBytes;
|
||||
|
||||
//if( Position != NULL) {
|
||||
// CursorPos.Offset = (UINT64)*Position;
|
||||
|
||||
// Status = Proto->SetCursorPosition(Proto,
|
||||
// (INTN)CursorPos.XYpos.Column,
|
||||
// (INTN)CursorPos.XYpos.Row);
|
||||
// if(RETURN_ERROR(Status)) {
|
||||
// return -1;
|
||||
// }
|
||||
//}
|
||||
|
||||
// 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
|
||||
BufferSize = 0; // We don't really know how many characters made it out
|
||||
}
|
||||
else {
|
||||
//BufferSize = NumChar;
|
||||
Stream->NumWritten += NumChar;
|
||||
//BufferSize = NumBytes;
|
||||
Stream->NumWritten += NumBytes;
|
||||
}
|
||||
EFIerrno = Status;
|
||||
EFIerrno = Status; // Make error reason available to caller
|
||||
return BufferSize;
|
||||
}
|
||||
|
||||
@@ -342,7 +346,8 @@ da_ConStat(
|
||||
return -1;
|
||||
}
|
||||
// All of our parameters are correct, so fill in the information.
|
||||
Buffer->st_blksize = 1;
|
||||
Buffer->st_blksize = 0; // Character device, not a block device
|
||||
Buffer->st_mode = filp->f_iflags;
|
||||
|
||||
// ConGetPosition
|
||||
if(Stream->InstanceNum == STDIN_FILENO) {
|
||||
@@ -504,6 +509,7 @@ __Cons_construct(
|
||||
|
||||
Stream->Cookie = CON_COOKIE;
|
||||
Stream->InstanceNum = i;
|
||||
Stream->CharState.A = 0; // Start in the initial state
|
||||
|
||||
switch(i) {
|
||||
case STDIN_FILENO:
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
EFI versions of NetBSD system calls.
|
||||
|
||||
Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
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.
|
||||
The full text of the license may be found at
|
||||
@@ -557,16 +557,38 @@ mkdir (const char *path, __mode_t perms)
|
||||
}
|
||||
|
||||
/** Open a file.
|
||||
The open() function establishes the connection between a file and a file
|
||||
descriptor. It creates an open file description that refers to a file
|
||||
and a file descriptor that refers to that open file description. The file
|
||||
descriptor is used by other I/O functions to refer to that file.
|
||||
|
||||
The open() function returns a file descriptor for the named file that is
|
||||
the lowest file descriptor not currently open for that process. The open
|
||||
file description is new, and therefore the file descriptor shall not
|
||||
share it with any other process in the system.
|
||||
|
||||
The file offset used to mark the current position within the file is set
|
||||
to the beginning of the file.
|
||||
|
||||
The EFI ShellOpenFileByName() function is used to perform the low-level
|
||||
file open operation. The primary task of open() is to translate from the
|
||||
flags used in the <stdio.h> environment to those used by the EFI function.
|
||||
|
||||
The file status flags and file access modes of the open file description
|
||||
are set according to the value of oflags.
|
||||
|
||||
Values for oflags are constructed by a bitwise-inclusive OR of flags from
|
||||
the following list, defined in <fcntl.h>. Applications shall specify
|
||||
exactly one of { O_RDONLY, O_RDWR, O_WRONLY } in the value of oflags.
|
||||
Any combination of { O_NONBLOCK, O_APPEND, O_CREAT, O_TRUNC, O_EXCL } may
|
||||
also be specified in oflags.
|
||||
|
||||
The only valid flag combinations for ShellOpenFileByName() are:
|
||||
- Read
|
||||
- Read/Write
|
||||
- Create/Read/Write
|
||||
|
||||
Values for mode specify the access permissions for newly created files.
|
||||
The mode value is saved in the FD to indicate permissions for further operations.
|
||||
|
||||
O_RDONLY -- flags = EFI_FILE_MODE_READ -- this is always done
|
||||
@@ -578,6 +600,25 @@ mkdir (const char *path, __mode_t perms)
|
||||
O_CREAT -- flags |= EFI_FILE_MODE_CREATE
|
||||
O_TRUNC -- delete first then create new
|
||||
O_EXCL -- if O_CREAT is also set, open will fail if the file already exists.
|
||||
|
||||
@param[in] Path The path argument points to a pathname naming the
|
||||
object to be opened.
|
||||
@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>.
|
||||
|
||||
@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.
|
||||
**/
|
||||
int
|
||||
open(
|
||||
|
Reference in New Issue
Block a user