kernel
Loading...
Searching...
No Matches
gop.c
Go to the documentation of this file.
1/*
2 * PROJECT: MatanelOS Kernel
3 * LICENSE: GPLv3
4 * PURPOSE: GOP Driver to draw onto screen Implementation (8×16 font)
5 */
6
7#include "gop.h"
8#define FONT8X16_IMPLEMENTATION
9#include "font8x16.h"
11#include "../../includes/me.h"
13
14 // integer font scale (1 = native 8×16, 2 = 16×32, etc)
15#define FONT_SCALE 1
16#define NUM_BUFFER_SIZE 128
17
18volatile void* ExclusiveOwnerShip = NULL;
19
20static inline bool gop_params_valid(const GOP_PARAMS* gop) {
21 if (!gop) return false;
22 if (!gop->FrameBufferBase) return false;
23 if (gop->Width == 0 || gop->Height == 0) return false;
24 if (gop->PixelsPerScanLine == 0) return false;
25 if (gop->PixelsPerScanLine < gop->Width) return false;
26 return true;
27}
28
29static inline void plot_pixel(GOP_PARAMS* gop, uint32_t x, uint32_t y, uint32_t color) {
30 if (x >= gop->Width || y >= gop->Height) return;
31
32 // Safety: Calculate offset in uint64 to prevent overflow before casting back
33 uint64_t offset = (uint64_t)y * gop->PixelsPerScanLine + x;
34 if (offset * 4 >= gop->FrameBufferSize) return;
35
36 uint32_t* fb = (uint32_t*)(uintptr_t)gop->FrameBufferBase;
37 fb[offset] = color;
38}
39
40static inline uint32_t char_width(void) { return 8 * FONT_SCALE; }
41static inline uint32_t line_height(void) { return 16 * FONT_SCALE; }
42
43bool gop_bold_enabled = false; // default
44uint32_t cursor_x = 0, cursor_y = 0;
46
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;
50
51 // Fallback for non-printable chars
52 if (c > 0x7F) c = '?';
53
54 const uint8_t* bitmap = font8x16[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;
59
60 // Draw with scaling
61 for (int dy = 0; dy < FONT_SCALE; dy++) {
62 for (int dx = 0; dx < FONT_SCALE; dx++) {
63 uint32_t px = x + col * FONT_SCALE + dx;
64 uint32_t py = y + row * FONT_SCALE + dy;
65
66 if (gop_bold_enabled) {
67 // Safe bold plotting
68 plot_pixel(gop, px, py, color);
69 plot_pixel(gop, px + 1, py, color);
70 }
71 else {
72 plot_pixel(gop, px, py, color);
73 }
74 }
75 }
76 }
77 }
78}
79
80static void draw_string(GOP_PARAMS* gop, const char* s, uint32_t x, uint32_t y, uint32_t color) {
81 while (*s) {
82 draw_char(gop, *s, x, y, color);
83 x += char_width();
84 s++;
85 }
86}
87
88static void fb_memmove32(uint32_t* dest, uint32_t* src, size_t count) {
89 if (dest < src) {
90 for (size_t i = 0; i < count; i++) dest[i] = src[i];
91 }
92 else if (dest > src) {
93 for (size_t i = count; i-- > 0; ) dest[i] = src[i];
94 }
95}
96
97static void gop_scroll(GOP_PARAMS* gop) {
98 if (!gop_params_valid(gop)) return;
99
100 uint32_t* fb = (uint32_t*)(uintptr_t)gop->FrameBufferBase;
101 uint32_t stride = gop->PixelsPerScanLine;
102 uint32_t h = gop->Height;
103 uint32_t w = gop->Width;
104 uint32_t lines = line_height();
105
106 if (gop->Height <= lines) return;
107
108 size_t count = (h - lines) * (size_t)stride;
109 fb_memmove32(&fb[0], &fb[lines * stride], count);
110
111 // clear bottom
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;
115
116 cursor_y = (cursor_y >= lines) ? (cursor_y - lines) : 0;
117}
118
119static void gop_put_char(GOP_PARAMS* gop, char c, uint32_t color) {
120 if (!gop_params_valid(gop)) return;
121
122 if (c == '\b') {
123 if (cursor_x >= char_width()) {
124 cursor_x -= char_width();
125 }
126 else {
127 if (cursor_y >= line_height()) {
128 cursor_y -= line_height();
129 cursor_x = gop->Width - char_width();
130 }
131 }
132 // Clear cell
133 for (uint32_t yy = cursor_y; yy < cursor_y + line_height(); yy++) {
134 for (uint32_t xx = cursor_x; xx < cursor_x + char_width(); xx++) {
135 plot_pixel(gop, xx, yy, 0); // Clear with black/bg
136 }
137 }
138 return;
139 }
140 if (c == '\n') {
141 cursor_x = 0;
142 cursor_y += line_height();
143 if (cursor_y + line_height() > gop->Height) gop_scroll(gop);
144 return;
145 }
146 if (c == '\r') {
147 cursor_x = 0;
148 return;
149 }
150
151 draw_char(gop, c, cursor_x, cursor_y, color);
152 cursor_x += char_width();
153
154 // Wrap text
155 if (cursor_x + char_width() > gop->Width) {
156 cursor_x = 0;
157 cursor_y += line_height();
158 if (cursor_y + line_height() > gop->Height) gop_scroll(gop);
159 }
160}
161
162static void gop_puts(GOP_PARAMS* gop, const char* s, uint32_t color) {
163 while (*s) {
164 gop_put_char(gop, *s++, color);
165 }
166}
167
168
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) {
171 char buf[32]; // Increased from 20 to 32 to be safe
172 size_t written = 0;
173
174 // Use the safe helper you already wrote for printf
175 buf_print_dec64(buf, sizeof(buf), &written, val);
176
177 gop_puts(gop, buf, color);
178}
179
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) {
182 char buf[32];
183 size_t written = 0;
184 buf_print_udec64(buf, sizeof(buf), &written, val);
185 gop_puts(gop, buf, color);
186}
187
188static void gop_print_hex(GOP_PARAMS* gop, uint64_t val, uint32_t color) {
189 char buf[32] = "0x0000000000000000"; // 64 bit addressing
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);
193 }
194 buf[18] = '\0'; // null terminator
195 gop_puts(gop, buf, color);
196}
197
198static void gop_print_hex_minimal(GOP_PARAMS* gop, uint64_t val, uint32_t color) {
199 if (val == 0) {
200 gop_puts(gop, "0x0", color);
201 return;
202 }
203
204 char buf[19]; // "0x" + up to 16 hex digits + null
205 buf[0] = '0';
206 buf[1] = 'x';
207 int pos = 2;
208 bool started = false;
209
210 for (int i = 15; i >= 0; i--) { // 16 nibbles for 64 bits
211 unsigned nib = (val >> (i * 4)) & 0xF;
212 if (nib || started) {
213 started = true;
214 buf[pos++] = (nib < 10 ? '0' + nib : 'a' + nib - 10);
215 }
216 }
217
218 buf[pos] = '\0';
219 gop_puts(gop, buf, color);
220}
221
222
224
225void gop_clear_screen(GOP_PARAMS* gop, uint32_t 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);
229}
230
231static inline void buf_put_char(char* buf, size_t size, size_t* written, char c) {
232 if (size > 0 && *written < size - 1) { // Strict -1 to reserve NUL
233 buf[*written] = c;
234 buf[*written + 1] = '\0'; // Always null terminate as we go
235 }
236 (*written)++;
237}
238
239static void buf_puts(char* buf, size_t size, size_t* written, const char* s) {
240 while (*s) {
241 buf_put_char(buf, size, written, *s++);
242 }
243}
244
245static void buf_print_dec64(char* buf, size_t size, size_t* written, int64_t value) {
246 char tmp[32];
247 char* t = tmp + sizeof(tmp) - 1;
248 bool neg = (value < 0);
249 uint64_t u;
250 *t = '\0';
251
252 if (!neg) {
253 u = (uint64_t)value;
254 }
255 else {
256 u = (uint64_t)(-(value + 1)) + 1; // Safe abs for INT64_MIN
257 }
258
259 if (u == 0) *--t = '0';
260 else while (u) { *--t = '0' + (u % 10); u /= 10; }
261
262 if (neg) *--t = '-';
263 buf_puts(buf, size, written, t);
264}
265
266static void buf_print_udec64(char* buf, size_t size, size_t* written, uint64_t value) {
267 char tmp[32];
268 char* t = tmp + sizeof(tmp) - 1;
269 *t = '\0';
270 if (value == 0) *--t = '0';
271 else while (value) { *--t = '0' + (value % 10); value /= 10; }
272 buf_puts(buf, size, written, t);
273}
274
275static void buf_print_hex64(char* buf, size_t size, size_t* written, uint64_t value) {
276 char tmp[32];
277 char* t = tmp + sizeof(tmp) - 1;
278 const char* hex = "0123456789abcdef";
279 *t = '\0';
280 if (value == 0) *--t = '0';
281 else while (value) { *--t = hex[value & 0xF]; value >>= 4; }
282 buf_puts(buf, size, written, t);
283}
284
285static void buf_print_binary64(char* buf, size_t size, size_t* written, uint64_t value) {
286 char tmp[66];
287 char* t = tmp + sizeof(tmp) - 1;
288 *t = '\0';
289 if (value == 0) *--t = '0';
290 else while (value) { *--t = (value & 1) ? '1' : '0'; value >>= 1; }
291 buf_puts(buf, size, written, t);
292}
293
294//-----------------------------------------------------------------------------
295// Helper: simple strchr for delimiter scanning
296//-----------------------------------------------------------------------------
297static char* strchr(const char* s, int c) {
298 while (*s) {
299 if (*s == (char)c) {
300 return (char*)s;
301 }
302 s++;
303 }
304 return NULL;
305}
306
314char* kstrncat(char* dest, const char* src, size_t max_len) {
315 if (!dest || !src || max_len == 0) return dest;
316
317 // Move dest_ptr to the end of the current string
318 size_t dest_len = 0;
319 while (dest_len < max_len && dest[dest_len] != '\0') {
320 dest_len++;
321 }
322
323 if (dest_len == max_len) {
324 // dest is already full, cannot append
325 return dest;
326 }
327
328 size_t i = 0;
329 while (dest_len + i < max_len - 1 && src[i] != '\0') {
330 dest[dest_len + i] = src[i];
331 i++;
332 }
333
334 // Null-terminate
335 dest[dest_len + i] = '\0';
336 return dest;
337}
338
339//-----------------------------------------------------------------------------
340// kstrlen: Return length of string (excluding null terminator).
341//-----------------------------------------------------------------------------
342size_t kstrlen(const char* str) {
343 size_t len = 0;
344 while (str && str[len] != '\0') {
345 len++;
346 }
347 return len;
348}
349
350//-----------------------------------------------------------------------------
351// kstrcpy: Copy string from src to dst. Assumes dst is large enough.
352//-----------------------------------------------------------------------------
353char* kstrcpy(char* dst, const char* src) {
354 char* ret = dst;
355 while ((*dst++ = *src++)) {
356 // copy until null terminator
357 }
358 return ret;
359}
360
361//-----------------------------------------------------------------------------
362// kstrncpy: Copy up to n characters from src to dst.
363// Assumes dst is large enough.
364//-----------------------------------------------------------------------------
365char* kstrncpy(char* dst, const char* src, size_t n) {
366 if (n == 0) return dst;
367 size_t i = 0;
368 while (i + 1 < n && src[i]) {
369 dst[i] = src[i];
370 i++;
371 }
372 dst[i] = '\0';
373 return dst;
374}
375
376static inline size_t kstrlcpy(char* dst, const char* src, size_t dst_size)
377{
378 const char* s = src;
379 size_t n = dst_size;
380
381 if (n != 0) {
382 while (--n != 0) {
383 char c = *s++;
384 *dst++ = c;
385 if (c == '\0') {
386 return (size_t)(s - src - 1);
387 }
388 }
389 /* out of space; NUL-terminate if possible */
390 *dst = '\0';
391 }
392
393 /* continue walking src to compute its length */
394 while (*s++)
395 ;
396 return (size_t)(s - src - 1);
397}
398
399/* -------------------
400 * kstrspn - like strspn
401 * -------------------
402 * Returns length of the initial segment of s consisting only of characters in accept.
403 */
404static inline size_t kstrspn(const char* s, const char* accept)
405{
406 const char* p = s;
407 for (; *p != '\0'; ++p) {
408 const char* a;
409 for (a = accept; *a != '\0' && *a != *p; ++a)
410 ;
411 if (*a == '\0') /* char p is NOT in accept */
412 break;
413 }
414 return (size_t)(p - s);
415}
416
417/* --------------------
418 * kstrcspn - like strcspn
419 * --------------------
420 * Returns length of the initial segment of s consisting of characters NOT in reject.
421 */
422static inline size_t kstrcspn(const char* s, const char* reject)
423{
424 const char* p = s;
425 for (; *p != '\0'; ++p) {
426 const char* r;
427 for (r = reject; *r != '\0' && *r != *p; ++r)
428 ;
429 if (*r != '\0') /* p matched a reject char */
430 break;
431 }
432 return (size_t)(p - s);
433}
434
435//-----------------------------------------------------------------------------
436// kstrtok: Tokenize string with delimiters.
437// Works like strtok, but without libc.
438// Keeps static state across calls unless str != NULL.
439//-----------------------------------------------------------------------------
440char* kstrtok_r(char* str, const char* delim, char** save_ptr)
441{
442 char* token_start;
443
444 if (!save_ptr) return NULL; /* defensive */
445
446 if (str != NULL) {
447 token_start = str;
448 }
449 else if (*save_ptr != NULL) {
450 token_start = *save_ptr;
451 }
452 else {
453 return NULL;
454 }
455
456 /* skip leading delimiters */
457 token_start += kstrspn(token_start, delim);
458
459 if (*token_start == '\0') {
460 *save_ptr = NULL;
461 return NULL;
462 }
463
464 char* token_end = token_start + kstrcspn(token_start, delim);
465
466 if (*token_end == '\0') {
467 *save_ptr = NULL;
468 }
469 else {
470 *token_end = '\0';
471 *save_ptr = token_end + 1;
472 }
473
474 return token_start;
475}
476
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);
480}
481
482int ksnprintf(char* buf, size_t bufsize, const char* fmt, ...) {
483 size_t written = 0;
484 va_list ap;
485 va_start(ap, fmt);
486
487 for (const char* p = fmt; *p; p++) {
488 if (*p == '%' && p[1]) {
489 p++;
490 // support optional length modifiers: 'l' and 'll'
491 int len = 0;
492 while (*p == 'l') {
493 len++;
494 p++;
495 if (len >= 2) break;
496 }
497 char spec = *p;
498 switch (spec) {
499 case 'd':
500 if (len >= 2) {
501 buf_print_dec64(buf, bufsize, &written, va_arg(ap, long long));
502 }
503 else if (len == 1) {
504 buf_print_dec64(buf, bufsize, &written, va_arg(ap, long));
505 }
506 else {
507 buf_print_dec64(buf, bufsize, &written, (int64_t)va_arg(ap, int));
508 }
509 break;
510 case 'u':
511 if (len >= 2) {
512 buf_print_udec64(buf, bufsize, &written, va_arg(ap, unsigned long long));
513 }
514 else if (len == 1) {
515 buf_print_udec64(buf, bufsize, &written, va_arg(ap, unsigned long));
516 }
517 else {
518 buf_print_udec64(buf, bufsize, &written, (uint64_t)va_arg(ap, unsigned int));
519 }
520 break;
521 case 'x':
522 if (len >= 2) {
523 buf_print_hex64(buf, bufsize, &written, va_arg(ap, unsigned long long));
524 }
525 else if (len == 1) {
526 buf_print_hex64(buf, bufsize, &written, va_arg(ap, unsigned long));
527 }
528 else {
529 buf_print_hex64(buf, bufsize, &written, (uint64_t)va_arg(ap, unsigned int));
530 }
531 break;
532 case 'p':
533 buf_puts(buf, bufsize, &written, "0x");
534 buf_print_hex64(buf, bufsize, &written, (uint64_t)(uintptr_t)va_arg(ap, void*));
535 break;
536 case 'c':
537 buf_put_char(buf, bufsize, &written, (char)va_arg(ap, int)); /* chars promoted to int */
538 break;
539 case 'b':
540 // 'b' - binary, treat as 64-bit if ll, otherwise adapt
541 if (len >= 2) {
542 buf_print_binary64(buf, bufsize, &written, va_arg(ap, unsigned long long));
543 }
544 else if (len == 1) {
545 buf_print_binary64(buf, bufsize, &written, va_arg(ap, unsigned long));
546 }
547 else {
548 buf_print_binary64(buf, bufsize, &written, (uint64_t)va_arg(ap, unsigned int));
549 }
550 break;
551 case 's': {
552 const char* s = va_arg(ap, const char*);
553 buf_puts(buf, bufsize, &written, s ? s : "(null)");
554 break;
555 }
556 case '%':
557 buf_put_char(buf, bufsize, &written, '%');
558 break;
559 default:
560 buf_put_char(buf, bufsize, &written, '%');
561 buf_put_char(buf, bufsize, &written, spec);
562 }
563 }
564 else {
565 buf_put_char(buf, bufsize, &written, *p);
566 }
567 }
568
569 va_end(ap);
570 if (bufsize > 0) {
571 buf[written < bufsize ? written : bufsize - 1] = '\0';
572 }
573
574 return (int)written;
575}
576
577static inline bool interrupts_enabled(void) {
578 unsigned long flags;
579 __asm__ __volatile__("pushfq; popq %0" : "=r"(flags));
580 return (flags & (1UL << 9)) != 0; // IF is bit 9
581}
582
583static void gop_print_binary(GOP_PARAMS* gop, uint64_t val, uint32_t color) {
584 char buf[65]; // 64 bits + null terminator
585 for (int i = 0; i < 64; i++) {
586 // fill buffer from MSB to LSB
587 buf[i] = (val & (1ULL << (63 - i))) ? '1' : '0';
588 }
589 buf[64] = '\0';
590 gop_puts(gop, buf, color);
591}
592
593int kstrcmp(const char* s1, const char* s2) {
594 while (*s1 && *s2) {
595 if (*s1 != *s2) return (int)((unsigned char)*s1 - (unsigned char)*s2);
596 s1++;
597 s2++;
598 }
599 return (int)((unsigned char)*s1 - (unsigned char)*s2);
600}
601
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;
607 }
608 return 0;
609}
610
612
613static void acquire_tmp_lock(SPINLOCK* lock) {
614 if (!lock) return;
615 // spin until we grab the lock.
616 while (__sync_lock_test_and_set(&lock->locked, 1)) {
617 __asm__ volatile("pause" ::: "memory"); /* x86 pause — CPU relax hint */
618 }
619 // Memory barrier to prevent instruction reordering
620 __asm__ volatile("" ::: "memory");
621}
622
623static void release_tmp_lock(SPINLOCK* lock) {
624 if (!lock) return;
625 // Memory barrier before release
626 __asm__ __volatile("" ::: "memory");
627 __sync_lock_release(&lock->locked);
628}
629
630#ifdef DISABLE_GOP
631USED static void gop_printfz(uint32_t color, const char* fmt, ...) {
632#else
633void gop_printf(uint32_t color, const char* fmt, ...) {
634#endif
635 // Re-entrancy check: If we already own it, we are safe to print,
636 // but if another core owns it, we return to avoid deadlocks in high-IRQL.
637 void* owner = InterlockedCompareExchangePointer((volatile void* volatile*)&ExclusiveOwnerShip, NULL, NULL);
638 if (unlikely(owner && owner != MeGetCurrentProcessor())) return;
639
640 bool prev_if = interrupts_enabled();
641 acquire_tmp_lock(&gop_lock); // well if we get a page fault down there you can say bye bye to cpu execution (deadlock), more reason to hate this function, god can we move already to gui?
642 __cli(); // Critical section
643
644 GOP_PARAMS* gop = &gop_local;
645 va_list ap;
646 va_start(ap, fmt);
647
648 // One buffer to rule them all.
649 // Large enough for binary(64) + null + slop.
650 __attribute__((aligned(16))) char scratch[NUM_BUFFER_SIZE];
651 size_t written = 0;
652
653 for (const char* p = fmt; *p; p++) {
654 if (*p == '*' && p[1] == '*') {
656 p++;
657 continue;
658 }
659 if (*p == '%' && p[1]) {
660 p++;
661 // Length modifiers
662 int len = 0;
663 while (*p == 'l') { len++; p++; if (len >= 2) break; }
664
665 char spec = *p;
666
667 // Reset scratch buffer for this specific specifier
668 written = 0;
669 scratch[0] = '\0';
670
671 switch (spec) {
672 case 'd':
673 if (len >= 2) buf_print_dec64(scratch, NUM_BUFFER_SIZE, &written, va_arg(ap, long long));
674 else if (len == 1) buf_print_dec64(scratch, NUM_BUFFER_SIZE, &written, va_arg(ap, long));
675 else buf_print_dec64(scratch, NUM_BUFFER_SIZE, &written, (int64_t)va_arg(ap, int));
676 gop_puts(gop, scratch, color);
677 break;
678 case 'u':
679 if (len >= 2) buf_print_udec64(scratch, NUM_BUFFER_SIZE, &written, va_arg(ap, unsigned long long));
680 else if (len == 1) buf_print_udec64(scratch, NUM_BUFFER_SIZE, &written, va_arg(ap, unsigned long));
681 else buf_print_udec64(scratch, NUM_BUFFER_SIZE, &written, (uint64_t)va_arg(ap, unsigned int));
682 gop_puts(gop, scratch, color);
683 break;
684 case 'x':
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);
689 break;
690 case 'p':
691 buf_print_hex64(scratch, NUM_BUFFER_SIZE, &written, (uint64_t)(uintptr_t)va_arg(ap, void*));
692 gop_puts(gop, "0x", color);
693 gop_puts(gop, scratch, color);
694 break;
695 case 'b':
696 // Binary can be long, ensure buffer is big enough (NUM_BUFFER_SIZE 128 is safe for 64 bits)
697 if (len >= 2) buf_print_binary64(scratch, NUM_BUFFER_SIZE, &written, va_arg(ap, unsigned long long));
698 else buf_print_binary64(scratch, NUM_BUFFER_SIZE, &written, (uint64_t)va_arg(ap, unsigned int));
699 gop_puts(gop, scratch, color);
700 break;
701 case 'c':
702 gop_put_char(gop, (char)va_arg(ap, int), color);
703 break;
704 case 's': {
705 const char* str = va_arg(ap, const char*);
706 gop_puts(gop, str ? str : "(null)", color);
707 } break;
708 case '%':
709 gop_put_char(gop, '%', color);
710 break;
711 default:
712 gop_put_char(gop, '%', color);
713 gop_put_char(gop, spec, color);
714 }
715 }
716 else {
717 gop_put_char(gop, *p, color);
718 }
719 }
720
721 va_end(ap);
722 release_tmp_lock(&gop_lock);
723 if (prev_if) __sti();
724}
725
727 void* me = (void*)MeGetCurrentProcessor();
728
729 for (;;) {
731 if (prev == NULL)
732 return; // acquired
733
734 __pause();
735 }
736}
737
739 // Trust the caller, just set the ExclusiveOwnerShip pointer to NULL.
741}
#define USED
Definition annotations.h:39
FORCEINLINE void * InterlockedCompareExchangePointer(volatile void *volatile *target, void *value, void *comparand)
Definition atomic.h:177
FORCEINLINE void * InterlockedExchangePointer(volatile void *volatile *target, void *value)
Definition atomic.h:176
uint32_t cursor_y
Definition gop.c:44
GOP_PARAMS gop_local
Definition gop.c:223
uint32_t cursor_x
Definition gop.c:44
struct _GOP_PARAMS GOP_PARAMS
const uint8_t font8x16[256][16]
void MgAcquireExclusiveGopOwnerShip(void)
Definition gop.c:726
volatile void * ExclusiveOwnerShip
Definition gop.c:18
char * kstrncat(char *dest, const char *src, size_t max_len)
Concatenates src onto dest, up to max_len total bytes in dest.
Definition gop.c:314
#define FONT_SCALE
Definition gop.c:15
size_t kstrlen(const char *str)
Definition gop.c:342
void gop_printf(uint32_t color, const char *fmt,...)
Definition gop.c:633
int ksnprintf(char *buf, size_t bufsize, const char *fmt,...)
Definition gop.c:482
void MgReleaseExclusiveGopOwnerShip(void)
Definition gop.c:738
char * kstrtok_r(char *str, const char *delim, char **save_ptr)
Definition gop.c:440
char * kstrcpy(char *dst, const char *src)
Definition gop.c:353
#define NUM_BUFFER_SIZE
Definition gop.c:16
char * kstrncpy(char *dst, const char *src, size_t n)
Definition gop.c:365
SPINLOCK gop_lock
Definition gop.c:611
void gop_clear_screen(GOP_PARAMS *gop, uint32_t color)
Definition gop.c:225
bool gop_bold_enabled
Definition gop.c:43
int kstrncmp(const char *s1, const char *s2, size_t length)
Definition gop.c:602
int kstrcmp(const char *s1, const char *s2)
Definition gop.c:593
FORCEINLINE void __pause(void)
Definition intrin.h:239
FORCEINLINE void __sti(void)
Definition intrin.h:59
FORCEINLINE void __cli(void)
Definition intrin.h:43
#define unlikely(x)
Definition macros.h:62
FORCEINLINE PPROCESSOR MeGetCurrentProcessor(void)
Definition me.h:369
void const char * fmt
Definition mg.h:69
typedef __attribute__
Definition fat32.h:64
uint32_t flags
Definition mh.h:2
struct _ACPI_SDT_HEADER h
Definition mh.h:0
struct _SPINLOCK SPINLOCK
#define va_arg(ap, type)
Definition stdarg_myos.h:12
#define va_end(ap)
Definition stdarg_myos.h:13
#define va_start(ap, last)
Definition stdarg_myos.h:11
__builtin_va_list va_list
Definition stdarg_myos.h:9
uint64_t FrameBufferBase
Definition efi.h:43
uint32_t Height
Definition efi.h:46
uint64_t FrameBufferSize
Definition efi.h:44
uint32_t Width
Definition efi.h:45
uint32_t PixelsPerScanLine
Definition efi.h:47
volatile uint32_t locked
Definition ms.h:37