Skip to content

Commit 59817ca

Browse files
bors[bot]phil-opp
andcommitted
35: Add support for 320x200 256 color VGA video mode r=phil-opp a=phil-opp Co-authored-by: Philipp Oppermann <[email protected]>
2 parents 616ec7f + 23772c0 commit 59817ca

File tree

14 files changed

+330
-61
lines changed

14 files changed

+330
-61
lines changed

.travis.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,5 @@ script:
4141
- cd example-kernel; cargo xbuild --target x86_64-example-kernel.json; cd ..
4242
- cd builder; cargo run -- --kernel ../example-kernel/target/x86_64-example-kernel/debug/example-kernel; cd ..
4343
- qemu-system-x86_64 -drive format=raw,file=target/x86_64-bootloader/release/bootimage.bin -device isa-debug-exit,iobase=0xf4,iosize=0x04 -display none; if [ $? -eq 123 ]; then (exit 0); else (exit 1); fi
44+
- cd builder; cargo run -- --kernel ../example-kernel/target/x86_64-example-kernel/debug/example-kernel --features vga_320x200; cd ..
45+
- qemu-system-x86_64 -drive format=raw,file=target/x86_64-bootloader/release/bootimage.bin -device isa-debug-exit,iobase=0xf4,iosize=0x04 -display none; if [ $? -eq 123 ]; then (exit 0); else (exit 1); fi

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,15 @@ x86_64 = "0.2.7"
1515
usize_conversions = "0.2.0"
1616
fixedvec = "0.2.3"
1717

