Initial commit

This commit is contained in:
pjht 2024-09-09 09:44:51 -05:00
commit 7612fba1e4
Signed by: pjht
GPG Key ID: 7B5F6AFBEC7EE78E
8 changed files with 1031 additions and 0 deletions

5
.cargo/config.toml Normal file
View File

@ -0,0 +1,5 @@
[build]
target = "x86_64-unknown-mikros"
[install]
root = "../os_build/sysroot"

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

529
Cargo.lock generated Normal file
View File

@ -0,0 +1,529 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "ahash"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [
"cfg-if",
"once_cell",
"version_check",
"zerocopy",
]
[[package]]
name = "allocator-api2"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
[[package]]
name = "atomic-polyfill"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
dependencies = [
"critical-section",
]
[[package]]
name = "autocfg"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]]
name = "bga"
version = "0.1.0"
dependencies = [
"dev_driver_rpc",
"devfs_rpc",
"file_rpc",
"fontdue",
"itertools",
"parking_lot",
"pci_rpc",
"rhexdump",
"syslog_rpc",
"volatile 0.6.1",
"x86_64",
]
[[package]]
name = "bit_field"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
[[package]]
name = "bitflags"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cobs"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15"
[[package]]
name = "critical-section"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f64009896348fc5af4222e9cf7d7d82a95a256c634ebcf61c53e4ea461422242"
[[package]]
name = "dev_driver_rpc"
version = "0.1.0"
dependencies = [
"parking_lot",
"postcard",
"serde",
]
[[package]]
name = "devfs_rpc"
version = "0.1.0"
dependencies = [
"parking_lot",
"postcard",
"serde",
]
[[package]]
name = "either"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "embedded-io"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced"
[[package]]
name = "embedded-io"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d"
[[package]]
name = "file_rpc"
version = "0.1.0"
dependencies = [
"parking_lot",
"postcard",
"serde",
]
[[package]]
name = "fontdue"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efe23d02309319171d00d794c9ff48d4f903c0e481375b1b04b017470838af04"
dependencies = [
"hashbrown",
"ttf-parser",
]
[[package]]
name = "hash32"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
dependencies = [
"byteorder",
]
[[package]]
name = "hashbrown"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
dependencies = [
"ahash",
"allocator-api2",
]
[[package]]
name = "heapless"
version = "0.7.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f"
dependencies = [
"atomic-polyfill",
"hash32",
"rustc_version",
"serde",
"spin",
"stable_deref_trait",
]
[[package]]
name = "itertools"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
dependencies = [
"either",
]
[[package]]
name = "libc"
version = "0.2.158"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
[[package]]
name = "lock_api"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "parking_lot"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-targets",
]
[[package]]
name = "pci_rpc"
version = "0.1.0"
dependencies = [
"parking_lot",
"postcard",
]
[[package]]
name = "postcard"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f7f0a8d620d71c457dd1d47df76bb18960378da56af4527aaa10f515eee732e"
dependencies = [
"cobs",
"embedded-io 0.4.0",
"embedded-io 0.6.1",
"heapless",
"postcard-derive",
"serde",
]
[[package]]
name = "postcard-derive"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0239fa9c1d225d4b7eb69925c25c5e082307a141e470573fbbe3a817ce6a7a37"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "proc-macro2"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
dependencies = [
"bitflags",
]
[[package]]
name = "rhexdump"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a92cbe1a3dd221e3777fef339115d3b85e17a538668e03a0f3ae9c6a98351c7"
[[package]]
name = "rustc_version"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
dependencies = [
"semver",
]
[[package]]
name = "rustversion"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "semver"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
[[package]]
name = "serde"
version = "1.0.210"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.210"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.77",
]
[[package]]
name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "spin"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
dependencies = [
"lock_api",
]
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syslog_rpc"
version = "0.1.0"
dependencies = [
"parking_lot",
"postcard",
"syslog_structs",
]
[[package]]
name = "syslog_structs"
version = "0.1.0"
dependencies = [
"serde",
]
[[package]]
name = "ttf-parser"
version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8"
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "volatile"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "442887c63f2c839b346c192d047a7c87e73d0689c9157b00b53dcc27dd5ea793"
[[package]]
name = "volatile"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af8ca9a5d4debca0633e697c88269395493cebf2e10db21ca2dbde37c1356452"
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "x86_64"
version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bc79523af8abf92fb1a970c3e086c5a343f6bcc1a0eb890f575cbb3b45743df"
dependencies = [
"bit_field",
"bitflags",
"rustversion",
"volatile 0.4.6",
]
[[package]]
name = "zerocopy"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.77",
]

