@@ -5,6 +5,74 @@ use core::fmt::Write;
5
5
use spin:: Mutex ;
6
6
7
7
static LOG_LOCK : Mutex < ( ) > = Mutex :: new ( ( ) ) ;
8
+ static mut VGA_WRITER : VgaWriter = VgaWriter :: new ( ) ;
9
+
10
+ const VGA_BASE_ADDR : usize = 0xB8000 ;
11
+ const VGA_WIDTH : usize = 80 ;
12
+ const VGA_HEIGHT : usize = 25 ;
13
+ const VGA_ATTRIB : u16 = 0x0F00 ; // black background, white text
14
+
15
+ fn get_vga_ptr ( ) -> * mut [ u16 ; VGA_WIDTH * VGA_HEIGHT ] {
16
+ VGA_BASE_ADDR as _
17
+ }
18
+
19
+ unsafe fn scroll_vga ( ) {
20
+ let vga_mem = get_vga_ptr ( ) ;
21
+ for y in 1 ..VGA_HEIGHT {
22
+ for x in 0 ..VGA_WIDTH {
23
+ ( * vga_mem) [ ( y - 1 ) * VGA_WIDTH + x] = ( * vga_mem) [ y * VGA_WIDTH + x] ;
24
+ }
25
+ }
26
+ clear_line_vga ( VGA_HEIGHT - 1 ) ;
27
+ }
28
+
29
+ unsafe fn clear_line_vga ( y : usize ) {
30
+ let vga_mem = get_vga_ptr ( ) ;
31
+ for x in 0 ..VGA_WIDTH {
32
+ ( * vga_mem) [ y * VGA_WIDTH + x] = VGA_ATTRIB | 0x20 ;
33
+ }
34
+ }
35
+
36
+ pub unsafe fn clear_vga ( ) {
37
+ for y in 0 ..VGA_HEIGHT {
38
+ clear_line_vga ( y) ;
39
+ }
40
+ }
41
+
42
+ pub unsafe fn raw_write_vga (
43
+ s : impl AsRef < str > ,
44
+ mut x : usize ,
45
+ mut y : usize ,
46
+ ) -> ( usize , usize ) {
47
+ let vga_mem = get_vga_ptr ( ) ;
48
+ for byte in s. as_ref ( ) . bytes ( ) {
49
+ // move cursor on newlines (0x0A) and carriage-returns (0x0D)
50
+ if byte == 0x0A {
51
+ y += 1 ;
52
+ x = 0 ;
53
+ continue ;
54
+ } else if byte == 0x0D {
55
+ x = 0 ;
56
+ continue ;
57
+ }
58
+
59
+ if y >= VGA_HEIGHT {
60
+ scroll_vga ( ) ;
61
+ y = VGA_HEIGHT - 1 ;
62
+ }
63
+
64
+ ( * vga_mem) [ y * VGA_WIDTH + x] = VGA_ATTRIB | ( byte as u16 ) ;
65
+
66
+ x += 1 ;
67
+
68
+ if x >= VGA_WIDTH {
69
+ y += 1 ;
70
+ x = 0 ;
71
+ }
72
+ }
73
+
74
+ ( x, y)
75
+ }
8
76
9
77
pub fn write_console ( s : impl AsRef < str > ) {
10
78
let lock = LOG_LOCK . lock ( ) ;
@@ -14,6 +82,9 @@ pub fn write_console(s: impl AsRef<str>) {
14
82
15
83
// NOTE: the caller should hold `LOG_LOCK`
16
84
pub unsafe fn raw_write_console ( s : impl AsRef < str > ) {
85
+ // mirror console output to VGA
86
+ VGA_WRITER . write ( s. as_ref ( ) ) ;
87
+
17
88
//FIXME: what about addresses above 4GB?
18
89
let len = s. as_ref ( ) . len ( ) ;
19
90
let ptr = s. as_ref ( ) . as_ptr ( ) ;
@@ -25,6 +96,37 @@ pub unsafe fn raw_write_console(s: impl AsRef<str>) {
25
96
: "volatile" ) ;
26
97
}
27
98
99
+ pub struct VgaWriter {
100
+ cur_x : usize ,
101
+ cur_y : usize ,
102
+ }
103
+
104
+ impl VgaWriter {
105
+ pub const fn new ( ) -> Self {
106
+ VgaWriter { cur_x : 0 , cur_y : 0 }
107
+ }
108
+
109
+ pub unsafe fn write ( & mut self , s : impl AsRef < str > ) {
110
+ if self . cur_x == 0 && self . cur_y == 0 {
111
+ clear_vga ( ) ;
112
+ }
113
+ let ( x, y) = raw_write_vga ( s, self . cur_x , self . cur_y ) ;
114
+ self . cur_x = x;
115
+ self . cur_y = y;
116
+ }
117
+ }
118
+
119
+ impl fmt:: Write for VgaWriter {
120
+ fn write_str ( & mut self , s : & str ) -> fmt:: Result {
121
+ unsafe { self . write ( s) } ;
122
+ Ok ( ( ) )
123
+ }
124
+
125
+ fn write_fmt ( & mut self , args : fmt:: Arguments ) -> Result < ( ) , fmt:: Error > {
126
+ fmt:: write ( self , args)
127
+ }
128
+ }
129
+
28
130
pub struct DirectLogger ;
29
131
impl DirectLogger {
30
132
pub const fn new ( ) -> Self {
0 commit comments