18+
[dependencies.font8x8]
19+
version = "0.2.4"
20+
default-features = false
21+
features = ["unicode"]
22+
23+
[features]
24+
default = []
25+
vga_320x200 = []
26+
1827
[profile.dev]
1928
panic = "abort"
2029

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,8 @@ dd if=target/x86_64-blog_os/debug/bootimage-blog_os.bin of=/dev/sdX && sync
3535
```
3636

3737
Where sdX is the device name of your USB stick. **Be careful** to choose the correct device name, because everything on that device is overwritten.
38+
39+
## Features
40+
The bootloader crate can be configured through some cargo features:
41+
42+
- `vga_320x200`: This feature switches the VGA hardware to mode 0x13, a graphics mode with resolution 320x200 and 256 colors per pixel. The framebuffer is linear and lives at address `0xa0000`.

bors.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
status = [
2+
"continuous-integration/travis-ci/push"
3+
]

src/main.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ extern crate x86_64;
1414
extern crate xmas_elf;
1515
#[macro_use]
1616
extern crate fixedvec;
17+
extern crate font8x8;
1718

1819
use bootloader::bootinfo::BootInfo;
1920
use core::panic::PanicInfo;
@@ -32,6 +33,11 @@ global_asm!(include_str!("stage_3.s"));
3233
global_asm!(include_str!("stage_4.s"));
3334
global_asm!(include_str!("context_switch.s"));
3435

36+
#[cfg(feature = "vga_320x200")]
37+
global_asm!(include_str!("video_mode/vga_320x200.s"));
38+
#[cfg(not(feature = "vga_320x200"))]
39+
global_asm!(include_str!("video_mode/vga_text_80x25.s"));
40+
3541
extern "C" {
3642
fn context_switch(boot_info: VirtAddr, entry_point: VirtAddr, stack_pointer: VirtAddr) -> !;
3743
}

src/printer/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#[cfg(not(feature = "vga_320x200"))]
2+
pub use self::vga_text_80x25::*;
3+
4+
#[cfg(feature = "vga_320x200")]
5+
pub use self::vga_320x200::*;
6+
7+
mod vga_text_80x25;
8+
mod vga_320x200;

src/printer/vga_320x200.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
use core::fmt::{Result, Write};
2+
use core::slice;
3+
use core::sync::atomic::{AtomicUsize, Ordering};
4+
5+
const VGA_BUFFER: *mut u8 = 0xa0000 as *mut _;
6+
const SCREEN_WIDTH: usize = 320;
7+
const SCREEN_HEIGHT: usize = 200;
8+
9+
pub static X_POS: AtomicUsize = AtomicUsize::new(1); // must not be 0 so that we don't have a .bss section
10+
pub static Y_POS: AtomicUsize = AtomicUsize::new(1); // must not be 0 so that we don't have a .bss section
11+
12+
pub struct Printer;
13+
14+
impl Printer {
15+
pub fn clear_screen(&mut self) {
16+
let vga_buffer = Self::vga_buffer();
17+
for byte in vga_buffer {
18+
*byte = 0x00;
19+
}
20+
X_POS.store(0, Ordering::SeqCst);
21+
Y_POS.store(0, Ordering::SeqCst);
22+
}
23+
24+
fn vga_buffer() -> &'static mut [u8] {
25+
unsafe { slice::from_raw_parts_mut(VGA_BUFFER, SCREEN_WIDTH * SCREEN_HEIGHT) }
26+
}
27+
28+
fn newline(&mut self) {
29+
let y_pos = Y_POS.fetch_add(8, Ordering::SeqCst);
30+
X_POS.store(0, Ordering::SeqCst);
31+
if y_pos >= SCREEN_HEIGHT {
32+
self.clear_screen();
33+
}
34+
}
35+
36+
fn write_char(&mut self, c: char) {
37+
use font8x8::{self, UnicodeFonts};
38+
39+
if c == '\n' {
40+
self.newline();
41+
return;
42+
}
43+
44+
let vga_buffer = Self::vga_buffer();
45+
46+
let x_pos = X_POS.fetch_add(8, Ordering::SeqCst);
47+
let y_pos = Y_POS.load(Ordering::SeqCst);
48+
49+
match c {
50+
' '..='~' => {
51+
let rendered = font8x8::BASIC_FONTS
52+
.get(c)
53+
.expect("character not found in basic font");
54+
for (y, byte) in rendered.iter().enumerate() {
55+
for (x, bit) in (0..8).enumerate() {
56+
if *byte & (1 << bit) == 0 {
57+
continue
58+
}
59+
let color = 0xf;
60+
vga_buffer[(y_pos + y) * SCREEN_WIDTH + x_pos + x] = color;
61+
}
62+
}
63+
}
64+
_ => panic!("unprintable character"),
65+
}
66+
67+
if x_pos + 8 >= SCREEN_WIDTH {
68+
self.newline();
69+
}
70+
}
71+
}
72+
73+
impl Write for Printer {
74+
fn write_str(&mut self, s: &str) -> Result {
75+
for c in s.chars() {
76+
self.write_char(c);
77+
}
78+
79+
Ok(())
80+
}
81+
}
File renamed without changes.

src/stage_1.s

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ _start:
2323
mov sp, 0x7c00
2424

2525
lea si, boot_start_str
26-
call println
26+
call real_mode_println
2727

2828
enable_a20:
2929
# enable A20-Line via IO-Port 92, might not work on all motherboards
@@ -107,38 +107,38 @@ spin:
107107
# esi: points at zero-terminated String
108108
# CLOBBER
109109
# ax
110-
println:
111-
call print
110+
real_mode_println:
111+
call real_mode_print
112112
mov al, 13 # \r
113-
call print_char
113+
call real_mode_print_char
114114
mov al, 10 # \n
115-
jmp print_char
115+
jmp real_mode_print_char
116116

117117
# print a string
118118
# IN
119119
# esi: points at zero-terminated String
120120
# CLOBBER
121121
# ax
122-
print:
122+
real_mode_print:
123123
cld
124-
print_loop:
124+
real_mode_print_loop:
125125
# note: if direction flag is set (via std)
126126
# this will DECREMENT the ptr, effectively
127127
# reading/printing in reverse.
128128
lodsb al, BYTE PTR [esi]
129129
test al, al
130-
jz print_done
131-
call print_char
132-
jmp print_loop
133-
print_done:
130+
jz real_mode_print_done
131+
call real_mode_print_char
132+
jmp real_mode_print_loop
133+
real_mode_print_done:
134134
ret
135135

136136
# print a character
137137
# IN
138138
# al: character to print
139139
# CLOBBER
140140
# ah
141-
print_char:
141+
real_mode_print_char:
142142
mov ah, 0x0e
143143
int 0x10
144144
ret
@@ -148,7 +148,7 @@ print_char:
148148
# bx: the number
149149
# CLOBBER
150150
# al, cx
151-
print_hex:
151+
real_mode_print_hex:
152152
mov cx, 4
153153
.lp:
154154
mov al, bh
@@ -161,28 +161,27 @@ print_hex:
161161
.below_0xA:
162162
add al, '0'
163163

164-
call print_char
164+
call real_mode_print_char
165165

166166
shl bx, 4
167167
loop .lp
168168

169169
ret
170170

171-
error:
172-
call println
171+
real_mode_error:
172+
call real_mode_println
173173
jmp spin
174174

175175
no_int13h_extensions:
176176
lea si, no_int13h_extensions_str
177-
jmp error
177+
jmp real_mode_error
178178

179179
rest_of_bootloader_load_failed:
180180
lea si, rest_of_bootloader_load_failed_str
181-
jmp error
181+
jmp real_mode_error
182182

183183
boot_start_str: .asciz "Booting (first stage)..."
184184
error_str: .asciz "Error: "
185-
no_cpuid_str: .asciz "No CPUID support"
186185
no_int13h_extensions_str: .asciz "No support for int13h extensions"
187186
rest_of_bootloader_load_failed_str: .asciz "Failed to load rest of bootloader"
188187

0 commit comments

Comments
 (0)