17
Cargo.toml Normal file
View File

@ -0,0 +1,17 @@
[package]
name = "bga"
version = "0.1.0"
edition = "2021"
[dependencies]
dev_driver_rpc = { version = "0.1.0", path = "../dev_driver_rpc" }
devfs_rpc = { version = "0.1.0", path = "../devfs/devfs_rpc" }
file_rpc = { version = "0.1.0", path = "../file_rpc" }
fontdue = { version = "0.9.2", default-features = false, features = ["hashbrown"] }
itertools = "0.13.0"
parking_lot = "0.12.3"
pci_rpc = { version = "0.1.0", path = "../pci/pci_rpc" }
rhexdump = "0.2.0"
syslog_rpc = { version = "0.1.0", path = "../syslog/syslog_rpc" }
volatile = { version = "0.6.1", features = ["unstable"] }
x86_64 = "0.15.1"

BIN
FiraCode-Regular.ttf Normal file

Binary file not shown.

57
edid.rs Normal file
View File

@ -0,0 +1,57 @@
//let mut edid = [0; 1024];
//
//let edid_vol = unsafe {
// VolatilePtr::new(NonNull::slice_from_raw_parts(
// NonNull::new(reg_base).unwrap(),
// 1024,
// ))
//};
//
//edid_vol.copy_into_slice(&mut edid);
//
//rhexdump!(&edid);
//
//if edid[35] & 0xC0 > 0 {
// println!("Established timing 720x400");
//}
//if edid[35] & 0x3C > 0 {
// println!("Established timing 640x480");
//}
//if (edid[35] & 0x3 > 0) | (edid[36] & 0xC0 > 0) {
// println!("Established timing 800x600");
//}
//if edid[36] & 0x20 > 0 {
// println!("Established timing 832x624");
//}
//if edid[36] & 0x1E > 0 {
// println!("Established timing 1024x768");
//}
//if edid[36] & 0x1 > 0 {
// println!("Established timing 1280x1024");
//}
//if edid[37] & 0x80 > 0 {
// println!("Established timing 1152x870");
//}
//
//for i in 0..7 {
// let offset = 38 + 2 * i;
// let xres = ((edid[offset] as u32) + 31) * 8;
// let aspect = (edid[offset] & 0xC0) >> 6;
// let yres = match aspect {
// 0 => (xres / 16) * 10,
// 1 => (xres / 4) * 3,
// 2 => (xres / 5) * 4,
// 3 => (xres / 16) * 9,
// _ => panic!("Invalid aspect!"),
// };
// println!("Standard res {i}: {xres}x{yres}");
//}
//
//for (i, offset) in [0x36, 0x48, 0x5A, 0x6C].iter().enumerate() {
// let xres = edid[offset + 2] as u32 | ((edid[offset + 4] as u32 & 0xF0) << 4);
// if xres == 0 {
// continue;
// }
// let yres = edid[offset + 5] as u32 | ((edid[offset + 7] as u32 & 0xF0) << 4);
// println!("Detailed res {i}: {xres}x{yres}");
//}

2
rust-toolchain.toml Normal file
View File

@ -0,0 +1,2 @@
[toolchain]
channel = "dev-x86_64-unknown-mikros"

420
src/main.rs Normal file
View File

