8#define FONT8X16_IMPLEMENTATION
19static inline bool gop_params_valid(
const GOP_PARAMS* gop) {
20 if (!gop)
return false;
22 if (gop->
Width == 0 || gop->
Height == 0)
return false;
27static inline void plot_pixel(
GOP_PARAMS* gop, uint32_t x, uint32_t y, uint32_t color) {
28 if (!gop_params_valid(gop))
return;
32 fb[y * stride + x] = color;
35static inline uint32_t char_width(
void) {
return 8 *
FONT_SCALE; }
36static inline uint32_t line_height(
void) {
return 16 *
FONT_SCALE; }
42static void draw_char(
GOP_PARAMS* gop,
char c_, uint32_t x, uint32_t y, uint32_t color) {
43 uint8_t c = (uint8_t)c_;
47 for (
int row = 0; row < 16; row++) {
48 uint8_t bits = bitmap[row];
49 for (
int col = 0; col < 8; col++) {
51 if (!(bits & (1 << (7 - col))))
57 if (py >= gop->
Height)
continue;
60 if (px < gop->Width) {
63 if (px < gop->Width && py < gop->Height) plot_pixel(gop, px, py, color);
64 if ((px + 1) < gop->
Width && py < gop->Height) plot_pixel(gop, px + 1, py, color);
65 if (px < gop->Width && (py + 1) < gop->
Height) plot_pixel(gop, px, py + 1, color);
66 if ((px + 1) < gop->
Width && (py + 1) < gop->
Height) plot_pixel(gop, px + 1, py + 1, color);
69 plot_pixel(gop, px, py, color);
78static void draw_string(
GOP_PARAMS* gop,
const char* s, uint32_t x, uint32_t y, uint32_t color) {
80 draw_char(gop, *s, x, y, color);
86static void fb_memmove32(uint32_t* dest, uint32_t* src,
size_t count) {
89 for (
size_t i = 0; i < count; i++) dest[i] = src[i];
91 else if (dest > src) {
93 for (
size_t i = count; i-- > 0; ) dest[i] = src[i];
101 uint32_t w = gop->
Width;
102 uint32_t lines = line_height();
105 size_t count = (
h - lines) * (
size_t)stride;
106 fb_memmove32(&fb[0], &fb[lines * stride], count);
109 for (uint32_t yy =
h - lines; yy <
h; yy++)
110 for (uint32_t xx = 0; xx < w; xx++)
111 fb[yy * stride + xx] = 0;
116static void gop_put_char(
GOP_PARAMS* gop,
char c, uint32_t color) {
117 if (!gop_params_valid(gop))
return;
133 plot_pixel(gop, xx, yy, color);
158static void gop_puts(
GOP_PARAMS* gop,
const char* s, uint32_t color) {
160 gop_put_char(gop, *s++, color);
164static void sprint_dec(
char* buf, int64_t v) {
183 tmp[i++] =
'0' + (v % 10);
197static void gop_print_dec(
GOP_PARAMS* gop, int64_t val, uint32_t color) {
199 sprint_dec(buf, val);
200 gop_puts(gop, buf, color);
203static void buf_print_udec64(
char* buf,
size_t size,
size_t* written, uint64_t value);
204static void gop_print_udec(
GOP_PARAMS* gop, uint64_t val, uint32_t color) {
207 buf_print_udec64(buf,
sizeof(buf), &written, val);
208 gop_puts(gop, buf, color);
211static void gop_print_hex(
GOP_PARAMS* gop, uint64_t val, uint32_t color) {
212 char buf[19] =
"0x0000000000000000";
213 for (
int i = 0; i < 16; i++) {
214 unsigned nib = (val >> ((15 - i) * 4)) & 0xF;
215 buf[2 + i] = (nib < 10 ?
'0' + nib :
'a' + nib - 10);
218 gop_puts(gop, buf, color);
221static void gop_print_hex_minimal(
GOP_PARAMS* gop, uint64_t val, uint32_t color) {
223 gop_puts(gop,
"0x0", color);
232 bool started =
false;
234 for (
int i = 0; i < 16; i++) {
235 unsigned nib = (val >> ((15 - i) * 4)) & 0xF;
236 if (nib != 0 || started) {
238 buf[pos++] = (nib < 10 ?
'0' + nib :
'a' + nib - 10);
243 gop_puts(gop, buf, color);
250 for (uint32_t y = 0; y < gop->
Height; y++)
251 for (uint32_t x = 0; x < gop->
Width; x++)
252 plot_pixel(gop, x, y, color);
255static inline void buf_put_char(
char* buf,
size_t size,
size_t* written,
char c) {
256 if (size > 0 && *written + 1 < size) {
262static void buf_puts(
char* buf,
size_t size,
size_t* written,
const char* s) {
264 buf_put_char(buf, size, written, *s++);
268static void buf_print_dec64(
char* buf,
size_t size,
size_t* written, int64_t value) {
270 char* t = tmp +
sizeof(tmp) - 1;
271 bool neg = (value < 0);
280 u = (uint64_t)(-(value + 1)) + 1;
288 *--t =
'0' + (u % 10);
293 buf_puts(buf, size, written, t);
296static void buf_print_udec64(
char* buf,
size_t size,
size_t* written, uint64_t value) {
298 char* t = tmp +
sizeof(tmp) - 1;
305 *--t =
'0' + (value % 10);
309 buf_puts(buf, size, written, t);
312static void buf_print_hex64(
char* buf,
size_t size,
size_t* written, uint64_t value) {
314 char* t = tmp +
sizeof(tmp) - 1;
315 const char* hex =
"0123456789abcdef";
322 *--t = hex[value & 0xF];
326 buf_puts(buf, size, written, t);
329static void buf_print_binary64(
char* buf,
size_t size,
size_t* written, uint64_t value) {
331 char* t = tmp +
sizeof(tmp) - 1;
338 *--t = (value & 1) ?
'1' :
'0';
342 buf_puts(buf, size, written, t);
348static char* strchr(
const char* s,
int c) {
365char*
kstrncat(
char* dest,
const char* src,
size_t max_len) {
366 if (!dest || !src || max_len == 0)
return dest;
370 while (dest_len < max_len && dest[dest_len] !=
'\0') {
374 if (dest_len == max_len) {
380 while (dest_len + i < max_len - 1 && src[i] !=
'\0') {
381 dest[dest_len + i] = src[i];
386 dest[dest_len + i] =
'\0';
395 while (str && str[len] !=
'\0') {
406 while ((*dst++ = *src++)) {
416char*
kstrncpy(
char* dst,
const char* src,
size_t n) {
417 if (n == 0)
return dst;
419 while (i + 1 < n && src[i]) {
427static inline size_t kstrlcpy(
char* dst,
const char* src,
size_t dst_size)
437 return (
size_t)(s - src - 1);
447 return (
size_t)(s - src - 1);
455static inline size_t kstrspn(
const char* s,
const char* accept)
458 for (; *p !=
'\0'; ++p) {
460 for (a = accept; *a !=
'\0' && *a != *p; ++a)
465 return (
size_t)(p - s);
473static inline size_t kstrcspn(
const char* s,
const char* reject)
476 for (; *p !=
'\0'; ++p) {
478 for (r = reject; *r !=
'\0' && *r != *p; ++r)
483 return (
size_t)(p - s);
491char*
kstrtok_r(
char* str,
const char* delim,
char** save_ptr)
495 if (!save_ptr)
return NULL;
500 else if (*save_ptr != NULL) {
501 token_start = *save_ptr;
508 token_start += kstrspn(token_start, delim);
510 if (*token_start ==
'\0') {
515 char* token_end = token_start + kstrcspn(token_start, delim);
517 if (*token_end ==
'\0') {
522 *save_ptr = token_end + 1;
528static void buf_print_hex64_minimal(
char* buf,
size_t size,
size_t* written, uint64_t value) {
530 char* t = tmp +
sizeof(tmp) - 1;
531 const char* hex =
"0123456789abcdef";
538 *--t = hex[value & 0xF];
542 buf_puts(buf, size, written,
"0x");
543 buf_puts(buf, size, written, t);
546int ksnprintf(
char* buf,
size_t bufsize,
const char* fmt, ...) {
551 for (
const char* p = fmt; *p; p++) {
552 if (*p ==
'%' && p[1]) {
565 buf_print_dec64(buf, bufsize, &written,
va_arg(ap,
long long));
568 buf_print_dec64(buf, bufsize, &written,
va_arg(ap,
long));
571 buf_print_dec64(buf, bufsize, &written, (int64_t)
va_arg(ap,
int));
576 buf_print_udec64(buf, bufsize, &written,
va_arg(ap,
unsigned long long));
579 buf_print_udec64(buf, bufsize, &written,
va_arg(ap,
unsigned long));
582 buf_print_udec64(buf, bufsize, &written, (uint64_t)
va_arg(ap,
unsigned int));
587 buf_print_hex64(buf, bufsize, &written,
va_arg(ap,
unsigned long long));
590 buf_print_hex64(buf, bufsize, &written,
va_arg(ap,
unsigned long));
593 buf_print_hex64(buf, bufsize, &written, (uint64_t)
va_arg(ap,
unsigned int));
597 buf_puts(buf, bufsize, &written,
"0x");
598 buf_print_hex64(buf, bufsize, &written, (uint64_t)(uintptr_t)
va_arg(ap,
void*));
601 buf_put_char(buf, bufsize, &written, (
char)
va_arg(ap,
int));
606 buf_print_binary64(buf, bufsize, &written,
va_arg(ap,
unsigned long long));
609 buf_print_binary64(buf, bufsize, &written,
va_arg(ap,
unsigned long));
612 buf_print_binary64(buf, bufsize, &written, (uint64_t)
va_arg(ap,
unsigned int));
616 const char* s =
va_arg(ap,
const char*);
617 buf_puts(buf, bufsize, &written, s ? s :
"(null)");
621 buf_put_char(buf, bufsize, &written,
'%');
624 buf_put_char(buf, bufsize, &written,
'%');
625 buf_put_char(buf, bufsize, &written, spec);
629 buf_put_char(buf, bufsize, &written, *p);
635 buf[written < bufsize ? written : bufsize - 1] =
'\0';
641static inline bool interrupts_enabled(
void) {
643 __asm__ __volatile__(
"pushfq; popq %0" :
"=r"(
flags));
644 return (
flags & (1UL << 9)) != 0;
647static void gop_print_binary(
GOP_PARAMS* gop, uint64_t val, uint32_t color) {
649 for (
int i = 0; i < 64; i++) {
651 buf[i] = (val & (1ULL << (63 - i))) ?
'1' :
'0';
654 gop_puts(gop, buf, color);
659 if (*s1 != *s2)
return (
int)((
unsigned char)*s1 - (
unsigned char)*s2);
663 return (
int)((
unsigned char)*s1 - (
unsigned char)*s2);
666int kstrncmp(
const char* s1,
const char* s2,
size_t length) {
667 if (!length)
return length;
668 for (
size_t i = 0; i < length; i++, s1++, s2++) {
669 if (*s1 != *s2)
return (
int)((
unsigned char)*s1 - (
unsigned char)*s2);
670 if (*s1 ==
'\0')
return 0;
677static void acquire_tmp_lock(
SPINLOCK* lock) {
680 while (__sync_lock_test_and_set(&lock->
locked, 1)) {
681 __asm__
volatile(
"pause" :::
"memory");
684 __asm__
volatile(
"" :::
"memory");
687static void release_tmp_lock(
SPINLOCK* lock) {
690 __asm__ __volatile(
"" :::
"memory");
691 __sync_lock_release(&lock->
locked);
700 bool prev_if = interrupts_enabled();
706 for (
const char* p = fmt; *p; p++) {
707 if (*p ==
'*' && p[1] ==
'*') {
712 if (*p ==
'%' && p[1]) {
725 gop_print_dec(gop, (int64_t)
va_arg(ap,
long long), color);
728 gop_print_dec(gop, (int64_t)
va_arg(ap,
long), color);
731 gop_print_dec(gop, (int64_t)
va_arg(ap,
int), color);
736 gop_print_udec(gop, (uint64_t)
va_arg(ap,
unsigned long long), color);
739 gop_print_udec(gop, (uint64_t)
va_arg(ap,
unsigned long), color);
742 gop_print_udec(gop, (uint64_t)
va_arg(ap,
unsigned int), color);
747 gop_print_hex_minimal(gop, (uint64_t)
va_arg(ap,
unsigned long long), color);
750 gop_print_hex_minimal(gop, (uint64_t)
va_arg(ap,
unsigned long), color);
753 gop_print_hex_minimal(gop, (uint64_t)
va_arg(ap,
unsigned int), color);
757 gop_print_hex(gop, (uint64_t)(uintptr_t)
va_arg(ap,
void*), color);
761 gop_put_char(gop, (
char)ch, color);
766 gop_print_binary(gop, (uint64_t)
va_arg(ap,
unsigned long long), color);
769 gop_print_binary(gop, (uint64_t)
va_arg(ap,
unsigned long), color);
772 gop_print_binary(gop, (uint64_t)
va_arg(ap,
unsigned int), color);
776 const char* str =
va_arg(ap,
const char*);
777 if (str) gop_puts(gop, str, color);
779 case '%': gop_put_char(gop,
'%', color);
break;
781 gop_put_char(gop,
'%', color);
782 gop_put_char(gop, spec, color);
786 gop_put_char(gop, *p, color);
791 if (prev_if)
__sti();
FORCEINLINE void * InterlockedCompareExchangePointer(volatile void *volatile *target, void *value, void *comparand)
FORCEINLINE void * InterlockedExchangePointer(volatile void *volatile *target, void *value)
struct _GOP_PARAMS GOP_PARAMS
const uint8_t font8x16[256][16]
void MgAcquireExclusiveGopOwnerShip(void)
volatile void * ExclusiveOwnerShip
char * kstrncat(char *dest, const char *src, size_t max_len)
Concatenates src onto dest, up to max_len total bytes in dest.
size_t kstrlen(const char *str)
void gop_printf(uint32_t color, const char *fmt,...)
int ksnprintf(char *buf, size_t bufsize, const char *fmt,...)
void MgReleaseExclusiveGopOwnerShip(void)
char * kstrtok_r(char *str, const char *delim, char **save_ptr)
char * kstrcpy(char *dst, const char *src)
char * kstrncpy(char *dst, const char *src, size_t n)
void gop_clear_screen(GOP_PARAMS *gop, uint32_t color)
int kstrncmp(const char *s1, const char *s2, size_t length)
int kstrcmp(const char *s1, const char *s2)
FORCEINLINE void __pause(void)
FORCEINLINE void __sti(void)
FORCEINLINE void __cli(void)
FORCEINLINE PPROCESSOR MeGetCurrentProcessor(void)
struct _ACPI_SDT_HEADER h
struct _SPINLOCK SPINLOCK
#define va_start(ap, last)
__builtin_va_list va_list
uint32_t PixelsPerScanLine