@@ -5,6 +5,74 @@ use core::fmt::Write;
55use spin:: Mutex ;
66
77static 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+ }
876
977pub fn write_console ( s : impl AsRef < str > ) {
1078 let lock = LOG_LOCK . lock ( ) ;
@@ -14,6 +82,9 @@ pub fn write_console(s: impl AsRef<str>) {
1482
1583// NOTE: the caller should hold `LOG_LOCK`
1684pub unsafe fn raw_write_console ( s : impl AsRef < str > ) {
85+ // mirror console output to VGA
86+ VGA_WRITER . write ( s. as_ref ( ) ) ;
87+
1788 //FIXME: what about addresses above 4GB?
1889 let len = s. as_ref ( ) . len ( ) ;
1990 let ptr = s. as_ref ( ) . as_ptr ( ) ;
@@ -25,6 +96,37 @@ pub unsafe fn raw_write_console(s: impl AsRef<str>) {
2596 : "volatile" ) ;
2697}
2798
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+
28130pub struct DirectLogger ;
29131impl DirectLogger {
30132 pub const fn new ( ) -> Self {
0 commit comments