Add Socket Libraries.

Add Posix functions for porting compatibility.
Fix compliance issues with ISO/IEC 9899:199409
New Functions:
  setenv(), fparseln(), GetFileNameFromPath(), rename(),
  realpath(), setprogname(), getprogname(), strlcat(), strlcpy(),
  strsep(), setitimer(), getitimer(), timegm(), getopt(), basename(),
  mkstemp(), ffs(), vsnprintf(), snprintf(), getpass(), usleep(), select(),
  writev(), strcasecmp(), getcwd(), chdir(), tcgetpgrp(), getpgrp(), gettimeofday(),
  bcopy(), 


git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12061 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
darylm503
2011-07-30 00:30:44 +00:00
parent f766dd76fd
commit d7ce700605
199 changed files with 36115 additions and 686 deletions

View File

@@ -45,6 +45,12 @@ static const int stdioFlags[NUM_SPECIAL] = {
static DeviceNode *ConNode[NUM_SPECIAL];
static ConInstance *ConInstanceList;
static wchar_t *ConReadBuf;
/* Flags settable by Ioctl */
static BOOLEAN TtyCooked;
static BOOLEAN TtyEcho;
ssize_t
WideTtyCvt( CHAR16 *dest, const char *buf, size_t n)
{
@@ -127,74 +133,6 @@ da_ConSeek(
}
}
static
ssize_t
EFIAPI
da_ConRead(
IN OUT struct __filedes *filp,
IN OUT off_t *offset, // Console ignores this
IN size_t BufferSize,
OUT VOID *Buffer
)
{
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *Proto;
ConInstance *Stream;
CHAR16 *OutPtr;
EFI_INPUT_KEY Key;
UINTN NumChar;
UINTN Edex;
EFI_STATUS Status = RETURN_SUCCESS;
UINTN i;
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;
}
// 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.
Proto = (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)Stream->Dev;
OutPtr = Buffer;
NumChar = (BufferSize - 1) / sizeof(CHAR16);
i = 0;
do {
if((Stream->UnGetKey.UnicodeChar == CHAR_NULL) && (Stream->UnGetKey.ScanCode == SCAN_NULL)) {
Status = gBS->WaitForEvent( 1, &Proto->WaitForKey, &Edex);
if(Status != RETURN_SUCCESS) {
break;
}
Status = Proto->ReadKeyStroke(Proto, &Key);
if(Status != RETURN_SUCCESS) {
break;
}
}
else {
Key.ScanCode = Stream->UnGetKey.ScanCode;
Key.UnicodeChar = Stream->UnGetKey.UnicodeChar;
Stream->UnGetKey.ScanCode = SCAN_NULL;
Stream->UnGetKey.UnicodeChar = CHAR_NULL;
}
if(Key.ScanCode == SCAN_NULL) {
*OutPtr++ = Key.UnicodeChar;
++i;
}
if(iswcntrl(Key.UnicodeChar)) { // If a control character, or a scan code
break;
}
} while(i < NumChar);
*OutPtr = L'\0'; // Terminate the input buffer
EFIerrno = Status;
return (ssize_t)(i * sizeof(CHAR16)); // Will be 0 if we didn't get a key
}
/* Write a NULL terminated WCS to the EFI console.
@param[in,out] BufferSize Number of bytes in Buffer. Set to zero if
@@ -265,6 +203,109 @@ da_ConWrite(
return BufferSize;
}
/** Read characters from the console input device.
@param[in,out] filp Pointer to file descriptor for this file.
@param[in,out] 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.
**/
static
ssize_t
EFIAPI
da_ConRead(
IN OUT struct __filedes *filp,
IN OUT off_t *offset, // Console ignores this
IN size_t BufferSize,
OUT VOID *Buffer
)
{
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *Proto;
ConInstance *Stream;
wchar_t *OutPtr;
EFI_INPUT_KEY Key;
UINTN NumChar;
UINTN Edex;
EFI_STATUS Status = RETURN_SUCCESS;
UINTN i;
char EchoBuff[MB_CUR_MAX + 1];
int NumEcho;
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;
}
// 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.
Proto = (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)Stream->Dev;
OutPtr = ConReadBuf;
NumChar = (BufferSize > MAX_INPUT)? MAX_INPUT : BufferSize;
i = 0;
do {
if((Stream->UnGetKey.UnicodeChar == CHAR_NULL) && (Stream->UnGetKey.ScanCode == SCAN_NULL)) {
Status = gBS->WaitForEvent( 1, &Proto->WaitForKey, &Edex);
if(Status != RETURN_SUCCESS) {
break;
}
Status = Proto->ReadKeyStroke(Proto, &Key);
if(Status != RETURN_SUCCESS) {
break;
}
}
else {
Key.ScanCode = Stream->UnGetKey.ScanCode;
Key.UnicodeChar = Stream->UnGetKey.UnicodeChar;
Stream->UnGetKey.ScanCode = SCAN_NULL;
Stream->UnGetKey.UnicodeChar = CHAR_NULL;
}
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);
}
++i;
EchoBuff[NumEcho] = 0; /* Terminate the Echo buffer */
if(TtyEcho) {
/* Echo the character just input */
da_ConWrite(&gMD->fdarray[STDOUT_FILENO], NULL, 2, EchoBuff);
}
}
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
}
/** Console-specific helper function for the fstat() function.
st_size Set to number of characters read for stdin and number written for stdout and stderr.
@@ -347,27 +388,28 @@ da_ConIoctl(
int
EFIAPI
da_ConOpen(
DeviceNode *DevNode,
struct __filedes *filp,
void *DevInstance,
int DevInstance, // Not used for console devices
wchar_t *Path, // Not used for console devices
wchar_t *Flags // Not used for console devices
wchar_t *MPath // Not used for console devices
)
{
ConInstance *Stream;
if((filp == NULL) ||
(DevInstance == NULL))
(DevNode == NULL))
{
EFIerrno = RETURN_INVALID_PARAMETER;
return -1;
}
Stream = (ConInstance *)DevInstance;
Stream = (ConInstance *)DevNode->InstanceList;
// 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
}
gMD->StdIo[Stream->InstanceNum] = (ConInstance *)DevInstance;
gMD->StdIo[Stream->InstanceNum] = Stream;
filp->f_iflags |= (S_IFREG | _S_IFCHR | _S_ICONSOLE);
filp->f_offset = 0;
filp->f_ops = &Stream->Abstraction;
@@ -448,7 +490,8 @@ __Cons_construct(
int i;
ConInstanceList = (ConInstance *)AllocateZeroPool(NUM_SPECIAL * sizeof(ConInstance));
if(ConInstanceList == NULL) {
ConReadBuf = (wchar_t *)AllocateZeroPool((MAX_INPUT + 1) * sizeof(wchar_t));
if((ConInstanceList == NULL) || (ConReadBuf == NULL)) {
return RETURN_OUT_OF_RESOURCES;
}
@@ -507,6 +550,10 @@ __Cons_construct(
}
Stream->Parent = ConNode[i];
}
/* Initialize Ioctl flags until Ioctl is really implemented. */
TtyCooked = TRUE;
TtyEcho = TRUE;
return Status;
}
@@ -527,6 +574,9 @@ __Cons_deconstruct(
if(ConInstanceList != NULL) {
FreePool(ConInstanceList);
}
if(ConReadBuf != NULL) {
FreePool(ConReadBuf);
}
return RETURN_SUCCESS;
}

