Compare commits

...

28 Commits

Author SHA1 Message Date
Philipp Oppermann
d8b6293a72 Merge branch 'post-3.2' into post-3.3 2025-02-10 14:25:35 +01:00
Philipp Oppermann
f57582a83c Run cargo update for bootloader crate 2025-02-10 14:24:45 +01:00
Philipp Oppermann
15535d6217 Allow splitting of framebuffer 2023-12-29 20:36:54 +01:00
Philipp Oppermann
521d4b2fd2 Rearrange circle and text 2023-12-29 20:23:52 +01:00
Philipp Oppermann
563c19731f Simplify framebuffer code 2023-12-29 20:20:42 +01:00
Philipp Oppermann
79f47fda12 Use embedded-graphics crate to draw shapes and text 2023-12-29 19:27:56 +01:00
Philipp Oppermann
00fa82937a Write blue rectangle to the screen 2023-12-29 18:42:32 +01:00
Philipp Oppermann
54b3a26202 Run cargo update 2023-12-29 16:54:52 +01:00
Philipp Oppermann
d56d98988c Run cargo update 2023-07-09 11:30:35 +02:00
Philipp Oppermann
54e41b79a5 Remove striped output example again 2023-07-09 11:29:33 +02:00
Philipp Oppermann
cf28a5fdf9 Print something to the screen 2023-05-01 15:05:34 +02:00
Philipp Oppermann
2a49491fc7 Add a qemu-uefi executable to start the UEFI disk image in QEMU 2023-05-01 14:34:05 +02:00
Philipp Oppermann
ba8b0392b8 Add a qemu-bios executable to start the BIOS disk image in QEMU 2023-05-01 14:20:01 +02:00
Philipp Oppermann
98da4b2f9a Fix rust-analyzer errors 2023-05-01 14:19:34 +02:00
Philipp Oppermann
34b1eb4741 Create the disk image in a build script 2023-05-01 13:23:37 +02:00
Philipp Oppermann
51e0dc1b63 Set default rustup profile 2023-04-30 17:16:23 +02:00
Philipp Oppermann
a4b2b853b9 Add rust-src component 2023-04-30 17:14:08 +02:00
Philipp Oppermann
0a21782583 Update CI script for second post 2023-04-30 17:10:47 +02:00
Philipp Oppermann
e2dca79d0d Use bootloader crate to create bootable disk images 2023-04-30 16:52:24 +02:00
Philipp Oppermann
913d5189c9 Silence unused variable warning 2023-04-30 16:52:03 +02:00
Philipp Oppermann
29c919962f Add an artifact dependency on the kernel 2023-04-30 15:40:47 +02:00
Philipp Oppermann
0eee1e080b Use nightly Rust 2023-04-30 15:08:43 +02:00
Philipp Oppermann
ecf8fe826b Create a cargo workspace with a new blog_os crate at the root 2023-04-30 14:53:36 +02:00
Philipp Oppermann
4ea28d0910 Merge branch 'post-3.1' into post-3.2 2023-04-30 14:00:52 +02:00
Philipp Oppermann
88329503ad Merge branch 'post-3.1' into post-3.2 2023-03-25 20:31:48 +01:00
Philipp Oppermann
7ff6510352 Use bootloader_api::entry_point macro 2023-03-25 20:12:41 +01:00
Philipp Oppermann
eb78b1fb9b Add bootloader_api dependency 2023-03-25 19:49:46 +01:00
Philipp Oppermann
2dc10d0198 Update README for second post 2023-03-25 19:19:58 +01:00
13 changed files with 794 additions and 36 deletions

2
.cargo/config.toml Normal file
View File

@@ -0,0 +1,2 @@
[unstable]
bindeps = true

View File

