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