#include #include #include #include #include #include // EDK2 CRT Support Header #include // Global variables required by CrtLibSupport.h int errno = 0; FILE *stderr = NULL; // Better malloc/free with size tracking typedef struct { size_t size; char data[]; } AllocHeader; void *my_malloc(size_t size) { AllocHeader *hdr; if (gBS->AllocatePool(EfiLoaderData, size + sizeof(AllocHeader), (void**)&hdr) != EFI_SUCCESS) { return NULL; } hdr->size = size; return hdr->data; } void my_free(void *ptr) { if (ptr) { AllocHeader *hdr = (AllocHeader*)((char*)ptr - sizeof(AllocHeader)); gBS->FreePool(hdr); } } void *my_realloc(void *ptr, size_t size) { if (!ptr) return my_malloc(size); if (size == 0) { my_free(ptr); return NULL; } AllocHeader *old_hdr = (AllocHeader*)((char*)ptr - sizeof(AllocHeader)); size_t old_size = old_hdr->size; void *new_ptr = my_malloc(size); if (!new_ptr) return NULL; CopyMem(new_ptr, ptr, old_size < size ? old_size : size); my_free(ptr); return new_ptr; } // Redirect standard malloc/free/realloc to our versions #undef malloc #undef free #undef realloc void *malloc(size_t size) { return my_malloc(size); } void free(void *ptr) { my_free(ptr); } void *realloc(void *ptr, size_t size) { return my_realloc(ptr, size); } void *calloc(size_t nmemb, size_t size) { size_t total = nmemb * size; void *ptr = malloc(total); if (ptr) { SetMem(ptr, total, 0); } return ptr; } // IO int printf(const char *format, ...) { return 0; } int vsnprintf(char *str, size_t size, const char *format, va_list ap) { return (int)AsciiVSPrint(str, size, format, ap); } int snprintf(char *str, size_t size, const char *format, ...) { VA_LIST Marker; VA_START(Marker, format); UINTN Return = AsciiVSPrint(str, size, format, Marker); VA_END(Marker); return (int)Return; } // sprintf is a macro in CrtLibSupport.h, so we don't define it. // Math // Duktape needs math. EDK2 doesn't provide standard math lib. // We might need to implement simple versions or pull in a math lib. // For now, stubs. double floor(double x) { return (double)(int)x; } // Very wrong for negative/large double ceil(double x) { return (double)(int)x + 1; } double fabs(double x) { return x < 0 ? -x : x; } double pow(double x, double y) { return 0; } // TODO double sqrt(double x) { return 0; } double sin(double x) { return 0; } double cos(double x) { return 0; } double tan(double x) { return 0; } double asin(double x) { return 0; } double acos(double x) { return 0; } double atan(double x) { return 0; } double atan2(double y, double x) { return 0; } double exp(double x) { return 0; } double log(double x) { return 0; } double log10(double x) { return 0; } double fmod(double x, double y) { return 0; } // Other void abort(void) { // CpuDeadLoop(); while(1); } void exit(int status) { // CpuDeadLoop(); while(1); } // Global gBS EFI_BOOT_SERVICES *gBS = NULL; int _fltused = 0; // Stack probe (needed for MSVC ABI) void __chkstk(void) { return; } // Memory functions #undef memset #undef memcpy #undef memcmp void *memset(void *s, int c, size_t n) { unsigned char *p = s; while (n--) { *p++ = (unsigned char)c; } return s; } void *memcpy(void *dest, const void *src, size_t n) { char *d = dest; const char *s = src; while (n--) { *d++ = *s++; } return dest; } int memcmp(const void *s1, const void *s2, size_t n) { const unsigned char *p1 = s1, *p2 = s2; while (n--) { if (*p1 != *p2) { return *p1 - *p2; } p1++; p2++; } return 0; } void *SetMem(void *Buffer, UINTN Length, UINT8 Value) { return memset(Buffer, Value, Length); } void *CopyMem(void *Destination, const void *Source, UINTN Length) { return memcpy(Destination, Source, Length); } INTN CompareMem(const void *Destination, const void *Source, UINTN Length) { return (INTN)memcmp(Destination, Source, Length); } // String functions UINTN AsciiStrnLenS(const CHAR8 *String, UINTN MaxSize) { UINTN len = 0; while (len < MaxSize && String[len] != 0) { len++; } return len; } INTN AsciiStrnCmp(const CHAR8 *FirstString, const CHAR8 *SecondString, UINTN Length) { if (Length == 0) return 0; while (Length > 0 && *FirstString && *SecondString) { if (*FirstString != *SecondString) break; FirstString++; SecondString++; Length--; } if (Length == 0) return 0; return *FirstString - *SecondString; } int strcmp(const char *s1, const char *s2) { while (*s1 && (*s1 == *s2)) { s1++; s2++; } return *(const unsigned char *)s1 - *(const unsigned char *)s2; } // Print functions // Minimal vsnprintf implementation #include static void simple_append(char **str, size_t *size, char c) { if (*size > 1) { **str = c; (*str)++; (*size)--; } } static void simple_append_str(char **str, size_t *size, const char *s) { while (*s) { simple_append(str, size, *s++); } } static void simple_append_hex(char **str, size_t *size, UINT64 num) { char buf[17]; const char *digits = "0123456789ABCDEF"; int i = 0; if (num == 0) { simple_append(str, size, '0'); return; } while (num > 0) { buf[i++] = digits[num % 16]; num /= 16; } while (i > 0) { simple_append(str, size, buf[--i]); } } static void simple_append_dec(char **str, size_t *size, INT64 num) { char buf[21]; int i = 0; int neg = 0; if (num < 0) { neg = 1; num = -num; } if (num == 0) { simple_append(str, size, '0'); return; } while (num > 0) { buf[i++] = (num % 10) + '0'; num /= 10; } if (neg) simple_append(str, size, '-'); while (i > 0) { simple_append(str, size, buf[--i]); } } UINTN AsciiVSPrint(CHAR8 *StartOfBuffer, UINTN BufferSize, CONST CHAR8 *FormatString, VA_LIST Marker) { char *str = StartOfBuffer; size_t size = BufferSize; const char *fmt = FormatString; while (*fmt) { if (*fmt == '%') { fmt++; if (*fmt == 's') { char *s = VA_ARG(Marker, char*); simple_append_str(&str, &size, s ? s : "(null)"); } else if (*fmt == 'd') { int d = VA_ARG(Marker, int); simple_append_dec(&str, &size, d); } else if (*fmt == 'x' || *fmt == 'X') { unsigned int x = VA_ARG(Marker, unsigned int); simple_append_hex(&str, &size, x); } else if (*fmt == 'p') { void *p = VA_ARG(Marker, void*); simple_append_hex(&str, &size, (UINT64)p); } else if (*fmt == '%') { simple_append(&str, &size, '%'); } else { simple_append(&str, &size, '%'); simple_append(&str, &size, *fmt); } } else { simple_append(&str, &size, *fmt); } fmt++; } *str = 0; return (UINTN)(str - StartOfBuffer); } UINTN AsciiSPrint(CHAR8 *StartOfBuffer, UINTN BufferSize, CONST CHAR8 *FormatString, ...) { VA_LIST Marker; VA_START(Marker, FormatString); UINTN ret = AsciiVSPrint(StartOfBuffer, BufferSize, FormatString, Marker); VA_END(Marker); return ret; } // Time functions struct tm *gmtime(const time_t *timep) { return NULL; } time_t mktime(struct tm *tm) { return 0; } int sscanf(const char *str, const char *format, ...) { return 0; } time_t time(time_t *tloc) { return 0; } double difftime(time_t time1, time_t time0) { return (double)(time1 - time0); } double cbrt(double x) { return 0; } double log2(double x) { return 0; } double trunc(double x) { return (double)(int)x; } // Needed for CrtLibSupport headers to work? // They use VA_LIST etc which are in Base.h