Proper VGA driver, just missing print! / println! support.

This commit is contained in:
Guillaume DIDIER 2019-10-06 17:16:19 +02:00
parent 49d7c3e508
commit 5a528f7508
15 changed files with 1858 additions and 48 deletions

View File

@ -1,5 +1,5 @@
[build] [build]
target = "x86_64-D.TinctoriusAzureaus.json" target = "x86_64-D.TinctoriusAzureus.json"
[target.'cfg(target_os = "none")'] [target.'cfg(target_os = "none")']
runner = "bootimage runner" runner = "bootimage runner"

3
.gitignore vendored
View File

@ -6,3 +6,6 @@
#Cargo.lock #Cargo.lock
# These are backup files generated by rustfmt # These are backup files generated by rustfmt
**/*.rs.bk **/*.rs.bk
bootimage-kernel.iso
kernel.sym
bochsout.txt

View File

@ -1,7 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<module type="CPP_MODULE" version="4"> <module type="CPP_MODULE" version="4">
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" /> <content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/kernel/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/kernel/examples" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/kernel/tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/kernel/benches" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/examples" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/benches" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/vga_buffer/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/vga_buffer/examples" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/vga_buffer/tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/vga_buffer/benches" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/kernel/target" />
<excludeFolder url="file://$MODULE_DIR$/target" />
<excludeFolder url="file://$MODULE_DIR$/vga_buffer/target" />
</content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
</component> </component>

View File

@ -10,17 +10,23 @@
</component> </component>
<component name="CargoProjects"> <component name="CargoProjects">
<cargoProject FILE="$PROJECT_DIR$/Cargo.toml" /> <cargoProject FILE="$PROJECT_DIR$/Cargo.toml" />
<cargoProject FILE="$PROJECT_DIR$/vga_buffer/Cargo.toml" />
</component> </component>
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="7ddf063a-3554-4ac7-a5a5-6e243077d67d" name="Default Changelist" comment=""> <list default="true" id="7ddf063a-3554-4ac7-a5a5-6e243077d67d" name="Default Changelist" comment="">
<change afterPath="$PROJECT_DIR$/.cargo/config" afterDir="false" /> <change afterPath="$PROJECT_DIR$/src/main.rs" afterDir="false" />
<change afterPath="$PROJECT_DIR$/rust-toolchain" afterDir="false" /> <change afterPath="$PROJECT_DIR$/vga_buffer/Cargo.toml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/x86_64-D.TinctoriusAzureaus.json" afterDir="false" /> <change afterPath="$PROJECT_DIR$/vga_buffer/src/lib.rs" afterDir="false" />
<change afterPath="$PROJECT_DIR$/x86_64-D.TinctoriusAzureus.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.cargo/config" beforeDir="false" afterPath="$PROJECT_DIR$/.cargo/config" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.gitignore" beforeDir="false" afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/DendrobatesTinctoriusAzureus.iml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/DendrobatesTinctoriusAzureus.iml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Cargo.lock" beforeDir="false" afterPath="$PROJECT_DIR$/Cargo.lock" afterDir="false" /> <change beforePath="$PROJECT_DIR$/Cargo.lock" beforeDir="false" afterPath="$PROJECT_DIR$/Cargo.lock" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Cargo.toml" beforeDir="false" afterPath="$PROJECT_DIR$/Cargo.toml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/Cargo.toml" beforeDir="false" afterPath="$PROJECT_DIR$/Cargo.toml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kernel/Cargo.toml" beforeDir="false" afterPath="$PROJECT_DIR$/kernel/Cargo.toml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/kernel/Cargo.toml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/kernel/src/main.rs" beforeDir="false" afterPath="$PROJECT_DIR$/kernel/src/main.rs" afterDir="false" /> <change beforePath="$PROJECT_DIR$/kernel/src/main.rs" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/x86_64-D.TinctoriusAzureaus.json" beforeDir="false" />
</list> </list>
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" /> <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
@ -31,6 +37,13 @@
<component name="ClangdSettings"> <component name="ClangdSettings">
<option name="formatViaClangd" value="false" /> <option name="formatViaClangd" value="false" />
</component> </component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="Rust File" />
</list>
</option>
</component>
<component name="Git.Settings"> <component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" /> <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component> </component>
@ -47,8 +60,16 @@
<property name="node.js.path.for.package.tslint" value="project" /> <property name="node.js.path.for.package.tslint" value="project" />
<property name="node.js.selected.package.eslint" value="(autodetect)" /> <property name="node.js.selected.package.eslint" value="(autodetect)" />
<property name="node.js.selected.package.tslint" value="(autodetect)" /> <property name="node.js.selected.package.tslint" value="(autodetect)" />
<property name="nodejs_package_manager_path" value="npm" />
<property name="org.rust.cargo.project.model.PROJECT_DISCOVERY" value="true" /> <property name="org.rust.cargo.project.model.PROJECT_DISCOVERY" value="true" />
<property name="settings.editor.selected.configurable" value="language.rust.rustfmt" /> <property name="org.rust.hideDetachedFileNotifications/Volumes/Pepins/Users/guillaumedidier/Documents/Etudes/PhD/CPUDissector/DendrobatesTinctoriusAzureus/vga_buffer/src/lib.rs" value="true" />
<property name="settings.editor.selected.configurable" value="language.rust.cargo" />
</component>
<component name="RunAnythingCache">
<option name="myCommands">
<command value="cargo clippy" />
<command value="cargo xclippy" />
</option>
</component> </component>
<component name="RunDashboard"> <component name="RunDashboard">
<option name="ruleStates"> <option name="ruleStates">
@ -64,26 +85,65 @@
</component> </component>
<component name="RunManager" selected="Cargo Command.Build kernel"> <component name="RunManager" selected="Cargo Command.Build kernel">
<configuration name="Build kernel" type="CargoCommandRunConfiguration" factoryName="Cargo Command"> <configuration name="Build kernel" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
<option name="channel" value="NIGHTLY" /> <option name="channel" value="DEFAULT" />
<option name="command" value="xbuild" /> <option name="command" value="xbuild" />
<option name="allFeatures" value="false" /> <option name="allFeatures" value="false" />
<option name="nocapture" value="false" /> <option name="nocapture" value="false" />
<option name="emulateTerminal" value="true" /> <option name="emulateTerminal" value="true" />
<option name="backtrace" value="SHORT" /> <option name="backtrace" value="SHORT" />
<option name="workingDirectory" value="file://$PROJECT_DIR$/kernel" /> <option name="workingDirectory" value="file://$PROJECT_DIR$" />
<envs />
<method v="2">
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
</method>
</configuration>
<configuration name="Clean" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
<option name="channel" value="DEFAULT" />
<option name="command" value="clean" />
<option name="allFeatures" value="false" />
<option name="nocapture" value="false" />
<option name="emulateTerminal" value="true" />
<option name="backtrace" value="SHORT" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
<envs />
<method v="2">
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
</method>
</configuration>
<configuration name="Clippy" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
<option name="channel" value="DEFAULT" />
<option name="command" value="xclippy" />
<option name="allFeatures" value="false" />
<option name="nocapture" value="false" />
<option name="emulateTerminal" value="false" />
<option name="backtrace" value="SHORT" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
<envs />
<method v="2">
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
</method>
</configuration>
<configuration name="Expand dendrobates_tinctoreus_azureus" type="CargoCommandRunConfiguration" factoryName="Cargo Command" temporary="true">
<option name="channel" value="DEFAULT" />
<option name="command" value="expand --bin dendrobates_tinctoreus_azureus --color=always --theme=GitHub --tests" />
<option name="allFeatures" value="false" />
<option name="nocapture" value="false" />
<option name="emulateTerminal" value="false" />
<option name="backtrace" value="SHORT" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
<envs /> <envs />
<method v="2"> <method v="2">
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" /> <option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
</method> </method>
</configuration> </configuration>
<configuration name="Run kernel" type="CargoCommandRunConfiguration" factoryName="Cargo Command" temporary="true"> <configuration name="Run kernel" type="CargoCommandRunConfiguration" factoryName="Cargo Command" temporary="true">
<option name="channel" value="NIGHTLY" /> <option name="channel" value="DEFAULT" />
<option name="command" value="xrun" /> <option name="command" value="xrun" />
<option name="allFeatures" value="false" /> <option name="allFeatures" value="false" />
<option name="nocapture" value="false" /> <option name="nocapture" value="false" />
<option name="emulateTerminal" value="true" /> <option name="emulateTerminal" value="true" />
<option name="backtrace" value="SHORT" /> <option name="backtrace" value="SHORT" />
<option name="workingDirectory" value="file://$PROJECT_DIR$/kernel" /> <option name="workingDirectory" value="file://$PROJECT_DIR$" />
<envs /> <envs />
<method v="2"> <method v="2">
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" /> <option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
@ -96,17 +156,22 @@
<option name="nocapture" value="false" /> <option name="nocapture" value="false" />
<option name="emulateTerminal" value="true" /> <option name="emulateTerminal" value="true" />
<option name="backtrace" value="SHORT" /> <option name="backtrace" value="SHORT" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
<envs /> <envs />
<method v="2"> <method v="2">
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" /> <option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
</method> </method>
</configuration> </configuration>
<list> <list>
<item itemvalue="Cargo Command.Clippy" />
<item itemvalue="Cargo Command.Build kernel" /> <item itemvalue="Cargo Command.Build kernel" />
<item itemvalue="Cargo Command.Clean" />
<item itemvalue="Cargo Command.Run kernel" /> <item itemvalue="Cargo Command.Run kernel" />
<item itemvalue="Cargo Command.Expand dendrobates_tinctoreus_azureus" />
</list> </list>
<recent_temporary> <recent_temporary>
<list> <list>
<item itemvalue="Cargo Command.Expand dendrobates_tinctoreus_azureus" />
<item itemvalue="Cargo Command.Run kernel" /> <item itemvalue="Cargo Command.Run kernel" />
</list> </list>
</recent_temporary> </recent_temporary>
@ -116,6 +181,7 @@
<option name="runExternalLinterOnTheFly" value="true" /> <option name="runExternalLinterOnTheFly" value="true" />
<option name="runRustfmtOnSave" value="true" /> <option name="runRustfmtOnSave" value="true" />
<option name="toolchainHomeDirectory" value="$USER_HOME$/.cargo/bin" /> <option name="toolchainHomeDirectory" value="$USER_HOME$/.cargo/bin" />
<option name="version" value="2" />
</component> </component>
<component name="SvnConfiguration"> <component name="SvnConfiguration">
<configuration /> <configuration />
@ -128,6 +194,10 @@
<option name="presentableId" value="Default" /> <option name="presentableId" value="Default" />
<updated>1569934487744</updated> <updated>1569934487744</updated>
<workItem from="1569934492535" duration="5355000" /> <workItem from="1569934492535" duration="5355000" />
<workItem from="1570003006617" duration="2487000" />
<workItem from="1570093731306" duration="4682000" />
<workItem from="1570347619224" duration="2476000" />
<workItem from="1570370780740" duration="3966000" />
</task> </task>
<task id="LOCAL-00001" summary="Add CLion config files"> <task id="LOCAL-00001" summary="Add CLion config files">
<created>1569934966982</created> <created>1569934966982</created>
@ -147,7 +217,9 @@
<map> <map>
<entry key="MAIN"> <entry key="MAIN">
<value> <value>
<State /> <State>
<option name="COLUMN_ORDER" />
</State>
</value> </value>
</entry> </entry>
</map> </map>

86
Cargo.lock generated
View File

@ -1,10 +1,28 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
[[package]]
name = "array-init"
version = "0.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bit_field"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "bit_field" name = "bit_field"
version = "0.10.0" version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bitflags"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "bootloader" name = "bootloader"
version = "0.8.1" version = "0.8.1"
@ -14,12 +32,78 @@ dependencies = [
] ]
[[package]] [[package]]
name = "kernel" name = "cast"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "dendrobates_tinctoreus_azureus"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"bootloader 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "bootloader 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"vga_buffer 0.1.0",
"x86_64 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "nodrop"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "spin"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ux"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "vga_buffer"
version = "0.1.0"
dependencies = [
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"volatile 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "volatile"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "x86_64"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"array-init 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ux 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[metadata] [metadata]
"checksum array-init 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "23589ecb866b460d3a0f1278834750268c607e8e28a1b982c907219f3178cd72"
"checksum bit_field 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a165d606cf084741d4ac3a28fb6e9b1eb0bd31f6cd999098cfddb0b2ab381dc0" "checksum bit_field 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a165d606cf084741d4ac3a28fb6e9b1eb0bd31f6cd999098cfddb0b2ab381dc0"
"checksum bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed8765909f9009617974ab6b7d332625b320b33c326b1e9321382ef1999b5d56"
"checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2"
"checksum bootloader 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "45dd858bd74a742ec0fe887722952c263abd0825aa8d33a3704917a97d7bd41e" "checksum bootloader 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "45dd858bd74a742ec0fe887722952c263abd0825aa8d33a3704917a97d7bd41e"
"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
"checksum ux 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "88dfeb711b61ce620c0cb6fd9f8e3e678622f0c971da2a63c4b3e25e88ed012f"
"checksum volatile 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6af0edf5b4faacc31fc51159244d78d65ec580f021afcef7bd53c04aeabc7f29"
"checksum x86_64 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "997837f3913aac8f67164683258756d712376849906c8d609f844084bc03ef84"

View File

@ -1,6 +1,29 @@
[workspace] [workspace]
members = [ members = [
"kernel", "vga_buffer",
] ]
[package]
name = "dendrobates_tinctoreus_azureus"
version = "0.1.0"
authors = ["Guillaume DIDIER <guillaume.didier.2014@polytechnique.org>"]
edition = "2018"
[package.metadata.bootimage]
run-command = ["./scripts/bochs.sh", "{}"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
x86_64 = "0.7.5"
vga_buffer = { path = "vga_buffer" }
[dependencies.bootloader]
version = "^0.8.1"
features = ["sse"]
[profile.dev]
opt-level = 0
debug = 2

View File

@ -1,28 +0,0 @@
// main.rs
// main file of the kernel
#![no_std]
#![no_main]
use core::panic::PanicInfo;
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}
static HELLO: &[u8] = b"Hello Frog!";
#[no_mangle]
pub extern "C" fn _start() -> ! {
let vga_buffer = 0xb8000 as *mut u8;
for (i, &byte) in HELLO.iter().enumerate() {
unsafe {
*vga_buffer.offset(i as isize * 2) = byte;
*vga_buffer.offset(i as isize * 2 + 1) = 0xb;
}
}
loop {}
}

7
scripts/bochs.sh Executable file
View File

@ -0,0 +1,7 @@
#!/bin/sh
set -e
#bootimage build
dd if=/dev/zero of=target/x86_64-D.TinctoriusAzureus/debug/bootimage-kernel.iso count=1008 bs=512
dd if=$1 of=target/x86_64-D.TinctoriusAzureus/debug/bootimage-kernel.iso conv=notrunc
./scripts/syms.sh target/x86_64-D.TinctoriusAzureus/debug/dendrobates_tinctoreus_azureus
bochs -f scripts/bochsrc

1263
scripts/bochsrc Normal file

File diff suppressed because it is too large Load Diff

7
scripts/gdb.sh Normal file
View File

@ -0,0 +1,7 @@
#!/bin/sh
set -me
bootimage build
qemu-system-x86_64 -drive format=raw,file=target/x86_64-solstice/debug/bootimage-solstice.bin -no-reboot -S -s &
sleep 0.5
gdb target/x86_64-solstice/debug/solstice -ex "target remote :1234"
pkill qemu

1
scripts/syms.sh Executable file
View File

@ -0,0 +1 @@
nm target/x86_64-D.TinctoriusAzureus/debug/dendrobates_tinctoreus_azureus | grep -i " T " | awk '{ print $1" "$3 }' > kernel.sym

86
src/main.rs Normal file
View File

@ -0,0 +1,86 @@
// main.rs
// main file of the kernel
#![no_std] // This is a free standing program
#![no_main] // This has no crt0
use core::fmt::Write;
use core::panic::PanicInfo; // required for custom panic handler
use x86_64;
use vga_buffer;
// Custom panic handler, required for freestanding program
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}
// static greeting string, for hello world kernel
static HELLO: &[u8] = b"Hello Blue Frog!";
static YES: &[u8] = b"yes";
static NO: &[u8] = b"no";
static a: f64 = 420.0;
static b: f64 = 42.0;
static d: f64 = 0.1;
// Kernel entry point
#[no_mangle]
pub extern "C" fn _start() -> ! {
// TODO: Take care of cpuid stuff and set-up all floating point exetnsions
// TODO: We may also need to enable debug registers ?
let vga_buffer = 0xb8000 as *mut u8;
for (i, &byte) in HELLO.iter().enumerate() {
unsafe {
*vga_buffer.offset(i as isize * 2) = byte;
*vga_buffer.offset(i as isize * 2 + 1) = 0xb;
}
}
// magic break ?
x86_64::instructions::bochs_breakpoint();
let c = a * d;
x86_64::instructions::bochs_breakpoint();
if b == c {
for (i, &byte) in YES.iter().enumerate() {
unsafe {
*vga_buffer.offset(i as isize * 2) = byte;
*vga_buffer.offset(i as isize * 2 + 1) = 0xb;
}
}
} else {
for (i, &byte) in NO.iter().enumerate() {
unsafe {
*vga_buffer.offset(i as isize * 2) = byte;
*vga_buffer.offset(i as isize * 2 + 1) = 0xb;
}
}
}
x86_64::instructions::bochs_breakpoint();
writeln!(
vga_buffer::WRITER.lock(),
"The numbers are {} and {}",
42,
1.0 / 3.0
)
.unwrap();
writeln!(
vga_buffer::WRITER.lock(),
"a is {}, b is {}, c is {}, d is {}",
a,
b,
c,
d
)
.unwrap();
loop {}
}

