mirror of
https://github.com/rdmsr/zag.git
synced 2026-10-27 13:58:20 +00:00
fbconsole -> bootvid
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
//! Very bad and slow framebuffer console.
|
//! Very bad and slow framebuffer console.
|
||||||
const r = @import("root");
|
const r = @import("root");
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
const pl = r.pl;
|
const pl = r.pl;
|
||||||
const ke = r.ke;
|
const ke = r.ke;
|
||||||
const ex = r.ex;
|
|
||||||
|
|
||||||
const PSF1_MAGIC: u16 = 0x0436;
|
const PSF1_MAGIC: u16 = 0x0436;
|
||||||
const PSF2_MAGIC: u32 = 0x864ab572;
|
const PSF2_MAGIC: u32 = 0x864ab572;
|
||||||
@@ -28,25 +28,33 @@ const Psf2Header = extern struct {
|
|||||||
const FontInfo = struct {
|
const FontInfo = struct {
|
||||||
header_size: usize,
|
header_size: usize,
|
||||||
glyph_size: usize,
|
glyph_size: usize,
|
||||||
width: usize,
|
width: u16,
|
||||||
height: usize,
|
height: u16,
|
||||||
};
|
};
|
||||||
|
|
||||||
const font_file = @embedFile("sun12x22.psfu");
|
const Cursor = struct {
|
||||||
|
x: u16 = 0,
|
||||||
|
y: u16 = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
const font_file = @embedFile("sun12x22-ascii.psf");
|
||||||
|
const text_color: u32 = 0xFFFFFFFF;
|
||||||
|
const bg_color: u32 = 0xFF000000;
|
||||||
|
const crash_bg_color: u32 = 0xFF0000FF;
|
||||||
|
const window_padding: usize = 10;
|
||||||
|
|
||||||
var font: FontInfo = undefined;
|
var font: FontInfo = undefined;
|
||||||
var framebuffer: [*]u32 = undefined;
|
var framebuffer: [*]u32 = undefined;
|
||||||
var framebuffer_width: usize = 0;
|
var framebuffer_width: usize = 0;
|
||||||
var framebuffer_height: usize = 0;
|
var framebuffer_height: usize = 0;
|
||||||
|
|
||||||
const bg_color: u32 = 0xFFFFFFFF;
|
var cursor: Cursor = .{};
|
||||||
const text_color: u32 = 0xFF000000;
|
var console_width: u16 = 0;
|
||||||
const window_padding: usize = 10;
|
var console_height: u16 = 0;
|
||||||
|
|
||||||
var content_x: usize = 0;
|
|
||||||
var content_y: usize = 0;
|
|
||||||
var content_w: usize = 0;
|
var content_w: usize = 0;
|
||||||
var content_h: usize = 0;
|
var content_h: usize = 0;
|
||||||
var visible_h: usize = 0;
|
var enabled = true;
|
||||||
|
|
||||||
fn load_font() void {
|
fn load_font() void {
|
||||||
if (font_file.len >= @sizeOf(Psf2Header)) {
|
if (font_file.len >= @sizeOf(Psf2Header)) {
|
||||||
@@ -61,6 +69,7 @@ fn load_font() void {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (font_file.len >= @sizeOf(Psf1Header)) {
|
if (font_file.len >= @sizeOf(Psf1Header)) {
|
||||||
const h1: *const Psf1Header = @ptrCast(@alignCast(font_file.ptr));
|
const h1: *const Psf1Header = @ptrCast(@alignCast(font_file.ptr));
|
||||||
if (h1.magic == PSF1_MAGIC) {
|
if (h1.magic == PSF1_MAGIC) {
|
||||||
@@ -73,121 +82,95 @@ fn load_font() void {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
font = .{ .header_size = 0, .glyph_size = 0, .width = 0, .height = 0 };
|
|
||||||
|
font = .{
|
||||||
|
.header_size = 0,
|
||||||
|
.glyph_size = 0,
|
||||||
|
.width = 0,
|
||||||
|
.height = 0,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn plot_character(x: usize, y: usize, c: u8) void {
|
fn plot_character(x: usize, y: usize, c: u8) void {
|
||||||
const bytes_per_row = font.glyph_size / font.height;
|
const bytes_per_row = font.glyph_size / font.height;
|
||||||
const glyph_offset = font.header_size + (@as(usize, c) * font.glyph_size);
|
const glyph_offset = font.header_size + (@as(usize, c) * font.glyph_size);
|
||||||
const glyph_data = font_file[glyph_offset..(glyph_offset + font.glyph_size)];
|
const glyph_data = font_file[glyph_offset..(glyph_offset + font.glyph_size)];
|
||||||
|
const start_x = window_padding + x;
|
||||||
|
const start_y = window_padding + y;
|
||||||
|
|
||||||
for (0..font.height) |row| {
|
for (0..font.height) |row| {
|
||||||
var row_data: u32 = 0;
|
var row_data: u32 = 0;
|
||||||
|
|
||||||
for (0..bytes_per_row) |b| {
|
for (0..bytes_per_row) |b| {
|
||||||
row_data = (row_data << 8) | @as(u32, glyph_data[row * bytes_per_row + b]);
|
row_data = (row_data << 8) | @as(u32, glyph_data[row * bytes_per_row + b]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const shift_base = bytes_per_row * 8;
|
const shift_base = bytes_per_row * 8;
|
||||||
|
|
||||||
for (0..font.width) |col| {
|
for (0..font.width) |col| {
|
||||||
if ((row_data & (@as(u32, 1) << @intCast(shift_base - 1 - col))) != 0) {
|
if ((row_data & (@as(u32, 1) << @intCast(shift_base - 1 - col))) != 0) {
|
||||||
framebuffer[(y + row) * framebuffer_width + (x + col)] = text_color;
|
framebuffer[(start_y + row) * framebuffer_width + (start_x + col)] = text_color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var cursor_x: usize = 0;
|
fn scroll() void {
|
||||||
var cursor_y: usize = 0;
|
const rows_to_shift = (console_height - 1) * font.height;
|
||||||
|
|
||||||
fn clear_content_rows(y: usize, height: usize) void {
|
// Move all lines up.
|
||||||
for (0..height) |row| {
|
for (0..rows_to_shift) |row| {
|
||||||
const dst_y = content_y + y + row;
|
const dst_y = window_padding + row;
|
||||||
if (dst_y >= content_y + visible_h) break;
|
const src_y = dst_y + font.height;
|
||||||
|
|
||||||
for (0..content_w) |col| {
|
for (0..content_w) |col| {
|
||||||
framebuffer[dst_y * framebuffer_width + content_x + col] = bg_color;
|
framebuffer[dst_y * framebuffer_width + window_padding + col] =
|
||||||
}
|
framebuffer[src_y * framebuffer_width + window_padding + col];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_up(pixels: usize) void {
|
// Clear the last line.
|
||||||
if (pixels >= visible_h) {
|
for (0..font.height) |row| {
|
||||||
clear_content_rows(0, visible_h);
|
const dst_y = window_padding + (console_height - 1) * font.height + row;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const remaining_h = visible_h - pixels;
|
|
||||||
for (0..remaining_h) |row| {
|
|
||||||
const dst_y = content_y + row;
|
|
||||||
const src_y = dst_y + pixels;
|
|
||||||
|
|
||||||
for (0..content_w) |col| {
|
for (0..content_w) |col| {
|
||||||
framebuffer[dst_y * framebuffer_width + content_x + col] =
|
framebuffer[dst_y * framebuffer_width + window_padding + col] = bg_color;
|
||||||
framebuffer[src_y * framebuffer_width + content_x + col];
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clear_content_rows(remaining_h, pixels);
|
pub fn disable() void {
|
||||||
|
enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ensure_cursor_visible() void {
|
pub fn crash() void {
|
||||||
while (cursor_y + font.height > visible_h) {
|
cursor.x = 0;
|
||||||
scroll_up(font.height);
|
cursor.y = 0;
|
||||||
cursor_y -= font.height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn newline() void {
|
for (0..framebuffer_width * framebuffer_height) |i| {
|
||||||
cursor_x = 0;
|
framebuffer[i] = crash_bg_color;
|
||||||
cursor_y += font.height;
|
|
||||||
|
|
||||||
while (cursor_y > visible_h) {
|
|
||||||
scroll_up(font.height);
|
|
||||||
cursor_y -= font.height;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_char(c: u8) void {
|
pub fn write_char(c: u8) void {
|
||||||
if (font.width == 0 or font.height == 0 or content_w < font.width or visible_h < font.height) {
|
if (!enabled) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Backspace.
|
|
||||||
if (c == '\x08') {
|
|
||||||
if (cursor_x >= font.width) {
|
|
||||||
cursor_x -= font.width;
|
|
||||||
ensure_cursor_visible();
|
|
||||||
for (0..font.height) |row| {
|
|
||||||
const dst_y = content_y + cursor_y + row;
|
|
||||||
for (0..font.width) |col| {
|
|
||||||
framebuffer[dst_y * framebuffer_width + content_x + cursor_x + col] = bg_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c == '\n') {
|
if (c == '\n') {
|
||||||
newline();
|
cursor.x = 0;
|
||||||
|
cursor.y += 1;
|
||||||
|
|
||||||
|
if (cursor.y >= console_height) {
|
||||||
|
cursor.y = console_height - 1;
|
||||||
|
scroll();
|
||||||
|
}
|
||||||
} else if (c == '\r') {
|
} else if (c == '\r') {
|
||||||
cursor_x = 0;
|
cursor.x = 0;
|
||||||
} else {
|
} else {
|
||||||
if (cursor_x + font.width > content_w) {
|
plot_character(cursor.x * font.width, cursor.y * font.height, c);
|
||||||
newline();
|
cursor.x += 1;
|
||||||
}
|
|
||||||
|
|
||||||
ensure_cursor_visible();
|
|
||||||
plot_character(content_x + cursor_x, content_y + cursor_y, c);
|
|
||||||
cursor_x += font.width;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write(_: ?*anyopaque, s: []const u8) void {
|
|
||||||
for (s) |c| {
|
|
||||||
write_char(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var console: ex.Console = .{ .ctx = null, .link = undefined, .write = write };
|
|
||||||
|
|
||||||
pub fn init(boot_info: *r.BootInfo) void {
|
pub fn init(boot_info: *r.BootInfo) void {
|
||||||
framebuffer = @ptrFromInt(boot_info.framebuffer.?.address);
|
framebuffer = @ptrFromInt(boot_info.framebuffer.?.address);
|
||||||
framebuffer_width = boot_info.framebuffer.?.width;
|
framebuffer_width = boot_info.framebuffer.?.width;
|
||||||
@@ -195,15 +178,17 @@ pub fn init(boot_info: *r.BootInfo) void {
|
|||||||
|
|
||||||
load_font();
|
load_font();
|
||||||
|
|
||||||
content_x = window_padding;
|
|
||||||
content_y = window_padding;
|
|
||||||
content_w = framebuffer_width - (window_padding * 2);
|
content_w = framebuffer_width - (window_padding * 2);
|
||||||
content_h = framebuffer_height - (window_padding * 2);
|
content_h = framebuffer_height - (window_padding * 2);
|
||||||
visible_h = if (font.height == 0) 0 else content_h - (content_h % font.height);
|
|
||||||
|
console_width = @intCast(content_w / font.width);
|
||||||
|
console_height = std.math.divCeil(
|
||||||
|
u16,
|
||||||
|
@intCast(content_h),
|
||||||
|
font.height,
|
||||||
|
) catch unreachable;
|
||||||
|
|
||||||
for (0..framebuffer_width * framebuffer_height) |i| {
|
for (0..framebuffer_width * framebuffer_height) |i| {
|
||||||
framebuffer[i] = bg_color;
|
framebuffer[i] = bg_color;
|
||||||
}
|
}
|
||||||
|
|
||||||
ex.console.register(&console);
|
|
||||||
}
|
}
|
||||||
Binary file not shown.
Binary file not shown.
@@ -8,9 +8,6 @@ const ps = r.ps;
|
|||||||
const exp = ex.private;
|
const exp = ex.private;
|
||||||
const rtl = @import("rtl");
|
const rtl = @import("rtl");
|
||||||
|
|
||||||
// XXX
|
|
||||||
const fbconsole = @import("../dev/fbconsole.zig");
|
|
||||||
|
|
||||||
pub fn init() void {
|
pub fn init() void {
|
||||||
mm.init();
|
mm.init();
|
||||||
ps.init();
|
ps.init();
|
||||||
@@ -34,8 +31,4 @@ pub fn init() void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r.boot_info.framebuffer != null) {
|
|
||||||
// fbconsole.init(r.boot_info);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ const ke = r.ke;
|
|||||||
const arch = r.arch;
|
const arch = r.arch;
|
||||||
const kep = ke.private;
|
const kep = ke.private;
|
||||||
const ex = r.ex;
|
const ex = r.ex;
|
||||||
|
const bv = r.bv;
|
||||||
|
|
||||||
var thread0: ke.Thread = undefined;
|
var thread0: ke.Thread = undefined;
|
||||||
|
|
||||||
@@ -31,6 +32,7 @@ fn init() linksection(r.init) void {
|
|||||||
ke.ncpus = 1;
|
ke.ncpus = 1;
|
||||||
kep.impl.early_init();
|
kep.impl.early_init();
|
||||||
kep.tunable.init();
|
kep.tunable.init();
|
||||||
|
bv.init(r.boot_info);
|
||||||
std.log.info("Welcome to the machine", .{});
|
std.log.info("Welcome to the machine", .{});
|
||||||
pl.early_init();
|
pl.early_init();
|
||||||
kep.log.init();
|
kep.log.init();
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ const r = @import("root");
|
|||||||
const pl = r.pl;
|
const pl = r.pl;
|
||||||
const ke = r.ke;
|
const ke = r.ke;
|
||||||
const kep = ke.private;
|
const kep = ke.private;
|
||||||
|
const bv = r.bv;
|
||||||
|
|
||||||
var out_lock: ke.SpinLock = .init();
|
var out_lock: ke.SpinLock = .init();
|
||||||
|
|
||||||
@@ -29,6 +30,7 @@ const DebugWriter = struct {
|
|||||||
var total_written: usize = 0;
|
var total_written: usize = 0;
|
||||||
for (data) |slice| {
|
for (data) |slice| {
|
||||||
for (slice) |byte| {
|
for (slice) |byte| {
|
||||||
|
bv.write_char(byte);
|
||||||
pl.impl.debug_write(byte);
|
pl.impl.debug_write(byte);
|
||||||
}
|
}
|
||||||
total_written += slice.len;
|
total_written += slice.len;
|
||||||
|
|||||||
+3
-4
@@ -4,6 +4,7 @@ const r = @import("root");
|
|||||||
const ksyms = @import("ksyms");
|
const ksyms = @import("ksyms");
|
||||||
const ke = r.ke;
|
const ke = r.ke;
|
||||||
const kep = ke.private;
|
const kep = ke.private;
|
||||||
|
const bv = r.bv;
|
||||||
|
|
||||||
extern var text_start_addr: u8;
|
extern var text_start_addr: u8;
|
||||||
extern var text_end_addr: u8;
|
extern var text_end_addr: u8;
|
||||||
@@ -78,8 +79,7 @@ pub fn panic_with_frame(
|
|||||||
frame: usize,
|
frame: usize,
|
||||||
) noreturn {
|
) noreturn {
|
||||||
_ = kep.impl.disable_interrupts();
|
_ = kep.impl.disable_interrupts();
|
||||||
|
bv.crash();
|
||||||
std.log.info("Crash count is {} on cpu {}", .{ crash_count.load(.monotonic), ke.cpu.current() });
|
|
||||||
|
|
||||||
if (crash_count.fetchAdd(1, .monotonic) != 0) {
|
if (crash_count.fetchAdd(1, .monotonic) != 0) {
|
||||||
std.log.err("Recursive panic from CPU {}", .{ke.cpu.current()});
|
std.log.err("Recursive panic from CPU {}", .{ke.cpu.current()});
|
||||||
@@ -97,10 +97,9 @@ pub fn panic_with_frame(
|
|||||||
|
|
||||||
_ = ke.ipl.raise(.High);
|
_ = ke.ipl.raise(.High);
|
||||||
|
|
||||||
std.log.err("KERNEL PANIC: {s} on CPU {}, curthread is {*}", .{
|
std.log.err("KERNEL PANIC: {s} on CPU {}", .{
|
||||||
msg,
|
msg,
|
||||||
ke.cpu.current(),
|
ke.cpu.current(),
|
||||||
kep.sched.percpu.local().current_thread.?,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
std.log.err("Stack trace:", .{});
|
std.log.err("Stack trace:", .{});
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ pub const ps = @import("proc/root.zig");
|
|||||||
pub const BootInfo = @import("loader/info.zig");
|
pub const BootInfo = @import("loader/info.zig");
|
||||||
pub const tests = @import("tests/root.zig");
|
pub const tests = @import("tests/root.zig");
|
||||||
pub const rcu = @import("rcu/root.zig");
|
pub const rcu = @import("rcu/root.zig");
|
||||||
|
pub const bv = @import("bootvid/bootvid.zig");
|
||||||
|
|
||||||
const config = @import("config");
|
const config = @import("config");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user