mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-08 02:40:28 +00:00
[metal] Add a uprintf() routine, for non-emergency boot logging
This commit is contained in:
parent
ec3275179f
commit
e68658501f
7 changed files with 104 additions and 25 deletions
|
@ -735,6 +735,8 @@ void abort(void) wontreturn;
|
|||
#endif
|
||||
|
||||
#define __weak_reference(sym, alias) \
|
||||
__weak_reference_impl(sym, alias)
|
||||
#define __weak_reference_impl(sym, alias) \
|
||||
__asm__(".weak\t" #alias "\n\t" \
|
||||
".equ\t" #alias ", " #sym "\n\t" \
|
||||
".type\t" #alias ",@notype")
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/runtime/pc.internal.h"
|
||||
|
||||
// Code and data structures for bare metal interrupt handling.
|
||||
|
|
|
@ -385,14 +385,29 @@ privileged long kloghandle(void) {
|
|||
return __klog_handle;
|
||||
}
|
||||
|
||||
privileged void _klog_serial(const char *b, size_t n) {
|
||||
size_t i;
|
||||
uint16_t dx;
|
||||
unsigned char al;
|
||||
for (i = 0; i < n; ++i) {
|
||||
for (;;) {
|
||||
dx = 0x3F8 + UART_LSR;
|
||||
asm("inb\t%1,%0" : "=a"(al) : "dN"(dx));
|
||||
if (al & UART_TTYTXR) break;
|
||||
asm("pause");
|
||||
}
|
||||
dx = 0x3F8;
|
||||
asm volatile("outb\t%0,%1"
|
||||
: /* no inputs */
|
||||
: "a"(b[i]), "dN"(dx));
|
||||
}
|
||||
}
|
||||
|
||||
privileged void klog(const char *b, size_t n) {
|
||||
#ifdef __x86_64__
|
||||
int e;
|
||||
long h;
|
||||
size_t i;
|
||||
uint16_t dx;
|
||||
uint32_t wrote;
|
||||
unsigned char al;
|
||||
long rax, rdi, rsi, rdx;
|
||||
if ((h = kloghandle()) == -1) {
|
||||
return;
|
||||
|
@ -407,18 +422,7 @@ privileged void klog(const char *b, size_t n) {
|
|||
if (_weaken(_klog_vga)) {
|
||||
_weaken(_klog_vga)(b, n);
|
||||
}
|
||||
for (i = 0; i < n; ++i) {
|
||||
for (;;) {
|
||||
dx = 0x3F8 + UART_LSR;
|
||||
asm("inb\t%1,%0" : "=a"(al) : "dN"(dx));
|
||||
if (al & UART_TTYTXR) break;
|
||||
asm("pause");
|
||||
}
|
||||
dx = 0x3F8;
|
||||
asm volatile("outb\t%0,%1"
|
||||
: /* no inputs */
|
||||
: "a"(b[i]), "dN"(dx));
|
||||
}
|
||||
_klog_serial(b, n);
|
||||
} else {
|
||||
asm volatile("syscall"
|
||||
: "=a"(rax), "=D"(rdi), "=S"(rsi), "=d"(rdx)
|
||||
|
@ -1152,3 +1156,6 @@ privileged void kprintf(const char *fmt, ...) {
|
|||
kvprintf(fmt, v);
|
||||
va_end(v);
|
||||
}
|
||||
|
||||
__weak_reference(kprintf, uprintf);
|
||||
__weak_reference(kvprintf, uvprintf);
|
||||
|
|
|
@ -9,25 +9,49 @@
|
|||
#define kvsnprintf __kvsnprintf
|
||||
#define kloghandle __kloghandle
|
||||
#define kisdangerous __kisdangerous
|
||||
#define uprintf __uprintf
|
||||
#define uvprintf __uvprintf
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
void kprintf(const char *, ...);
|
||||
size_t ksnprintf(char *, size_t, const char *, ...);
|
||||
void kvprintf(const char *, va_list);
|
||||
size_t kvsnprintf(char *, size_t, const char *, va_list);
|
||||
bool kisdangerous(const void *);
|
||||
|
||||
void kprintf(const char *, ...);
|
||||
size_t ksnprintf(char *, size_t, const char *, ...);
|
||||
void kvprintf(const char *, va_list);
|
||||
size_t kvsnprintf(char *, size_t, const char *, va_list);
|
||||
|
||||
bool kisdangerous(const void *);
|
||||
|
||||
void klog(const char *, size_t);
|
||||
void _klog_serial(const char *, size_t);
|
||||
long kloghandle(void);
|
||||
|
||||
void uprintf(const char *, ...);
|
||||
void uvprintf(const char *, va_list);
|
||||
|
||||
#ifndef TINY
|
||||
#define KINFOF(FMT, ...) \
|
||||
do { \
|
||||
uprintf("\r\e[35m%s:%d: " FMT "\e[0m\n", \
|
||||
__FILE__, __LINE__, ## __VA_ARGS__); \
|
||||
} while (0)
|
||||
#define KWARNF(FMT, ...) \
|
||||
do { \
|
||||
uprintf("\r\e[94;49mwarn: %s:%d: " FMT "\e[0m\n", \
|
||||
__FILE__, __LINE__, ## __VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define KINFOF(FMT, ...) ((void)0)
|
||||
#define KWARNF(FMT, ...) ((void)0)
|
||||
#endif
|
||||
#define KDIEF(FMT, ...) \
|
||||
do { \
|
||||
kprintf("\r\e[30;101mfatal: %s:%d: " FMT "\e[0m\n", \
|
||||
__FILE__, __LINE__, ## __VA_ARGS__); \
|
||||
for (;;) asm volatile("cli\n\thlt"); \
|
||||
} while (0)
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* _COSMO_SOURCE */
|
||||
|
|
|
@ -33,8 +33,8 @@
|
|||
#ifdef __x86_64__
|
||||
|
||||
/*
|
||||
* @fileoverview Instantiation of routines for emergency or system console
|
||||
* output in graphical video modes.
|
||||
* @fileoverview Instantiation of routines for emergency console output in
|
||||
* graphical video modes.
|
||||
*
|
||||
* @see libc/vga/tty-graph.inc
|
||||
*/
|
||||
|
|
|
@ -25,7 +25,10 @@
|
|||
│ OTHER DEALINGS IN THE SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/runtime/pc.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/vga/vga.internal.h"
|
||||
|
||||
|
@ -72,4 +75,47 @@ textstartup void _vga_init(void) {
|
|||
}
|
||||
}
|
||||
|
||||
#if !IsTiny()
|
||||
/**
|
||||
* Non-emergency console vprintf(), useful for dumping debugging or
|
||||
* informational messages at program startup.
|
||||
*
|
||||
* @see uprintf()
|
||||
*/
|
||||
void uvprintf(const char *fmt, va_list v) {
|
||||
if (!IsMetal()) {
|
||||
kvprintf(fmt, v);
|
||||
} else {
|
||||
long size = __get_safe_size(8000, 3000);
|
||||
char *buf = alloca(size);
|
||||
CheckLargeStackAllocation(buf, size);
|
||||
size_t count = kvsnprintf(buf, size, fmt, v);
|
||||
if (count >= size) count = size - 1;
|
||||
_TtyWrite(&_vga_tty, buf, count);
|
||||
_klog_serial(buf, count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Non-emergency console printf(), useful for dumping debugging or
|
||||
* informational messages at program startup.
|
||||
*
|
||||
* uprintf() is similar to kprintf(), but on bare metal with VGA support, it
|
||||
* uses the normal, fast graphical console, rather than initializing an
|
||||
* emergency console. This makes uprintf() faster — on bare metal — at the
|
||||
* expense of being less crash-proof.
|
||||
*
|
||||
* (The uprintf() function name comes from the FreeBSD kernel.)
|
||||
*
|
||||
* @see kprintf()
|
||||
* @see https://man.freebsd.org/cgi/man.cgi?query=uprintf&sektion=9&n=1
|
||||
*/
|
||||
void uprintf(const char *fmt, ...) {
|
||||
va_list v;
|
||||
va_start(v, fmt);
|
||||
uvprintf(fmt, v);
|
||||
va_end(v);
|
||||
}
|
||||
#endif /* !IsTiny() */
|
||||
|
||||
#endif /* __x86_64__ */
|
||||
|
|
|
@ -255,8 +255,7 @@ void _TtyGraphMoveLineCells(struct Tty *, size_t, size_t, size_t, size_t,
|
|||
size_t);
|
||||
|
||||
/*
|
||||
* Routines that implement emergency or system console output in graphical
|
||||
* video modes.
|
||||
* Routines that implement emergency console output in graphical video modes.
|
||||
*/
|
||||
void _TtyKlog16Update(struct Tty *);
|
||||
void _TtyKlog16DrawChar(struct Tty *, size_t, size_t, wchar_t);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue