lsiutil/source/helper.c

1242 lines
26 KiB
C
Executable File

/***************************************************************************
* *
* Copyright 2012 LSI Corporation. All rights reserved. *
* *
* This file is confidential and a trade secret of LSI Corporation. The *
* receipt of or possession of this file does not convey any rights to *
* reproduce or disclose its contents or to manufacture, use, or sell *
* anything it may describe, in whole, or in part, without the specific *
* written consent of LSI Corporation. *
* *
***************************************************************************
*/
/*
* helper -- EFI helper routines commonly found in a CRTL
*
* Written by Stephen F. Shirron, September 15, 2006
*/
EFI_STATUS last_efi_status;
int errno;
int optind;
char *optarg;
EFI_HANDLE gImageHandle;
EFI_LOADED_IMAGE *gLoadedImage;
EFI_EVENT gSleepEvent;
size_t strlen(const char *s)
{
const char *c = s;
while (*c++);
return c - s - 1;
}
char *strcpy(char *s1, const char *s2)
{
char *c1 = s1;
const char *c2 = s2;
while (*c1++ = *c2++);
return s1;
}
char *strncpy(char *s1, const char *s2, size_t n)
{
unsigned char *c1 = s1;
const char *c2 = s2;
size_t t = 0;
while (t++ < n && (*c1++ = *c2++));
while (t++ < n) *c1++ = 0;
return s1;
}
char *strcat(char *s1, const char *s2)
{
char *c1 = s1;
const char *c2 = s2;
while (*c1) c1++;
while (*c1++ = *c2++);
return s1;
}
char *strncat(char *s1, const char *s2, size_t n)
{
char *c1 = s1;
const char *c2 = s2;
size_t t;
while (*c1) c1++;
t = 0;
while (t++ < n && (*c1++ = *c2++));
if (t >= n && *(c1-1)) *c1 = 0;
return s1;
}
char *strchr(const char *s1, int t)
{
while (*s1) if (*s1++ == t) return (char *)--s1;
return NULL;
}
int strcmp(const char *s1, const char *s2)
{
while (*s1 && *s1 == *s2) s1++, s2++;
if (*s1 < *s2) return -1;
if (*s1 > *s2) return 1;
return 0;
}
int strncmp(const char *s1, const char *s2, size_t n)
{
while (n && *s1 && *s1 == *s2) n--, s1++, s2++;
if (n == 0) return 0;
if (*s1 < *s2) return -1;
if (*s1 > *s2) return 1;
return 0;
}
int toupper(int c)
{
if (c >= 'a' && c <= 'z') return c - 'a' + 'A';
return c;
}
int tolower(int c)
{
if (c >= 'A' && c <= 'Z') return c - 'A' + 'a';
return c;
}
int strcasecmp(const char *s1, const char *s2)
{
while (*s1 && tolower(*s1) == tolower(*s2)) s1++, s2++;
if (tolower(*s1) < tolower(*s2)) return -1;
if (tolower(*s1) > tolower(*s2)) return 1;
return 0;
}
int strncasecmp(const char *s1, const char *s2, size_t n)
{
while (n && *s1 && tolower(*s1) == tolower(*s2)) n--, s1++, s2++;
if (n == 0) return 0;
if (tolower(*s1) < tolower(*s2)) return -1;
if (tolower(*s1) > tolower(*s2)) return 1;
return 0;
}
void *memset(void *s, int t, size_t n)
{
char *c = s;
while (n) n--, *c++ = t;
return s;
}
void *memcpy(void *s2, const void *s1, size_t n)
{
const char *c1 = s1;
char *c2 = s2;
while (n) n--, *c2++ = *c1++;
return s2;
}
int memcmp(const void *s1, const void *s2, size_t n)
{
const char *c1 = s1;
const char *c2 = s2;
while (n && *c1 == *c2) n--, c1++, c2++;
if (n == 0) return 0;
if (*c1 < *c2) return -1;
if (*c1 > *c2) return 1;
return 0;
}
void bzero(void *s, size_t n)
{
char *c = s;
while (n)
{
*c++ = 0;
n--;
}
}
void bcopy(const void *s1, void *s2, size_t n)
{
const char *c1 = s1;
char *c2 = s2;
while (n)
{
*c2++ = *c1++;
n--;
}
}
int isdigit(int c)
{
if (c >= '0' && c <= '9') return 1;
return 0;
}
int isxdigit(int c)
{
if (c >= '0' && c <= '9') return 1;
if (c >= 'a' && c <= 'f') return 1;
if (c >= 'A' && c <= 'F') return 1;
return 0;
}
int isalpha(int c)
{
if (c >= 'a' && c <= 'z') return 1;
if (c >= 'A' && c <= 'Z') return 1;
return 0;
}
int isalnum(int c)
{
if (c >= '0' && c <= '9') return 1;
if (c >= 'a' && c <= 'z') return 1;
if (c >= 'A' && c <= 'Z') return 1;
return 0;
}
int isprint(int c)
{
if (c >= ' ' && c <= '~') return 1;
return 0;
}
void *malloc(size_t size)
{
return AllocatePool(size);
}
void *realloc(void *oldp, size_t size)
{
void *newp = malloc(size);
memcpy(newp, oldp, size);
free(oldp);
return newp;
}
void free(void *p)
{
FreePool(p);
}
static void convert_unicode_ascii(const CHAR16 *s1, char *s2, int n)
{
int i;
char c;
for (i = 0; i < n; i++)
{
c = (char)*s1++;
*s2++ = c;
if (c == 0)
break;
}
}
static int convert_dtoi(const char *s, int *r, int w)
{
int n = 0;
char c;
*r = 0;
while (isdigit(c = *s++))
{
*r *= 10;
*r += c - '0';
n++;
if (n == w)
return n;
}
return n;
}
static int convert_xtoi(const char *s, int *r, int w)
{
int n = 0;
char c;
*r = 0;
while (isxdigit(c = *s++))
{
*r *= 16;
if (isdigit(c))
*r += c - '0';
else
*r += tolower(c) - 'a' + 10;
n++;
if (n == w)
return n;
}
return n;
}
static int convert_itod(char *s, int64_t r)
{
char c;
char buffer[32];
int i;
int n = 0;
int negative = 0;
if (r < 0)
{
r = -r;
*s++ = '-';
negative = 1;
}
do
{
c = (char)(r % 10);
r /= 10;
buffer[n] = c + '0';
n++;
}
while (r);
for (i = 0; i < n; i++)
s[i] = buffer[n - i - 1];
s[n] = 0;
return n + negative;
}
static int convert_itox(char *s, uint64_t r)
{
char c;
char buffer[32];
int i;
int n = 0;
uint64_t r0 = r;
do
{
c = (char)(r % 16);
r /= 16;
if (c < 10)
buffer[n] = c + '0';
else
buffer[n] = c + 'a' - 10;
n++;
}
while (r);
for (i = 0; i < n; i++)
s[i] = buffer[n - i - 1];
s[n] = 0;
return n;
}
char *fgets(char *s, int size, FILE *stream)
{
CHAR16 buffer[256];
if (stream == stdin)
{
Input(NULL, buffer, sizeof buffer / 2);
convert_unicode_ascii(buffer, s, size);
APrint("\n");
return s;
}
printf("fgets from a file not implemented yet!\n");
return NULL;
}
int sscanf(const char *s, const char *format, ...)
{
va_list args;
char c;
int n = 0;
int w;
char *as;
int *ad;
int *ax;
int t;
const char *b;
va_start(args, format);
b = s;
while ((c = *format++))
{
while (*s == ' ')
*s++;
if (c == '%')
{
c = *format++;
w = 0;
if (isdigit(c))
{
format += convert_dtoi(--format, &w, 0);
c = *format++;
}
if (!c)
break;
switch (c)
{
case 's':
if (!*s)
break;
as = va_arg(args, char *);
while ((c = *s))
{
s++;
if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
break;
*as++ = c;
}
*as = 0;
n++;
break;
case 'c':
if (!*s)
break;
as = va_arg(args, char *);
*as = *s++;
n++;
break;
case 'd':
if (!*s)
break;
ad = va_arg(args, int *);
t = convert_dtoi(s, ad, w);
if (t)
{
s += t;
n++;
}
break;
case 'x':
if (!*s)
break;
ax = va_arg(args, int *);
t = convert_xtoi(s, ax, w);
if (t)
{
s += t;
n++;
}
break;
case 'n':
ad = va_arg(args, int *);
*ad = (int)(s - b);
break;
}
}
else if (c != ' ')
{
if (*s++ != c)
break;
}
}
va_end(args);
return n;
}
int vsprintf(char *s1, const char *format, va_list args)
{
char c;
char *s;
char s2[256];
char b[32];
int len;
int n = 0;
int t = 0;
int i;
int w;
char ac;
char *as;
int64_t ad;
int64_t ax;
#if !EFIEBC
double af;
#endif
int left;
char pad;
int minw;
int maxw;
int longint;
if (!s1)
s = s2;
else
s = s1;
while ((c = *format++))
{
if (c == '%')
{
c = *format++;
left = 0;
pad = ' ';
minw = 1;
maxw = 100;
longint = 0;
if (c == '-')
{
left = 1;
c = *format++;
}
if (c == '0')
{
pad = '0';
c = *format++;
}
if (isdigit(c))
{
format += convert_dtoi(--format, &minw, 0);
c = *format++;
}
if (c == '.')
{
c = *format++;
if (isdigit(c))
{
format += convert_dtoi(--format, &maxw, 0);
c = *format++;
}
}
if (c == 'l')
{
c = *format++;
if (c == 'l')
c = *format++;
longint = 1;
}
if (!c)
break;
switch (c)
{
case 'c':
ac = (char)va_arg(args, int);
b[0] = ac;
b[1] = 0;
as = b;
break;
case 's':
as = va_arg(args, char *);
break;
case 'd':
if (longint)
ad = (int64_t)va_arg(args, int64_t);
else
ad = (int)va_arg(args, int);
convert_itod(b, ad);
as = b;
break;
case 'x':
if (longint)
ax = (uint64_t)va_arg(args, uint64_t);
else
ax = (unsigned int)va_arg(args, unsigned int);
convert_itox(b, ax);
as = b;
break;
case 'X':
if (longint)
ax = (uint64_t)va_arg(args, uint64_t);
else
ax = (unsigned int)va_arg(args, unsigned int);
convert_itox(b, ax);
for (i = 0; i < (int)strlen(b); i++)
b[i] = toupper(b[i]);
as = b;
break;
case 'p':
ax = (uint64_t)va_arg(args, void *);
convert_itox(b, ax);
as = b;
break;
#if !EFIEBC
case 'f':
af = (double)va_arg(args, double);
for (i = 0, ax = 1; i < maxw; i++, ax *= 10);
ad = (int64_t)(af * ax + 0.5);
convert_itod(b, ad);
if (maxw)
{
len = (int)strlen(b);
if (len < maxw + 1)
{
for (i = maxw + 1; i > maxw - len; i--)
b[i] = b[i-maxw-1+len];
for (i = 0; i < maxw + 1 - len; i++)
b[i] = '0';
len = maxw + 1;
}
for (i = len + 1; i > len - maxw; i--)
b[i] = b[i-1];
b[i] = '.';
}
as = b;
maxw = 100;
break;
#endif
default:
s[n++] = c;
as = NULL;
minw = 0;
break;
}
if (minw)
{
len = (int)strlen(as);
if (as != b)
{
if (len > maxw)
len = maxw;
}
w = minw - len;
if (!left && w > 0)
{
memset(s + n, pad, w);
n += w;
}
memcpy(s + n, as, len);
n += len;
if (left && w > 0)
{
memset(s + n, pad, w);
n += w;
}
}
}
else
{
s[n++] = c;
}
if (c == '\n' && !s1)
{
s[n] = 0;
t += n;
if (n)
APrint("%a", s);
n = 0;
}
}
s[n] = 0;
t += n;
if (n && !s1)
APrint("%a", s);
return n;
}
#if sfs
int printf(const char *format, ...)
{
va_list args;
int n;
va_start(args, format);
n = vsprintf(NULL, format, args);
va_end(args);
return n;
}
#endif
int sprintf(char *s, const char *format, ...)
{
va_list args;
int n;
va_start(args, format);
n = vsprintf(s, format, args);
va_end(args);
return n;
}
#define MAX_HANDLES 32
EFI_FILE_HANDLE gFileHandles[MAX_HANDLES];
FILE *fopen(const char *name, const char *mode)
{
int flags;
int fd;
if (strchr(mode, 'r'))
flags = O_RDONLY;
else if (strchr(mode, 'w'))
flags = O_RDWR | O_CREAT | O_TRUNC;
else if (strchr(mode, 'a'))
flags = O_RDWR | O_CREAT;
fd = open(name, flags);
if (fd < 0)
return NULL;
return (FILE *)fd;
}
int fclose(FILE *stream)
{
return close((int)stream);
}
#if sfs
int fprintf(FILE *stream, const char *format, ...)
{
va_list args;
char *s;
char s2[256];
int n;
if (stream == stdout || stream == stderr)
s = NULL;
else
s = s2;
va_start(args, format);
n = vsprintf(s, format, args);
va_end(args);
if (s)
n = write((int)stream, s, n);
return n;
}
#endif
int fflush(FILE *stream)
{
EFI_FILE_HANDLE file;
EFI_STATUS status;
int fd = (int)stream;
if (fd < 4)
return -1;
fd -= 4;
if (fd > MAX_HANDLES)
return -1;
file = gFileHandles[fd];
if (!file)
return -1;
status = file->Flush(file);
if (EFI_ERROR(status))
{
last_efi_status = status;
printf("Flush failed!\n");
}
return 0;
}
int fputs(const char *s, FILE *stream)
{
int n;
n = (int)strlen(s);
if (stream == stdout || stream == stderr)
APrint("%a", s);
else
write((int)stream, s, n);
return n;
}
int fputc(int c, FILE *stream)
{
if (stream == stdout || stream == stderr)
APrint("%c", (UINTN)c);
else
write((int)stream, (void *)&c, 1);
return 1;
}
int open(const char *name, int flags, ...)
{
EFI_FILE_IO_INTERFACE *fileIo;
EFI_FILE_HANDLE root;
EFI_FILE_HANDLE file;
EFI_FILE_INFO *info;
EFI_GUID SimpleFileSystemProtocol = SIMPLE_FILE_SYSTEM_PROTOCOL;
EFI_STATUS status;
CHAR16 *path;
CHAR16 filename[128];
UINTN i;
UINT64 mode;
int fd;
for (fd = 0; fd < MAX_HANDLES; fd++)
if (!gFileHandles[fd])
break;
if (fd == MAX_HANDLES)
return -1;
if (*name == '.' || (isalnum(*name) && !strchr(name, ':')))
{
path = DevicePathToStr(gLoadedImage->FilePath);
// APrint("loaded image = <%s>\n", path);
for (i = StrLen(path) - 1; i > 0; i--)
if (path[i] == L'/')
break;
// if the path contains "/." at the end, remove it
if (i >= 2 && path[i-2] == '/' && path[i-1] == '.')
i -= 2;
// if the path doesn't end with "\", add one
if (!(i >= 1 && path[i-1] == '\\'))
path[i++] = '\\';
// throw away the rest of the string
path[i] = 0;
StrCpy(filename, path);
FreePool(path);
} else
filename[0] = 0;
for (i = StrLen(filename); *name; i++)
filename[i] = (CHAR16)*name++;
filename[i] = 0;
// APrint("filename = <%s>\n", filename);
status = BS->HandleProtocol(gLoadedImage->DeviceHandle,
&SimpleFileSystemProtocol, &fileIo);
if (EFI_ERROR(status))
{
last_efi_status = status;
printf("HandleProtocol(SimpleFileSystem) failed!\n");
return -1;
}
status = fileIo->OpenVolume(fileIo, &root);
if (EFI_ERROR(status))
{
last_efi_status = status;
printf("OpenVolume failed!\n");
return -1;
}
mode = EFI_FILE_MODE_READ;
if (flags & O_RDWR)
mode |= EFI_FILE_MODE_WRITE;
if (flags & O_CREAT)
mode |= EFI_FILE_MODE_CREATE;
status = root->Open(root, &file, filename, mode, 0);
if (EFI_ERROR(status))
{
last_efi_status = status;
APrint("Open of <%s> failed!\n", filename);
return -1;
}
if (flags & O_CREAT)
{
info = LibFileInfo(file);
if (info)
{
if (flags & O_TRUNC)
{
info->FileSize = 0;
info->PhysicalSize = 0;
status = file->SetInfo(file, &GenericFileInfo, (UINTN)info->Size, info);
if (EFI_ERROR(status))
{
last_efi_status = status;
APrint("SetInfo of <%s> failed!\n", filename);
}
}
else
{
status = file->SetPosition(file, info->FileSize);
if (EFI_ERROR(status))
{
last_efi_status = status;
APrint("SetPosition of <%s> failed!\n", filename);
}
}
FreePool(info);
}
}
gFileHandles[fd] = file;
fd += 4;
return fd;
}
int close(int fd)
{
EFI_FILE_HANDLE file;
EFI_STATUS status;
if (fd < 4)
return -1;
fd -= 4;
if (fd > MAX_HANDLES)
return -1;
file = gFileHandles[fd];
if (!file)
return -1;
status = file->Close(file);
if (EFI_ERROR(status))
{
last_efi_status = status;
printf("Close failed!\n");
}
return 0;
}
ssize_t read(int fd, void *buf, size_t count)
{
EFI_FILE_HANDLE file;
EFI_STATUS status;
UINTN size = count;
if (fd < 4)
return -1;
fd -= 4;
if (fd > MAX_HANDLES)
return -1;
file = gFileHandles[fd];
if (!file)
return -1;
status = file->Read(file, &size, buf);
if (EFI_ERROR(status))
{
last_efi_status = status;
printf("Read failed!\n");
return -1;
}
return (ssize_t)size;
}
ssize_t write(int fd, const void *buf, size_t count)
{
EFI_FILE_HANDLE file;
EFI_STATUS status;
UINTN size = count;
if (fd < 4)
return -1;
fd -= 4;
if (fd > MAX_HANDLES)
return -1;
file = gFileHandles[fd];
if (!file)
return -1;
status = file->Write(file, &size, (void *)buf);
if (EFI_ERROR(status))
{
last_efi_status = status;
printf("Write failed!\n");
return -1;
}
return (ssize_t)size;
}
int fstat(int fd, struct stat *buf)
{
EFI_FILE_HANDLE file;
EFI_FILE_INFO *info;
if (fd < 4)
return -1;
fd -= 4;
if (fd > MAX_HANDLES)
return -1;
file = gFileHandles[fd];
if (!file)
return -1;
info = LibFileInfo(file);
if (!info)
{
printf("GetInfo failed!\n");
return -1;
}
buf->st_size = (size_t)info->FileSize;
FreePool(info);
return 0;
}
static int rand_seed = 152L;
int rand(void)
{
rand_seed = rand_seed * 69069L + 1;
return ((rand_seed >> 16) + (rand_seed << 16));
}
void perror(const char *s)
{
if (s && *s)
APrint("%a: ", s);
APrint("%r\n", last_efi_status);
}
static int dpm[] = {
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
};
#ifndef DISABLE_TIMEOUTS
time_t time(time_t *t)
{
EFI_TIME et;
time_t local_t;
int days;
RT->GetTime(&et, NULL);
days = dpm[et.Month - 1] + et.Day - 1;
if (et.Year >= 1970)
{
days += (et.Year - 1970) * 365;
// all modulo-4 years since 1970 are leap years, up until 2100
days += (et.Year - 1969) / 4;
}
local_t = ((days * 24 + et.Hour) * 60 + et.Minute) * 60 + et.Second;
if (t)
*t = local_t;
return local_t;
}
#endif
static const char *day_name[] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
static const char *mon_name[] = {
"Mar", "Apr", "May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec", "Jan", "Feb"
};
static const int days_per[12] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
static char ctime_result[26];
char *ctime(const time_t *seconds)
{
int f, k, m, D, C, d; // going to use Zeller's Rule to derive the weekday
int days, leap, year, month, day, hours, mins, secs, t;
days = *seconds / 86400;
t = days;
year = 1970;
// if it's already past 2004, get that out of the way quick
if (t >= 12418)
{
t -= 12418;
year += 34;
}
for (; ; year++)
{
// this simple rule is good until 2100
leap = (year % 4) == 0;
if (t < 365 + leap)
break;
t -= 365 + leap;
}
month = 0;
// if it's already past June, get that out of the way quick
if (t >= 181 + leap)
{
t -= 181 + leap;
month += 6;
}
for (; ; month++)
{
if (t < days_per[month])
break;
t -= days_per[month];
if (month == 1)
{
if (t < leap)
break;
t -= leap;
}
}
day = t + 1;
t = *seconds - days * 86400;
hours = t / 3600;
t -= hours * 3600;
mins = t / 60;
t -= mins * 60;
secs = t;
k = day;
m = month - 1;
D = year % 100;
C = year / 100;
if (m < 1)
{
m += 12;
D -= 1;
}
f = k + (13*m-1)/5 + D + D/4 + C/4 - 2*C;
d = f % 7;
if (d < 0)
d += 7;
sprintf(ctime_result, "%.3s %.3s%3d %02d:%02d:%02d %d\n",
day_name[d], mon_name[m-1],
day, hours, mins, secs, year);
return ctime_result;
}
VOID EfiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
EFI_TIME et;
EFI_STATUS status;
int i;
int argc;
char **argv;
int n;
InitializeShellApplication(ImageHandle, SystemTable);
gImageHandle = ImageHandle;
status = BS->HandleProtocol(gImageHandle, &LoadedImageProtocol, &gLoadedImage);
if (EFI_ERROR(status))
{
last_efi_status = status;
printf("HandleProtocol(LoadedImage) failed!\n");
gLoadedImage = NULL;
}
status = BS->CreateEvent(EVT_TIMER, 0, NULL, NULL, &gSleepEvent);
if (EFI_ERROR(status))
gSleepEvent = NULL;
RT->GetTime(&et, NULL);
if (et.Year % 4 == 0 && et.Year % 100 != 0 && et.Year % 400 == 0)
dpm[3]++;
argc = (int)SI->Argc;
argv = malloc(sizeof argv * argc);
for (i = 0; i < argc; i++)
{
n = (int)StrLen(SI->Argv[i]) + 1;
argv[i] = malloc(n);
convert_unicode_ascii(SI->Argv[i], argv[i], n);
}
main(argc, argv);
}
void exit(int status)
{
if (gSleepEvent)
BS->CloseEvent(gSleepEvent);
if (status == 0)
BS->Exit(gImageHandle, EFI_SUCCESS, 0, NULL);
else
BS->Exit(gImageHandle, EFIERR_OEM(status), 0, NULL);
}
unsigned int sleep(unsigned int seconds)
{
UINTN unused;
if (gSleepEvent)
{
BS->SetTimer(gSleepEvent, TimerRelative, seconds * 10000000);
BS->WaitForEvent(1, &gSleepEvent, &unused);
}
else
{
BS->Stall(seconds * 1000000);
}
return 0;
}
void mdelay(int milliseconds)
{
BS->Stall(milliseconds * 1000);
}
void udelay(int microseconds)
{
BS->Stall(microseconds);
}
int _fltused;
#include "getopt.c"
/* vi: set sw=4 ts=4 sts=4 et :iv */