@@ -15,8 +15,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- run: rustup target add x86_64-unknown-none
- run: cargo check --target x86_64-unknown-none
- run: cargo check
test:
name: Test
@@ -30,9 +29,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- run: rustup target add x86_64-unknown-none
- run: cargo build --target x86_64-unknown-none
- run: cargo build
fmt:
name: Check Formatting
@@ -46,7 +43,4 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: rustup target add x86_64-unknown-none
- run: rustup component add clippy
- run: cargo clippy --target x86_64-unknown-none
- run: cargo clippy

514
Cargo.lock generated
View File

@@ -1,7 +1,519 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
version = 4
[[package]]
name = "anyhow"
version = "1.0.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9d19de80eff169429ac1e9f48fffb163916b448a44e8e046186232046d9e1f9"
[[package]]
name = "autocfg"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "az"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973"
[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
[[package]]
name = "bitvec"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
dependencies = [
"funty",
"radium",
"tap",
"wyz",
]
[[package]]
name = "blog_os"
version = "0.1.0"
dependencies = [
"bootloader",
"kernel",
"ovmf-prebuilt",
]
[[package]]
name = "bootloader"
version = "0.11.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "718ebb60a92a2e37f9c6c6ab26f0adfd117aa6f1a8cd08d07bbd5a7762ff0812"
dependencies = [
"anyhow",
"bootloader-boot-config",
"fatfs",
"gpt",
"llvm-tools",
"mbrman",
"serde_json",
"tempfile",
]
[[package]]
name = "bootloader-boot-config"
version = "0.11.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a4ff46e7fd938aa06b17d44dce17f605105da3df01b1ae8a7f02d248c9b12f6"
dependencies = [
"serde",
]
[[package]]
name = "bootloader_api"
version = "0.11.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77fadafc2a2fa690f4f14a2e2a41c65d9e810b7fe959245bdf6d3b9c6d7e4bf1"
[[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 = "crc"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe"
dependencies = [
"crc-catalog",
]
[[package]]
name = "crc-catalog"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
[[package]]
name = "embedded-graphics"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0649998afacf6d575d126d83e68b78c0ab0e00ca2ac7e9b3db11b4cbe8274ef0"
dependencies = [
"az",
"byteorder",
"embedded-graphics-core",
"float-cmp",
"micromath",
]
[[package]]
name = "embedded-graphics-core"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba9ecd261f991856250d2207f6d8376946cd9f412a2165d3b75bc87a0bc7a044"
dependencies = [
"az",
"byteorder",
]
[[package]]
name = "errno"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "fastrand"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
[[package]]
name = "fatfs"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05669f8e7e2d7badc545c513710f0eba09c2fbef683eb859fd79c46c355048e0"
dependencies = [
"bitflags 1.3.2",
"byteorder",
"log",
]
[[package]]
name = "float-cmp"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4"
dependencies = [
"num-traits",
]
[[package]]
name = "funty"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
[[package]]
name = "getrandom"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "gpt"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8283e7331b8c93b9756e0cfdbcfb90312852f953c6faf9bf741e684cc3b6ad69"
dependencies = [
"bitflags 2.4.1",
"crc",
"log",
"uuid",
]
[[package]]
name = "itoa"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
[[package]]
name = "kernel"
version = "0.1.0"
dependencies = [
"bootloader_api",
"embedded-graphics",
]
[[package]]
name = "libc"
version = "0.2.151"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
[[package]]
name = "linux-raw-sys"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
[[package]]
name = "llvm-tools"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "955be5d0ca0465caf127165acb47964f911e2bc26073e865deb8be7189302faf"
[[package]]
name = "log"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "mbrman"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c487024623ae38584610237dd1be8932bb2b324474b23c37a25f9fbe6bf5e9e"
dependencies = [
"bincode",
"bitvec",
"serde",
"serde-big-array",
"thiserror",
]
[[package]]
name = "micromath"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3c8dda44ff03a2f238717214da50f65d5a53b45cd213a7370424ffdb6fae815"
[[package]]
name = "num-traits"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
dependencies = [
"autocfg",
]
[[package]]
name = "ovmf-prebuilt"
version = "0.1.0-alpha.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa50141d081512ab30fd9e7e7692476866df5098b028536ad6680212e717fa8d"
[[package]]
name = "proc-macro2"
version = "1.0.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [
"proc-macro2",
]
[[package]]
name = "radium"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
[[package]]
name = "redox_syscall"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "rustix"
version = "0.38.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316"
dependencies = [
"bitflags 2.4.1",
"errno",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "ryu"
version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
[[package]]
name = "serde"
version = "1.0.193"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde-big-array"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3323f09a748af288c3dc2474ea6803ee81f118321775bffa3ac8f7e65c5e90e7"
dependencies = [
"serde",
]
[[package]]
name = "serde_derive"
version = "1.0.193"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "syn"
version = "2.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tap"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]]
name = "tempfile"
version = "3.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa"
dependencies = [
"cfg-if",
"fastrand",
"redox_syscall",
"rustix",
"windows-sys",
]
[[package]]
name = "thiserror"
version = "1.0.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83a48fd946b02c0a526b2e9481c8e2a17755e47039164a86c4070446e3a4614d"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7fbe9b594d6568a6a1443250a7e67d80b74e1e96f6d1715e1e21cc1888291d3"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "uuid"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560"
dependencies = [
"getrandom",
]
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
[[package]]
name = "windows_i686_gnu"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
[[package]]
name = "windows_i686_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
[[package]]
name = "wyz"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
dependencies = [
"tap",
]

View File

@@ -1,8 +1,15 @@
[package]
name = "kernel"
name = "blog_os"
version = "0.1.0"
edition = "2021"
default-run = "blog_os"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[workspace]
members = ["kernel"]
[dependencies]
ovmf-prebuilt = "0.1.0-alpha"
[build-dependencies]
kernel = { path = "kernel", artifact = "bin", target = "x86_64-unknown-none" }
bootloader = "0.11.3"

View File

@@ -1,23 +1,16 @@
# Blog OS (Minimal Kernel)
# Blog OS (Booting)
[![Build Status](https://github.com/phil-opp/blog_os/workflows/Code/badge.svg?branch=post-3.1)](https://github.com/phil-opp/blog_os/actions?query=workflow%3A%22Code%22+branch%3Apost-3.1)
[![Build Status](https://github.com/phil-opp/blog_os/workflows/Code/badge.svg?branch=post-3.2)](https://github.com/phil-opp/blog_os/actions?query=workflow%3A%22Code%22+branch%3Apost-3.2)
This repository contains the source code for the [Minimal Kernel][post] post of the [Writing an OS in Rust](https://os.phil-opp.com) series.
This repository contains the source code for the [Booting][post] post of the [Writing an OS in Rust](https://os.phil-opp.com) series.
[post]: https://os.phil-opp.com/minimal-kernel
[post]: https://os.phil-opp.com/booting
**Check out the [master branch](https://github.com/phil-opp/blog_os) for more information.**
## Building
- Install the `x86_64-unknown-none` target using rustup:
```
rustup target add x86_64-unknown-none
```
- Build by running:
```
cargo build --target x86_64-unknown-none
```
TODO
## License

21
build.rs Normal file
View File

@@ -0,0 +1,21 @@
use bootloader::DiskImageBuilder;
use std::{env, path::PathBuf};
fn main() {
// set by cargo for the kernel artifact dependency
let kernel_path = env::var("CARGO_BIN_FILE_KERNEL").unwrap();
let disk_builder = DiskImageBuilder::new(PathBuf::from(kernel_path));
// specify output paths
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let uefi_path = out_dir.join("blog_os-uefi.img");
let bios_path = out_dir.join("blog_os-bios.img");
// create the disk images
disk_builder.create_uefi_image(&uefi_path).unwrap();
disk_builder.create_bios_image(&bios_path).unwrap();
// pass the disk image paths via environment variables
println!("cargo:rustc-env=UEFI_IMAGE={}", uefi_path.display());
println!("cargo:rustc-env=BIOS_IMAGE={}", bios_path.display());
}

13
kernel/Cargo.toml Normal file
View File

@@ -0,0 +1,13 @@
[package]
name = "kernel"
version = "0.1.0"
edition = "2021"
[[bin]]
name = "kernel"
test = false
bench = false
[dependencies]
bootloader_api = "0.11.0"
embedded-graphics = "0.8.1"

138
kernel/src/framebuffer.rs Normal file
View File

@@ -0,0 +1,138 @@
use bootloader_api::info::{FrameBuffer, FrameBufferInfo, PixelFormat};
use embedded_graphics::{
draw_target::DrawTarget,
geometry::{self, Point},
pixelcolor::{Rgb888, RgbColor},
Pixel,
};
pub struct Display {
framebuffer: &'static mut [u8],
info: FrameBufferInfo,
}
impl Display {
pub fn new(framebuffer: &'static mut FrameBuffer) -> Display {
Self {
info: framebuffer.info(),
framebuffer: framebuffer.buffer_mut(),
}
}
fn draw_pixel(&mut self, coordinates: Point, color: Rgb888) {
// ignore any pixels that are out of bounds.
let position = match (coordinates.x.try_into(), coordinates.y.try_into()) {
(Ok(x), Ok(y)) if x < self.info.width && y < self.info.height => Position { x, y },
_ => return, // ignore out-of-bounds pixel
};
let color = Color {
red: color.r(),
green: color.g(),
blue: color.b(),
};
set_pixel_in(self.framebuffer, self.info, position, color);
}
pub fn split_at_line(self, line_index: usize) -> (Self, Self) {
assert!(line_index < self.info.height);
let byte_offset = line_index * self.info.stride * self.info.bytes_per_pixel;
let (first_buffer, second_buffer) = self.framebuffer.split_at_mut(byte_offset);
let first = Self {
framebuffer: first_buffer,
info: FrameBufferInfo {
byte_len: byte_offset,
height: line_index,
..self.info
},
};
let second = Self {
framebuffer: second_buffer,
info: FrameBufferInfo {
byte_len: self.info.byte_len - byte_offset,
height: self.info.height - line_index,
..self.info
},
};
(first, second)
}
}
impl DrawTarget for Display {
type Color = Rgb888;
/// Drawing operations can never fail.
type Error = core::convert::Infallible;
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
where
I: IntoIterator<Item = Pixel<Self::Color>>,
{
for Pixel(coordinates, color) in pixels.into_iter() {
self.draw_pixel(coordinates, color);
}
Ok(())
}
}
impl geometry::OriginDimensions for Display {
fn size(&self) -> geometry::Size {
geometry::Size::new(
self.info.width.try_into().unwrap(),
self.info.height.try_into().unwrap(),
)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Position {
pub x: usize,
pub y: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Color {
pub red: u8,
pub green: u8,
pub blue: u8,
}
pub fn set_pixel_in(
framebuffer: &mut [u8],
info: FrameBufferInfo,
position: Position,
color: Color,
) {
// calculate offset to first byte of pixel
let byte_offset = {
// use stride to calculate pixel offset of target line
let line_offset = position.y * info.stride;
// add x position to get the absolute pixel offset in buffer
let pixel_offset = line_offset + position.x;
// convert to byte offset
pixel_offset * info.bytes_per_pixel
};
// set pixel based on color format
let pixel_bytes = &mut framebuffer[byte_offset..];
match info.pixel_format {
PixelFormat::Rgb => {
pixel_bytes[0] = color.red;
pixel_bytes[1] = color.green;
pixel_bytes[2] = color.blue;
}
PixelFormat::Bgr => {
pixel_bytes[0] = color.blue;
pixel_bytes[1] = color.green;
pixel_bytes[2] = color.red;
}
PixelFormat::U8 => {
// use a simple average-based grayscale transform
let gray = color.red / 3 + color.green / 3 + color.blue / 3;
pixel_bytes[0] = gray;
}
other => panic!("unknown pixel format {other:?}"),
}
}

50
kernel/src/main.rs Normal file
View File

@@ -0,0 +1,50 @@
#![no_std]
#![no_main]
use core::{convert::Infallible, panic::PanicInfo};
use bootloader_api::BootInfo;
use embedded_graphics::{
draw_target::DrawTarget,
geometry::Point,
mono_font::{ascii::FONT_10X20, MonoTextStyle},
pixelcolor::{Rgb888, RgbColor},
primitives::{Circle, PrimitiveStyle, StyledDrawable},
text::Text,
Drawable,
};
mod framebuffer;
bootloader_api::entry_point!(kernel_main);
fn kernel_main(boot_info: &'static mut BootInfo) -> ! {
if let Some(framebuffer) = boot_info.framebuffer.as_mut() {
let height = framebuffer.info().height;
let display = framebuffer::Display::new(framebuffer);
let (mut upper, mut lower) = display.split_at_line(height / 2);
upper.clear(Rgb888::RED).unwrap_or_else(infallible);
lower.clear(Rgb888::BLUE).unwrap_or_else(infallible);
let style = PrimitiveStyle::with_fill(Rgb888::YELLOW);
Circle::new(Point::new(50, 50), 300)
.draw_styled(&style, &mut upper)
.unwrap_or_else(infallible);
let character_style = MonoTextStyle::new(&FONT_10X20, Rgb888::BLUE);
let text = Text::new("Hello, world!", Point::new(140, 210), character_style);
text.draw(&mut upper).unwrap_or_else(infallible);
}
loop {}
}
/// This function is called on panic.
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}
fn infallible<T>(v: Infallible) -> T {
match v {}
}

5
rust-toolchain.toml Normal file
View File

@@ -0,0 +1,5 @@
[toolchain]
channel = "nightly"
profile = "default"
targets = ["x86_64-unknown-none"]
components = ["rust-src", "llvm-tools-preview"]

12
src/bin/qemu-bios.rs Normal file
View File

@@ -0,0 +1,12 @@
use std::{
env,
process::{self, Command},
};
fn main() {
let mut qemu = Command::new("qemu-system-x86_64");
qemu.arg("-drive");
qemu.arg(format!("format=raw,file={}", env!("BIOS_IMAGE")));
let exit_status = qemu.status().unwrap();
process::exit(exit_status.code().unwrap_or(-1));
}

13
src/bin/qemu-uefi.rs Normal file
View File

@@ -0,0 +1,13 @@
use std::{
env,
process::{self, Command},
};
fn main() {
let mut qemu = Command::new("qemu-system-x86_64");
qemu.arg("-drive");
qemu.arg(format!("format=raw,file={}", env!("UEFI_IMAGE")));
qemu.arg("-bios").arg(ovmf_prebuilt::ovmf_pure_efi());
let exit_status = qemu.status().unwrap();
process::exit(exit_status.code().unwrap_or(-1));
}

View File

@@ -1,15 +1,13 @@
#![no_std]
#![no_main]
use std::{env, fs};
use core::panic::PanicInfo;
fn main() {
let current_exe = env::current_exe().unwrap();
let uefi_target = current_exe.with_file_name("uefi.img");
let bios_target = current_exe.with_file_name("bios.img");
#[no_mangle]
pub extern "C" fn _start() -> ! {
loop {}
}
/// This function is called on panic.
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
fs::copy(env!("UEFI_IMAGE"), &uefi_target).unwrap();
fs::copy(env!("BIOS_IMAGE"), &bios_target).unwrap();
println!("UEFI disk image at {}", uefi_target.display());
println!("BIOS disk image at {}", bios_target.display());
}