mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-08 19:00:27 +00:00
[metal] VGA console can now show "screen of death" upon a crash
There is now a new function _klog_vga(), which can be called by kprintf() to output system messages — e.g. information about CPU exceptions — on the VGA screen.
This commit is contained in:
parent
7059a7109d
commit
5aaadf1162
7 changed files with 595 additions and 315 deletions
|
@ -55,6 +55,7 @@
|
|||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/thread/tls.h"
|
||||
#include "libc/thread/tls2.h"
|
||||
#include "libc/vga/vga.internal.h"
|
||||
|
||||
extern hidden struct SymbolTable *__symtab;
|
||||
|
||||
|
@ -188,6 +189,7 @@ privileged static void klog(const char *b, size_t n) {
|
|||
: /* no inputs */
|
||||
: "a"(b[i]), "dN"(dx));
|
||||
}
|
||||
if (_weaken(_klog_vga)) _weaken(_klog_vga)(b, n);
|
||||
} else {
|
||||
asm volatile("syscall"
|
||||
: "=a"(rax), "=D"(rdi), "=S"(rsi), "=d"(rdx)
|
||||
|
|
|
@ -30,258 +30,24 @@
|
|||
#include "libc/vga/vga.internal.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Routines to support output in graphical video modes for
|
||||
* bare metal VGA.
|
||||
* @fileoverview Instantiation of routines for normal console output in
|
||||
* graphical video modes.
|
||||
*
|
||||
* @see libc/vga/tty.c
|
||||
* @see libc/vga/tty-graph.inc
|
||||
*/
|
||||
|
||||
static void TtyDirty(struct Tty *tty, size_t gy1, size_t gx1,
|
||||
size_t gy2, size_t gx2) {
|
||||
if (tty->updy1 > gy1) tty->updy1 = gy1;
|
||||
if (tty->updx1 > gx1) tty->updx1 = gx1;
|
||||
if (tty->updy2 < gy2) tty->updy2 = gy2;
|
||||
if (tty->updx2 < gx2) tty->updx2 = gx2;
|
||||
}
|
||||
#undef KLOGTTY
|
||||
|
||||
static void TtyResetDirty(struct Tty *tty) {
|
||||
tty->updy1 = tty->updx1 = tty->updy2 = tty->updx2 = 0;
|
||||
}
|
||||
|
||||
unrollloops void _TtyBgr565Update(struct Tty *tty) {
|
||||
size_t gy1 = tty->updy1, gy2 = tty->updy2,
|
||||
gx1 = tty->updx1, gx2 = tty->updx2,
|
||||
xsfb = tty->xsfb, xs = tty->xs;
|
||||
if (gy1 < gy2 && gx1 < gx2) {
|
||||
size_t yleft = gy2 - gy1, xleft;
|
||||
char *cplotter = tty->fb + gy1 * xsfb + gx1 * sizeof(TtyBgr565Color);
|
||||
const char *creader = tty->canvas + gy1 * xs
|
||||
+ gx1 * sizeof(TtyCanvasColor);
|
||||
TtyResetDirty(tty);
|
||||
while (yleft-- != 0) {
|
||||
TtyBgr565Color *plotter = (TtyBgr565Color *)cplotter;
|
||||
const TtyCanvasColor *reader = (const TtyCanvasColor *)creader;
|
||||
TtyCanvasColor c;
|
||||
xleft = gx2 - gx1;
|
||||
while (xleft-- != 0) {
|
||||
uint16_t w;
|
||||
c.w = reader->w;
|
||||
++reader;
|
||||
w = htole16(c.bgr.b >> 3 | c.bgr.g >> 2 << 5 | c.bgr.r >> 3 << 11);
|
||||
*plotter++ = (TtyBgr565Color){w};
|
||||
}
|
||||
cplotter += xsfb;
|
||||
creader += xs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unrollloops void _TtyBgr555Update(struct Tty *tty) {
|
||||
size_t gy1 = tty->updy1, gy2 = tty->updy2,
|
||||
gx1 = tty->updx1, gx2 = tty->updx2,
|
||||
xsfb = tty->xsfb, xs = tty->xs;
|
||||
if (gy1 < gy2 && gx1 < gx2) {
|
||||
size_t yleft = gy2 - gy1, xleft;
|
||||
char *cplotter = tty->fb + gy1 * xsfb + gx1 * sizeof(TtyBgr555Color);
|
||||
const char *creader = tty->canvas + gy1 * xs
|
||||
+ gx1 * sizeof(TtyCanvasColor);
|
||||
TtyResetDirty(tty);
|
||||
while (yleft-- != 0) {
|
||||
TtyBgr555Color *plotter = (TtyBgr555Color *)cplotter;
|
||||
const TtyCanvasColor *reader = (const TtyCanvasColor *)creader;
|
||||
TtyCanvasColor c;
|
||||
xleft = gx2 - gx1;
|
||||
while (xleft-- != 0) {
|
||||
uint16_t w;
|
||||
c.w = reader->w;
|
||||
++reader;
|
||||
w = htole16(c.bgr.b >> 3 | c.bgr.g >> 3 << 5 | c.bgr.r >> 3 << 10);
|
||||
*plotter++ = (TtyBgr555Color){w};
|
||||
}
|
||||
cplotter += xsfb;
|
||||
creader += xs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unrollloops void _TtyBgrxUpdate(struct Tty *tty) {
|
||||
size_t gy1 = tty->updy1, gy2 = tty->updy2,
|
||||
gx1 = tty->updx1, gx2 = tty->updx2,
|
||||
xsfb = tty->xsfb, xs = tty->xs;
|
||||
if (gy1 < gy2 && gx1 < gx2) {
|
||||
size_t yleft = gy2 - gy1, xleft;
|
||||
char *cplotter = tty->fb + gy1 * xsfb + gx1 * sizeof(TtyBgrxColor);
|
||||
const char *creader = tty->canvas + gy1 * xs
|
||||
+ gx1 * sizeof(TtyCanvasColor);
|
||||
TtyResetDirty(tty);
|
||||
while (yleft-- != 0) {
|
||||
TtyBgrxColor *plotter = (TtyBgrxColor *)cplotter;
|
||||
const TtyCanvasColor *reader = (const TtyCanvasColor *)creader;
|
||||
xleft = gx2 - gx1;
|
||||
while (xleft-- != 0) {
|
||||
TtyCanvasColor c = *reader++;
|
||||
c.bgr.x = 0xff;
|
||||
*plotter++ = c;
|
||||
}
|
||||
cplotter += xsfb;
|
||||
creader += xs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unrollloops void _TtyRgbxUpdate(struct Tty *tty) {
|
||||
size_t gy1 = tty->updy1, gy2 = tty->updy2,
|
||||
gx1 = tty->updx1, gx2 = tty->updx2,
|
||||
xsfb = tty->xsfb, xs = tty->xs;
|
||||
if (gy1 < gy2 && gx1 < gx2) {
|
||||
size_t yleft = gy2 - gy1, xleft;
|
||||
char *cplotter = tty->fb + gy1 * xsfb + gx1 * sizeof(TtyRgbxColor);
|
||||
const char *creader = tty->canvas + gy1 * xs
|
||||
+ gx1 * sizeof(TtyCanvasColor);
|
||||
TtyResetDirty(tty);
|
||||
while (yleft-- != 0) {
|
||||
TtyRgbxColor *plotter = (TtyRgbxColor *)cplotter;
|
||||
const TtyCanvasColor *reader = (const TtyCanvasColor *)creader;
|
||||
TtyCanvasColor ic;
|
||||
TtyRgbxColor oc;
|
||||
xleft = gx2 - gx1;
|
||||
while (xleft-- != 0) {
|
||||
ic.w = reader->w;
|
||||
++reader;
|
||||
oc = (TtyRgbxColor){.rgb.r = ic.bgr.r, .rgb.g = ic.bgr.g,
|
||||
.rgb.b = ic.bgr.b, .rgb.x = 0xff};
|
||||
plotter->w = oc.w;
|
||||
++plotter;
|
||||
}
|
||||
cplotter += xsfb;
|
||||
creader += xs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void TtyGraphDrawBitmap(struct Tty *tty, size_t gy, size_t gx,
|
||||
TtyCanvasColor fg, TtyCanvasColor bg,
|
||||
const uint8_t *bitmap,
|
||||
size_t bm_ht, size_t bm_wid) {
|
||||
size_t xs = tty->xs;
|
||||
char *cplotter = tty->canvas + gy * xs
|
||||
+ gx * sizeof(TtyCanvasColor);
|
||||
size_t yleft = bm_ht, xleft;
|
||||
while (yleft-- != 0) {
|
||||
TtyCanvasColor *plotter = (TtyCanvasColor *)cplotter;
|
||||
xleft = bm_wid;
|
||||
while (xleft >= 8) {
|
||||
uint8_t bits = *bitmap++;
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
xleft -= 8;
|
||||
}
|
||||
if (xleft) {
|
||||
uint8_t bits = *bitmap++;
|
||||
switch (xleft) {
|
||||
default:
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
/* fall through */
|
||||
case 6:
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
/* fall through */
|
||||
case 5:
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
/* fall through */
|
||||
case 4:
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
/* fall through */
|
||||
case 3:
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
/* fall through */
|
||||
case 2:
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
/* fall through */
|
||||
case 1:
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
}
|
||||
}
|
||||
cplotter += xs;
|
||||
}
|
||||
TtyDirty(tty, gy, gx, gy + bm_ht, gx + bm_wid);
|
||||
}
|
||||
|
||||
static unrollloops void TtyGraphFillRect(struct Tty *tty,
|
||||
size_t gy, size_t gx,
|
||||
size_t fill_ht, size_t fill_wid,
|
||||
TtyCanvasColor bg) {
|
||||
size_t xs = tty->xs;
|
||||
char *cplotter = tty->canvas + gy * xs + gx * sizeof(TtyCanvasColor);
|
||||
size_t yleft = fill_ht, xleft;
|
||||
while (yleft-- != 0) {
|
||||
TtyCanvasColor *plotter = (TtyCanvasColor *)cplotter;
|
||||
size_t i;
|
||||
for (i = 0; i < fill_wid; ++i)
|
||||
*plotter++ = bg;
|
||||
cplotter += xs;
|
||||
}
|
||||
TtyDirty(tty, gy, gx, gy + fill_ht, gx + fill_wid);
|
||||
}
|
||||
|
||||
static void TtyGraphMoveRect(struct Tty *tty, size_t dgy, size_t dgx,
|
||||
size_t sgy, size_t sgx, size_t ht, size_t wid) {
|
||||
size_t xs = tty->xs, xm = wid * sizeof(TtyCanvasColor);
|
||||
char *canvas = tty->canvas;
|
||||
TtyDirty(tty, dgy, dgx, dgy + ht, dgx + wid);
|
||||
if (dgy < sgy) {
|
||||
while (ht-- != 0) {
|
||||
memmove(canvas + dgy * xs + dgx * sizeof(TtyCanvasColor),
|
||||
canvas + sgy * xs + sgx * sizeof(TtyCanvasColor), xm);
|
||||
++dgy;
|
||||
++sgy;
|
||||
}
|
||||
} else if (dgy > sgy) {
|
||||
while (ht-- != 0)
|
||||
memmove(canvas + (dgy + ht) * xs + dgx * sizeof(TtyCanvasColor),
|
||||
canvas + (sgy + ht) * xs + sgx * sizeof(TtyCanvasColor), xm);
|
||||
}
|
||||
}
|
||||
|
||||
void _TtyGraphDrawChar(struct Tty *tty, size_t y, size_t x, wchar_t wc) {
|
||||
/* TODO: allow configuring a different font later. */
|
||||
const uint8_t *glyph;
|
||||
const size_t glyph_ht = ARRAYLEN(_vga_font_default_direct[0]);
|
||||
TtyCanvasColor fg = tty->fg, bg = tty->bg;
|
||||
if ((tty->pr & kTtyFlip) != 0)
|
||||
fg = bg, bg = tty->fg;
|
||||
if (wc < L' ' || wc >= L' ' + ARRAYLEN(_vga_font_default_direct))
|
||||
glyph = _vga_font_default_direct[0];
|
||||
else
|
||||
glyph = _vga_font_default_direct[wc - L' '];
|
||||
if (glyph_ht >= VGA_ASSUME_CHAR_HEIGHT_PX)
|
||||
TtyGraphDrawBitmap(tty, y * tty->yc, x * tty->xc, fg, bg,
|
||||
glyph, VGA_ASSUME_CHAR_HEIGHT_PX, 8);
|
||||
else {
|
||||
/*
|
||||
* Glyph is not tall enough. Draw it out, then pad the bottom of the
|
||||
* character cell with the background color.
|
||||
*/
|
||||
TtyGraphDrawBitmap(tty, y * tty->yc, x * tty->xc, fg, bg,
|
||||
glyph, glyph_ht, 8);
|
||||
TtyGraphFillRect(tty, y * tty->yc + glyph_ht, x * tty->xc,
|
||||
VGA_ASSUME_CHAR_HEIGHT_PX - glyph_ht, 8, bg);
|
||||
}
|
||||
}
|
||||
|
||||
void _TtyGraphEraseLineCells(struct Tty *tty, size_t y, size_t x, size_t n) {
|
||||
size_t yc = tty->yc, xc = tty->xc;
|
||||
TtyGraphFillRect(tty, y * yc, x * xc, yc, n * xc, tty->bg);
|
||||
}
|
||||
|
||||
void _TtyGraphMoveLineCells(struct Tty *tty, size_t dsty, size_t dstx,
|
||||
size_t srcy, size_t srcx, size_t n) {
|
||||
size_t yc = tty->yc, xc = tty->xc;
|
||||
TtyGraphMoveRect(tty, dsty * yc, dstx * xc, srcy * yc, srcx * xc,
|
||||
yc, n * xc);
|
||||
}
|
||||
#define COLOR TtyCanvasColor
|
||||
#define BPP 32
|
||||
#define MAPCOLOR TtyGraphMapColor
|
||||
#define DIRTY TtyGraphDirty
|
||||
#undef UPDATE
|
||||
#define RESETDIRTY TtyGraphResetDirty
|
||||
#define DRAWBITMAP TtyGraphDrawBitmap
|
||||
#define FILLRECT TtyGraphFillRect
|
||||
#define MOVERECT TtyGraphMoveRect
|
||||
#define DRAWCHAR _TtyGraphDrawChar
|
||||
#define ERASELINECELLS _TtyGraphEraseLineCells
|
||||
#define MOVELINECELLS _TtyGraphMoveLineCells
|
||||
#include "libc/vga/tty-graph.inc"
|
||||
|
|
329
libc/vga/tty-graph.inc
Normal file
329
libc/vga/tty-graph.inc
Normal file
|
@ -0,0 +1,329 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ This is free and unencumbered software released into the public domain. │
|
||||
│ │
|
||||
│ Anyone is free to copy, modify, publish, use, compile, sell, or │
|
||||
│ distribute this software, either in source code form or as a compiled │
|
||||
│ binary, for any purpose, commercial or non-commercial, and by any │
|
||||
│ means. │
|
||||
│ │
|
||||
│ In jurisdictions that recognize copyright laws, the author or authors │
|
||||
│ of this software dedicate any and all copyright interest in the │
|
||||
│ software to the public domain. We make this dedication for the benefit │
|
||||
│ of the public at large and to the detriment of our heirs and │
|
||||
│ successors. We intend this dedication to be an overt act of │
|
||||
│ relinquishment in perpetuity of all present and future rights to this │
|
||||
│ software under copyright law. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │
|
||||
│ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │
|
||||
│ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │
|
||||
│ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR │
|
||||
│ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
|
||||
│ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR │
|
||||
│ OTHER DEALINGS IN THE SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/newbie.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/vga/vga.internal.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Template for routines to support output in graphical video
|
||||
* modes for bare metal VGA.
|
||||
*
|
||||
* If KLOGTTY is undefined, this file expands to code that writes to a
|
||||
* separate off-screen canvas buffer — which should be allocated beforehand
|
||||
* — before drawing to the actual video memory.
|
||||
*
|
||||
* If KLOGTTY is defined, this file instead expands to code that can
|
||||
* implement an emergency console. The graphics routines will directly write
|
||||
* to video memory. This may result in slower output, but will work even if
|
||||
* we cannot allocate an off-screen canvas for whatever reason.
|
||||
*
|
||||
* @see libc/vga/tty.greg.c
|
||||
* @see libc/vga/tty-graph.c
|
||||
* @see libc/vga/tty-klog.greg.c
|
||||
*/
|
||||
|
||||
#ifndef KLOGTTY
|
||||
|
||||
static COLOR MAPCOLOR(struct Tty *tty, TtyCanvasColor ic) {
|
||||
return ic;
|
||||
}
|
||||
|
||||
static void DIRTY(struct Tty *tty, size_t gy1, size_t gx1,
|
||||
size_t gy2, size_t gx2) {
|
||||
if (tty->updy1 > gy1) tty->updy1 = gy1;
|
||||
if (tty->updx1 > gx1) tty->updx1 = gx1;
|
||||
if (tty->updy2 < gy2) tty->updy2 = gy2;
|
||||
if (tty->updx2 < gx2) tty->updx2 = gx2;
|
||||
}
|
||||
|
||||
static void RESETDIRTY(struct Tty *tty) {
|
||||
tty->updy1 = tty->updx1 = tty->updy2 = tty->updx2 = 0;
|
||||
}
|
||||
|
||||
unrollloops void _TtyBgr565Update(struct Tty *tty) {
|
||||
size_t gy1 = tty->updy1, gy2 = tty->updy2,
|
||||
gx1 = tty->updx1, gx2 = tty->updx2,
|
||||
xsfb = tty->xsfb, xs = tty->xs;
|
||||
if (gy1 < gy2 && gx1 < gx2) {
|
||||
size_t yleft = gy2 - gy1, xleft;
|
||||
char *cplotter = tty->fb + gy1 * xsfb + gx1 * sizeof(TtyBgr565Color);
|
||||
const char *creader = tty->canvas + gy1 * xs
|
||||
+ gx1 * sizeof(TtyCanvasColor);
|
||||
RESETDIRTY(tty);
|
||||
while (yleft-- != 0) {
|
||||
TtyBgr565Color *plotter = (TtyBgr565Color *)cplotter;
|
||||
const TtyCanvasColor *reader = (const TtyCanvasColor *)creader;
|
||||
TtyCanvasColor c;
|
||||
xleft = gx2 - gx1;
|
||||
while (xleft-- != 0) {
|
||||
uint16_t w;
|
||||
c.w = reader->w;
|
||||
++reader;
|
||||
w = htole16(c.bgr.b >> 3 | c.bgr.g >> 2 << 5 | c.bgr.r >> 3 << 11);
|
||||
*plotter++ = (TtyBgr565Color){w};
|
||||
}
|
||||
cplotter += xsfb;
|
||||
creader += xs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unrollloops void _TtyBgr555Update(struct Tty *tty) {
|
||||
size_t gy1 = tty->updy1, gy2 = tty->updy2,
|
||||
gx1 = tty->updx1, gx2 = tty->updx2,
|
||||
xsfb = tty->xsfb, xs = tty->xs;
|
||||
if (gy1 < gy2 && gx1 < gx2) {
|
||||
size_t yleft = gy2 - gy1, xleft;
|
||||
char *cplotter = tty->fb + gy1 * xsfb + gx1 * sizeof(TtyBgr555Color);
|
||||
const char *creader = tty->canvas + gy1 * xs
|
||||
+ gx1 * sizeof(TtyCanvasColor);
|
||||
RESETDIRTY(tty);
|
||||
while (yleft-- != 0) {
|
||||
TtyBgr555Color *plotter = (TtyBgr555Color *)cplotter;
|
||||
const TtyCanvasColor *reader = (const TtyCanvasColor *)creader;
|
||||
TtyCanvasColor c;
|
||||
xleft = gx2 - gx1;
|
||||
while (xleft-- != 0) {
|
||||
uint16_t w;
|
||||
c.w = reader->w;
|
||||
++reader;
|
||||
w = htole16(c.bgr.b >> 3 | c.bgr.g >> 3 << 5 | c.bgr.r >> 3 << 10);
|
||||
*plotter++ = (TtyBgr555Color){w};
|
||||
}
|
||||
cplotter += xsfb;
|
||||
creader += xs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unrollloops void _TtyBgrxUpdate(struct Tty *tty) {
|
||||
size_t gy1 = tty->updy1, gy2 = tty->updy2,
|
||||
gx1 = tty->updx1, gx2 = tty->updx2,
|
||||
xsfb = tty->xsfb, xs = tty->xs;
|
||||
if (gy1 < gy2 && gx1 < gx2) {
|
||||
size_t yleft = gy2 - gy1, xleft;
|
||||
char *cplotter = tty->fb + gy1 * xsfb + gx1 * sizeof(TtyBgrxColor);
|
||||
const char *creader = tty->canvas + gy1 * xs
|
||||
+ gx1 * sizeof(TtyCanvasColor);
|
||||
RESETDIRTY(tty);
|
||||
while (yleft-- != 0) {
|
||||
TtyBgrxColor *plotter = (TtyBgrxColor *)cplotter;
|
||||
const TtyCanvasColor *reader = (const TtyCanvasColor *)creader;
|
||||
xleft = gx2 - gx1;
|
||||
while (xleft-- != 0) {
|
||||
TtyCanvasColor c = *reader++;
|
||||
c.bgr.x = 0xff;
|
||||
*plotter++ = c;
|
||||
}
|
||||
cplotter += xsfb;
|
||||
creader += xs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unrollloops void _TtyRgbxUpdate(struct Tty *tty) {
|
||||
size_t gy1 = tty->updy1, gy2 = tty->updy2,
|
||||
gx1 = tty->updx1, gx2 = tty->updx2,
|
||||
xsfb = tty->xsfb, xs = tty->xs;
|
||||
if (gy1 < gy2 && gx1 < gx2) {
|
||||
size_t yleft = gy2 - gy1, xleft;
|
||||
char *cplotter = tty->fb + gy1 * xsfb + gx1 * sizeof(TtyRgbxColor);
|
||||
const char *creader = tty->canvas + gy1 * xs
|
||||
+ gx1 * sizeof(TtyCanvasColor);
|
||||
RESETDIRTY(tty);
|
||||
while (yleft-- != 0) {
|
||||
TtyRgbxColor *plotter = (TtyRgbxColor *)cplotter;
|
||||
const TtyCanvasColor *reader = (const TtyCanvasColor *)creader;
|
||||
TtyCanvasColor ic;
|
||||
TtyRgbxColor oc;
|
||||
xleft = gx2 - gx1;
|
||||
while (xleft-- != 0) {
|
||||
ic.w = reader->w;
|
||||
++reader;
|
||||
oc = (TtyRgbxColor){.rgb.r = ic.bgr.r, .rgb.g = ic.bgr.g,
|
||||
.rgb.b = ic.bgr.b, .rgb.x = 0xff};
|
||||
plotter->w = oc.w;
|
||||
++plotter;
|
||||
}
|
||||
cplotter += xsfb;
|
||||
creader += xs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else /* KLOGTTY */
|
||||
|
||||
static COLOR MAPCOLOR(struct Tty *tty, TtyCanvasColor ic) {
|
||||
#if BPP == 16
|
||||
if (tty->type == PC_VIDEO_BGR565)
|
||||
return htole16(ic.bgr.b >> 3 | ic.bgr.g >> 2 << 5 | ic.bgr.r >> 3 << 11);
|
||||
else
|
||||
return htole16(ic.bgr.b >> 3 | ic.bgr.g >> 3 << 5 | ic.bgr.r >> 3 << 10);
|
||||
#else
|
||||
if (tty->type == PC_VIDEO_BGRX8888)
|
||||
return ic.w;
|
||||
else {
|
||||
TtyRgbxColor oc = (TtyRgbxColor){.rgb.r = ic.bgr.r, .rgb.g = ic.bgr.g,
|
||||
.rgb.b = ic.bgr.b, .rgb.x = 0xff};
|
||||
return oc.w;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void DIRTY(struct Tty *tty, size_t gy1, size_t gx1,
|
||||
size_t gy2, size_t gx2) {
|
||||
}
|
||||
|
||||
static void RESETDIRTY(struct Tty *tty) {
|
||||
}
|
||||
|
||||
void UPDATE(struct Tty *tty) {
|
||||
}
|
||||
|
||||
#endif /* KLOGTTY */
|
||||
|
||||
static void DRAWBITMAP(struct Tty *tty, size_t gy, size_t gx,
|
||||
COLOR fg, COLOR bg, const uint8_t *bitmap,
|
||||
size_t bm_ht, size_t bm_wid) {
|
||||
size_t xs = tty->xs;
|
||||
char *cplotter = tty->canvas + gy * xs + gx * sizeof(COLOR);
|
||||
size_t yleft = bm_ht, xleft;
|
||||
while (yleft-- != 0) {
|
||||
COLOR *plotter = (COLOR *)cplotter;
|
||||
xleft = bm_wid;
|
||||
while (xleft >= 8) {
|
||||
uint8_t bits = *bitmap++;
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
xleft -= 8;
|
||||
}
|
||||
if (xleft) {
|
||||
uint8_t bits = *bitmap++;
|
||||
switch (xleft) {
|
||||
default:
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
/* fall through */
|
||||
case 6:
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
/* fall through */
|
||||
case 5:
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
/* fall through */
|
||||
case 4:
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
/* fall through */
|
||||
case 3:
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
/* fall through */
|
||||
case 2:
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
/* fall through */
|
||||
case 1:
|
||||
*plotter++ = __builtin_add_overflow(bits, bits, &bits) ? fg : bg;
|
||||
}
|
||||
}
|
||||
cplotter += xs;
|
||||
}
|
||||
DIRTY(tty, gy, gx, gy + bm_ht, gx + bm_wid);
|
||||
}
|
||||
|
||||
static unrollloops void FILLRECT(struct Tty *tty, size_t gy, size_t gx,
|
||||
size_t fill_ht, size_t fill_wid, COLOR bg) {
|
||||
size_t xs = tty->xs;
|
||||
char *cplotter = tty->canvas + gy * xs + gx * sizeof(COLOR);
|
||||
size_t yleft = fill_ht, xleft;
|
||||
while (yleft-- != 0) {
|
||||
COLOR *plotter = (COLOR *)cplotter;
|
||||
size_t i;
|
||||
for (i = 0; i < fill_wid; ++i)
|
||||
*plotter++ = bg;
|
||||
cplotter += xs;
|
||||
}
|
||||
DIRTY(tty, gy, gx, gy + fill_ht, gx + fill_wid);
|
||||
}
|
||||
|
||||
static void MOVERECT(struct Tty *tty, size_t dgy, size_t dgx,
|
||||
size_t sgy, size_t sgx, size_t ht, size_t wid) {
|
||||
size_t xs = tty->xs, xm = wid * sizeof(COLOR);
|
||||
char *canvas = tty->canvas;
|
||||
DIRTY(tty, dgy, dgx, dgy + ht, dgx + wid);
|
||||
if (dgy < sgy) {
|
||||
while (ht-- != 0) {
|
||||
memmove(canvas + dgy * xs + dgx * sizeof(COLOR),
|
||||
canvas + sgy * xs + sgx * sizeof(COLOR), xm);
|
||||
++dgy;
|
||||
++sgy;
|
||||
}
|
||||
} else if (dgy > sgy) {
|
||||
while (ht-- != 0)
|
||||
memmove(canvas + (dgy + ht) * xs + dgx * sizeof(COLOR),
|
||||
canvas + (sgy + ht) * xs + sgx * sizeof(COLOR), xm);
|
||||
}
|
||||
}
|
||||
|
||||
void DRAWCHAR(struct Tty *tty, size_t y, size_t x, wchar_t wc) {
|
||||
/* TODO: allow configuring a different font later. */
|
||||
const uint8_t *glyph;
|
||||
const size_t glyph_ht = ARRAYLEN(_vga_font_default_direct[0]);
|
||||
COLOR fg = MAPCOLOR(tty, tty->fg), bg = MAPCOLOR(tty, tty->bg);
|
||||
if ((tty->pr & kTtyFlip) != 0)
|
||||
fg = bg, bg = MAPCOLOR(tty, tty->fg);
|
||||
if (wc < L' ' || wc >= L' ' + ARRAYLEN(_vga_font_default_direct))
|
||||
glyph = _vga_font_default_direct[0];
|
||||
else
|
||||
glyph = _vga_font_default_direct[wc - L' '];
|
||||
if (glyph_ht >= VGA_ASSUME_CHAR_HEIGHT_PX)
|
||||
DRAWBITMAP(tty, y * tty->yc, x * tty->xc, fg, bg, glyph,
|
||||
VGA_ASSUME_CHAR_HEIGHT_PX, 8);
|
||||
else {
|
||||
/*
|
||||
* Glyph is not tall enough. Draw it out, then pad the bottom of the
|
||||
* character cell with the background color.
|
||||
*/
|
||||
DRAWBITMAP(tty, y * tty->yc, x * tty->xc, fg, bg, glyph, glyph_ht, 8);
|
||||
FILLRECT(tty, y * tty->yc + glyph_ht, x * tty->xc,
|
||||
VGA_ASSUME_CHAR_HEIGHT_PX - glyph_ht, 8, bg);
|
||||
}
|
||||
}
|
||||
|
||||
void ERASELINECELLS(struct Tty *tty, size_t y, size_t x, size_t n) {
|
||||
size_t yc = tty->yc, xc = tty->xc;
|
||||
FILLRECT(tty, y * yc, x * xc, yc, n * xc, MAPCOLOR(tty, tty->bg));
|
||||
}
|
||||
|
||||
void MOVELINECELLS(struct Tty *tty, size_t dsty, size_t dstx,
|
||||
size_t srcy, size_t srcx, size_t n) {
|
||||
size_t yc = tty->yc, xc = tty->xc;
|
||||
MOVERECT(tty, dsty * yc, dstx * xc, srcy * yc, srcx * xc, yc, n * xc);
|
||||
}
|
94
libc/vga/tty-klog.greg.c
Normal file
94
libc/vga/tty-klog.greg.c
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ This is free and unencumbered software released into the public domain. │
|
||||
│ │
|
||||
│ Anyone is free to copy, modify, publish, use, compile, sell, or │
|
||||
│ distribute this software, either in source code form or as a compiled │
|
||||
│ binary, for any purpose, commercial or non-commercial, and by any │
|
||||
│ means. │
|
||||
│ │
|
||||
│ In jurisdictions that recognize copyright laws, the author or authors │
|
||||
│ of this software dedicate any and all copyright interest in the │
|
||||
│ software to the public domain. We make this dedication for the benefit │
|
||||
│ of the public at large and to the detriment of our heirs and │
|
||||
│ successors. We intend this dedication to be an overt act of │
|
||||
│ relinquishment in perpetuity of all present and future rights to this │
|
||||
│ software under copyright law. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │
|
||||
│ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │
|
||||
│ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │
|
||||
│ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR │
|
||||
│ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
|
||||
│ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR │
|
||||
│ OTHER DEALINGS IN THE SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/newbie.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/mman.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/vga/vga.internal.h"
|
||||
|
||||
/*
|
||||
* @fileoverview Instantiation of routines for emergency or system console
|
||||
* output in graphical video modes.
|
||||
*
|
||||
* @see libc/vga/tty-graph.inc
|
||||
*/
|
||||
|
||||
#define KLOGTTY
|
||||
|
||||
/* Instantiate output routines for 16-bit pixel formats. */
|
||||
#define COLOR uint16_t
|
||||
#define BPP 16
|
||||
#define MAPCOLOR TtyKlog16MapColor
|
||||
#define DIRTY TtyKlog16Dirty
|
||||
#define UPDATE _TtyKlog16Update
|
||||
#define RESETDIRTY TtyKlog16ResetDirty
|
||||
#define DRAWBITMAP TtyKlog16DrawBitmap
|
||||
#define FILLRECT TtyKlog16FillRect
|
||||
#define MOVERECT TtyKlog16MoveRect
|
||||
#define DRAWCHAR _TtyKlog16DrawChar
|
||||
#define ERASELINECELLS _TtyKlog16EraseLineCells
|
||||
#define MOVELINECELLS _TtyKlog16MoveLineCells
|
||||
#include "libc/vga/tty-graph.inc"
|
||||
|
||||
#undef COLOR
|
||||
#undef BPP
|
||||
#undef MAPCOLOR
|
||||
#undef BG
|
||||
#undef DIRTY
|
||||
#undef UPDATE
|
||||
#undef RESETDIRTY
|
||||
#undef DRAWBITMAP
|
||||
#undef FILLRECT
|
||||
#undef MOVERECT
|
||||
#undef DRAWCHAR
|
||||
#undef ERASELINECELLS
|
||||
#undef MOVELINECELLS
|
||||
|
||||
/* Instantiate output routines for 32-bit pixel formats. */
|
||||
#define COLOR uint32_t
|
||||
#define BPP 32
|
||||
#define MAPCOLOR TtyKlog32MapColor
|
||||
#define DIRTY TtyKlog32Dirty
|
||||
#define UPDATE _TtyKlog32Update
|
||||
#define RESETDIRTY TtyKlog32ResetDirty
|
||||
#define DRAWBITMAP TtyKlog32DrawBitmap
|
||||
#define FILLRECT TtyKlog32FillRect
|
||||
#define MOVERECT TtyKlog32MoveRect
|
||||
#define DRAWCHAR _TtyKlog32DrawChar
|
||||
#define ERASELINECELLS _TtyKlog32EraseLineCells
|
||||
#define MOVELINECELLS _TtyKlog32MoveLineCells
|
||||
#include "libc/vga/tty-graph.inc"
|
||||
|
||||
static unsigned short klog_y = 0, klog_x = 0;
|
||||
|
||||
privileged void _klog_vga(const char *b, size_t n) {
|
||||
struct Tty tty;
|
||||
_vga_reinit(&tty, klog_y, klog_x, kTtyKlog);
|
||||
_TtyWrite(&tty, b, n);
|
||||
klog_y = _TtyGetY(&tty);
|
||||
klog_x = _TtyGetX(&tty);
|
||||
}
|
|
@ -67,10 +67,10 @@ static void SetXsFb(struct Tty *tty, unsigned short xsfb) {
|
|||
tty->xsfb = xsfb;
|
||||
}
|
||||
|
||||
static bool SetWcs(struct Tty *tty, bool alloc_wcs) {
|
||||
static bool SetWcs(struct Tty *tty, unsigned init_flags) {
|
||||
#ifdef VGA_USE_WCS
|
||||
struct DirectMap dm;
|
||||
if (!alloc_wcs)
|
||||
if (!(init_flags & kTtyAllocWcs))
|
||||
return false;
|
||||
dm = sys_mmap_metal(NULL, Yn(tty) * Xn(tty) * sizeof(wchar_t),
|
||||
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
|
||||
|
@ -102,48 +102,75 @@ static wchar_t *Wcs(struct Tty *tty) {
|
|||
#endif
|
||||
}
|
||||
|
||||
static void TtyNoopUpdate(struct Tty *);
|
||||
static void TtyTextDrawChar(struct Tty *, size_t, size_t, wchar_t);
|
||||
static void TtyTextEraseLineCells(struct Tty *, size_t, size_t, size_t);
|
||||
static void TtyTextMoveLineCells(struct Tty *, size_t, size_t, size_t, size_t,
|
||||
size_t);
|
||||
|
||||
static void TtySetType(struct Tty *tty, unsigned char type) {
|
||||
static void TtySetType(struct Tty *tty, unsigned char type,
|
||||
unsigned init_flags) {
|
||||
tty->type = type;
|
||||
switch (type) {
|
||||
case PC_VIDEO_BGR565:
|
||||
tty->update = _TtyBgr565Update;
|
||||
goto graphics_mode;
|
||||
case PC_VIDEO_BGR555:
|
||||
tty->update = _TtyBgr555Update;
|
||||
goto graphics_mode;
|
||||
case PC_VIDEO_BGRX8888:
|
||||
tty->update = _TtyBgrxUpdate;
|
||||
goto graphics_mode;
|
||||
case PC_VIDEO_RGBX8888:
|
||||
tty->update = _TtyRgbxUpdate;
|
||||
graphics_mode:
|
||||
tty->drawchar = _TtyGraphDrawChar;
|
||||
tty->eraselinecells = _TtyGraphEraseLineCells;
|
||||
tty->movelinecells = _TtyGraphMoveLineCells;
|
||||
break;
|
||||
default:
|
||||
tty->drawchar = TtyTextDrawChar;
|
||||
tty->eraselinecells = TtyTextEraseLineCells;
|
||||
tty->movelinecells = TtyTextMoveLineCells;
|
||||
if ((init_flags & kTtyKlog) == 0) {
|
||||
switch (type) {
|
||||
case PC_VIDEO_BGR565:
|
||||
tty->update = _TtyBgr565Update;
|
||||
goto graphics_mode;
|
||||
case PC_VIDEO_BGR555:
|
||||
tty->update = _TtyBgr555Update;
|
||||
goto graphics_mode;
|
||||
case PC_VIDEO_BGRX8888:
|
||||
tty->update = _TtyBgrxUpdate;
|
||||
goto graphics_mode;
|
||||
case PC_VIDEO_RGBX8888:
|
||||
tty->update = _TtyRgbxUpdate;
|
||||
graphics_mode:
|
||||
tty->drawchar = _TtyGraphDrawChar;
|
||||
tty->eraselinecells = _TtyGraphEraseLineCells;
|
||||
tty->movelinecells = _TtyGraphMoveLineCells;
|
||||
break;
|
||||
default:
|
||||
tty->update = TtyNoopUpdate;
|
||||
tty->drawchar = TtyTextDrawChar;
|
||||
tty->eraselinecells = TtyTextEraseLineCells;
|
||||
tty->movelinecells = TtyTextMoveLineCells;
|
||||
}
|
||||
} else {
|
||||
switch (type) {
|
||||
case PC_VIDEO_BGR565:
|
||||
case PC_VIDEO_BGR555:
|
||||
tty->update = _TtyKlog16Update;
|
||||
tty->drawchar = _TtyKlog16DrawChar;
|
||||
tty->eraselinecells = _TtyKlog16EraseLineCells;
|
||||
tty->movelinecells = _TtyKlog16MoveLineCells;
|
||||
break;
|
||||
case PC_VIDEO_BGRX8888:
|
||||
case PC_VIDEO_RGBX8888:
|
||||
tty->update = _TtyKlog32Update;
|
||||
tty->drawchar = _TtyKlog32DrawChar;
|
||||
tty->eraselinecells = _TtyKlog32EraseLineCells;
|
||||
tty->movelinecells = _TtyKlog32MoveLineCells;
|
||||
break;
|
||||
default:
|
||||
tty->update = TtyNoopUpdate;
|
||||
tty->drawchar = TtyTextDrawChar;
|
||||
tty->eraselinecells = TtyTextEraseLineCells;
|
||||
tty->movelinecells = TtyTextMoveLineCells;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _StartTty(struct Tty *tty, unsigned char type,
|
||||
unsigned short yp, unsigned short xp, unsigned short xsfb,
|
||||
unsigned short starty, unsigned short startx,
|
||||
unsigned char yc, unsigned char xc, void *fb, bool alloc_wcs) {
|
||||
unsigned char yc, unsigned char xc, void *fb,
|
||||
unsigned init_flags) {
|
||||
unsigned short yn, xn, xs = xp * sizeof(TtyCanvasColor);
|
||||
struct DirectMap dm;
|
||||
memset(tty, 0, sizeof(struct Tty));
|
||||
SetYp(tty, yp);
|
||||
SetXp(tty, xp);
|
||||
SetXsFb(tty, xsfb);
|
||||
tty->xs = xs;
|
||||
if (type == PC_VIDEO_TEXT) {
|
||||
yn = yp;
|
||||
xn = xp;
|
||||
|
@ -151,14 +178,23 @@ void _StartTty(struct Tty *tty, unsigned char type,
|
|||
} else {
|
||||
yn = yp / yc;
|
||||
xn = xp / xc;
|
||||
dm = sys_mmap_metal(NULL, (size_t)yp * xs, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (dm.addr == (void *)-1) {
|
||||
/* We are a bit low on memory. Try to go on anyway. */
|
||||
if ((init_flags & kTtyKlog) != 0) {
|
||||
tty->canvas = fb;
|
||||
starty = startx = 0;
|
||||
} else
|
||||
tty->canvas = dm.addr;
|
||||
xs = xsfb;
|
||||
} else {
|
||||
dm = sys_mmap_metal(NULL, (size_t)yp * xs, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (dm.addr == (void *)-1) {
|
||||
/*
|
||||
* We are a bit low on memory. Try to go on anyway, & initialize
|
||||
* our tty as an emergency console.
|
||||
*/
|
||||
init_flags |= kTtyKlog;
|
||||
tty->canvas = fb;
|
||||
xs = xsfb;
|
||||
} else
|
||||
tty->canvas = dm.addr;
|
||||
}
|
||||
}
|
||||
SetYn(tty, yn);
|
||||
SetXn(tty, xn);
|
||||
|
@ -169,8 +205,10 @@ void _StartTty(struct Tty *tty, unsigned char type,
|
|||
if (startx >= xn) startx = xn - 1;
|
||||
tty->y = starty;
|
||||
tty->x = startx;
|
||||
TtySetType(tty, type);
|
||||
if (SetWcs(tty, alloc_wcs)) {
|
||||
if ((init_flags & kTtyKlog) != 0) init_flags &= ~kTtyAllocWcs;
|
||||
tty->xs = xs;
|
||||
TtySetType(tty, type, init_flags);
|
||||
if (SetWcs(tty, init_flags)) {
|
||||
wchar_t *wcs = Wcs(tty);
|
||||
size_t n = (size_t)yn * xn, i;
|
||||
if (type == PC_VIDEO_TEXT) {
|
||||
|
@ -335,6 +373,9 @@ static uint8_t TtyGetTextAttr(struct Tty *tty) {
|
|||
return attr;
|
||||
}
|
||||
|
||||
static void TtyNoopUpdate(struct Tty *tty) {
|
||||
}
|
||||
|
||||
static void TtyTextDrawChar(struct Tty *tty, size_t y, size_t x, wchar_t wc) {
|
||||
uint8_t attr = TtyGetTextAttr(tty);
|
||||
struct VgaTextCharCell *ccs = (struct VgaTextCharCell *)tty->canvas;
|
||||
|
|
|
@ -31,34 +31,40 @@
|
|||
|
||||
struct Tty _vga_tty;
|
||||
|
||||
void _vga_reinit(struct Tty *tty, unsigned short starty, unsigned short startx,
|
||||
unsigned init_flags) {
|
||||
struct mman *mm = (struct mman *)(BANE + 0x0500);
|
||||
unsigned char vid_type = mm->pc_video_type;
|
||||
unsigned short height = mm->pc_video_height, width = mm->pc_video_width,
|
||||
stride = mm->pc_video_stride;
|
||||
uint64_t vid_buf_phy = mm->pc_video_framebuffer;
|
||||
void *vid_buf = (void *)(BANE + vid_buf_phy);
|
||||
size_t vid_buf_sz = mm->pc_video_framebuffer_size;
|
||||
uint8_t chr_ht, chr_wid;
|
||||
if (vid_type == PC_VIDEO_TEXT) {
|
||||
unsigned short chr_ht_val = mm->pc_video_char_height;
|
||||
if (chr_ht_val > 32 || chr_ht_val < 2)
|
||||
chr_ht = VGA_ASSUME_CHAR_HEIGHT_PX;
|
||||
else
|
||||
chr_ht = chr_ht_val;
|
||||
} else
|
||||
chr_ht = VGA_ASSUME_CHAR_HEIGHT_PX;
|
||||
chr_wid = VGA_ASSUME_CHAR_WIDTH_PX;
|
||||
/* Make sure the video buffer is mapped into virtual memory. */
|
||||
__invert_memory_area(mm, __get_pml4t(), vid_buf_phy, vid_buf_sz, PAGE_RW);
|
||||
/*
|
||||
* Initialize our tty structure from the current screen geometry, screen
|
||||
* contents, cursor position, & character dimensions.
|
||||
*/
|
||||
_StartTty(tty, vid_type, height, width, stride, starty, startx,
|
||||
chr_ht, chr_wid, vid_buf, init_flags);
|
||||
}
|
||||
|
||||
__attribute__((__constructor__)) static textstartup void _vga_init(void) {
|
||||
if (IsMetal()) {
|
||||
struct mman *mm = (struct mman *)(BANE + 0x0500);
|
||||
unsigned char vid_type = mm->pc_video_type;
|
||||
unsigned short height = mm->pc_video_height, width = mm->pc_video_width,
|
||||
stride = mm->pc_video_stride;
|
||||
uint64_t vid_buf_phy = mm->pc_video_framebuffer;
|
||||
void *vid_buf = (void *)(BANE + vid_buf_phy);
|
||||
size_t vid_buf_sz = mm->pc_video_framebuffer_size;
|
||||
unsigned short starty = mm->pc_video_curs_info.y,
|
||||
startx = mm->pc_video_curs_info.x;
|
||||
uint8_t chr_ht, chr_wid;
|
||||
if (vid_type == PC_VIDEO_TEXT) {
|
||||
unsigned short chr_ht_val = mm->pc_video_char_height;
|
||||
if (chr_ht_val > 32 || chr_ht_val < 2)
|
||||
chr_ht = VGA_ASSUME_CHAR_HEIGHT_PX;
|
||||
else
|
||||
chr_ht = chr_ht_val;
|
||||
} else
|
||||
chr_ht = VGA_ASSUME_CHAR_HEIGHT_PX;
|
||||
chr_wid = VGA_ASSUME_CHAR_WIDTH_PX;
|
||||
/* Make sure the video buffer is mapped into virtual memory. */
|
||||
__invert_memory_area(mm, __get_pml4t(), vid_buf_phy, vid_buf_sz, PAGE_RW);
|
||||
/*
|
||||
* Initialize our tty structure from the current screen geometry,
|
||||
* screen contents, cursor position, & character dimensions.
|
||||
*/
|
||||
_StartTty(&_vga_tty, vid_type, height, width, stride, starty, startx,
|
||||
chr_ht, chr_wid, vid_buf, false);
|
||||
_vga_reinit(&_vga_tty, starty, startx, 0);
|
||||
}
|
||||
}
|
|
@ -75,6 +75,16 @@
|
|||
*/
|
||||
#undef VGA_PERSNICKETY_STATUS
|
||||
|
||||
/* Flags which are passed to _StartTty(). */
|
||||
#define kTtyAllocWcs 0x01 /* allocate Unicode character array
|
||||
(if VGA_USE_WCS also defined) */
|
||||
#define kTtyKlog 0x02 /* the system might be in an abnormal
|
||||
state, & we are setting up the tty
|
||||
to show system messages */
|
||||
|
||||
/**
|
||||
* Flags for Tty::pr. These govern properties of individual character cells.
|
||||
*/
|
||||
#define kTtyFg 0x0001
|
||||
#define kTtyBg 0x0002
|
||||
#define kTtyBold 0x0004
|
||||
|
@ -89,6 +99,10 @@
|
|||
#define kTtyStrike 0x0800
|
||||
#define kTtyConceal 0x1000
|
||||
|
||||
/**
|
||||
* Flags for Tty::conf. These govern the current state of the teletypewriter
|
||||
* as a whole.
|
||||
*/
|
||||
#define kTtyBell 0x001
|
||||
#define kTtyRedzone 0x002
|
||||
#define kTtyNocursor 0x004
|
||||
|
@ -181,14 +195,15 @@ struct Tty {
|
|||
* Canvas to draw into. In text modes, this is simply the frame buffer
|
||||
* itself. In graphics modes, this should be separate from the frame
|
||||
* buffer, & possibly allocated from main memory; we must arrange to
|
||||
* update the frame buffer from the canvas every now & then. In general
|
||||
* the canvas's pixel format — given by _TtyCanvasType() — may be
|
||||
* different from the frame buffer's.
|
||||
* update the frame buffer from the canvas every now & then.
|
||||
*
|
||||
* During normal operation, the canvas's pixel format is given by
|
||||
* _TtyCanvasType(), & may be different from the frame buffer's.
|
||||
*/
|
||||
char *canvas;
|
||||
/**
|
||||
* Which portions of the canvas have been updated & should later be drawn
|
||||
* to screen with tty->update().
|
||||
* to screen with Tty::update().
|
||||
*/
|
||||
unsigned short updy1, updx1, updy2, updx2;
|
||||
#ifdef VGA_USE_WCS
|
||||
|
@ -219,6 +234,15 @@ forceinline unsigned char _TtyCanvasType(struct Tty *tty) {
|
|||
return tty->type == PC_VIDEO_TEXT ? PC_VIDEO_TEXT : PC_VIDEO_BGRX8888;
|
||||
}
|
||||
|
||||
forceinline unsigned short _TtyGetY(struct Tty *tty) {
|
||||
return tty->y;
|
||||
}
|
||||
|
||||
forceinline unsigned short _TtyGetX(struct Tty *tty) {
|
||||
return tty->x;
|
||||
}
|
||||
|
||||
/* Routines that implement normal graphical console output. */
|
||||
void _TtyBgrxUpdate(struct Tty *);
|
||||
void _TtyRgbxUpdate(struct Tty *);
|
||||
void _TtyBgr565Update(struct Tty *);
|
||||
|
@ -228,9 +252,25 @@ void _TtyGraphEraseLineCells(struct Tty *, size_t, size_t, size_t);
|
|||
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.
|
||||
*/
|
||||
void _TtyKlog16Update(struct Tty *);
|
||||
void _TtyKlog16DrawChar(struct Tty *, size_t, size_t, wchar_t);
|
||||
void _TtyKlog16EraseLineCells(struct Tty *, size_t, size_t, size_t);
|
||||
void _TtyKlog16MoveLineCells(struct Tty *, size_t, size_t, size_t, size_t,
|
||||
size_t);
|
||||
void _TtyKlog32Update(struct Tty *);
|
||||
void _TtyKlog32DrawChar(struct Tty *, size_t, size_t, wchar_t);
|
||||
void _TtyKlog32EraseLineCells(struct Tty *, size_t, size_t, size_t);
|
||||
void _TtyKlog32MoveLineCells(struct Tty *, size_t, size_t, size_t, size_t,
|
||||
size_t);
|
||||
|
||||
/* High-level teletypewriter routines. */
|
||||
void _StartTty(struct Tty *, unsigned char, unsigned short, unsigned short,
|
||||
unsigned short, unsigned short, unsigned short,
|
||||
unsigned char, unsigned char, void *, bool);
|
||||
unsigned char, unsigned char, void *, unsigned);
|
||||
ssize_t _TtyRead(struct Tty *, void *, size_t);
|
||||
ssize_t _TtyWrite(struct Tty *, const void *, size_t);
|
||||
ssize_t _TtyWriteInput(struct Tty *, const void *, size_t);
|
||||
|
@ -246,6 +286,8 @@ void _TtySetX(struct Tty *, unsigned short);
|
|||
extern const uint8_t _vga_font_default_direct[95][13];
|
||||
extern struct Tty _vga_tty;
|
||||
|
||||
void _vga_reinit(struct Tty *, unsigned short, unsigned short, unsigned);
|
||||
void _klog_vga(const char *, size_t);
|
||||
ssize_t sys_readv_vga(struct Fd *, const struct iovec *, int);
|
||||
ssize_t sys_writev_vga(struct Fd *, const struct iovec *, int);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue