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
|
#endif
|
||||||
|
|
||||||
#define __weak_reference(sym, alias) \
|
#define __weak_reference(sym, alias) \
|
||||||
|
__weak_reference_impl(sym, alias)
|
||||||
|
#define __weak_reference_impl(sym, alias) \
|
||||||
__asm__(".weak\t" #alias "\n\t" \
|
__asm__(".weak\t" #alias "\n\t" \
|
||||||
".equ\t" #alias ", " #sym "\n\t" \
|
".equ\t" #alias ", " #sym "\n\t" \
|
||||||
".type\t" #alias ",@notype")
|
".type\t" #alias ",@notype")
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/runtime/pc.internal.h"
|
#include "libc/runtime/pc.internal.h"
|
||||||
|
|
||||||
// Code and data structures for bare metal interrupt handling.
|
// Code and data structures for bare metal interrupt handling.
|
||||||
|
|
|
@ -385,14 +385,29 @@ privileged long kloghandle(void) {
|
||||||
return __klog_handle;
|
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) {
|
privileged void klog(const char *b, size_t n) {
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
int e;
|
int e;
|
||||||
long h;
|
long h;
|
||||||
size_t i;
|
|
||||||
uint16_t dx;
|
|
||||||
uint32_t wrote;
|
uint32_t wrote;
|
||||||
unsigned char al;
|
|
||||||
long rax, rdi, rsi, rdx;
|
long rax, rdi, rsi, rdx;
|
||||||
if ((h = kloghandle()) == -1) {
|
if ((h = kloghandle()) == -1) {
|
||||||
return;
|
return;
|
||||||
|
@ -407,18 +422,7 @@ privileged void klog(const char *b, size_t n) {
|
||||||
if (_weaken(_klog_vga)) {
|
if (_weaken(_klog_vga)) {
|
||||||
_weaken(_klog_vga)(b, n);
|
_weaken(_klog_vga)(b, n);
|
||||||
}
|
}
|
||||||
for (i = 0; i < n; ++i) {
|
_klog_serial(b, n);
|
||||||
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));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
asm volatile("syscall"
|
asm volatile("syscall"
|
||||||
: "=a"(rax), "=D"(rdi), "=S"(rsi), "=d"(rdx)
|
: "=a"(rax), "=D"(rdi), "=S"(rsi), "=d"(rdx)
|
||||||
|
@ -1152,3 +1156,6 @@ privileged void kprintf(const char *fmt, ...) {
|
||||||
kvprintf(fmt, v);
|
kvprintf(fmt, v);
|
||||||
va_end(v);
|
va_end(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__weak_reference(kprintf, uprintf);
|
||||||
|
__weak_reference(kvprintf, uvprintf);
|
||||||
|
|
|
@ -9,25 +9,49 @@
|
||||||
#define kvsnprintf __kvsnprintf
|
#define kvsnprintf __kvsnprintf
|
||||||
#define kloghandle __kloghandle
|
#define kloghandle __kloghandle
|
||||||
#define kisdangerous __kisdangerous
|
#define kisdangerous __kisdangerous
|
||||||
|
#define uprintf __uprintf
|
||||||
|
#define uvprintf __uvprintf
|
||||||
|
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
|
|
||||||
COSMOPOLITAN_C_START_
|
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 *, ...);
|
void kprintf(const char *, ...);
|
||||||
size_t ksnprintf(char *, size_t, const char *, ...);
|
size_t ksnprintf(char *, size_t, const char *, ...);
|
||||||
void kvprintf(const char *, va_list);
|
void kvprintf(const char *, va_list);
|
||||||
size_t kvsnprintf(char *, size_t, const char *, va_list);
|
size_t kvsnprintf(char *, size_t, const char *, va_list);
|
||||||
|
|
||||||
bool kisdangerous(const void *);
|
bool kisdangerous(const void *);
|
||||||
|
|
||||||
void klog(const char *, size_t);
|
void klog(const char *, size_t);
|
||||||
|
void _klog_serial(const char *, size_t);
|
||||||
long kloghandle(void);
|
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_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
#endif /* _COSMO_SOURCE */
|
#endif /* _COSMO_SOURCE */
|
||||||
|
|
|
@ -33,8 +33,8 @@
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @fileoverview Instantiation of routines for emergency or system console
|
* @fileoverview Instantiation of routines for emergency console output in
|
||||||
* output in graphical video modes.
|
* graphical video modes.
|
||||||
*
|
*
|
||||||
* @see libc/vga/tty-graph.inc
|
* @see libc/vga/tty-graph.inc
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -25,7 +25,10 @@
|
||||||
│ OTHER DEALINGS IN THE SOFTWARE. │
|
│ OTHER DEALINGS IN THE SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/runtime/pc.internal.h"
|
#include "libc/runtime/pc.internal.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/runtime/stack.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/vga/vga.internal.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__ */
|
#endif /* __x86_64__ */
|
||||||
|
|
|
@ -255,8 +255,7 @@ void _TtyGraphMoveLineCells(struct Tty *, size_t, size_t, size_t, size_t,
|
||||||
size_t);
|
size_t);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Routines that implement emergency or system console output in graphical
|
* Routines that implement emergency console output in graphical video modes.
|
||||||
* video modes.
|
|
||||||
*/
|
*/
|
||||||
void _TtyKlog16Update(struct Tty *);
|
void _TtyKlog16Update(struct Tty *);
|
||||||
void _TtyKlog16DrawChar(struct Tty *, size_t, size_t, wchar_t);
|
void _TtyKlog16DrawChar(struct Tty *, size_t, size_t, wchar_t);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue