├── .cargo └── config.toml ├── .gitignore ├── .vscode └── settings.json ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── imgs └── Screenshot.png ├── runner ├── Cargo.toml └── src │ └── main.rs ├── rust-toolchain.toml └── src ├── graphical.rs ├── logger.rs └── main.rs /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [unstable] 2 | bindeps = true 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "rust-analyzer.cargo.target": "x86_64-unknown-none", 3 | "rust-analyzer.checkOnSave.extraArgs": [ 4 | "-Z", 5 | "build-std", 6 | "-p", 7 | "test-kernel" 8 | ], 9 | "rust-analyzer.checkOnSave.allTargets": false, 10 | "rust-analyzer.checkOnSave.overrideCommand": [ 11 | "cargo", 12 | "check", 13 | "-p", 14 | "test-kernel", 15 | "--message-format=json" 16 | ] 17 | } -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "android_system_properties" 7 | version = "0.1.5" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 10 | dependencies = [ 11 | "libc", 12 | ] 13 | 14 | [[package]] 15 | name = "anyhow" 16 | version = "1.0.64" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "b9a8f622bcf6ff3df478e9deba3e03e4e04b300f8e6a139e192c05fa3490afc7" 19 | 20 | [[package]] 21 | name = "autocfg" 22 | version = "1.1.0" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 25 | 26 | [[package]] 27 | name = "bincode" 28 | version = "1.3.3" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" 31 | dependencies = [ 32 | "serde", 33 | ] 34 | 35 | [[package]] 36 | name = "bit_field" 37 | version = "0.10.1" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4" 40 | 41 | [[package]] 42 | name = "bitflags" 43 | version = "1.3.2" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 46 | 47 | [[package]] 48 | name = "bitvec" 49 | version = "0.22.3" 50 | source = "registry+https://github.com/rust-lang/crates.io-index" 51 | checksum = "5237f00a8c86130a0cc317830e558b966dd7850d48a953d998c813f01a41b527" 52 | dependencies = [ 53 | "funty", 54 | "radium", 55 | "tap", 56 | "wyz", 57 | ] 58 | 59 | [[package]] 60 | name = "bootloader" 61 | version = "0.11.0-alpha" 62 | source = "git+https://github.com/rust-osdev/bootloader?branch=next#c78a2f540acce48f805a998070f8cd2368945e75" 63 | dependencies = [ 64 | "anyhow", 65 | "fatfs", 66 | "gpt", 67 | "llvm-tools", 68 | "mbrman", 69 | "tempfile", 70 | ] 71 | 72 | [[package]] 73 | name = "bootloader_api" 74 | version = "0.1.0-alpha.0" 75 | source = "git+https://github.com/rust-osdev/bootloader?branch=next#c78a2f540acce48f805a998070f8cd2368945e75" 76 | 77 | [[package]] 78 | name = "build_const" 79 | version = "0.2.2" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "b4ae4235e6dac0694637c763029ecea1a2ec9e4e06ec2729bd21ba4d9c863eb7" 82 | 83 | [[package]] 84 | name = "bumpalo" 85 | version = "3.11.0" 86 | source = "registry+https://github.com/rust-lang/crates.io-index" 87 | checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" 88 | 89 | [[package]] 90 | name = "byteorder" 91 | version = "1.4.3" 92 | source = "registry+https://github.com/rust-lang/crates.io-index" 93 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 94 | 95 | [[package]] 96 | name = "cfg-if" 97 | version = "1.0.0" 98 | source = "registry+https://github.com/rust-lang/crates.io-index" 99 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 100 | 101 | [[package]] 102 | name = "chrono" 103 | version = "0.4.22" 104 | source = "registry+https://github.com/rust-lang/crates.io-index" 105 | checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" 106 | dependencies = [ 107 | "iana-time-zone", 108 | "js-sys", 109 | "num-integer", 110 | "num-traits", 111 | "time", 112 | "wasm-bindgen", 113 | "winapi", 114 | ] 115 | 116 | [[package]] 117 | name = "core-foundation-sys" 118 | version = "0.8.3" 119 | source = "registry+https://github.com/rust-lang/crates.io-index" 120 | checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" 121 | 122 | [[package]] 123 | name = "crc" 124 | version = "1.8.1" 125 | source = "registry+https://github.com/rust-lang/crates.io-index" 126 | checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" 127 | dependencies = [ 128 | "build_const", 129 | ] 130 | 131 | [[package]] 132 | name = "fastrand" 133 | version = "1.8.0" 134 | source = "registry+https://github.com/rust-lang/crates.io-index" 135 | checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" 136 | dependencies = [ 137 | "instant", 138 | ] 139 | 140 | [[package]] 141 | name = "fatfs" 142 | version = "0.3.5" 143 | source = "registry+https://github.com/rust-lang/crates.io-index" 144 | checksum = "e18f80a87439240dac45d927fd8f8081b6f1e34c03e97271189fa8a8c2e96c8f" 145 | dependencies = [ 146 | "bitflags", 147 | "byteorder", 148 | "chrono", 149 | "log", 150 | ] 151 | 152 | [[package]] 153 | name = "funty" 154 | version = "1.2.0" 155 | source = "registry+https://github.com/rust-lang/crates.io-index" 156 | checksum = "1847abb9cb65d566acd5942e94aea9c8f547ad02c98e1649326fc0e8910b8b1e" 157 | 158 | [[package]] 159 | name = "getrandom" 160 | version = "0.2.7" 161 | source = "registry+https://github.com/rust-lang/crates.io-index" 162 | checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" 163 | dependencies = [ 164 | "cfg-if", 165 | "libc", 166 | "wasi 0.11.0+wasi-snapshot-preview1", 167 | ] 168 | 169 | [[package]] 170 | name = "gpt" 171 | version = "3.0.0" 172 | source = "registry+https://github.com/rust-lang/crates.io-index" 173 | checksum = "5dd7365d734a70ac5dd7be791b0c96083852188df015b8c665bb2dadb108a743" 174 | dependencies = [ 175 | "bitflags", 176 | "crc", 177 | "log", 178 | "uuid", 179 | ] 180 | 181 | [[package]] 182 | name = "iana-time-zone" 183 | version = "0.1.47" 184 | source = "registry+https://github.com/rust-lang/crates.io-index" 185 | checksum = "4c495f162af0bf17656d0014a0eded5f3cd2f365fdd204548c2869db89359dc7" 186 | dependencies = [ 187 | "android_system_properties", 188 | "core-foundation-sys", 189 | "js-sys", 190 | "once_cell", 191 | "wasm-bindgen", 192 | "winapi", 193 | ] 194 | 195 | [[package]] 196 | name = "instant" 197 | version = "0.1.12" 198 | source = "registry+https://github.com/rust-lang/crates.io-index" 199 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" 200 | dependencies = [ 201 | "cfg-if", 202 | ] 203 | 204 | [[package]] 205 | name = "js-sys" 206 | version = "0.3.59" 207 | source = "registry+https://github.com/rust-lang/crates.io-index" 208 | checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" 209 | dependencies = [ 210 | "wasm-bindgen", 211 | ] 212 | 213 | [[package]] 214 | name = "libc" 215 | version = "0.2.132" 216 | source = "registry+https://github.com/rust-lang/crates.io-index" 217 | checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" 218 | 219 | [[package]] 220 | name = "llvm-tools" 221 | version = "0.1.1" 222 | source = "registry+https://github.com/rust-lang/crates.io-index" 223 | checksum = "955be5d0ca0465caf127165acb47964f911e2bc26073e865deb8be7189302faf" 224 | 225 | [[package]] 226 | name = "log" 227 | version = "0.4.17" 228 | source = "registry+https://github.com/rust-lang/crates.io-index" 229 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 230 | dependencies = [ 231 | "cfg-if", 232 | ] 233 | 234 | [[package]] 235 | name = "mbrman" 236 | version = "0.4.2" 237 | source = "registry+https://github.com/rust-lang/crates.io-index" 238 | checksum = "ef6f6de0b8cfc56e13dc3ac3c662d9419f8aa5e3ebceb2d0eb25abce49e00395" 239 | dependencies = [ 240 | "bincode", 241 | "bitvec", 242 | "serde", 243 | "thiserror", 244 | ] 245 | 246 | [[package]] 247 | name = "noto-sans-mono-bitmap" 248 | version = "0.1.6" 249 | source = "registry+https://github.com/rust-lang/crates.io-index" 250 | checksum = "f45ec3ff6dc7bea48d52dd14a5565be0d596ac4758c9a55e42539177001a983b" 251 | 252 | [[package]] 253 | name = "num-integer" 254 | version = "0.1.45" 255 | source = "registry+https://github.com/rust-lang/crates.io-index" 256 | checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" 257 | dependencies = [ 258 | "autocfg", 259 | "num-traits", 260 | ] 261 | 262 | [[package]] 263 | name = "num-traits" 264 | version = "0.2.15" 265 | source = "registry+https://github.com/rust-lang/crates.io-index" 266 | checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" 267 | dependencies = [ 268 | "autocfg", 269 | ] 270 | 271 | [[package]] 272 | name = "once_cell" 273 | version = "1.14.0" 274 | source = "registry+https://github.com/rust-lang/crates.io-index" 275 | checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" 276 | 277 | [[package]] 278 | name = "ovmf-prebuilt" 279 | version = "0.1.0-alpha.1" 280 | source = "registry+https://github.com/rust-lang/crates.io-index" 281 | checksum = "fa50141d081512ab30fd9e7e7692476866df5098b028536ad6680212e717fa8d" 282 | 283 | [[package]] 284 | name = "proc-macro2" 285 | version = "1.0.43" 286 | source = "registry+https://github.com/rust-lang/crates.io-index" 287 | checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" 288 | dependencies = [ 289 | "unicode-ident", 290 | ] 291 | 292 | [[package]] 293 | name = "quote" 294 | version = "1.0.21" 295 | source = "registry+https://github.com/rust-lang/crates.io-index" 296 | checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" 297 | dependencies = [ 298 | "proc-macro2", 299 | ] 300 | 301 | [[package]] 302 | name = "radium" 303 | version = "0.6.2" 304 | source = "registry+https://github.com/rust-lang/crates.io-index" 305 | checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb" 306 | 307 | [[package]] 308 | name = "redox_syscall" 309 | version = "0.2.16" 310 | source = "registry+https://github.com/rust-lang/crates.io-index" 311 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 312 | dependencies = [ 313 | "bitflags", 314 | ] 315 | 316 | [[package]] 317 | name = "remove_dir_all" 318 | version = "0.5.3" 319 | source = "registry+https://github.com/rust-lang/crates.io-index" 320 | checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" 321 | dependencies = [ 322 | "winapi", 323 | ] 324 | 325 | [[package]] 326 | name = "runner" 327 | version = "0.1.0" 328 | dependencies = [ 329 | "anyhow", 330 | "bootloader", 331 | "ovmf-prebuilt", 332 | "test-kernel", 333 | ] 334 | 335 | [[package]] 336 | name = "rustversion" 337 | version = "1.0.9" 338 | source = "registry+https://github.com/rust-lang/crates.io-index" 339 | checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" 340 | 341 | [[package]] 342 | name = "serde" 343 | version = "1.0.145" 344 | source = "registry+https://github.com/rust-lang/crates.io-index" 345 | checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b" 346 | dependencies = [ 347 | "serde_derive", 348 | ] 349 | 350 | [[package]] 351 | name = "serde_derive" 352 | version = "1.0.145" 353 | source = "registry+https://github.com/rust-lang/crates.io-index" 354 | checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c" 355 | dependencies = [ 356 | "proc-macro2", 357 | "quote", 358 | "syn", 359 | ] 360 | 361 | [[package]] 362 | name = "syn" 363 | version = "1.0.99" 364 | source = "registry+https://github.com/rust-lang/crates.io-index" 365 | checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" 366 | dependencies = [ 367 | "proc-macro2", 368 | "quote", 369 | "unicode-ident", 370 | ] 371 | 372 | [[package]] 373 | name = "tap" 374 | version = "1.0.1" 375 | source = "registry+https://github.com/rust-lang/crates.io-index" 376 | checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" 377 | 378 | [[package]] 379 | name = "tempfile" 380 | version = "3.3.0" 381 | source = "registry+https://github.com/rust-lang/crates.io-index" 382 | checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" 383 | dependencies = [ 384 | "cfg-if", 385 | "fastrand", 386 | "libc", 387 | "redox_syscall", 388 | "remove_dir_all", 389 | "winapi", 390 | ] 391 | 392 | [[package]] 393 | name = "test-kernel" 394 | version = "0.1.0" 395 | dependencies = [ 396 | "bootloader_api", 397 | "noto-sans-mono-bitmap", 398 | "uart_16550", 399 | ] 400 | 401 | [[package]] 402 | name = "thiserror" 403 | version = "1.0.37" 404 | source = "registry+https://github.com/rust-lang/crates.io-index" 405 | checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" 406 | dependencies = [ 407 | "thiserror-impl", 408 | ] 409 | 410 | [[package]] 411 | name = "thiserror-impl" 412 | version = "1.0.37" 413 | source = "registry+https://github.com/rust-lang/crates.io-index" 414 | checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" 415 | dependencies = [ 416 | "proc-macro2", 417 | "quote", 418 | "syn", 419 | ] 420 | 421 | [[package]] 422 | name = "time" 423 | version = "0.1.44" 424 | source = "registry+https://github.com/rust-lang/crates.io-index" 425 | checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" 426 | dependencies = [ 427 | "libc", 428 | "wasi 0.10.0+wasi-snapshot-preview1", 429 | "winapi", 430 | ] 431 | 432 | [[package]] 433 | name = "uart_16550" 434 | version = "0.2.18" 435 | source = "registry+https://github.com/rust-lang/crates.io-index" 436 | checksum = "b074eb9300ad949edd74c529c0e8d451625af71bb948e6b65fe69f72dc1363d9" 437 | dependencies = [ 438 | "bitflags", 439 | "rustversion", 440 | "x86_64", 441 | ] 442 | 443 | [[package]] 444 | name = "unicode-ident" 445 | version = "1.0.3" 446 | source = "registry+https://github.com/rust-lang/crates.io-index" 447 | checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" 448 | 449 | [[package]] 450 | name = "uuid" 451 | version = "0.8.2" 452 | source = "registry+https://github.com/rust-lang/crates.io-index" 453 | checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" 454 | dependencies = [ 455 | "getrandom", 456 | ] 457 | 458 | [[package]] 459 | name = "volatile" 460 | version = "0.4.5" 461 | source = "registry+https://github.com/rust-lang/crates.io-index" 462 | checksum = "e3ca98349dda8a60ae74e04fd90c7fb4d6a4fbe01e6d3be095478aa0b76f6c0c" 463 | 464 | [[package]] 465 | name = "wasi" 466 | version = "0.10.0+wasi-snapshot-preview1" 467 | source = "registry+https://github.com/rust-lang/crates.io-index" 468 | checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" 469 | 470 | [[package]] 471 | name = "wasi" 472 | version = "0.11.0+wasi-snapshot-preview1" 473 | source = "registry+https://github.com/rust-lang/crates.io-index" 474 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 475 | 476 | [[package]] 477 | name = "wasm-bindgen" 478 | version = "0.2.82" 479 | source = "registry+https://github.com/rust-lang/crates.io-index" 480 | checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" 481 | dependencies = [ 482 | "cfg-if", 483 | "wasm-bindgen-macro", 484 | ] 485 | 486 | [[package]] 487 | name = "wasm-bindgen-backend" 488 | version = "0.2.82" 489 | source = "registry+https://github.com/rust-lang/crates.io-index" 490 | checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" 491 | dependencies = [ 492 | "bumpalo", 493 | "log", 494 | "once_cell", 495 | "proc-macro2", 496 | "quote", 497 | "syn", 498 | "wasm-bindgen-shared", 499 | ] 500 | 501 | [[package]] 502 | name = "wasm-bindgen-macro" 503 | version = "0.2.82" 504 | source = "registry+https://github.com/rust-lang/crates.io-index" 505 | checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" 506 | dependencies = [ 507 | "quote", 508 | "wasm-bindgen-macro-support", 509 | ] 510 | 511 | [[package]] 512 | name = "wasm-bindgen-macro-support" 513 | version = "0.2.82" 514 | source = "registry+https://github.com/rust-lang/crates.io-index" 515 | checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" 516 | dependencies = [ 517 | "proc-macro2", 518 | "quote", 519 | "syn", 520 | "wasm-bindgen-backend", 521 | "wasm-bindgen-shared", 522 | ] 523 | 524 | [[package]] 525 | name = "wasm-bindgen-shared" 526 | version = "0.2.82" 527 | source = "registry+https://github.com/rust-lang/crates.io-index" 528 | checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" 529 | 530 | [[package]] 531 | name = "winapi" 532 | version = "0.3.9" 533 | source = "registry+https://github.com/rust-lang/crates.io-index" 534 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 535 | dependencies = [ 536 | "winapi-i686-pc-windows-gnu", 537 | "winapi-x86_64-pc-windows-gnu", 538 | ] 539 | 540 | [[package]] 541 | name = "winapi-i686-pc-windows-gnu" 542 | version = "0.4.0" 543 | source = "registry+https://github.com/rust-lang/crates.io-index" 544 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 545 | 546 | [[package]] 547 | name = "winapi-x86_64-pc-windows-gnu" 548 | version = "0.4.0" 549 | source = "registry+https://github.com/rust-lang/crates.io-index" 550 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 551 | 552 | [[package]] 553 | name = "wyz" 554 | version = "0.4.0" 555 | source = "registry+https://github.com/rust-lang/crates.io-index" 556 | checksum = "129e027ad65ce1453680623c3fb5163cbf7107bfe1aa32257e7d0e63f9ced188" 557 | dependencies = [ 558 | "tap", 559 | ] 560 | 561 | [[package]] 562 | name = "x86_64" 563 | version = "0.14.10" 564 | source = "registry+https://github.com/rust-lang/crates.io-index" 565 | checksum = "100555a863c0092238c2e0e814c1096c1e5cf066a309c696a87e907b5f8c5d69" 566 | dependencies = [ 567 | "bit_field", 568 | "bitflags", 569 | "rustversion", 570 | "volatile", 571 | ] 572 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | cargo-features = ["per-package-target"] 2 | 3 | [package] 4 | name = "test-kernel" 5 | version = "0.1.0" 6 | edition = "2021" 7 | default-target = "x86_64-unknown-none" 8 | 9 | [workspace] 10 | members = ["runner"] 11 | resolver = "2" 12 | 13 | [dependencies] 14 | bootloader_api = { git = "https://github.com/rust-osdev/bootloader", branch = "next" } 15 | uart_16550 = "0.2.10" 16 | 17 | [dependencies.noto-sans-mono-bitmap] 18 | version = "0.1.2" 19 | default-features = false 20 | features = ["regular", "size_14"] 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Tom Dohrmann 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # test kernel 2 | 3 | This repo implements a simple kernel that can be used for testing https://github.com/rust-osdev/bootloader. 4 | 5 | ## Building an image 6 | 7 | Run this command to build an image and start it in qemu. 8 | 9 | ```shell 10 | $ cargo run -p runner 11 | ``` 12 | 13 | The image will be placed in `target/uefi.img` and can be flashed onto a USB flash drive for testing with real hardware. 14 | 15 | ## Expected output 16 | 17 | The test kernel will do the following things: 18 | - Clear the framebuffer. 19 | - Draw a colored square into each corner of the screen to test if the framebuffer information provided by the bootloader is correct 20 | - Log the bootloader version 21 | - Log the offset of the physical memory mapping created by the bootloader 22 | - Log the memory map provided by the bootloader 23 | - Attempt to write all usable memory to check if the memory map is correct 24 | 25 | Last but not least, the test kernel will log "Done". If this message isn't logged one of the tests caused a crash. 26 | 27 | ![image of the expected output](imgs/Screenshot.png) 28 | 29 | Log messages will be displayed on the framebuffer (if one exists) and written to the first serial port. -------------------------------------------------------------------------------- /imgs/Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Freax13/test-kernel/1013121f1d9d619248ed609e48cf0d47d5a04e6e/imgs/Screenshot.png -------------------------------------------------------------------------------- /runner/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "runner" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | anyhow = "1.0.64" 10 | bootloader = { git = "https://github.com/rust-osdev/bootloader", branch = "next" } 11 | ovmf-prebuilt = "0.1.0-alpha.1" 12 | test-kernel = { path = "..", artifact = "bin", target = "x86_64-unknown-none" } 13 | 14 | [build-dependencies] 15 | test-kernel = { path = "..", artifact = "bin", target = "x86_64-unknown-none" } 16 | -------------------------------------------------------------------------------- /runner/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::process::Command; 2 | 3 | use anyhow::Result; 4 | 5 | fn main() -> Result<()> { 6 | let out_gpt_path = &AsRef::as_ref("target/uefi.img"); 7 | bootloader::UefiBoot::new(AsRef::as_ref(env!( 8 | "CARGO_BIN_FILE_TEST_KERNEL_test-kernel" 9 | ))) 10 | .create_disk_image(out_gpt_path)?; 11 | 12 | let out_bios_path = &AsRef::as_ref("target/bios.img"); 13 | bootloader::BiosBoot::new(AsRef::as_ref(env!( 14 | "CARGO_BIN_FILE_TEST_KERNEL_test-kernel" 15 | ))) 16 | .create_disk_image(out_bios_path)?; 17 | 18 | let mut cmd = Command::new("qemu-system-x86_64"); 19 | cmd.arg("-bios").arg(ovmf_prebuilt::ovmf_pure_efi()); 20 | cmd.arg("-drive") 21 | .arg(format!("format=raw,file={}", out_gpt_path.display())); 22 | let mut child = cmd.spawn()?; 23 | child.wait()?; 24 | 25 | Ok(()) 26 | } 27 | -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "nightly" 3 | components = ["rust-src", "llvm-tools-preview"] 4 | -------------------------------------------------------------------------------- /src/graphical.rs: -------------------------------------------------------------------------------- 1 | use core::{ 2 | cmp, 3 | fmt::{Display, Write}, 4 | sync::atomic::{AtomicUsize, Ordering}, 5 | }; 6 | 7 | use bootloader_api::info::{FrameBuffer, PixelFormat}; 8 | use noto_sans_mono_bitmap::{BitmapHeight, FontWeight}; 9 | 10 | use super::Color; 11 | 12 | const CORNERS_SIZE_RATION: f32 = 0.2; 13 | const PADDING: usize = 10; 14 | 15 | static mut FRAMEBUFFER: Option = None; 16 | 17 | pub(super) fn init_framebuffer(framebuffer: Option) { 18 | let mut framebuffer = if let Some(framebuffer) = framebuffer { 19 | framebuffer 20 | } else { 21 | return; 22 | }; 23 | 24 | framebuffer.buffer_mut().fill(0); 25 | 26 | draw_test_colors(&mut framebuffer); 27 | 28 | unsafe { 29 | FRAMEBUFFER = Some(framebuffer); 30 | } 31 | } 32 | 33 | fn corners_size(framebuffer: &FrameBuffer) -> usize { 34 | let width = ((framebuffer.info().width as f32) * CORNERS_SIZE_RATION) as usize; 35 | let height = ((framebuffer.info().height as f32) * CORNERS_SIZE_RATION) as usize; 36 | cmp::min(width, height) 37 | } 38 | 39 | fn draw_test_colors(framebuffer: &mut FrameBuffer) { 40 | let size = corners_size(framebuffer); 41 | 42 | for x in 0..size { 43 | for y in 0..size { 44 | let width = framebuffer.info().width; 45 | let height = framebuffer.info().height; 46 | 47 | set_pixel(framebuffer, x, y, Color::Red, 255); 48 | set_pixel(framebuffer, width - x - 1, y, Color::Green, 255); 49 | set_pixel(framebuffer, x, height - y - 1, Color::Blue, 255); 50 | set_pixel( 51 | framebuffer, 52 | width - x - 1, 53 | height - y - 1, 54 | Color::Yellow, 55 | 255, 56 | ); 57 | } 58 | } 59 | } 60 | 61 | pub fn write(display: impl Display, color: Color) { 62 | let framebuffer = if let Some(framebuffer) = unsafe { FRAMEBUFFER.as_mut() } { 63 | framebuffer 64 | } else { 65 | return; 66 | }; 67 | 68 | static LINE_IDX: AtomicUsize = AtomicUsize::new(0); 69 | 70 | let corners_size = corners_size(framebuffer); 71 | 72 | let mut formatter = Formatter { 73 | framebuffer, 74 | x: PADDING + corners_size, 75 | y: PADDING + LINE_IDX.fetch_add(14, Ordering::SeqCst), 76 | color, 77 | }; 78 | write!(formatter, "{display}").unwrap(); 79 | } 80 | 81 | struct Formatter<'a> { 82 | framebuffer: &'a mut FrameBuffer, 83 | x: usize, 84 | y: usize, 85 | color: Color, 86 | } 87 | 88 | impl Write for Formatter<'_> { 89 | fn write_str(&mut self, s: &str) -> core::fmt::Result { 90 | for c in s.chars() { 91 | if self.x + 14 < self.framebuffer.info().width { 92 | self.write_char(c); 93 | } 94 | } 95 | Ok(()) 96 | } 97 | } 98 | 99 | impl Formatter<'_> { 100 | fn write_char(&mut self, c: char) { 101 | let bitmap = 102 | noto_sans_mono_bitmap::get_bitmap(c, FontWeight::Regular, BitmapHeight::Size14) 103 | .unwrap_or_else(|| { 104 | noto_sans_mono_bitmap::get_bitmap( 105 | '?', 106 | FontWeight::Regular, 107 | BitmapHeight::Size14, 108 | ) 109 | .unwrap() 110 | }); 111 | 112 | let corners_size = corners_size(&self.framebuffer); 113 | 114 | // Calculate the bounding box for log messages. 115 | let top = PADDING; 116 | let left = corners_size + PADDING; 117 | let bottom = self.framebuffer.info().height - PADDING - 1; 118 | let right = self.framebuffer.info().width - corners_size - PADDING - 1; 119 | 120 | for (bits, y) in bitmap.bitmap().iter().zip(self.y..) { 121 | for (&intensity, x) in bits.iter().zip(self.x..) { 122 | if y >= top && y <= bottom && x >= left && x <= right { 123 | set_pixel(self.framebuffer, x, y, self.color, intensity); 124 | } 125 | } 126 | } 127 | self.x += bitmap.width(); 128 | } 129 | } 130 | 131 | fn set_pixel(framebuffer: &mut FrameBuffer, x: usize, y: usize, color: Color, intensity: u8) { 132 | // Convert the color and intensity to bytes. 133 | let bytes = match framebuffer.info().pixel_format { 134 | PixelFormat::Rgb => [color.r(), color.g(), color.b(), 0], 135 | PixelFormat::Bgr => [color.b(), color.g(), color.r(), 0], 136 | PixelFormat::U8 => [color.greyscale(), 0, 0, 0], 137 | _ => { 138 | // Fall back to RGB. 139 | [color.r(), color.g(), color.b(), 0] 140 | } 141 | }; 142 | let bytes = bytes.map(|pixel| (u16::from(pixel) * u16::from(intensity) / 255) as u8); 143 | let bytes = &bytes[..framebuffer.info().bytes_per_pixel]; 144 | 145 | // Write the bytes to the framebuffer. 146 | let start = (framebuffer.info().stride * y + x) * framebuffer.info().bytes_per_pixel; 147 | framebuffer.buffer_mut()[start..][..bytes.len()].copy_from_slice(bytes); 148 | } 149 | 150 | impl Color { 151 | fn r(&self) -> u8 { 152 | match self { 153 | Color::White => 0xc0, 154 | Color::Red => 0xff, 155 | Color::Green => 0x00, 156 | Color::Blue => 0x00, 157 | Color::Yellow => 0xff, 158 | } 159 | } 160 | 161 | fn g(&self) -> u8 { 162 | match self { 163 | Color::White => 0xc0, 164 | Color::Red => 0x00, 165 | Color::Green => 0xff, 166 | Color::Blue => 0x00, 167 | Color::Yellow => 0xff, 168 | } 169 | } 170 | 171 | fn b(&self) -> u8 { 172 | match self { 173 | Color::White => 0xc0, 174 | Color::Red => 0x00, 175 | Color::Green => 0x00, 176 | Color::Blue => 0xff, 177 | Color::Yellow => 0x00, 178 | } 179 | } 180 | 181 | fn greyscale(&self) -> u8 { 182 | match self { 183 | Color::White => 0xc0, 184 | Color::Red => 0xc0, 185 | Color::Green => 0xc0, 186 | Color::Blue => 0xc0, 187 | Color::Yellow => 0xc0, 188 | } 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /src/logger.rs: -------------------------------------------------------------------------------- 1 | use core::fmt::{Display, Write}; 2 | 3 | use bootloader_api::info::FrameBuffer; 4 | use uart_16550::SerialPort; 5 | 6 | use crate::graphical; 7 | 8 | #[derive(Clone, Copy)] 9 | pub enum Color { 10 | White, 11 | Red, 12 | Green, 13 | Blue, 14 | Yellow, 15 | } 16 | 17 | static mut SERIAL_PORT: SerialPort = unsafe { SerialPort::new(0x03F8) }; 18 | 19 | pub fn init(framebuffer: Option) { 20 | graphical::init_framebuffer(framebuffer); 21 | } 22 | 23 | pub fn log(display: impl Display, color: Color) { 24 | graphical::write(&display, color); 25 | 26 | unsafe { 27 | write!(SERIAL_PORT, "{}{display}\r\n", color.escape_sequence()).unwrap(); 28 | } 29 | } 30 | 31 | impl Color { 32 | fn escape_sequence(&self) -> &'static str { 33 | match self { 34 | Color::White => "\x1b[m\x1b[97m", 35 | Color::Red => "\x1b[m\x1b[91m", 36 | Color::Green => "\x1b[m\x1b[92m", 37 | Color::Blue => "\x1b[m\x1b[94m", 38 | Color::Yellow => "\x1b[m\x1b[93m", 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use core::panic::PanicInfo; 5 | 6 | use bootloader_api::{ 7 | config::Mapping, 8 | entry_point, 9 | info::{MemoryRegionKind, Optional}, 10 | BootInfo, BootloaderConfig, 11 | }; 12 | use logger::{log, Color}; 13 | 14 | mod graphical; 15 | mod logger; 16 | 17 | const CONFIG: BootloaderConfig = { 18 | let mut config = BootloaderConfig::new_default(); 19 | 20 | config.mappings.physical_memory = Some(Mapping::Dynamic); 21 | 22 | config 23 | }; 24 | 25 | entry_point!(main, config = &CONFIG); 26 | 27 | fn main(boot_info: &'static mut BootInfo) -> ! { 28 | let framebuffer = core::mem::replace(&mut boot_info.framebuffer, Optional::None); 29 | let framebuffer = framebuffer.into_option(); 30 | 31 | logger::init(framebuffer); 32 | 33 | let prelease_str = if boot_info.api_version.pre_release() { 34 | "(prerelease)" 35 | } else { 36 | "" 37 | }; 38 | log( 39 | format_args!( 40 | "Bootloader version: {}.{}.{} {}", 41 | boot_info.api_version.version_major(), 42 | boot_info.api_version.version_minor(), 43 | boot_info.api_version.version_patch(), 44 | prelease_str 45 | ), 46 | Color::White, 47 | ); 48 | 49 | let physical_memory_offset = boot_info 50 | .physical_memory_offset 51 | .into_option() 52 | .expect("the bootloader should map all physical memory for us"); 53 | log( 54 | format_args!("Physical memory offset: {physical_memory_offset:#018x}"), 55 | Color::White, 56 | ); 57 | 58 | log( 59 | format_args!("Memory regions: {}", boot_info.memory_regions.len()), 60 | Color::White, 61 | ); 62 | 63 | // Merge contiguous memory regions of the same kind and log them. 64 | boot_info 65 | .memory_regions 66 | .sort_unstable_by_key(|region| region.start); 67 | let mut iter = boot_info.memory_regions.iter().copied(); 68 | if let Some(mut prev) = iter.next() { 69 | for next in iter { 70 | if prev.end != next.start || prev.kind != next.kind { 71 | log( 72 | format_args!("{:#018x} - {:#018x}: {:?}", prev.start, prev.end, prev.kind), 73 | Color::White, 74 | ); 75 | 76 | prev = next; 77 | } else { 78 | prev.end = next.end; 79 | } 80 | } 81 | 82 | log( 83 | format_args!("{:#018x} - {:#018x}: {:?}", prev.start, prev.end, prev.kind), 84 | Color::White, 85 | ); 86 | } 87 | 88 | log("Writing to usable memory regions", Color::White); 89 | 90 | for region in boot_info 91 | .memory_regions 92 | .iter() 93 | .filter(|region| region.kind == MemoryRegionKind::Usable) 94 | { 95 | let addr = physical_memory_offset + region.start; 96 | let size = region.end - region.start; 97 | unsafe { 98 | core::ptr::write_bytes(addr as *mut u8, 0xff, size as usize); 99 | } 100 | } 101 | 102 | log("Done!", Color::White); 103 | 104 | loop {} 105 | } 106 | 107 | #[panic_handler] 108 | fn panic_handler(info: &PanicInfo) -> ! { 109 | log(format_args!("{info}"), Color::Red); 110 | 111 | loop {} 112 | } 113 | --------------------------------------------------------------------------------