View File

@ -1,5 +1,5 @@
[package] [package]
name = "kernel" name = "vga_buffer"
version = "0.1.0" version = "0.1.0"
authors = ["Guillaume DIDIER <guillaume.didier.2014@polytechnique.org>"] authors = ["Guillaume DIDIER <guillaume.didier.2014@polytechnique.org>"]
edition = "2018" edition = "2018"
@ -7,7 +7,9 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
volatile = "0.2.6"
spin = "0.5.2"
[dependencies.bootloader] [dependencies.lazy_static]
version = "^0.8.1" version = "1.0"
features = ["sse"] features = ["spin_no_std"]

274
vga_buffer/src/lib.rs Normal file
View File

@ -0,0 +1,274 @@
#![no_std] // This is a free standing program
use core::fmt;
use core::intrinsics::transmute;
use lazy_static::lazy_static;
use spin::Mutex;
use volatile::Volatile;
pub const BUFFER_HEIGHT: usize = 25;
pub const BUFFER_WIDTH: usize = 80;
const BRIGHT_BIT: u8 = 0x4;
const EMPTY_CHAR: u8 = b' ';
const NEWLINE_CHAR: u8 = b'\n';
const BACKSPACE_CHAR: u8 = 0x8;
const UNPRINTABLE_CHAR: u8 = 0xfe;
const PRINTABLE_RANGE_START: u8 = 0x20;
const PRINTABLE_RANGE_STOP: u8 = 0x7f;
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Color {
Black = 0x0,
Blue = 0x1,
Green = 0x2,
Cyan = 0x3,
Red = 0x4,
Magenta = 0x5,
Brown = 0x6,
LightGray = 0x7,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum ForegroundColor {
Black = 0x0,
Blue = 0x1,
Green = 0x2,
Cyan = 0x3,
Red = 0x4,
Magenta = 0x5,
Brown = 0x6,
LightGray = 0x7,
DarkGray = 0x8,
LightBlue = 0x9,
LightGreen = 0xa,
LightCyan = 0xb,
LightRed = 0xc,
Pink = 0xd,
Yellow = 0xe,
White = 0xf,
}
impl ForegroundColor {
pub fn new(color: Color, bright: bool) -> ForegroundColor {
if bright {
unsafe { transmute(BRIGHT_BIT | (color as u8)) }
} else {
unsafe { transmute(color) }
}
}
}
impl From<Color> for ForegroundColor {
fn from(color: Color) -> Self {
unsafe { transmute(color) }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(transparent)]
pub struct ColorCode(u8);
impl ColorCode {
fn new_with_blink(foreground: ForegroundColor, background: Color, blink: bool) -> ColorCode {
ColorCode((foreground as u8) | (blink as u8) << 7 | (background as u8) << 4)
}
fn new(foreground: ForegroundColor, background: Color) -> ColorCode {
ColorCode::new_with_blink(foreground, background, false)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(C)]
pub struct ScreenChar {
ascii_char: u8,
color_code: ColorCode,
}
#[repr(transparent)]
struct Buffer {
chars: [[Volatile<ScreenChar>; BUFFER_WIDTH]; BUFFER_HEIGHT],
}
// The writer could eventually also show the cursor
pub struct Writer {
column_position: usize,
row_position: usize,
color_code: ColorCode,
buffer: &'static mut Buffer,
}
impl Writer {
fn new(color_code: ColorCode, buffer: &'static mut Buffer) -> Writer {
let mut w = Writer {
column_position: 0,
row_position: 0,
color_code: color_code,
buffer: buffer,
};
w.clear_screen();
w
}
fn clear_screen(&mut self) {
for i in 0..BUFFER_HEIGHT {
for j in 0..BUFFER_WIDTH {
self.draw(
i,
j,
ScreenChar {
ascii_char: EMPTY_CHAR,
color_code: self.color_code,
},
);
}
}
}
fn getchar(&self, row: usize, col: usize) -> ScreenChar {
self.buffer.chars[row][col].read()
}
fn draw(&mut self, row: usize, col: usize, sc: ScreenChar) {
self.buffer.chars[row][col].write(sc);
}
fn scroll(&mut self) {
for i in 0..BUFFER_HEIGHT - 1 {
for j in 0..BUFFER_WIDTH {
let sc = self.getchar(i + 1, j);
self.draw(i, j, sc);
}
}
for j in 0..BUFFER_WIDTH {
self.draw(
BUFFER_HEIGHT - 1,
j,
ScreenChar {
ascii_char: EMPTY_CHAR,
color_code: self.color_code,
},
);
}
}
fn set_cursor_row(&mut self, row_position: usize) {
assert!(row_position < BUFFER_HEIGHT);
self.row_position = row_position;
}
fn set_cursor_col(&mut self, column_position: usize) {
assert!(column_position < BUFFER_WIDTH);
self.column_position = column_position;
}
fn cursor_offset(&mut self, offset: isize) {
let mut line_pos: isize = offset + self.column_position as isize;
let mut height_pos: isize = self.row_position as isize;
while line_pos < 0 {
height_pos -= 1;
line_pos += BUFFER_WIDTH as isize;
}
while line_pos >= BUFFER_WIDTH as isize {
height_pos += 1;
line_pos -= BUFFER_WIDTH as isize;
}
while height_pos >= BUFFER_HEIGHT as isize {
height_pos -= 1;
self.scroll();
}
if height_pos < 0 {
height_pos = 0;
line_pos = 0;
}
assert!(height_pos >= 0);
assert!(line_pos >= 0);
self.set_cursor_col(line_pos as usize);
self.set_cursor_row(height_pos as usize);
}
fn put_byte(&mut self, byte: u8) {
match byte {
NEWLINE_CHAR => {
// Empty line
for i in self.column_position..BUFFER_WIDTH {
self.draw(
self.row_position,
i,
ScreenChar {
ascii_char: EMPTY_CHAR,
color_code: self.color_code,
},
);
}
self.set_cursor_col(0);
self.cursor_offset(BUFFER_WIDTH as isize)
}
BACKSPACE_CHAR => {
self.draw(
self.row_position,
self.column_position,
ScreenChar {
ascii_char: EMPTY_CHAR,
color_code: self.color_code,
},
);
self.cursor_offset(-1);
}
byte => {
self.draw(
self.row_position,
self.column_position,
ScreenChar {
ascii_char: byte,
color_code: self.color_code,
},
);
self.cursor_offset(1);
}
}
}
fn put_bytes(&mut self, s: &str) {
for byte in s.bytes() {
match byte {
// printable ASCII byte or newline
PRINTABLE_RANGE_START..=PRINTABLE_RANGE_STOP | NEWLINE_CHAR | BACKSPACE_CHAR => {
self.put_byte(byte)
}
// not part of printable ASCII range
_ => self.put_byte(UNPRINTABLE_CHAR),
}
}
}
}
impl fmt::Write for Writer {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.put_bytes(s);
Ok(())
}
}
lazy_static! {
pub static ref WRITER: Mutex<Writer> = Mutex::new(Writer::new(
ColorCode::new(ForegroundColor::Yellow, Color::Blue),
unsafe { &mut *(0xb8000 as *mut Buffer) },
));
}