@ -0,0 +1,420 @@
#![warn(clippy::pedantic)]
#![allow(clippy::cast_lossless)]
#![allow(clippy::cast_possible_truncation)]
#![allow(clippy::cast_possible_wrap)]
#![allow(clippy::cast_precision_loss)]
#![allow(clippy::cast_sign_loss)]
#![allow(clippy::match_same_arms)]
#![allow(clippy::missing_panics_doc)]
#![allow(clippy::missing_errors_doc)]
#![allow(clippy::similar_names)]
#![allow(clippy::too_many_lines)]
#![allow(clippy::wildcard_imports)]
#![allow(clippy::cast_ptr_alignment)]
#![warn(clippy::nursery)]
#![allow(clippy::suspicious_operation_groupings)]
#![allow(clippy::option_if_let_else)]
#![allow(clippy::non_send_fields_in_send_ty)]
#![allow(clippy::missing_const_for_fn)]
#![allow(clippy::while_float)]
#![allow(clippy::tuple_array_conversions)]
use core::str;
use std::{
borrow::Cow, collections::HashMap, fmt::{self, Write}, os::mikros::{address_space::ACTIVE_SPACE, ipc, syscalls}
};
use fontdue::{layout::{CoordinateSystem, GlyphRasterConfig, Layout, LayoutSettings, TextStyle, WrapStyle}, Font, FontSettings};
use itertools::Itertools;
use parking_lot::Mutex;
use x86_64::structures::paging::PageTableFlags;
#[allow(unused)]
const VBE_ID_NUM: usize = 0;
#[allow(unused)]
const VBE_XRES_NUM: usize = 1;
#[allow(unused)]
const VBE_YRES_NUM: usize = 2;
#[allow(unused)]
const VBE_BPP_NUM: usize = 3;
#[allow(unused)]
const VBE_ENABLE_NUM: usize = 4;
#[allow(unused)]
const VBE_BANK_NUM: usize = 5;
#[allow(unused)]
const VBE_VIRT_WIDTH_NUM: usize = 6;
#[allow(unused)]
const VBE_VIRT_HEIGHT_NUM: usize = 7;
#[allow(unused)]
const VBE_INDEX_X_NUM: usize = 8;
#[allow(unused)]
const VBE_INDEX_Y_NUM: usize = 9;
const BGA_MMIO_VBE_OFFSET: usize = 0x500;
pub struct Bga {
mmio_base: *mut u8,
framebuffer_base: *mut u8,
draw_buffer: Vec<u8>,
scroll_offset: usize,
xres: usize,
yres: usize,
}
unsafe impl Send for Bga {}
unsafe impl Sync for Bga {}
impl Bga {
pub unsafe fn new(mmio_base: *mut u8, framebuffer_base: *mut u8) -> Self {
Self { mmio_base, framebuffer_base, draw_buffer: Vec::new(), scroll_offset: 0, xres: 0, yres: 0}
}
// Changes the screenn resolution. Also clears the screen.
pub fn set_resolution(&mut self, xres: u16, yres: u16) {
let vbe_base = self.vbe_base();
unsafe {
vbe_base.wrapping_add(VBE_ENABLE_NUM).write_volatile(0x0);
vbe_base.wrapping_add(VBE_XRES_NUM).write_volatile(xres);
vbe_base.wrapping_add(VBE_YRES_NUM).write_volatile(yres);
vbe_base.wrapping_add(VBE_BPP_NUM).write_volatile(0x20);
vbe_base.wrapping_add(VBE_ENABLE_NUM).write_volatile(0x41);
}
self.draw_buffer.resize(xres as usize * yres as usize * 4 * 2, 0);
self.draw_buffer.fill(0);
self.scroll_offset = 0;
self.xres = xres as usize;
self.yres = yres as usize;
}
pub fn clear(&mut self) {
self.draw_buffer.fill(0);
self.scroll_offset = 0;
}
pub fn set_pixel(&mut self, row: usize, col: usize, value: u8) {
if row >= self.yres || col >= self.xres {
return;
}
let row_offset = self.row_byte_offset(row + self.scroll_offset);
self.draw_buffer[row_offset+col*4..][..4].fill(value);
}
pub fn update_screen(&mut self) {
let scroll_top_byte_offset = self.row_byte_offset(self.scroll_offset);
let scroll_bot_byte_offset = self.row_byte_offset(self.scroll_offset + self.yres);
let visible_buf = &self.draw_buffer[scroll_top_byte_offset..scroll_bot_byte_offset];
unsafe { self.framebuffer_base.copy_from_nonoverlapping(&visible_buf[0], visible_buf.len()) };
}
fn vbe_base(&self) -> *mut u16 {
self.mmio_base.wrapping_add(BGA_MMIO_VBE_OFFSET).cast::<u16>()
}
fn row_byte_offset(&self, row: usize) -> usize {
4 * self.xres * row
}
fn clear_raw_row(&mut self, row: usize) {
if row >= self.yres*2 {
return;
}
let offset = self.row_byte_offset(row);
self.draw_buffer[offset..][..(self.xres * 4)].fill(0);
}
pub fn clear_row(&mut self, row: usize) {
if row >= self.yres {
return;
}
self.clear_raw_row(row + self.scroll_offset);
}
// TODO: Explain this function's logic
fn scroll_by(&mut self, offset: usize) {
if offset > self.yres {
return;
}
let old_offset = self.scroll_offset;
self.scroll_offset += offset;
if self.scroll_offset >= self.yres {
for row in (old_offset + self.yres)..(self.yres*2) {
self.clear_raw_row(row);
}
self.scroll_offset -= self.yres;
let half_buf_size = self.row_byte_offset(self.yres);
let (scr_1,scr_2) = self.draw_buffer.split_at_mut(half_buf_size);
scr_1.copy_from_slice(scr_2);
for row in (self.yres)..(self.yres + self.scroll_offset) {
self.clear_raw_row(row);
}
} else {
for row in (old_offset + self.yres)..(self.scroll_offset + self.yres) {
self.clear_raw_row(row);
}
}
}
}
pub struct FramebufferWriter {
out_string: String,
font: Font,
layout: Layout,
next_line_y: usize,
glyph_cache: HashMap<GlyphRasterConfig, Vec<u8>>,
cursor_height: usize,
}
impl FramebufferWriter {
fn new(font: Font, fbuf: &Bga) -> Self {
let mut layout = Layout::new(CoordinateSystem::PositiveYDown);
layout.reset(&LayoutSettings {
max_width: Some(fbuf.xres as f32),
max_height: Some(fbuf.yres as f32),
wrap_style: WrapStyle::Letter,
..Default::default()
});
Self {
out_string: String::new(),
font,
layout,
next_line_y: 0,
glyph_cache: HashMap::new(),
cursor_height: 0,
}
}
fn update_screen(&mut self, fbuf: &mut Bga) {
self.layout.clear();
self.layout.append(&[&self.font], &TextStyle::new(&self.out_string, 12.0, 0));
let text_height = self.layout.height();
self.layout.append(&[&self.font], &TextStyle::new("\u{2588}", 12.0, 0));
if (self.next_line_y + self.layout.height() as usize) > fbuf.yres {
let excess_y =
self.layout.height() as usize - (fbuf.yres - self.next_line_y);
fbuf.scroll_by(excess_y);
self.next_line_y -= excess_y;
}
for row in 0..usize::max(self.cursor_height+5,text_height as usize) {
fbuf.clear_row(self.next_line_y + row);
}
//for row in 0..(fbuf.yres - self.next_line_y) {
// fbuf.clear_row(self.next_line_y + row);
//}
self.cursor_height = (self.layout.height() - text_height) as usize;
let glyphs = self.layout.glyphs();
let mut first_line_top_offset = None;
for line in self.layout.lines().unwrap() {
if first_line_top_offset.is_none() {
first_line_top_offset = Some((line.baseline_y - line.max_ascent) as usize);
}
let first_line_top_offset = first_line_top_offset.unwrap();
for glyph_pos in &glyphs[line.glyph_start..=line.glyph_end] {
if glyph_pos.width == 0 || glyph_pos.height == 0 {
continue;
}
let bitmap: Cow<[u8]> = if let Some(bitmap) = self.glyph_cache.get(&glyph_pos.key) {
bitmap.into()
} else {
let bitmap = self.font.rasterize_config(glyph_pos.key).1;
self.glyph_cache.insert(glyph_pos.key, bitmap.clone());
bitmap.into()
};
for (i, &pixel) in bitmap.iter().enumerate() {
let row = i / glyph_pos.width;
let col = i % glyph_pos.width;
fbuf.set_pixel(
row + glyph_pos.y as usize - first_line_top_offset + self.next_line_y,
col + glyph_pos.x as usize,
pixel,
);
}
}
}
let last_line = self.layout.lines().unwrap().last().unwrap();
fbuf.update_screen();
let first_char_offset = glyphs[last_line.glyph_start].byte_offset;
let last_char_offset = glyphs[last_line.glyph_end -1].byte_offset;
let mut last_char_end = last_char_offset + 1;
while last_char_end < self.out_string.len() && !self.out_string.is_char_boundary(last_char_end) {
last_char_end += 1;
}
let log_line_slice = &self.out_string[first_char_offset..last_char_end];
let before_last_height = (last_line.baseline_y - last_line.max_ascent) as usize;
if self.out_string.ends_with('\n') {
self.out_string.clear();
self.next_line_y += text_height as usize;
} else {
self.out_string = log_line_slice.to_string();
self.next_line_y += before_last_height;
}
}
}
impl fmt::Write for FramebufferWriter {
fn write_char(&mut self, c: char) -> fmt::Result {
self.out_string.push(c);
Ok(())
}
fn write_str(&mut self, s: &str) -> core::fmt::Result {
self.out_string.push_str(s);
Ok(())
}
}
struct DevServ;
impl dev_driver_rpc::Server for DevServ {
fn open(&self, _path: &std::path::Path) -> Result<u64, ()> {
Ok(0)
}
}
struct FileServ {
fbwriter: Mutex<FramebufferWriter>,
fbuffer: Mutex<Bga>,
}
impl file_rpc::Server for FileServ {
fn read(
&self,
_fd: u64,
_pos: u64,
_len: usize,
) -> std::result::Result<std::borrow::Cow<'_, [u8]>, ()> {
Err(())
}
#[allow(clippy::significant_drop_tightening)]
fn write(&self, _fd: u64, _pos: u64, data: &[u8]) -> Result<(), ()> {
let string = str::from_utf8(data).map_err(|_| ())?;
let mut fbwriter = self.fbwriter.lock();
let mut fbuffer = self.fbuffer.lock();
let _ = fbwriter.write_str(string); // never errors
fbwriter.update_screen(&mut fbuffer);
Ok(())
}
fn close(&self, _fd: u64) {}
fn size(&self, _fd: u64) -> Option<u64> {
None
}
}
fn main() {
let syslog_pid = loop {
if let Some(pid) = syscalls::try_get_registered(2) {
break pid;
}
};
let syslog_client = syslog_rpc::Client::new(syslog_pid);
let (bus_str, dev_str, func_str, pci_pid_str, dev_id_str) = std::env::args()
.skip(1)
.collect_tuple::<(_, _, _, _, _)>()
.expect("Usage: bga <bus> <dev> <func> <PCI driver PID> <Device ID>");
let bus = bus_str
.parse::<u8>()
.unwrap_or_else(|_| panic!("{bus_str:?} is not a valid bus number"));
let dev = dev_str
.parse::<u8>()
.unwrap_or_else(|_| panic!("{dev_str:?} is not a valid device number"));
let func = func_str
.parse::<u8>()
.unwrap_or_else(|_| panic!("{func_str:?} is not a valid function number"));
let pci_pid = pci_pid_str
.parse::<u64>()
.unwrap_or_else(|_| panic!("{pci_pid_str:?} is not a valid PID"));
let dev_id = dev_id_str
.parse::<u64>()
.unwrap_or_else(|_| panic!("{dev_id_str:?} is not a valid device ID"));
syslog_client.send_text_message("bga", format!("Started on PCI device with address: Bus # {bus}, device # {dev}, and function # {func}")).unwrap();
syslog_client
.send_text_message("bga", format!("PCI driver has PID {pci_pid}"))
.unwrap();
let pci_client = pci_rpc::Client::new(pci_pid);
let bars = pci_client.get_bars(bus, dev, func).unwrap();
let mmio_base: *mut u8 = unsafe {
ACTIVE_SPACE
.lock()
.unwrap()
.map_free_to(
bars[2].1 as u64,
bars[2].2.div_ceil(4096) as usize,
(PageTableFlags::WRITABLE | PageTableFlags::WRITE_THROUGH).bits(),
)
.unwrap()
};
let framebuffer_base: *mut u8 = unsafe {
ACTIVE_SPACE
.lock()
.unwrap()
.map_free_to(
bars[0].1 as u64,
bars[0].2.div_ceil(4096) as usize,
(PageTableFlags::WRITABLE | PageTableFlags::WRITE_THROUGH).bits(),
)
.unwrap()
};
let vbe_base = mmio_base.wrapping_add(BGA_MMIO_VBE_OFFSET).cast::<u16>();
let version = unsafe { vbe_base.wrapping_add(VBE_ID_NUM).read_volatile() };
syslog_client
.send_text_message("bga", format!("BGA version {version:#x}"))
.unwrap();
if version != 0xB0C5 {
syslog_client
.send_text_message(
"bga",
"Error: Only compatible with version 0xB0C5, aborting",
)
.unwrap();
return;
}
let mut bga = unsafe { Bga::new(mmio_base, framebuffer_base) };
syslog_client
.send_text_message("bga", "Setting resolution to 1920x1050")
.unwrap();
bga.set_resolution(1920, 1050);
let font = Font::from_bytes(include_bytes!("../FiraCode-Regular.ttf").as_slice(), FontSettings::default()).unwrap();
let writer = FramebufferWriter::new(font, &bga);
dev_driver_rpc::register_server(Box::new(DevServ));
file_rpc::register_server(Box::new(FileServ {
fbwriter: Mutex::new(writer),
fbuffer: Mutex::new(bga),
}));
let devfs_pid;
loop {
if let Some(pid) = syscalls::try_get_registered(1) {
devfs_pid = pid;
break;
}
}
devfs_rpc::Client::new(devfs_pid)
.register_dev(&format!("bga{dev_id}"))
.unwrap();
loop {
ipc::process_messages();
}
}