summaryrefslogtreecommitdiff
path: root/StdLib/LibC/Uefi
diff options
context:
space:
mode:
authordarylm503 <darylm503@6f19259b-4bc3-4df7-8a09-765794883524>2011-07-30 00:30:44 +0000
committerdarylm503 <darylm503@6f19259b-4bc3-4df7-8a09-765794883524>2011-07-30 00:30:44 +0000
commitd7ce700605e1af0e455e31ec11f19ff21d26b525 (patch)
tree243b582ac3350e8c6ce6ca96fff13805318fd65c /StdLib/LibC/Uefi
parentf766dd76fde231ecd4f2e9faf99293e90902cebb (diff)
downloadedk2-platforms-d7ce700605e1af0e455e31ec11f19ff21d26b525.tar.xz
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
Diffstat (limited to 'StdLib/LibC/Uefi')
-rw-r--r--StdLib/LibC/Uefi/Devices/Console/daConsole.c198
-rw-r--r--StdLib/LibC/Uefi/Devices/UefiShell/daShell.c89
-rw-r--r--StdLib/LibC/Uefi/Devices/Utility/DevGenisis.c18
-rw-r--r--StdLib/LibC/Uefi/Devices/Utility/Path.c59
-rw-r--r--StdLib/LibC/Uefi/Devices/daConsole.inf14
-rw-r--r--StdLib/LibC/Uefi/Devices/daShell.inf14
-rw-r--r--StdLib/LibC/Uefi/Devices/daUtility.inf14
-rw-r--r--StdLib/LibC/Uefi/GetPass.c57
-rw-r--r--StdLib/LibC/Uefi/StubFunctions.c79
-rw-r--r--StdLib/LibC/Uefi/SysCalls.c96
-rw-r--r--StdLib/LibC/Uefi/Uefi.inf8
-rw-r--r--StdLib/LibC/Uefi/compat.c847
-rw-r--r--StdLib/LibC/Uefi/select.c256
-rw-r--r--StdLib/LibC/Uefi/writev.c143
14 files changed, 1719 insertions, 173 deletions
diff --git a/StdLib/LibC/Uefi/Devices/Console/daConsole.c b/StdLib/LibC/Uefi/Devices/Console/daConsole.c
index c579959081..5dfc18acb4 100644
--- a/StdLib/LibC/Uefi/Devices/Console/daConsole.c
+++ b/StdLib/LibC/Uefi/Devices/Console/daConsole.c
@@ -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;
}
diff --git a/StdLib/LibC/Uefi/Devices/UefiShell/daShell.c b/StdLib/LibC/Uefi/Devices/UefiShell/daShell.c
index 37870e8384..d56db49159 100644
--- a/StdLib/LibC/Uefi/Devices/UefiShell/daShell.c
+++ b/StdLib/LibC/Uefi/Devices/UefiShell/daShell.c
@@ -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;
diff --git a/StdLib/LibC/Uefi/Devices/Utility/DevGenisis.c b/StdLib/LibC/Uefi/Devices/Utility/DevGenisis.c
index 2bdb33ac53..6510ce7747 100644
--- a/StdLib/LibC/Uefi/Devices/Utility/DevGenisis.c
+++ b/StdLib/LibC/Uefi/Devices/Utility/DevGenisis.c
@@ -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.
diff --git a/StdLib/LibC/Uefi/Devices/Utility/Path.c b/StdLib/LibC/Uefi/Devices/Utility/Path.c
index 92bb1a20b7..96392e018d 100644
--- a/StdLib/LibC/Uefi/Devices/Utility/Path.c
+++ b/StdLib/LibC/Uefi/Devices/Utility/Path.c
@@ -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;
+}
diff --git a/StdLib/LibC/Uefi/Devices/daConsole.inf b/StdLib/LibC/Uefi/Devices/daConsole.inf
index 17865e4fec..802c6eb13c 100644
--- a/StdLib/LibC/Uefi/Devices/daConsole.inf
+++ b/StdLib/LibC/Uefi/Devices/daConsole.inf
@@ -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-
diff --git a/StdLib/LibC/Uefi/Devices/daShell.inf b/StdLib/LibC/Uefi/Devices/daShell.inf
index 7b56f37363..56710259b6 100644
--- a/StdLib/LibC/Uefi/Devices/daShell.inf
+++ b/StdLib/LibC/Uefi/Devices/daShell.inf
@@ -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-
diff --git a/StdLib/LibC/Uefi/Devices/daUtility.inf b/StdLib/LibC/Uefi/Devices/daUtility.inf
index 53daad28ac..6bdc1eead9 100644
--- a/StdLib/LibC/Uefi/Devices/daUtility.inf
+++ b/StdLib/LibC/Uefi/Devices/daUtility.inf
@@ -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-
diff --git a/StdLib/LibC/Uefi/GetPass.c b/StdLib/LibC/Uefi/GetPass.c
new file mode 100644
index 0000000000..9c0c1f4116
--- /dev/null
+++ b/StdLib/LibC/Uefi/GetPass.c
@@ -0,0 +1,57 @@
+/** @file Implement the getpass function.
+
+ Copyright (c) 2011, Intel Corporation <BR>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/ShellLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+
+static CHAR8 *ReturnStringAscii = NULL;
+
+char *getpass(const char *Prompt)
+{
+ BOOLEAN Ascii;
+ CHAR16 *ReturnString;
+
+ Ascii = FALSE;
+
+ Print(L"%a", Prompt);
+
+ ReturnString = ShellFileHandleReturnLine (gEfiShellParametersProtocol->StdIn, &Ascii);
+ if (ReturnString == NULL) {
+ return (NULL);
+ }
+
+ ReturnStringAscii = AllocateZeroPool((StrLen(ReturnString)+1)*sizeof(CHAR8));
+ if (ReturnStringAscii == NULL) {
+ return (NULL);
+ }
+
+ UnicodeStrToAsciiStr(ReturnString, ReturnStringAscii);
+
+ FreePool(ReturnString);
+
+ return (ReturnStringAscii);
+}
+
+EFI_STATUS
+EFIAPI
+DestructMePlease (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ SHELL_FREE_NON_NULL(ReturnStringAscii);
+
+ return EFI_SUCCESS;
+} \ No newline at end of file
diff --git a/StdLib/LibC/Uefi/StubFunctions.c b/StdLib/LibC/Uefi/StubFunctions.c
new file mode 100644
index 0000000000..da2eaf9148
--- /dev/null
+++ b/StdLib/LibC/Uefi/StubFunctions.c
@@ -0,0 +1,79 @@
+/** @file
+ Implement the invalid functions to return failures.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license
+
+ 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 <sys/EfiCdefs.h>
+#include <sys/featuretest.h>
+#include <namespace.h>
+#include <stdio.h>
+#include <pwd.h>
+#include <errno.h>
+
+struct passwd *
+getpwuid (uid_t uid)
+{
+ uid;
+ errno = EPERM;
+ return NULL;
+}
+
+char *getlogin (void)
+{
+ errno = EPERM;
+ return NULL;
+}
+
+struct passwd *
+getpwnam (const char *name)
+{
+ name;
+ errno = EPERM;
+ return NULL;
+}
+
+uid_t getuid (void)
+{
+ return 0;
+}
+
+pid_t fork (void)
+{
+ errno = EPERM;
+ return (-1);
+}
+
+int chmod (const char *c, mode_t m)
+{
+ errno = EPERM;
+ return (-1);
+}
+
+pid_t wait(int *stat_loc) {
+ return 0;
+}
+
+FILE *popen (const char *cmd, const char *type)
+{
+ errno = EPERM;
+ return NULL;
+}
+
+int pclose (FILE *stream)
+{
+ errno = EPERM;
+ return -1;
+}
+
+int access (const char *path, int amode)
+{
+ return 0;
+}
diff --git a/StdLib/LibC/Uefi/SysCalls.c b/StdLib/LibC/Uefi/SysCalls.c
index b3ca5b89b4..d2fb0c6af6 100644
--- a/StdLib/LibC/Uefi/SysCalls.c
+++ b/StdLib/LibC/Uefi/SysCalls.c
@@ -524,7 +524,7 @@ mkdir (const char *path, __mode_t perms)
int Instance = 0;
int retval = 0;
- Status = ParsePath(path, &NewPath, &Node, &Instance);
+ Status = ParsePath(path, &NewPath, &Node, &Instance, NULL);
if(Status == RETURN_SUCCESS) {
GenI = Node->InstanceList;
if(GenI == NULL) {
@@ -532,7 +532,7 @@ mkdir (const char *path, __mode_t perms)
retval = -1;
}
else {
- GenI += (Instance * Node->InstanceSize);
+ //GenI += (Instance * Node->InstanceSize);
retval = ((GenericInstance *)GenI)->Abstraction.fo_mkdir( path, perms);
}
free(NewPath);
@@ -567,11 +567,15 @@ mkdir (const char *path, __mode_t perms)
O_EXCL -- if O_CREAT is also set, open will fail if the file already exists.
**/
int
-open (const char *path, int oflags, int mode)
+open(
+ const char *path,
+ int oflags,
+ int mode
+ )
{
wchar_t *NewPath;
+ wchar_t *MPath;
DeviceNode *Node;
- char *GenI = NULL;
struct __filedes *filp;
int Instance = 0;
RETURN_STATUS Status;
@@ -579,10 +583,10 @@ open (const char *path, int oflags, int mode)
int fd = -1;
int doresult;
- Status = ParsePath(path, &NewPath, &Node, &Instance);
+ Status = ParsePath(path, &NewPath, &Node, &Instance, &MPath);
if(Status == RETURN_SUCCESS) {
- if((Node != NULL) &&
- ((GenI = Node->InstanceList) == NULL)) {
+ if((Node == NULL) ||
+ (Node->InstanceList == NULL)) {
errno = EPERM;
}
else {
@@ -595,15 +599,14 @@ open (const char *path, int oflags, int mode)
if( fd < 0 ) {
// All available FDs are in use
errno = EMFILE;
- return -1;
}
+ else {
filp = &gMD->fdarray[fd];
// Save the flags and mode in the File Descriptor
filp->Oflags = oflags;
filp->Omode = mode;
- GenI += (Instance * Node->InstanceSize);
- doresult = Node->OpenFunc(filp, GenI, NewPath, NULL);
+ doresult = Node->OpenFunc(Node, filp, Instance, NewPath, MPath);
if(doresult < 0) {
filp->f_iflags = 0; // Release this FD
fd = -1; // Indicate an error
@@ -618,8 +621,14 @@ open (const char *path, int oflags, int mode)
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;
}
@@ -748,6 +757,7 @@ poll (
}
} while (( 0 == SelectedFDs )
&& ( EFI_SUCCESS == Status ));
+
//
// Stop the timer
//
@@ -776,7 +786,6 @@ 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
argument points to the new pathname of the file.
@@ -807,7 +816,6 @@ poll (
shall be changed or created.
**/
int
-EFIAPI
rename(
const char *from,
const char *to
@@ -820,7 +828,7 @@ rename(
RETURN_STATUS Status;
int retval = -1;
- Status = ParsePath(from, &FromPath, &FromNode, &Instance);
+ Status = ParsePath(from, &FromPath, &FromNode, &Instance, NULL);
if(Status == RETURN_SUCCESS) {
GenI = FromNode->InstanceList;
if(GenI == NULL) {
@@ -828,7 +836,7 @@ rename(
retval = -1;
}
else {
- GenI += (Instance * FromNode->InstanceSize);
+ //GenI += (Instance * FromNode->InstanceSize);
retval = ((GenericInstance *)GenI)->Abstraction.fo_rename( from, to);
}
free(FromPath);
@@ -839,7 +847,6 @@ rename(
/**
**/
int
-EFIAPI
rmdir(
const char *path
)
@@ -1006,13 +1013,13 @@ ioctl(
from a file associated with a terminal may return one typed line of data.
If fildes does not refer to a directory, the function reads the requested
- number of bytes from the file at the file’s current position and returns
+ number of bytes from the file at the file's current position and returns
them in buf. If the read goes beyond the end of the file, the read
- length is truncated to the end of the file. The file’s current position is
+ length is truncated to the end of the file. The file's current position is
increased by the number of bytes returned.
If fildes refers to a directory, the function reads the directory entry at
- the file’s current position and returns the entry in buf. If buf
+ the file's current position and returns the entry in buf. If buf
is not large enough to hold the current directory entry, then
errno is set to EBUFSIZE, EFIerrno is set to EFI_BUFFER_TOO_SMALL, and the
current file position is not updated. The size of the buffer needed to read
@@ -1129,3 +1136,56 @@ char
return (UnicodeStrToAsciiStr(Cwd, buf));
}
+
+/** Change the current working directory.
+
+ The chdir() function shall cause the directory named by the pathname
+ pointed to by the path argument to become the current working directory;
+ that is, the starting point for path searches for pathnames not beginning
+ with '/'.
+
+ @param[in] path The new path to set.
+
+ @todo Add non-shell CWD changing.
+**/
+int
+chdir (const char *path)
+{
+ CONST CHAR16 *Cwd;
+ EFI_STATUS Status;
+ CHAR16 *UnicodePath;
+
+ Cwd = ShellGetCurrentDir(NULL);
+ if (Cwd != NULL) {
+ /* We have shell support */
+ UnicodePath = AllocatePool(((AsciiStrLen (path) + 1) * sizeof (CHAR16)));
+ if (UnicodePath == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ AsciiStrToUnicodeStr(path, UnicodePath);
+ Status = gEfiShellProtocol->SetCurDir(NULL, UnicodePath);
+ FreePool(UnicodePath);
+ if (EFI_ERROR(Status)) {
+ errno = EACCES;
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+
+ /* Add here for non-shell */
+ errno = EACCES;
+ return -1;
+}
+
+pid_t tcgetpgrp (int x)
+{
+ return ((pid_t)(UINTN)(gImageHandle));
+}
+
+pid_t getpgrp(void)
+{
+ return ((pid_t)(UINTN)(gImageHandle));
+}
+
diff --git a/StdLib/LibC/Uefi/Uefi.inf b/StdLib/LibC/Uefi/Uefi.inf
index 084d6c4fc3..30b619b409 100644
--- a/StdLib/LibC/Uefi/Uefi.inf
+++ b/StdLib/LibC/Uefi/Uefi.inf
@@ -16,18 +16,24 @@
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = LibUefi
- FILE_GUID = 39356e02-26bf-4cfb-9564-378ce25e702f
+ FILE_GUID = 1dcff17c-aa53-4b78-b234-864027555035
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
LIBRARY_CLASS = LibUefi
+ LIBRARY_CONSTRUCTOR = DestructMePlease
#
# VALID_ARCHITECTURES = IA32 X64 IPF
#
[Sources]
+ select.c
SysCalls.c
+ writev.c
Xform.c
+ compat.c
+ GetPass.c
+ StubFunctions.c
[Packages]
StdLib/StdLib.dec
diff --git a/StdLib/LibC/Uefi/compat.c b/StdLib/LibC/Uefi/compat.c
new file mode 100644
index 0000000000..7f250d15ff
--- /dev/null
+++ b/StdLib/LibC/Uefi/compat.c
@@ -0,0 +1,847 @@
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: compat.c,v 1.1.1.1 2008/08/24 05:33:08 gmcgarry Exp $
+
+ * Copyright (c) 1997, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Klaus Klein and Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $NetBSD: compat.c,v 1.1.1.1 2008/08/24 05:33:08 gmcgarry Exp $
+
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $NetBSD: compat.c,v 1.1.1.1 2008/08/24 05:33:08 gmcgarry Exp $
+ */
+#include <LibConfig.h>
+#include <string.h>
+#include <fcntl.h>
+
+#ifndef HAVE_GETOPT
+char *optarg;
+int optind = 1;
+int
+getopt(int argc, char **argv, char *args)
+{
+ size_t n;
+ size_t nlen = strlen(args);
+ char cmd;
+ char rv;
+
+ if (argv[optind] && *argv[optind] == '-') {
+ cmd = *(argv[optind] + 1);
+
+ for (n = 0; n < nlen; n++) {
+ if (args[n] == ':')
+ continue;
+ if (args[n] == cmd) {
+ rv = *(argv[optind] + 1);
+ if (args[n+1] == ':') {
+ if (*(argv[optind] + 2) != '\0') {
+ optarg = argv[optind] + 2;
+ optind += 1;
+ } else {
+ optarg = argv[optind + 1];
+ optind += 2;
+ }
+ if (!optarg)
+ optarg="";
+ return rv;
+ } else {
+ optarg = NULL;
+ optind += 1;
+ return rv;
+ }
+ }
+ }
+ }
+
+ return -1;
+}
+#endif
+
+#ifdef WIN32
+#define ISPATHSEPARATOR(x) ((x == '/') || (x == '\\'))
+#else
+#define ISPATHSEPARATOR(x) (x == '/')
+#endif
+
+#ifndef HAVE_BASENAME
+#ifndef PATH_MAX
+#define PATH_MAX 5000
+#endif
+
+char *
+basename(char *path)
+{
+ static char singledot[] = ".";
+ static char result[PATH_MAX];
+ char *p, *lastp;
+ size_t len;
+
+ /*
+ * If `path' is a null pointer or points to an empty string,
+ * return a pointer to the string ".".
+ */
+ if ((path == NULL) || (*path == '\0'))
+ return (singledot);
+
+ /* Strip trailing slashes, if any. */
+ lastp = path + strlen(path) - 1;
+ while (lastp != path && ISPATHSEPARATOR(*lastp))
+ lastp--;
+
+ /* Now find the beginning of this (final) component. */
+ p = lastp;
+ while (p != path && !ISPATHSEPARATOR(*(p - 1)))
+ p--;
+
+ /* ...and copy the result into the result buffer. */
+ len = (lastp - p) + 1 /* last char */;
+ if (len > (PATH_MAX - 1))
+ len = PATH_MAX - 1;
+
+ memcpy(result, p, len);
+ result[len] = '\0';
+
+ return (result);
+}
+#endif
+
+#if !defined(HAVE_MKSTEMP) && !defined(WIN32)
+int
+mkstemp(char *path)
+{
+ char *start, *trv;
+ unsigned int pid;
+
+ /* To guarantee multiple calls generate unique names even if
+ the file is not created. 676 different possibilities with 7
+ or more X's, 26 with 6 or less. */
+ static char xtra[2] = "aa";
+ int xcnt = 0;
+
+ pid = getpid();
+
+ /* Move to end of path and count trailing X's. */
+ for (trv = path; *trv; ++trv)
+ if (*trv == 'X')
+ xcnt++;
+ else
+ xcnt = 0;
+
+ /* Use at least one from xtra. Use 2 if more than 6 X's. */
+ if (*(trv - 1) == 'X')
+ *--trv = xtra[0];
+ if (xcnt > 6 && *(trv - 1) == 'X')
+ *--trv = xtra[1];
+
+ /* Set remaining X's to pid digits with 0's to the left. */
+ while (*--trv == 'X') {
+ *trv = (pid % 10) + '0';
+ pid /= 10;
+ }
+
+ /* update xtra for next call. */
+ if (xtra[0] != 'z')
+ xtra[0]++;
+ else {
+ xtra[0] = 'a';
+ if (xtra[1] != 'z')
+ xtra[1]++;
+ else
+ xtra[1] = 'a';
+ }
+
+ return open(path, O_CREAT | O_EXCL | O_RDWR, 0600);
+}
+#endif
+
+#ifndef HAVE_FFS
+int
+ffs(int x)
+{
+ int r = 1;
+ if (!x) return 0;
+ if (!(x & 0xffff)) { x >>= 16; r += 16; }
+ if (!(x & 0xff)) { x >>= 8; r += 8; }
+ if (!(x & 0xf)) { x >>= 4; r += 4; }
+ if (!(x & 3)) { x >>= 2; r += 2; }
+ if (!(x & 1)) { x >>= 1; r += 1; }
+
+ return r;
+}
+#endif
+
+/*
+ * Copyright Patrick Powell 1995
+ * This code is based on code written by Patrick Powell (papowell@astart.com)
+ * It may be used for any purpose as long as this notice remains intact
+ * on all source code distributions
+ */
+
+#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
+
+static void
+dopr(char *buffer, size_t maxlen, const char *format, va_list args);
+
+static void
+fmtstr(char *buffer, size_t *currlen, size_t maxlen, char *value, int flags,
+ int min, int max);
+
+static void
+fmtint(char *buffer, size_t *currlen, size_t maxlen, long value, int base,
+ int min, int max, int flags);
+
+static void
+fmtfp(char *buffer, size_t *currlen, size_t maxlen, long double fvalue,
+ int min, int max, int flags);
+
+static void
+dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
+
+/*
+ * dopr(): poor man's version of doprintf
+ */
+
+/* format read states */
+#define DP_S_DEFAULT 0
+#define DP_S_FLAGS 1
+#define DP_S_MIN 2
+#define DP_S_DOT 3
+#define DP_S_MAX 4
+#define DP_S_MOD 5
+#define DP_S_CONV 6
+#define DP_S_DONE 7
+
+/* format flags - Bits */
+#define DP_F_MINUS (1 << 0)
+#define DP_F_PLUS (1 << 1)
+#define DP_F_SPACE (1 << 2)
+#define DP_F_NUM (1 << 3)
+#define DP_F_ZERO (1 << 4)
+#define DP_F_UP (1 << 5)
+#define DP_F_UNSIGNED (1 << 6)
+
+/* Conversion Flags */
+#define DP_C_SHORT 1
+#define DP_C_LONG 2
+#define DP_C_LDOUBLE 3
+#define DP_C_LONG_LONG 4
+
+#define char_to_int(p) (p - '0')
+#define abs_val(p) (p < 0 ? -p : p)
+
+
+static void
+dopr(char *buffer, size_t maxlen, const char *format, va_list args)
+{
+ char *strvalue, ch;
+ long value;
+ long double fvalue;
+ int min = 0, max = -1, state = DP_S_DEFAULT, flags = 0, cflags = 0;
+ size_t currlen = 0;
+
+ ch = *format++;
+
+ while (state != DP_S_DONE) {
+ if ((ch == '\0') || (currlen >= maxlen))
+ state = DP_S_DONE;
+
+ switch(state) {
+ case DP_S_DEFAULT:
+ if (ch == '%')
+ state = DP_S_FLAGS;
+ else
+ dopr_outch(buffer, &currlen, maxlen, ch);
+ ch = *format++;
+ break;
+ case DP_S_FLAGS:
+ switch (ch) {
+ case '-':
+ flags |= DP_F_MINUS;
+ ch = *format++;
+ break;
+ case '+':
+ flags |= DP_F_PLUS;
+ ch = *format++;
+ break;
+ case ' ':
+ flags |= DP_F_SPACE;
+ ch = *format++;
+ break;
+ case '#':
+ flags |= DP_F_NUM;
+ ch = *format++;
+ break;
+ case '0':
+ flags |= DP_F_ZERO;
+ ch = *format++;
+ break;
+ default:
+ state = DP_S_MIN;
+ break;
+ }
+ break;
+ case DP_S_MIN:
+ if (isdigit((unsigned char)ch)) {
+ min = 10 * min + char_to_int (ch);
+ ch = *format++;
+ } else if (ch == '*') {
+ min = va_arg (args, int);
+ ch = *format++;
+ state = DP_S_DOT;
+ } else
+ state = DP_S_DOT;
+ break;
+ case DP_S_DOT:
+ if (ch == '.') {
+ state = DP_S_MAX;
+ ch = *format++;
+ } else
+ state = DP_S_MOD;
+ break;
+ case DP_S_MAX:
+ if (isdigit((unsigned char)ch)) {
+ if (max < 0)
+ max = 0;
+ max = 10 * max + char_to_int(ch);
+ ch = *format++;
+ } else if (ch == '*') {
+ max = va_arg (args, int);
+ ch = *format++;
+ state = DP_S_MOD;
+ } else
+ state = DP_S_MOD;
+ break;
+ case DP_S_MOD:
+ switch (ch) {
+ case 'h':
+ cflags = DP_C_SHORT;
+ ch = *format++;
+ break;
+ case 'l':
+ cflags = DP_C_LONG;
+ ch = *format++;
+ if (ch == 'l') {
+ cflags = DP_C_LONG_LONG;
+ ch = *format++;
+ }
+ break;
+ case 'q':
+ cflags = DP_C_LONG_LONG;
+ ch = *format++;
+ break;
+ case 'L':
+ cflags = DP_C_LDOUBLE;
+ ch = *format++;
+ break;
+ default:
+ break;
+ }
+ state = DP_S_CONV;
+ break;
+ case DP_S_CONV:
+ switch (ch) {
+ case 'd':
+ case 'i':
+ if (cflags == DP_C_SHORT)
+ value = va_arg(args, int);
+ else if (cflags == DP_C_LONG)
+ value = va_arg(args, long int);
+ else if (cflags == DP_C_LONG_LONG)
+ value = va_arg (args, long long);
+ else
+ value = va_arg (args, int);
+ fmtint(buffer, &currlen, maxlen, value, 10, min, max, flags);
+ break;
+ case 'o':
+ flags |= DP_F_UNSIGNED;
+ if (cflags == DP_C_SHORT)
+ value = va_arg(args, unsigned int);
+ else if (cflags == DP_C_LONG)
+ value = va_arg(args, unsigned long int);
+ else if (cflags == DP_C_LONG_LONG)
+ value = va_arg(args, unsigned long long);
+ else
+ value = va_arg(args, unsigned int);
+ fmtint(buffer, &currlen, maxlen, value, 8, min, max, flags);
+ break;
+ case 'u':
+ flags |= DP_F_UNSIGNED;
+ if (cflags == DP_C_SHORT)
+ value = va_arg(args, unsigned int);
+ else if (cflags == DP_C_LONG)
+ value = va_arg(args, unsigned long int);
+ else if (cflags == DP_C_LONG_LONG)
+ value = va_arg(args, unsigned long long);
+ else
+ value = va_arg(args, unsigned int);
+ fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
+ break;
+ case 'X':
+ flags |= DP_F_UP;
+ case 'x':
+ flags |= DP_F_UNSIGNED;
+ if (cflags == DP_C_SHORT)
+ value = va_arg(args, unsigned int);
+ else if (cflags == DP_C_LONG)
+ value = va_arg(args, unsigned long int);
+ else if (cflags == DP_C_LONG_LONG)
+ value = va_arg(args, unsigned long long);
+ else
+ value = va_arg(args, unsigned int);
+ fmtint(buffer, &currlen, maxlen, value, 16, min, max, flags);
+ break;
+ case 'f':
+ if (cflags == DP_C_LDOUBLE)
+ fvalue = va_arg(args, long double);
+ else
+ fvalue = va_arg(args, double);
+ /* um, floating point? */
+ fmtfp(buffer, &currlen, maxlen, fvalue, min, max, flags);
+ break;
+ case 'E':
+ flags |= DP_F_UP;
+ case 'e':
+ if (cflags == DP_C_LDOUBLE)
+ fvalue = va_arg(args, long double);
+ else
+ fvalue = va_arg(args, double);
+ break;
+ case 'G':
+ flags |= DP_F_UP;
+ case 'g':
+ if (cflags == DP_C_LDOUBLE)
+ fvalue = va_arg(args, long double);
+ else
+ fvalue = va_arg(args, double);
+ break;
+ case 'c':
+ dopr_outch(buffer, &currlen, maxlen, va_arg(args, int));
+ break;
+ case 's':
+ strvalue = va_arg(args, char *);
+ if (max < 0)
+ max = maxlen; /* ie, no max */
+ fmtstr(buffer, &currlen, maxlen, strvalue, flags, min, max);
+ break;
+ case 'p':
+ strvalue = va_arg(args, void *);
+ fmtint(buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);
+ break;
+ case 'n':
+ if (cflags == DP_C_SHORT) {
+ short int *num;
+ num = va_arg(args, short int *);
+ *num = currlen;
+ } else if (cflags == DP_C_LONG) {
+ long int *num;
+ num = va_arg(args, long int *);
+ *num = currlen;
+ } else if (cflags == DP_C_LONG_LONG) {
+ long long *num;
+ num = va_arg(args, long long *);
+ *num = currlen;
+ } else {
+ int *num;
+ num = va_arg(args, int *);
+ *num = currlen;
+ }
+ break;
+ case '%':
+ dopr_outch(buffer, &currlen, maxlen, ch);
+ break;
+ case 'w': /* not supported yet, treat as next char */
+ ch = *format++;
+ break;
+ default: /* Unknown, skip */
+ break;
+ }
+ ch = *format++;
+ state = DP_S_DEFAULT;
+ flags = cflags = min = 0;
+ max = -1;
+ break;
+ case DP_S_DONE:
+ break;
+ default: /* hmm? */
+ break; /* some picky compilers need this */
+ }
+ }
+ if (currlen < maxlen - 1)
+ buffer[currlen] = '\0';
+ else
+ buffer[maxlen - 1] = '\0';
+}
+
+static void
+fmtstr(char *buffer, size_t *currlen, size_t maxlen,
+ char *value, int flags, int min, int max)
+{
+ int cnt = 0, padlen, strln; /* amount to pad */
+
+ if (value == 0)
+ value = "<NULL>";
+
+ for (strln = 0; value[strln]; ++strln); /* strlen */
+ padlen = min - strln;
+ if (padlen < 0)
+ padlen = 0;
+ if (flags & DP_F_MINUS)
+ padlen = -padlen; /* Left Justify */
+
+ while ((padlen > 0) && (cnt < max)) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ --padlen;
+ ++cnt;
+ }
+ while (*value && (cnt < max)) {
+ dopr_outch(buffer, currlen, maxlen, *value++);
+ ++cnt;
+ }
+ while ((padlen < 0) && (cnt < max)) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ ++padlen;
+ ++cnt;
+ }
+}
+
+/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
+
+static void
+fmtint(char *buffer, size_t *currlen, size_t maxlen,
+ long value, int base, int min, int max, int flags)
+{
+ unsigned long uvalue;
+ char convert[20];
+ int signvalue = 0, place = 0, caps = 0;
+ int spadlen = 0; /* amount to space pad */
+ int zpadlen = 0; /* amount to zero pad */
+
+#define PADMAX(x,y) ((x) > (y) ? (x) : (y))
+
+ if (max < 0)
+ max = 0;
+
+ uvalue = value;
+
+ if (!(flags & DP_F_UNSIGNED)) {
+ if (value < 0) {
+ signvalue = '-';
+ uvalue = -value;
+ } else if (flags & DP_F_PLUS) /* Do a sign (+/i) */
+ signvalue = '+';
+ else if (flags & DP_F_SPACE)
+ signvalue = ' ';
+ }
+
+ if (flags & DP_F_UP)
+ caps = 1; /* Should characters be upper case? */
+ do {
+ convert[place++] =
+ (caps ? "0123456789ABCDEF" : "0123456789abcdef")
+ [uvalue % (unsigned)base];
+ uvalue = (uvalue / (unsigned)base );
+ } while (uvalue && (place < 20));
+ if (place == 20)
+ place--;
+ convert[place] = 0;
+
+ zpadlen = max - place;
+ spadlen = min - PADMAX(max, place) - (signvalue ? 1 : 0);
+ if (zpadlen < 0)
+ zpadlen = 0;
+ if (spadlen < 0)
+ spadlen = 0;
+ if (flags & DP_F_ZERO) {
+ zpadlen = PADMAX(zpadlen, spadlen);
+ spadlen = 0;
+ }
+ if (flags & DP_F_MINUS)
+ spadlen = -spadlen; /* Left Justifty */
+
+ /* Spaces */
+ while (spadlen > 0) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ --spadlen;
+ }
+
+ /* Sign */
+ if (signvalue)
+ dopr_outch(buffer, currlen, maxlen, signvalue);
+
+ /* Zeros */
+ if (zpadlen > 0) {
+ while (zpadlen > 0) {
+ dopr_outch(buffer, currlen, maxlen, '0');
+ --zpadlen;
+ }
+ }
+
+ /* Digits */
+ while (place > 0)
+ dopr_outch(buffer, currlen, maxlen, convert[--place]);
+
+ /* Left Justified spaces */
+ while (spadlen < 0) {
+ dopr_outch (buffer, currlen, maxlen, ' ');
+ ++spadlen;
+ }
+}
+
+static long double
+pow10(int exp)
+{
+ long double result = 1;
+
+ while (exp) {
+ result *= 10;
+ exp--;
+ }
+
+ return result;
+}
+
+static long
+round(long double value)
+{
+ long intpart = value;
+
+ value -= intpart;
+ if (value >= 0.5)
+ intpart++;
+
+ return intpart;
+}
+
+static void
+fmtfp(char *buffer, size_t *currlen, size_t maxlen, long double fvalue,
+ int min, int max, int flags)
+{
+ char iconvert[20], fconvert[20];
+ int signvalue = 0, iplace = 0, fplace = 0;
+ int padlen = 0; /* amount to pad */
+ int zpadlen = 0, caps = 0;
+ long intpart, fracpart;
+ long double ufvalue;
+
+ /*
+ * AIX manpage says the default is 0, but Solaris says the default
+ * is 6, and sprintf on AIX defaults to 6
+ */
+ if (max < 0)
+ max = 6;
+
+ ufvalue = abs_val(fvalue);
+
+ if (fvalue < 0)
+ signvalue = '-';
+ else if (flags & DP_F_PLUS) /* Do a sign (+/i) */
+ signvalue = '+';
+ else if (flags & DP_F_SPACE)
+ signvalue = ' ';
+
+ intpart = ufvalue;
+
+ /*
+ * Sorry, we only support 9 digits past the decimal because of our
+ * conversion method
+ */
+ if (max > 9)
+ max = 9;
+
+ /* We "cheat" by converting the fractional part to integer by
+ * multiplying by a factor of 10
+ */
+ fracpart = round((pow10 (max)) * (ufvalue - intpart));
+
+ if (fracpart >= pow10 (max)) {
+ intpart++;
+ fracpart -= pow10 (max);
+ }
+
+ /* Convert integer part */
+ do {
+ iconvert[iplace++] =
+ (caps ? "0123456789ABCDEF" : "0123456789abcdef")
+ [intpart % 10];
+ intpart = (intpart / 10);
+ } while(intpart && (iplace < 20));
+ if (iplace == 20)
+ iplace--;
+ iconvert[iplace] = 0;
+
+ /* Convert fractional part */
+ do {
+ fconvert[fplace++] =
+ (caps ? "0123456789ABCDEF" : "0123456789abcdef")
+ [fracpart % 10];
+ fracpart = (fracpart / 10);
+ } while(fracpart && (fplace < 20));
+ if (fplace == 20)
+ fplace--;
+ fconvert[fplace] = 0;
+
+ /* -1 for decimal point, another -1 if we are printing a sign */
+ padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
+ zpadlen = max - fplace;
+ if (zpadlen < 0)
+ zpadlen = 0;
+ if (padlen < 0)
+ padlen = 0;
+ if (flags & DP_F_MINUS)
+ padlen = -padlen; /* Left Justifty */
+
+ if ((flags & DP_F_ZERO) && (padlen > 0)) {
+ if (signvalue) {
+ dopr_outch(buffer, currlen, maxlen, signvalue);
+ --padlen;
+ signvalue = 0;
+ }
+ while (padlen > 0) {
+ dopr_outch(buffer, currlen, maxlen, '0');
+ --padlen;
+ }
+ }
+ while (padlen > 0) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ --padlen;
+ }
+ if (signvalue)
+ dopr_outch(buffer, currlen, maxlen, signvalue);
+
+ while (iplace > 0)
+ dopr_outch(buffer, currlen, maxlen, iconvert[--iplace]);
+
+ /*
+ * Decimal point. This should probably use locale to find the
+ * correct char to print out.
+ */
+ dopr_outch(buffer, currlen, maxlen, '.');
+
+ while (fplace > 0)
+ dopr_outch(buffer, currlen, maxlen, fconvert[--fplace]);
+
+ while (zpadlen > 0) {
+ dopr_outch(buffer, currlen, maxlen, '0');
+ --zpadlen;
+ }
+
+ while (padlen < 0) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ ++padlen;
+ }
+}
+
+static void
+dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
+{
+ if (*currlen < maxlen)
+ buffer[(*currlen)++] = c;
+}
+#endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */
+
+#ifndef HAVE_VSNPRINTF
+int
+vsnprintf(char *str, size_t count, const char *fmt, va_list args)
+{
+ str[0] = 0;
+ dopr(str, count, fmt, args);
+
+ return(strlen(str));
+}
+#endif /* !HAVE_VSNPRINTF */
+
+#ifndef HAVE_SNPRINTF
+int
+snprintf(char *str,size_t count,const char *fmt,...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ (void) vsnprintf(str, count, fmt, ap);
+ va_end(ap);
+
+ return(strlen(str));
+}
+
+#endif /* !HAVE_SNPRINTF */
diff --git a/StdLib/LibC/Uefi/select.c b/StdLib/LibC/Uefi/select.c
new file mode 100644
index 0000000000..8da03e65d0
--- /dev/null
+++ b/StdLib/LibC/Uefi/select.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 1982, 1986, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by the University of
+ * California, Berkeley, Intel Corporation, and its contributors.
+ *
+ * 4. Neither the name of University, Intel Corporation, or their respective
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS, INTEL CORPORATION AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS,
+ * INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @(#)sys_generic.c 8.5 (Berkeley) 1/21/94
+ * $Id: select.c,v 1.1.1.1 2003/11/19 01:50:30 kyu3 Exp $
+ */
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <LibConfig.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/poll.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <extern.h> /* For ffs() */
+#ifndef KERNEL
+#define KERNEL
+#include <errno.h>
+#undef KERNEL
+#else
+#include <errno.h>
+#endif
+
+#ifdef EFI_NT_EMULATOR
+#define _SELECT_DELAY_ 10000
+#else
+#define _SELECT_DELAY_ 1000
+#endif
+
+#define MAX_SLEEP_DELAY 0xfffffffe
+
+//
+// Name:
+// usleep
+//
+// Description:
+// Implement usleep(3) function.
+//
+// Arguments:
+// Microseconds to sleep.
+//
+// Returns:
+// 0
+//
+int
+usleep( useconds_t Microseconds )
+{
+ while ( MAX_SLEEP_DELAY < Microseconds ) {
+ gBS->Stall ( MAX_SLEEP_DELAY );
+ Microseconds -= MAX_SLEEP_DELAY;
+ }
+ gBS->Stall((UINTN)Microseconds );
+ return (0);
+}
+
+static int
+selscan(
+ fd_mask **ibits,
+ fd_mask **obits,
+ int nfd,
+ int *nselected
+ )
+{
+ int msk;
+ int i;
+ int j;
+ int fd;
+ int n;
+ struct pollfd pfd;
+ int FdCount;
+ fd_mask bits;
+ /* Note: backend also returns POLLHUP/POLLERR if appropriate. */
+ static int16_t flag[3] = { POLLRDNORM, POLLWRNORM, POLLRDBAND };
+
+ for (msk = 0, n = 0; msk < 3; msk++) {
+ if (ibits[msk] == NULL)
+ continue;
+ for (i = 0; i < nfd; i += NFDBITS) {
+ bits = ibits[ msk ][ i / NFDBITS ];
+ while (( 0 != (j = ffs(bits))) && ((fd = i + --j) < nfd)) {
+ bits &= ~(1 << j);
+
+ pfd.fd = fd;
+ pfd.events = flag[msk];
+ pfd.revents = 0;
+ FdCount = poll ( &pfd, 1, 0 );
+ if ( -1 == FdCount ) {
+ return errno;
+ }
+ if ( 0 != FdCount ) {
+ obits[msk][(fd)/NFDBITS] |=
+ (1 << ((fd) % NFDBITS));
+ n++;
+ break;
+ }
+ }
+ }
+ }
+ *nselected = n;
+ return (0);
+}
+
+int
+select(
+ int nd,
+ fd_set *in,
+ fd_set *ou,
+ fd_set *ex,
+ struct timeval *tv
+ )
+{
+ fd_mask *ibits[3], *obits[3], *selbits, *sbp;
+ int error, forever, nselected;
+ u_int nbufbytes, ncpbytes, nfdbits;
+ int64_t timo;
+
+ if (nd < 0)
+ return (EINVAL);
+
+ /*
+ * Allocate just enough bits for the non-null fd_sets. Use the
+ * preallocated auto buffer if possible.
+ */
+ nfdbits = roundup(nd, NFDBITS);
+ ncpbytes = nfdbits / NBBY;
+ nbufbytes = 0;
+ if (in != NULL)
+ nbufbytes += 2 * ncpbytes;
+ if (ou != NULL)
+ nbufbytes += 2 * ncpbytes;
+ if (ex != NULL)
+ nbufbytes += 2 * ncpbytes;
+ selbits = malloc(nbufbytes);
+
+ /*
+ * Assign pointers into the bit buffers and fetch the input bits.
+ * Put the output buffers together so that they can be bzeroed
+ * together.
+ */
+ sbp = selbits;
+#define getbits(name, x) \
+ do { \
+ if (name == NULL) \
+ ibits[x] = NULL; \
+ else { \
+ ibits[x] = sbp + nbufbytes / 2 / sizeof *sbp; \
+ obits[x] = sbp; \
+ sbp += ncpbytes / sizeof *sbp; \
+ bcopy(name, ibits[x], ncpbytes); \
+ } \
+ } while (0)
+ getbits(in, 0);
+ getbits(ou, 1);
+ getbits(ex, 2);
+#undef getbits
+ if (nbufbytes != 0)
+ memset(selbits, 0, nbufbytes / 2);
+
+ if (tv) {
+ timo = tv->tv_usec + (tv->tv_sec * 1000000);
+ forever = 0;
+ } else {
+ timo = 0;
+ forever = 1;
+ }
+
+ /*
+ * Poll for I/O events
+ */
+ nselected = 0;
+ do {
+ /*
+ * Scan for pending I/O
+ */
+ error = selscan(ibits, obits, nd, &nselected);
+ if (error || nselected)
+ break;
+
+ /*
+ * Adjust timeout is needed
+ */
+ if (timo) {
+ /*
+ * Give it a rest
+ */
+ usleep( _SELECT_DELAY_ );
+ timo -= _SELECT_DELAY_;
+ }
+
+ } while (timo > 0 || forever);
+
+ /* select is not restarted after signals... */
+ if (error == ERESTART)
+ error = EINTR;
+ else if (error == EWOULDBLOCK)
+ error = 0;
+
+#define putbits(name, x) if (name) bcopy(obits[x], name, ncpbytes)
+ if (error == 0) {
+ putbits(in, 0);
+ putbits(ou, 1);
+ putbits(ex, 2);
+#undef putbits
+ } else {
+ errno = error;
+ nselected = -1;
+ }
+
+ free( selbits );
+ return ( nselected );
+}
diff --git a/StdLib/LibC/Uefi/writev.c b/StdLib/LibC/Uefi/writev.c
new file mode 100644
index 0000000000..9cff086c6a
--- /dev/null
+++ b/StdLib/LibC/Uefi/writev.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software must
+ * display the following acknowledgement:
+ *
+ * This product includes software developed by Intel Corporation and its
+ * contributors.
+ *
+ * 4. Neither the name of Intel Corporation or its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*++
+
+Module Name:
+
+ writev.c
+
+Abstract:
+
+ Functions implementing the standard "writev" system call interface
+
+
+Revision History
+
+--*/
+#include <LibConfig.h>
+
+#ifdef foo
+#include <efi_interface.h>
+#include <unistd.h>
+#include <fcntl.h>
+#define KERNEL
+#include <errno.h>
+#undef KERNEL
+#include "./filedesc.h"
+
+#include <libc_debug.h>
+#include <assert.h>
+#endif
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/uio.h>
+#include <string.h>
+#ifndef KERNEL
+#define KERNEL
+#include <errno.h>
+#undef KERNEL
+#else
+#include <errno.h>
+#endif
+
+//
+// Name:
+// writev
+//
+// Description:
+// BSD writev interface for libc
+//
+// Arguments:
+// File Descriptor (index into file descriptor table)
+// iovec pointer
+// size of iovec array
+//
+// Returns:
+// number of bytes written
+//
+
+ssize_t
+writev(
+ int fd,
+ const struct iovec *iov,
+ int iovcnt
+ )
+{
+ const struct iovec *pVecTmp;
+ char *pBuf, *pBufTmp;
+ size_t TotalBytes, i, ret;
+
+ //
+ // See how much memory we'll need
+ //
+
+ for (i = 0, TotalBytes = 0, pVecTmp = iov; i < (size_t)iovcnt; i++, pVecTmp++) {
+ TotalBytes += pVecTmp->iov_len;
+ }
+
+ //
+ // Allocate a contiguous buffer
+ //
+
+ pBuf = (char*)malloc (TotalBytes);
+ if (pBuf == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ //
+ // Copy vectors to the buffer
+ //
+
+ for (pBufTmp = pBuf; iovcnt; iovcnt--) {
+ bcopy(iov->iov_base, pBuf, iov->iov_len);
+ pBuf += iov->iov_len;
+ iov++;
+ }
+
+ //
+ // Use standard write(2) then free buffer
+ //
+
+ ret = write (fd, pBuf, TotalBytes);
+ free (pBuf);
+
+ return (ret);
+}