View File

@@ -29,6 +29,7 @@
#include <wctype.h>
#include <wchar.h>
#include <sys/fcntl.h>
#include <sys/syslimits.h>
#include <kfile.h>
#include <Device/Device.h>
#include <MainData.h>
@@ -321,7 +322,7 @@ da_ShellIoctl(
void *argp ///< May be a pointer or a value
)
{
return 0;
return -EPERM;
}
/** Open an abstract Shell File.
@@ -329,10 +330,11 @@ da_ShellIoctl(
int
EFIAPI
da_ShellOpen(
DeviceNode *DevNode,
struct __filedes *filp,
void *DevInstance,
int DevInstance, /* Not used by Shell */
wchar_t *Path,
wchar_t *Flags
wchar_t *MPath
)
{
UINT64 OpenMode;
@@ -340,8 +342,10 @@ da_ShellOpen(
SHELL_FILE_HANDLE FileHandle;
GenericInstance *Gip;
char *NPath;
wchar_t *WPath;
RETURN_STATUS Status;
int oflags;
int retval;
EFIerrno = RETURN_SUCCESS;
@@ -356,6 +360,23 @@ da_ShellOpen(
return -1;
}
/* Re-create the full mapped path for the shell. */
if(MPath != NULL) {
WPath = AllocateZeroPool(PATH_MAX * sizeof(wchar_t) + 1);
if(WPath == NULL) {
errno = ENOMEM;
EFIerrno = RETURN_OUT_OF_RESOURCES;
return -1;
}
wcsncpy(WPath, MPath, NAME_MAX); /* Get the Map Name */
wcsncat(WPath, Path, (PATH_MAX - NAME_MAX)); /* Append the path */
}
else {
WPath = Path;
}
retval = -1; /* Initially assume failure. */
/* Do we care if the file already exists?
If O_TRUNC, then delete the file. It will be created anew subsequently.
If O_EXCL, then error if the file exists and O_CREAT is set.
@@ -363,23 +384,24 @@ da_ShellOpen(
!!!!!!!!! Change this to use ShellSetFileInfo() to actually truncate the file
!!!!!!!!! instead of deleting and re-creating it.
*/
do { /* Do fake exception handling */
if((oflags & O_TRUNC) || ((oflags & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT))) {
Status = ShellIsFile( Path );
Status = ShellIsFile( WPath );
if(Status == RETURN_SUCCESS) {
// The file exists
if(oflags & O_TRUNC) {
NPath = AllocateZeroPool(1024);
NPath = AllocateZeroPool(PATH_MAX);
if(NPath == NULL) {
errno = ENOMEM;
EFIerrno = RETURN_OUT_OF_RESOURCES;
return -1;
break;
}
wcstombs(NPath, Path, 1024);
wcstombs(NPath, WPath, PATH_MAX);
// We do a truncate by deleting the existing file and creating a new one.
if(unlink(NPath) != 0) {
filp->f_iflags = 0; // Release our reservation on this FD
FreePool(NPath);
return -1; // errno and EFIerrno are already set.
break;
}
FreePool(NPath);
}
@@ -387,32 +409,40 @@ da_ShellOpen(
errno = EEXIST;
EFIerrno = RETURN_ACCESS_DENIED;
filp->f_iflags = 0; // Release our reservation on this FD
return -1;
break;
}
}
}
// Call the EFI Shell's Open function
Status = ShellOpenFileByName( Path, &FileHandle, OpenMode, Attributes);
Status = ShellOpenFileByName( WPath, &FileHandle, OpenMode, Attributes);
if(RETURN_ERROR(Status)) {
filp->f_iflags = 0; // Release our reservation on this FD
// Set errno based upon Status
errno = EFI2errno(Status);
EFIerrno = Status;
return -1;
break;
}
retval = 0;
// Successfully got a regular File
filp->f_iflags |= S_IFREG;
// Update the info in the fd
filp->devdata = (void *)FileHandle;
Gip = (GenericInstance *)DevInstance;
Gip = (GenericInstance *)DevNode->InstanceList;
filp->f_offset = 0;
filp->f_ops = &Gip->Abstraction;
// filp->devdata = FileHandle;
// filp->devdata = FileHandle;
} while(FALSE);
return 0;
/* If we get this far, WPath is not NULL.
If MPath is not NULL, then WPath was allocated so we need to free it.
*/
if(MPath != NULL) {
FreePool(WPath);
}
return retval;
}
#include <sys/poll.h>
@@ -468,9 +498,10 @@ da_ShellRename(
RETURN_STATUS Status;
EFI_FILE_INFO *NewFileInfo;
EFI_FILE_INFO *OldFileInfo;
char *NewFn;
wchar_t *NewFn;
int OldFd;
SHELL_FILE_HANDLE FileHandle;
wchar_t *NormalizedPath;
// Open old file
OldFd = open(from, O_RDWR, 0);
@@ -482,22 +513,20 @@ da_ShellRename(
OldFileInfo = ShellGetFileInfo( FileHandle);
if(OldFileInfo != NULL) {
// Copy the Old file info into our new buffer, and free the old.
memcpy(OldFileInfo, NewFileInfo, sizeof(EFI_FILE_INFO));
memcpy(NewFileInfo, OldFileInfo, sizeof(EFI_FILE_INFO));
FreePool(OldFileInfo);
// Normalize path and convert to WCS.
NormalizedPath = NormalizePath(to);
if (NormalizedPath != NULL) {
// Strip off all but the file name portion of new
NewFn = strrchr(to, '/');
if(NewFn == NULL) {
NewFn = strrchr(to, '\\');
if(NewFn == NULL) {
NewFn = (char *)to;
}
}
// Convert new name from MBCS to WCS
(void)AsciiStrToUnicodeStr( NewFn, gMD->UString);
NewFn = GetFileNameFromPath(NormalizedPath);
// Copy the new file name into our new file info buffer
wcsncpy(NewFileInfo->FileName, gMD->UString, wcslen(gMD->UString)+1);
wcsncpy(NewFileInfo->FileName, NewFn, wcslen(NewFn) + 1);
// Update the size of the structure.
NewFileInfo->Size = sizeof(EFI_FILE_INFO) + StrSize(NewFn);
// Apply the new file name
Status = ShellSetFileInfo(FileHandle, NewFileInfo);
free(NormalizedPath);
free(NewFileInfo);
if(Status == EFI_SUCCESS) {
// File has been successfully renamed. We are DONE!
@@ -507,6 +536,12 @@ da_ShellRename(
EFIerrno = Status;
}
else {
free(NewFileInfo);
errno = ENOMEM;
}
}
else {
free(NewFileInfo);
errno = EIO;
}
}
@@ -619,7 +654,7 @@ __ctor_DevShell(
Stream->Abstraction.fo_poll = &da_ShellPoll;
Stream->Abstraction.fo_flush = &fnullop_flush;
Stream->Abstraction.fo_stat = &da_ShellStat;
Stream->Abstraction.fo_ioctl = &fbadop_ioctl;
Stream->Abstraction.fo_ioctl = &da_ShellIoctl;
Stream->Abstraction.fo_delete = &da_ShellDelete;
Stream->Abstraction.fo_rmdir = &da_ShellRmdir;
Stream->Abstraction.fo_mkdir = &da_ShellMkdir;

View File

@@ -31,33 +31,33 @@ DeviceNode *daCurrentDevice = NULL; ///< Device currently being accessed
fnullop_* Does nothing and returns success.
fbadop_* Does nothing and returns EPERM
*/
int fnullop_fcntl (struct __filedes *filp, UINT32 Cmd, void *p3, void *p4)
int EFIAPI fnullop_fcntl (struct __filedes *filp, UINT32 Cmd, void *p3, void *p4)
{ return 0; }
short fnullop_poll (struct __filedes *filp, short Events)
short EFIAPI fnullop_poll (struct __filedes *filp, short Events)
{
return ((POLLIN | POLLRDNORM | POLLOUT) & Events);
}
int fnullop_flush (struct __filedes *filp)
int EFIAPI fnullop_flush (struct __filedes *filp)
{ return 0; }
int fbadop_stat (struct __filedes *filp, struct stat *StatBuf, void *Buf)
int EFIAPI fbadop_stat (struct __filedes *filp, struct stat *StatBuf, void *Buf)
{ return -EPERM; }
int fbadop_ioctl (struct __filedes *filp, ULONGN Cmd, void *argp)
int EFIAPI fbadop_ioctl (struct __filedes *filp, ULONGN Cmd, void *argp)
{ return -EPERM; }
int fbadop_delete (struct __filedes *filp)
int EFIAPI fbadop_delete (struct __filedes *filp)
{ return -EPERM; }
int fbadop_mkdir (const char *path, __mode_t perms)
int EFIAPI fbadop_mkdir (const char *path, __mode_t perms)
{ return -EPERM; }
int fbadop_rename (const char *from, const char *to)
int EFIAPI fbadop_rename (const char *from, const char *to)
{ return -EPERM; }
int fbadop_rmdir (struct __filedes *filp)
int EFIAPI fbadop_rmdir (struct __filedes *filp)
{ return -EPERM; }
/** Add a new device to the device list.

View File

@@ -248,10 +248,16 @@ PathAlias(
/** Parse a path producing the target device, device instance, and file path.
It is the caller's responsibility to free() FullPath and MapPath when they
are no longer needed.
@param[in] path
@param[out] FullPath
@param[out] DevNode
@param[out] Which
@param[out] MapPath OPTIONAL. If not NULL, it points to the place to save a pointer
to the extracted map name. If the path didn't have a map name,
then *MapPath is set to NULL.
@retval RETURN_SUCCESS The path was parsed successfully.
@retval RETURN_NOT_FOUND The path does not map to a valid device.
@@ -266,7 +272,8 @@ ParsePath(
IN const char *path,
OUT wchar_t **FullPath,
OUT DeviceNode **DevNode,
OUT int *Which
OUT int *Which,
OUT wchar_t **MapPath
)
{
int MapLen;
@@ -301,7 +308,7 @@ reclassify:
// Get the Map Name, including the trailing ':'. */
MPath = calloc(MapLen+2, sizeof(wchar_t));
if(MPath != NULL) {
wmemcpy(MPath, WPath, MapLen+2);
wmemcpy(MPath, WPath, MapLen+1);
}
else {
errno = ENOMEM;
@@ -346,6 +353,12 @@ reclassify:
if(!RETURN_ERROR(Status)) {
*FullPath = WPath;
*Which = Instance;
if(MapPath != NULL) {
*MapPath = MPath;
}
else if(MPath != NULL) {
free(MPath); /* Caller doesn't want it so let MPath go free */
}
/* At this point, WPath is an absolute path,
MPath is either NULL or points to the Map Name,
@@ -359,6 +372,9 @@ reclassify:
if(Node != NULL) {
Status = RETURN_SUCCESS;
}
else {
Status = RETURN_NOT_FOUND;
}
}
else {
/* This is a mapped path. */
@@ -375,8 +391,41 @@ reclassify:
*DevNode = Node;
}
}
if(MPath != NULL) {
free(MPath); // We don't need this any more.
}
return Status;
}
/**
Parses a normalized wide character path and returns a pointer to the entry
following the last \. If a \ is not found in the path the return value will
be the same as the input value. All error conditions return NULL.
The behavior when passing in a path that has not been normalized is undefined.
@param Path - A pointer to a wide character string containing a path to a
directory or a file.
@return Pointer to the file name or terminal directory. NULL if an error is
detected.
**/
wchar_t *
EFIAPI
GetFileNameFromPath (
const wchar_t *Path
)
{
wchar_t *Tail;
if (Path == NULL) {
return NULL;
}
Tail = wcsrchr(Path, L'\\');
if(Tail == NULL) {
Tail = (wchar_t *) Path;
} else {
// Move to the next character after the '\\' to get the file name.
Tail++;
}
return Tail;
}

View File

@@ -16,7 +16,7 @@
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = DevConsole
FILE_GUID = 42c078ef-14a8-4e30-9329-6f12d796e54a
FILE_GUID = f6937495-1f44-4a8a-8a1b-5a669f9396f6
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
LIBRARY_CLASS = DevConsole
@@ -49,15 +49,3 @@
[Protocols]
gEfiSimpleTextInProtocolGuid
gEfiSimpleTextOutProtocolGuid
################################################################
#
# The Build Options, below, are only used when building the C library.
# DO NOT use them when building your application!
# Nasty things could happen if you do.
#
# /Oi is required for Microsoft VC++ to allow "intrinsic" functions to be
# defined in this library.
#
#[BuildOptions]
# MSFT:*_*_*_CC_FLAGS = /Oi-

View File

@@ -19,7 +19,7 @@
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = DevShell
FILE_GUID = 42c078ef-14a8-4e30-9329-6f12d796e54a
FILE_GUID = 0a1d4fd8-4704-4501-85eb-93399492cbed
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
LIBRARY_CLASS = DevShell
@@ -49,15 +49,3 @@
LibWchar
LibUefi
DevUtility
################################################################
#
# The Build Options, below, are only used when building the C library.
# DO NOT use them when building your application!
# Nasty things could happen if you do.
#
# /Oi is required for Microsoft VC++ to allow "intrinsic" functions to be
# defined in this library.
#
#[BuildOptions]
# MSFT:*_*_*_CC_FLAGS = /Oi-

View File

@@ -15,7 +15,7 @@
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = DevUtility
FILE_GUID = 42c078ef-14a8-4e30-9329-6f12d796e54a
FILE_GUID = d6a9928c-3397-4dd1-818f-c664ba6dcaaf
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
LIBRARY_CLASS = DevUtility
@@ -42,15 +42,3 @@
LibC
LibWchar
LibUefi
################################################################
#
# The Build Options, below, are only used when building the C library.
# DO NOT use them when building your application!
# Nasty things could happen if you do.
#
# /Oi- is required for Microsoft VC++ to allow "intrinsic" functions to be
# defined in this library.
#
#[BuildOptions]
# MSFT:*_*_*_CC_FLAGS = /Oi-