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-

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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<EFBFBD>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<EFBFBD>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<EFBFBD>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));
}

View File

@@ -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

847
StdLib/LibC/Uefi/compat.c Normal file
View File

@@ -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 */

256
StdLib/LibC/Uefi/select.c Normal file
View File

@@ -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 );
}

143
StdLib/LibC/Uefi/writev.c Normal file
View File

@@ -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);
}