8#define FONT8X16_IMPLEMENTATION
16#define NUM_BUFFER_SIZE 128
20static inline bool gop_params_valid(
const GOP_PARAMS* gop) {
21 if (!gop)
return false;
23 if (gop->
Width == 0 || gop->
Height == 0)
return false;
29static inline void plot_pixel(
GOP_PARAMS* gop, uint32_t x, uint32_t y, uint32_t color) {
40static inline uint32_t char_width(
void) {
return 8 *
FONT_SCALE; }
41static inline uint32_t line_height(
void) {
return 16 *
FONT_SCALE; }
47static void draw_char(
GOP_PARAMS* gop,
char c_, uint32_t x, uint32_t y, uint32_t color) {
48 uint8_t c = (uint8_t)c_;
49 if (!gop_params_valid(gop))
return;
52 if (c > 0x7F) c =
'?';
55 for (
int row = 0; row < 16; row++) {
56 uint8_t bits = bitmap[row];
57 for (
int col = 0; col < 8; col++) {
58 if (!(bits & (1 << (7 - col))))
continue;
68 plot_pixel(gop, px, py, color);
69 plot_pixel(gop, px + 1, py, color);
72 plot_pixel(gop, px, py, color);
80static void draw_string(
GOP_PARAMS* gop,
const char* s, uint32_t x, uint32_t y, uint32_t color) {
82 draw_char(gop, *s, x, y, color);
88static void fb_memmove32(uint32_t* dest, uint32_t* src,
size_t count) {
90 for (
size_t i = 0; i < count; i++) dest[i] = src[i];
92 else if (dest > src) {
93 for (
size_t i = count; i-- > 0; ) dest[i] = src[i];
98 if (!gop_params_valid(gop))
return;
103 uint32_t w = gop->
Width;
104 uint32_t lines = line_height();
106 if (gop->
Height <= lines)
return;
108 size_t count = (
h - lines) * (
size_t)stride;
109 fb_memmove32(&fb[0], &fb[lines * stride], count);
112 for (uint32_t yy =
h - lines; yy <
h; yy++)
113 for (uint32_t xx = 0; xx < w; xx++)
114 fb[yy * stride + xx] = 0;
119static void gop_put_char(
GOP_PARAMS* gop,
char c, uint32_t color) {
120 if (!gop_params_valid(gop))
return;
135 plot_pixel(gop, xx, yy, 0);
162static void gop_puts(
GOP_PARAMS* gop,
const char* s, uint32_t color) {
164 gop_put_char(gop, *s++, color);
169static void buf_print_dec64(
char* buf,
size_t size,
size_t* written, int64_t value);
170static void gop_print_dec(
GOP_PARAMS* gop, int64_t val, uint32_t color) {
175 buf_print_dec64(buf,
sizeof(buf), &written, val);
177 gop_puts(gop, buf, color);
180static void buf_print_udec64(
char* buf,
size_t size,
size_t* written, uint64_t value);
181static void gop_print_udec(
GOP_PARAMS* gop, uint64_t val, uint32_t color) {
184 buf_print_udec64(buf,
sizeof(buf), &written, val);
185 gop_puts(gop, buf, color);
188static void gop_print_hex(
GOP_PARAMS* gop, uint64_t val, uint32_t color) {
189 char buf[32] =
"0x0000000000000000";
190 for (
int i = 0; i < 16; i++) {
191 unsigned nib = (val >> ((15 - i) * 4)) & 0xF;
192 buf[2 + i] = (nib < 10 ?
'0' + nib :
'a' + nib - 10);
195 gop_puts(gop, buf, color);
198static void gop_print_hex_minimal(
GOP_PARAMS* gop, uint64_t val, uint32_t color) {
200 gop_puts(gop,
"0x0", color);
208 bool started =
false;
210 for (
int i = 15; i >= 0; i--) {
211 unsigned nib = (val >> (i * 4)) & 0xF;
212 if (nib || started) {
214 buf[pos++] = (nib < 10 ?
'0' + nib :
'a' + nib - 10);
219 gop_puts(gop, buf, color);
226 for (uint32_t y = 0; y < gop->
Height; y++)
227 for (uint32_t x = 0; x < gop->
Width; x++)
228 plot_pixel(gop, x, y, color);
231static inline void buf_put_char(
char* buf,
size_t size,
size_t* written,
char c) {
232 if (size > 0 && *written < size - 1) {
234 buf[*written + 1] =
'\0';
239static void buf_puts(
char* buf,
size_t size,
size_t* written,
const char* s) {
241 buf_put_char(buf, size, written, *s++);
245static void buf_print_dec64(
char* buf,
size_t size,
size_t* written, int64_t value) {
247 char* t = tmp +
sizeof(tmp) - 1;
248 bool neg = (value < 0);
256 u = (uint64_t)(-(value + 1)) + 1;
259 if (u == 0) *--t =
'0';
260 else while (u) { *--t =
'0' + (u % 10); u /= 10; }
263 buf_puts(buf, size, written, t);
266static void buf_print_udec64(
char* buf,
size_t size,
size_t* written, uint64_t value) {
268 char* t = tmp +
sizeof(tmp) - 1;
270 if (value == 0) *--t =
'0';
271 else while (value) { *--t =
'0' + (value % 10); value /= 10; }
272 buf_puts(buf, size, written, t);
275static void buf_print_hex64(
char* buf,
size_t size,
size_t* written, uint64_t value) {
277 char* t = tmp +
sizeof(tmp) - 1;
278 const char* hex =
"0123456789abcdef";
280 if (value == 0) *--t =
'0';
281 else while (value) { *--t = hex[value & 0xF]; value >>= 4; }
282 buf_puts(buf, size, written, t);
285static void buf_print_binary64(
char* buf,
size_t size,
size_t* written, uint64_t value) {
287 char* t = tmp +
sizeof(tmp) - 1;
289 if (value == 0) *--t =
'0';
290 else while (value) { *--t = (value & 1) ?
'1' :
'0'; value >>= 1; }
291 buf_puts(buf, size, written, t);
297static char* strchr(
const char* s,
int c) {
314char*
kstrncat(
char* dest,
const char* src,
size_t max_len) {
315 if (!dest || !src || max_len == 0)
return dest;
319 while (dest_len < max_len && dest[dest_len] !=
'\0') {
323 if (dest_len == max_len) {
329 while (dest_len + i < max_len - 1 && src[i] !=
'\0') {
330 dest[dest_len + i] = src[i];
335 dest[dest_len + i] =
'\0';
344 while (str && str[len] !=
'\0') {
355 while ((*dst++ = *src++)) {
365char*
kstrncpy(
char* dst,
const char* src,
size_t n) {
366 if (n == 0)
return dst;
368 while (i + 1 < n && src[i]) {
376static inline size_t kstrlcpy(
char* dst,
const char* src,
size_t dst_size)
386 return (
size_t)(s - src - 1);
396 return (
size_t)(s - src - 1);
404static inline size_t kstrspn(
const char* s,
const char* accept)
407 for (; *p !=
'\0'; ++p) {
409 for (a = accept; *a !=
'\0' && *a != *p; ++a)
414 return (
size_t)(p - s);
422static inline size_t kstrcspn(
const char* s,
const char* reject)
425 for (; *p !=
'\0'; ++p) {
427 for (r = reject; *r !=
'\0' && *r != *p; ++r)
432 return (
size_t)(p - s);
440char*
kstrtok_r(
char* str,
const char* delim,
char** save_ptr)
444 if (!save_ptr)
return NULL;
449 else if (*save_ptr != NULL) {
450 token_start = *save_ptr;
457 token_start += kstrspn(token_start, delim);
459 if (*token_start ==
'\0') {
464 char* token_end = token_start + kstrcspn(token_start, delim);
466 if (*token_end ==
'\0') {
471 *save_ptr = token_end + 1;
477static void buf_print_hex64_minimal(
char* buf,
size_t size,
size_t* written, uint64_t value) {
478 buf_puts(buf, size, written,
"0x");
479 buf_print_hex64(buf, size, written, value);
487 for (
const char* p =
fmt; *p; p++) {
488 if (*p ==
'%' && p[1]) {
501 buf_print_dec64(buf, bufsize, &written,
va_arg(ap,
long long));
504 buf_print_dec64(buf, bufsize, &written,
va_arg(ap,
long));
507 buf_print_dec64(buf, bufsize, &written, (int64_t)
va_arg(ap,
int));
512 buf_print_udec64(buf, bufsize, &written,
va_arg(ap,
unsigned long long));
515 buf_print_udec64(buf, bufsize, &written,
va_arg(ap,
unsigned long));
518 buf_print_udec64(buf, bufsize, &written, (uint64_t)
va_arg(ap,
unsigned int));
523 buf_print_hex64(buf, bufsize, &written,
va_arg(ap,
unsigned long long));
526 buf_print_hex64(buf, bufsize, &written,
va_arg(ap,
unsigned long));
529 buf_print_hex64(buf, bufsize, &written, (uint64_t)
va_arg(ap,
unsigned int));
533 buf_puts(buf, bufsize, &written,
"0x");
534 buf_print_hex64(buf, bufsize, &written, (uint64_t)(uintptr_t)
va_arg(ap,
void*));
537 buf_put_char(buf, bufsize, &written, (
char)
va_arg(ap,
int));
542 buf_print_binary64(buf, bufsize, &written,
va_arg(ap,
unsigned long long));
545 buf_print_binary64(buf, bufsize, &written,
va_arg(ap,
unsigned long));
548 buf_print_binary64(buf, bufsize, &written, (uint64_t)
va_arg(ap,
unsigned int));
552 const char* s =
va_arg(ap,
const char*);
553 buf_puts(buf, bufsize, &written, s ? s :
"(null)");
557 buf_put_char(buf, bufsize, &written,
'%');
560 buf_put_char(buf, bufsize, &written,
'%');
561 buf_put_char(buf, bufsize, &written, spec);
565 buf_put_char(buf, bufsize, &written, *p);
571 buf[written < bufsize ? written : bufsize - 1] =
'\0';
577static inline bool interrupts_enabled(
void) {
579 __asm__ __volatile__(
"pushfq; popq %0" :
"=r"(
flags));
580 return (
flags & (1UL << 9)) != 0;
583static void gop_print_binary(
GOP_PARAMS* gop, uint64_t val, uint32_t color) {
585 for (
int i = 0; i < 64; i++) {
587 buf[i] = (val & (1ULL << (63 - i))) ?
'1' :
'0';
590 gop_puts(gop, buf, color);
595 if (*s1 != *s2)
return (
int)((
unsigned char)*s1 - (
unsigned char)*s2);
599 return (
int)((
unsigned char)*s1 - (
unsigned char)*s2);
602int kstrncmp(
const char* s1,
const char* s2,
size_t length) {
603 if (!length)
return length;
604 for (
size_t i = 0; i < length; i++, s1++, s2++) {
605 if (*s1 != *s2)
return (
int)((
unsigned char)*s1 - (
unsigned char)*s2);
606 if (*s1 ==
'\0')
return 0;
613static void acquire_tmp_lock(
SPINLOCK* lock) {
616 while (__sync_lock_test_and_set(&lock->
locked, 1)) {
617 __asm__
volatile(
"pause" :::
"memory");
620 __asm__
volatile(
"" :::
"memory");
623static void release_tmp_lock(
SPINLOCK* lock) {
626 __asm__ __volatile(
"" :::
"memory");
627 __sync_lock_release(&lock->
locked);
631USED static void gop_printfz(uint32_t color,
const char*
fmt, ...) {
640 bool prev_if = interrupts_enabled();
653 for (
const char* p =
fmt; *p; p++) {
654 if (*p ==
'*' && p[1] ==
'*') {
659 if (*p ==
'%' && p[1]) {
663 while (*p ==
'l') { len++; p++;
if (len >= 2)
break; }
676 gop_puts(gop, scratch, color);
682 gop_puts(gop, scratch, color);
685 if (len >= 2) buf_print_hex64_minimal(scratch,
NUM_BUFFER_SIZE, &written,
va_arg(ap,
unsigned long long));
686 else if (len == 1) buf_print_hex64_minimal(scratch,
NUM_BUFFER_SIZE, &written,
va_arg(ap,
unsigned long));
687 else buf_print_hex64_minimal(scratch,
NUM_BUFFER_SIZE, &written, (uint64_t)
va_arg(ap,
unsigned int));
688 gop_puts(gop, scratch, color);
692 gop_puts(gop,
"0x", color);
693 gop_puts(gop, scratch, color);
697 if (len >= 2) buf_print_binary64(scratch,
NUM_BUFFER_SIZE, &written,
va_arg(ap,
unsigned long long));
699 gop_puts(gop, scratch, color);
702 gop_put_char(gop, (
char)
va_arg(ap,
int), color);
705 const char* str =
va_arg(ap,
const char*);
706 gop_puts(gop, str ? str :
"(null)", color);
709 gop_put_char(gop,
'%', color);
712 gop_put_char(gop,
'%', color);
713 gop_put_char(gop, spec, color);
717 gop_put_char(gop, *p, color);
723 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