Compare commits
102 Commits
0df671c3fc
..
pmm
| Author | SHA1 | Date | |
|---|---|---|---|
| 92fe618a99 | |||
| 192100be7a | |||
| 2915d0c879 | |||
| 9852cb14eb | |||
| db8dbff9f2 | |||
| 2178215a01 | |||
| 821759ec63 | |||
| ac0b47a45c | |||
| 15f59e68d5 | |||
| b7397d8a1b | |||
| 4fe6109e5b | |||
| e294a13a91 | |||
| 752800a3ca | |||
| 177fddcf7d | |||
| 375c5aa561 | |||
| b945416665 | |||
| 27ee8226d8 | |||
| 00d3a1de72 | |||
| f7723a3944 | |||
| 438ef7a748 | |||
| 2f7ab8fe6b | |||
| ca1c695e32 | |||
| 1c22f89665 | |||
| 1c147dd933 | |||
| 91044f5fad | |||
| d5b15826e2 | |||
| 39f1f4905d | |||
| 03a3469d20 | |||
| 2cbe9641aa | |||
| e303ecf5a4 | |||
| 2f08835d69 | |||
| 8d57540566 | |||
| 03290e52a3 | |||
| 8908a6a281 | |||
| aefc368d41 | |||
| 76ec29b7ec | |||
| d9bbdff08c | |||
| 7ff33659fe | |||
| efe3034ad0 | |||
| d9b66f8008 | |||
| 2be5b63af7 | |||
| 7e62bdae35 | |||
| b8aa203c05 | |||
| 9f83c5f295 | |||
| 914cb4e409 | |||
| 43b1db41ca | |||
| c763f512f1 | |||
| 5dc73e7000 | |||
| ca906767db | |||
| ef8d028211 | |||
| 2886fe5ecf | |||
| c2c552ef25 | |||
| e722874cee | |||
| 27b0ed634c | |||
| 72fe78cbc6 | |||
| f9bc75c4f3 | |||
| 494d00c53b | |||
| 114c70ffe9 | |||
| 361c67764d | |||
| 36cb118933 | |||
| 7b3ba170f0 | |||
| 49880fa9d7 | |||
| 0bbbf653f8 | |||
| 40ad5dbbf4 | |||
| 2b2219f5be | |||
| c1a8afb836 | |||
| 28afe25cca | |||
| 90faace7a2 | |||
| 5b1f04c1da | |||
| 3a232c8023 | |||
| 5eaf0d7c69 | |||
| b4d0b05e13 | |||
| 969756c691 | |||
| 5c9717d384 | |||
| bb5bf9115b | |||
| ae82e9c24b | |||
| ab0ec35094 | |||
| 2ee21dea05 | |||
| d12160c5d0 | |||
| f5f5aeb8dc | |||
| 34213ca744 | |||
| 3aca8fd720 | |||
| a88059c5ff | |||
| 68c3d2fa0e | |||
| af3215d887 | |||
| 11d63535e9 | |||
| ee8dae4981 | |||
| 650f34f354 | |||
| 1b313c67e0 | |||
| cb77883f4c | |||
| 16d94f37cb | |||
| d9f6b4b69a | |||
| cc56dc8072 | |||
| f0e25c7a5d | |||
| e626a3bcf2 | |||
| 34b960c20a | |||
| ee8de361dc | |||
| 60efcf39b6 | |||
| b028a97a44 | |||
| 294e6f0e33 | |||
| 76f070af8b | |||
| 2f0e09b9bc |
@@ -0,0 +1,24 @@
|
|||||||
|
[build]
|
||||||
|
target = "x86_64-kernel"
|
||||||
|
target-dir = "build/target"
|
||||||
|
|
||||||
|
[unstable]
|
||||||
|
build-std = ["core", "compiler_builtins", "alloc"]
|
||||||
|
build-std-features = ["compiler-builtins-mem"]
|
||||||
|
|
||||||
|
[env]
|
||||||
|
RUST_TARGET_PATH = { value = "kernel", relative = true }
|
||||||
|
|
||||||
|
# Run in debug mode.
|
||||||
|
[target.'cfg(all(target_arch = "x86_64", target_os = "none", debug_assertions))']
|
||||||
|
runner = "scripts/run_debug.sh"
|
||||||
|
|
||||||
|
# Otherwise we run in release mode.
|
||||||
|
[target.'cfg(all(target_arch = "x86_64", target_os = "none", not(debug_assertions)))']
|
||||||
|
runner = "scripts/run_release.sh"
|
||||||
|
|
||||||
|
# [registry]
|
||||||
|
# default = "gitea"
|
||||||
|
|
||||||
|
[registries.gitea]
|
||||||
|
index = "sparse+https://git.zxq5.dev/api/packages/OsDev/cargo/" # Sparse index
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
pull-request:
|
||||||
|
branches: [ main ]
|
||||||
|
|
||||||
|
name: Continuous integration
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||||
|
with:
|
||||||
|
target: x86_64-unknown-none
|
||||||
|
components: rust-src, llvm-tools-preview
|
||||||
|
toolchain: nightly
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
- run: cargo build
|
||||||
+15
-1
@@ -1 +1,15 @@
|
|||||||
/target
|
# Build output directories
|
||||||
|
/build/
|
||||||
|
/target/
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
*.o
|
||||||
|
*.bin
|
||||||
|
*.iso
|
||||||
|
*.img
|
||||||
|
*.elf
|
||||||
|
*.efi
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Rust specific
|
||||||
|
Cargo.lock
|
||||||
|
|||||||
Generated
+8
@@ -0,0 +1,8 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="EMPTY_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/kernel/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/lib_example/src" isTestSource="false" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
Generated
+8
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/FoundryOS.iml" filepath="$PROJECT_DIR$/.idea/FoundryOS.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+7
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
<mapping directory="$PROJECT_DIR$/build/limine" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Vendored
+9
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"rust-analyzer.cargo.allTargets": false,
|
||||||
|
"rust-analyzer.cargo.target": "x86_64-kernel",
|
||||||
|
"[rust]": {
|
||||||
|
"editor.defaultFormatter": "rust-lang.rust-analyzer",
|
||||||
|
"editor.formatOnSave": true
|
||||||
|
},
|
||||||
|
"rust-analyzer.check.command": "clippy",
|
||||||
|
}
|
||||||
Generated
+299
-1
@@ -2,6 +2,18 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bit_field"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.8.0"
|
version = "2.8.0"
|
||||||
@@ -9,10 +21,155 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
|
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "foundryos_kernel"
|
name = "cc"
|
||||||
|
version = "1.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c736e259eea577f443d5c86c304f9f4ae0295c43f3ba05c21f1d66b5f06001af"
|
||||||
|
dependencies = [
|
||||||
|
"shlex",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-queue",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.9.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-queue"
|
||||||
|
version = "0.3.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling"
|
||||||
|
version = "0.20.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core",
|
||||||
|
"darling_macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_core"
|
||||||
|
version = "0.20.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
|
||||||
|
dependencies = [
|
||||||
|
"fnv",
|
||||||
|
"ident_case",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"strsim",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_macro"
|
||||||
|
version = "0.20.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fnv"
|
||||||
|
version = "1.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foundry_os"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libk",
|
||||||
"limine",
|
"limine",
|
||||||
|
"pc-keyboard",
|
||||||
|
"pic8259",
|
||||||
|
"spin",
|
||||||
|
"x86_64",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-core"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-task"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-util"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-task",
|
||||||
|
"pin-project-lite",
|
||||||
|
"pin-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ident_case"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libk"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam",
|
||||||
|
"futures-util",
|
||||||
|
"libm",
|
||||||
|
"limine",
|
||||||
|
"linked_list_allocator",
|
||||||
|
"pc-keyboard",
|
||||||
|
"spin",
|
||||||
|
"x86_64",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libm"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"darling",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -23,3 +180,144 @@ checksum = "9ca87cab008b8efeebdbe037cd4d1438037d48c5cb6fed939ffa5aa06315a321"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linked_list_allocator"
|
||||||
|
version = "0.10.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286"
|
||||||
|
dependencies = [
|
||||||
|
"spinning_top",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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 = "pc-keyboard"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0ca629cbb3f0d5b699c338f0129ff78c9bfd7ea8b1258ad529bff490dc8ed5a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pic8259"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "62d9a86c292b165f757e47e7fd66855def189b2564609bc4203727b27c33db22"
|
||||||
|
dependencies = [
|
||||||
|
"x86_64",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-project-lite"
|
||||||
|
version = "0.2.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-utils"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.93"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.38"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shlex"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spin"
|
||||||
|
version = "0.9.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spinning_top"
|
||||||
|
version = "0.2.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b9eb1a2f4c41445a3a0ff9abc5221c5fcd28e1f13cd7c0397706f9ac938ddb0"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.98"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "volatile"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "442887c63f2c839b346c192d047a7c87e73d0689c9157b00b53dcc27dd5ea793"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "x86_64"
|
||||||
|
version = "0.15.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0f042214de98141e9c8706e8192b73f56494087cc55ebec28ce10f26c5c364ae"
|
||||||
|
dependencies = [
|
||||||
|
"bit_field",
|
||||||
|
"bitflags",
|
||||||
|
"rustversion",
|
||||||
|
"volatile",
|
||||||
|
]
|
||||||
|
|||||||
+23
-4
@@ -1,10 +1,29 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = ["kernel", "libk", "libm"]
|
||||||
"kernel"
|
|
||||||
]
|
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2024"
|
||||||
|
authors = ["The FoundryOS Contributors"]
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
opt-level = "z"
|
||||||
|
debug = true
|
||||||
|
# Leave this on to force Cargo to use the debug runner,
|
||||||
|
# which adds the necessary flags for GDB debugging if you
|
||||||
|
# set $USE_GDB (to any value) e.g. USE_GDB=1 cargo run
|
||||||
|
debug-assertions = true
|
||||||
|
overflow-checks = true
|
||||||
|
lto = false
|
||||||
|
incremental = false
|
||||||
|
codegen-units = 1
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
opt-level = 3
|
||||||
|
debug = false
|
||||||
|
debug-assertions = false
|
||||||
|
overflow-checks = false
|
||||||
|
lto = true
|
||||||
|
incremental = false
|
||||||
|
codegen-units = 1
|
||||||
|
|||||||
@@ -1,2 +1,52 @@
|
|||||||
# FoundryOS
|
# FoundryOS
|
||||||
|
|
||||||
|
## Cloning
|
||||||
|
```sh
|
||||||
|
git clone https://git.zxq5.dev/OsDev/FoundryOS.git
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build dependencies
|
||||||
|
|
||||||
|
* latest rust nightly release
|
||||||
|
* all necessary rust components installed
|
||||||
|
* xorriso: creates ISO images to be booted from.
|
||||||
|
* (Optional / Recommended) qemu: to run the kernel. (this may be packaged as qemu-desktop)
|
||||||
|
* (Optional) GDB: for debugging the kernel.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
rustup update
|
||||||
|
rustup override set nightly
|
||||||
|
rustup component add rust-src
|
||||||
|
rustup component add llvm-tools-preview
|
||||||
|
```
|
||||||
|
|
||||||
|
## Building & Running in qemu
|
||||||
|
```sh
|
||||||
|
cargo run
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running in GDB
|
||||||
|
```sh
|
||||||
|
USE_GDB=1 cargo run
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build errors
|
||||||
|
|
||||||
|
If you see a qemu error like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
qemu-system-x86_64: -drive if=pflash,format=raw,readonly=on,file=<...>/OVMF_CODE.fd: Could not open '<...>/OVMF_CODE.fd': No such file or directory
|
||||||
|
```
|
||||||
|
|
||||||
|
Simply delete the ./build directory and try to rebuild the program. Using the runner script or `cargo run` will download the required files for you, this is because the script only checks for the presence of one file and not the VARS file.
|
||||||
|
|
||||||
|
Alternatively, you may disable using a UEFI firmware with qemu like so:
|
||||||
|
```sh
|
||||||
|
USE_LEGACY_BIOS=1 cargo run
|
||||||
|
```
|
||||||
|
|
||||||
|
## Debugging
|
||||||
|
|
||||||
|
See [debugging](docs/Debugging/DEBUGGING.md) for some help with this, including commands to help with disassembly.
|
||||||
|
|
||||||
|
If you have any other issues, feel free to create an issue or a PR.
|
||||||
+8
-2
@@ -1,5 +1,11 @@
|
|||||||
timeout: 1
|
# Timeout in seconds that Limine will use before automatically booting.
|
||||||
|
timeout: 0
|
||||||
|
|
||||||
|
# The entry name that will be displayed in the boot menu.
|
||||||
/foundry-os
|
/foundry-os
|
||||||
|
# We use the Limine boot protocol.
|
||||||
protocol: limine
|
protocol: limine
|
||||||
kernel_path: boot()/boot/kernel
|
|
||||||
|
# Path to the kernel to boot. boot():/ represents the partition on which limine.conf is located.
|
||||||
|
kernel_path: boot():/boot/kernel
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
{
|
|
||||||
"llvm-target": "x86_64-unknown-none",
|
|
||||||
"data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
|
|
||||||
"arch": "x86_64",
|
|
||||||
"target-endian": "little",
|
|
||||||
"target-pointer-width": "64",
|
|
||||||
"target-c-int-width": "32",
|
|
||||||
"os": "none",
|
|
||||||
"executables": true,
|
|
||||||
"linker-flavor": "ld.lld",
|
|
||||||
"linker": "rust-lld",
|
|
||||||
"panic-strategy": "abort",
|
|
||||||
"disable-redzone": true,
|
|
||||||
"features": "-mmx,-sse,+soft-float",
|
|
||||||
"relocation-model": "static",
|
|
||||||
"code-model": "kernel",
|
|
||||||
"pre-link-args": {
|
|
||||||
"ld.lld": [
|
|
||||||
"--script=linker/linker.ld",
|
|
||||||
"-nostdlib",
|
|
||||||
"--no-dynamic-linker",
|
|
||||||
"-static",
|
|
||||||
"--no-pie",
|
|
||||||
"--gc-sections",
|
|
||||||
"--build-id=none",
|
|
||||||
"-z", "max-page-size=0x1000"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
[0;32m[1m Running kernel in debug mode.
|
||||||
|
[0;34m[1minfo[0m: Creating build directory structure
|
||||||
|
[0;34m[1minfo[0m: Copying files to ISO root
|
||||||
|
[0;32m[1m Copying[0m: /home/fantasypvp/Projects/OSdev/FoundryOS/build/target/x86_64-kernel/debug/kernel to /home/fantasypvp/Projects/OSdev/FoundryOS/build/iso_root/boot/kernel
|
||||||
|
[0;32m[1m Copying[0m: /home/fantasypvp/Projects/OSdev/FoundryOS/config/limine.conf to /home/fantasypvp/Projects/OSdev/FoundryOS/build/iso_root/boot/limine/limine.conf
|
||||||
|
[0;32m[1m Copying[0m: /home/fantasypvp/Projects/OSdev/FoundryOS/build/limine/limine-bios-cd.bin to /home/fantasypvp/Projects/OSdev/FoundryOS/build/iso_root/boot/limine/
|
||||||
|
[0;32m[1m Copying[0m: /home/fantasypvp/Projects/OSdev/FoundryOS/build/limine/limine-uefi-cd.bin to /home/fantasypvp/Projects/OSdev/FoundryOS/build/iso_root/boot/limine/
|
||||||
|
[0;32m[1m Copying[0m: /home/fantasypvp/Projects/OSdev/FoundryOS/build/limine/limine-bios.sys to /home/fantasypvp/Projects/OSdev/FoundryOS/build/iso_root/boot/limine/
|
||||||
|
[0;32m[1m Copying[0m: /home/fantasypvp/Projects/OSdev/FoundryOS/build/limine/BOOTX64.EFI to /home/fantasypvp/Projects/OSdev/FoundryOS/build/iso_root/EFI/BOOT/
|
||||||
|
[0;32m[1m Copying[0m: /home/fantasypvp/Projects/OSdev/FoundryOS/build/limine/BOOTIA32.EFI to /home/fantasypvp/Projects/OSdev/FoundryOS/build/iso_root/EFI/BOOT/
|
||||||
|
[0;32m[1mBuilding[0m: bootable ISO image
|
||||||
|
[0;34m[1minfo[0m: Installing Limine bootloader
|
||||||
|
[0;34m[1minfo[0m: KVM acceleration enabled
|
||||||
|
[0;34m[1minfo[0m: Running OS in QEMU...
|
||||||
|
[2J[01;01H[=3h[2J[01;01H[2J[01;01H[=3h[2J[01;01H[2J[01;01H[=3h[2J[01;01HBdsDxe: loading Boot0001 "UEFI QEMU DVD-ROM QM00005 " from PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x2,0xFFFF,0x0)
|
||||||
|
BdsDxe: starting Boot0001 "UEFI QEMU DVD-ROM QM00005 " from PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x2,0xFFFF,0x0)
|
||||||
|
[2J[01;01H[01;01H[2J[01;01H[01;01Hmap worked!got apic base
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
Vendored
+31
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"file-explorer": true,
|
||||||
|
"global-search": true,
|
||||||
|
"switcher": true,
|
||||||
|
"graph": true,
|
||||||
|
"backlink": true,
|
||||||
|
"canvas": true,
|
||||||
|
"outgoing-link": true,
|
||||||
|
"tag-pane": true,
|
||||||
|
"properties": false,
|
||||||
|
"page-preview": true,
|
||||||
|
"daily-notes": true,
|
||||||
|
"templates": true,
|
||||||
|
"note-composer": true,
|
||||||
|
"command-palette": true,
|
||||||
|
"slash-command": false,
|
||||||
|
"editor-status": true,
|
||||||
|
"bookmarks": true,
|
||||||
|
"markdown-importer": false,
|
||||||
|
"zk-prefixer": false,
|
||||||
|
"random-note": false,
|
||||||
|
"outline": true,
|
||||||
|
"word-count": true,
|
||||||
|
"slides": false,
|
||||||
|
"audio-recorder": false,
|
||||||
|
"workspaces": false,
|
||||||
|
"file-recovery": true,
|
||||||
|
"publish": false,
|
||||||
|
"sync": true,
|
||||||
|
"webviewer": false
|
||||||
|
}
|
||||||
Vendored
+22
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"collapse-filter": true,
|
||||||
|
"search": "",
|
||||||
|
"showTags": false,
|
||||||
|
"showAttachments": false,
|
||||||
|
"hideUnresolved": false,
|
||||||
|
"showOrphans": true,
|
||||||
|
"collapse-color-groups": true,
|
||||||
|
"colorGroups": [],
|
||||||
|
"collapse-display": true,
|
||||||
|
"showArrow": false,
|
||||||
|
"textFadeMultiplier": 0,
|
||||||
|
"nodeSizeMultiplier": 1,
|
||||||
|
"lineSizeMultiplier": 1,
|
||||||
|
"collapse-forces": true,
|
||||||
|
"centerStrength": 0.518713248970312,
|
||||||
|
"repelStrength": 10,
|
||||||
|
"linkStrength": 1,
|
||||||
|
"linkDistance": 250,
|
||||||
|
"scale": 1,
|
||||||
|
"close": true
|
||||||
|
}
|
||||||
Vendored
+198
@@ -0,0 +1,198 @@
|
|||||||
|
{
|
||||||
|
"main": {
|
||||||
|
"id": "20da7b1c0adc4114",
|
||||||
|
"type": "split",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "a20540b7c1ddbfca",
|
||||||
|
"type": "tabs",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "e1fb15cab546d0b6",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "markdown",
|
||||||
|
"state": {
|
||||||
|
"file": "Usage/Building The Kernel.md",
|
||||||
|
"mode": "source",
|
||||||
|
"source": false
|
||||||
|
},
|
||||||
|
"icon": "lucide-file",
|
||||||
|
"title": "Building The Kernel"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "6bf1f87bf81a3031",
|
||||||
|
"type": "tabs",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "add883d295e04659",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "markdown",
|
||||||
|
"state": {
|
||||||
|
"file": "Usage/Building The Kernel.md",
|
||||||
|
"mode": "preview",
|
||||||
|
"source": false
|
||||||
|
},
|
||||||
|
"icon": "lucide-file",
|
||||||
|
"title": "Building The Kernel"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"direction": "vertical"
|
||||||
|
},
|
||||||
|
"left": {
|
||||||
|
"id": "8c92fa79437d4f31",
|
||||||
|
"type": "split",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "e4a9f8318da249b0",
|
||||||
|
"type": "tabs",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "da6fd2aac65f47f1",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "file-explorer",
|
||||||
|
"state": {
|
||||||
|
"sortOrder": "alphabetical",
|
||||||
|
"autoReveal": false
|
||||||
|
},
|
||||||
|
"icon": "lucide-folder-closed",
|
||||||
|
"title": "Files"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3f86b26f003a0d1a",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "search",
|
||||||
|
"state": {
|
||||||
|
"query": "tag:#usage",
|
||||||
|
"matchingCase": false,
|
||||||
|
"explainSearch": false,
|
||||||
|
"collapseAll": false,
|
||||||
|
"extraContext": false,
|
||||||
|
"sortOrder": "alphabetical"
|
||||||
|
},
|
||||||
|
"icon": "lucide-search",
|
||||||
|
"title": "Search"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "39755dd9db653e17",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "bookmarks",
|
||||||
|
"state": {},
|
||||||
|
"icon": "lucide-bookmark",
|
||||||
|
"title": "Bookmarks"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"direction": "horizontal",
|
||||||
|
"width": 200,
|
||||||
|
"collapsed": true
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"id": "baa2a8e61b737fa6",
|
||||||
|
"type": "split",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "b628e7116722c59a",
|
||||||
|
"type": "tabs",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "eb1781be59af8c30",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "backlink",
|
||||||
|
"state": {
|
||||||
|
"file": "Usage/Building The Kernel.md",
|
||||||
|
"collapseAll": false,
|
||||||
|
"extraContext": false,
|
||||||
|
"sortOrder": "alphabetical",
|
||||||
|
"showSearch": false,
|
||||||
|
"searchQuery": "",
|
||||||
|
"backlinkCollapsed": false,
|
||||||
|
"unlinkedCollapsed": true
|
||||||
|
},
|
||||||
|
"icon": "links-coming-in",
|
||||||
|
"title": "Backlinks for Building The Kernel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "18e4602ee5825e11",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "outgoing-link",
|
||||||
|
"state": {
|
||||||
|
"file": "Usage/Building The Kernel.md",
|
||||||
|
"linksCollapsed": false,
|
||||||
|
"unlinkedCollapsed": true
|
||||||
|
},
|
||||||
|
"icon": "links-going-out",
|
||||||
|
"title": "Outgoing links from Building The Kernel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "df5aadad9f62dff1",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "tag",
|
||||||
|
"state": {
|
||||||
|
"sortOrder": "frequency",
|
||||||
|
"useHierarchy": false,
|
||||||
|
"showSearch": false,
|
||||||
|
"searchQuery": ""
|
||||||
|
},
|
||||||
|
"icon": "lucide-tags",
|
||||||
|
"title": "Tags"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "9bc68cb074d39ab5",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "outline",
|
||||||
|
"state": {
|
||||||
|
"file": "Usage/Building The Kernel.md",
|
||||||
|
"followCursor": false,
|
||||||
|
"showSearch": false,
|
||||||
|
"searchQuery": ""
|
||||||
|
},
|
||||||
|
"icon": "lucide-list",
|
||||||
|
"title": "Outline of Building The Kernel"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"currentTab": 2
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"direction": "horizontal",
|
||||||
|
"width": 300
|
||||||
|
},
|
||||||
|
"left-ribbon": {
|
||||||
|
"hiddenItems": {
|
||||||
|
"switcher:Open quick switcher": false,
|
||||||
|
"graph:Open graph view": false,
|
||||||
|
"canvas:Create new canvas": false,
|
||||||
|
"daily-notes:Open today's daily note": false,
|
||||||
|
"templates:Insert template": false,
|
||||||
|
"command-palette:Open command palette": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"active": "add883d295e04659",
|
||||||
|
"lastOpenFiles": [
|
||||||
|
"Usage",
|
||||||
|
"Welcome.md",
|
||||||
|
"Usage/Building The Kernel.md"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
# Debugging the Kernel
|
||||||
|
|
||||||
|
Here we will add some helpful tips on debugging the kernel.
|
||||||
|
|
||||||
|
## Disassembling a public function
|
||||||
|
|
||||||
|
To disassemble a public function, first we need a symbol in the public symbol table, so start by making the function fully public (including any parent modules). Do this as though you are trying to make a public function for a library crate (this includes the `kernel` crate). Simply mark the function and any parent modules as public, up until the point of [lib.rs (kernel link)](../../kernel/src/lib.rs).
|
||||||
|
|
||||||
|
Then, we need to find the specific demangled symbol to disassemble, because the default objdump output can be very verbose.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Change as required, I pipe to less and /SEARCH FOR FUNCTION HERE.
|
||||||
|
nm --demangle ./build/target/x86_64-kernel/debug/kernel | less
|
||||||
|
# Now just paste the symbol where it says YOUR_SYMBOL_HERE and profit. Use -Mintel for Intel assembly syntax.
|
||||||
|
objdump -Matt --source --line-numbers --visualize-jumps ./build/target/x86_64-kernel/debug/kernel --demangle=rust --disassemble="YOUR_SYMBOL_HERE"
|
||||||
|
```
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#usage
|
||||||
|
### Requirements
|
||||||
|
- Latest rust nightly release
|
||||||
|
> rustup update
|
||||||
|
> rustup override set nightly
|
||||||
|
- Specific rustup components that can be installed with the following commands:
|
||||||
|
> rustup component add rust-src
|
||||||
|
> rustup component add llvm-tools-preview
|
||||||
|
### Building
|
||||||
|
run the following command (in the root directory of the project)
|
||||||
|
> ./run.sh
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
[build]
|
|
||||||
target = "../customos"
|
|
||||||
target-dir = "./target"
|
|
||||||
|
|
||||||
[unstable]
|
|
||||||
build-std = ["core", "compiler_builtins"]
|
|
||||||
build-std-features = ["compiler-builtins-mem"]
|
|
||||||
+20
-3
@@ -1,7 +1,24 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "foundryos_kernel"
|
name = "foundry_os"
|
||||||
version = "0.1.0"
|
edition.workspace = true
|
||||||
edition = "2021"
|
version.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
limine = "0.3.1"
|
limine = "0.3.1"
|
||||||
|
libk = { path = "../libk" }
|
||||||
|
x86_64 = "0.15.2"
|
||||||
|
spin = "0.9.8"
|
||||||
|
pic8259 = "0.11.0"
|
||||||
|
pc-keyboard = "0.8.0"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
cc = "1.2.14"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = []
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "kernel"
|
||||||
|
path = "src/main.rs"
|
||||||
|
test = false
|
||||||
|
|||||||
+5
-6
@@ -1,7 +1,6 @@
|
|||||||
fn main() {
|
fn main() {
|
||||||
let arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap();
|
// Tell cargo to rerun if these files change
|
||||||
// Tell cargo to pass the linker script to the linker..
|
println!("cargo:rerun-if-changed=src");
|
||||||
println!("cargo:rustc-link-arg=-Tlinker-{arch}.ld");
|
println!("cargo:rerun-if-changed=linker.ld");
|
||||||
// ..and to re-run if it changes.
|
println!("cargo:rerun-if-changed=../config/limine.conf");
|
||||||
println!("cargo:rerun-if-changed=linker-{arch}.ld");
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
Signature: 8a477f597d28d172789f06886806bc55
|
|
||||||
# This file is a cache directory tag created by cargo.
|
|
||||||
# For information about cache directory tags see https://bford.info/cachedir/
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
2c12b06536f46cd1
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
{"rustc":5637828655848808591,"features":"","declared_features":"","target":0,"profile":0,"path":0,"deps":[[16831489395241507197,"build_script_build",false,2449660372133931133]],"local":[{"RerunIfChanged":{"output":"../customos/debug/build/compiler_builtins-7ff902764ead3159/output","paths":["build.rs","configure.rs"]}}],"rustflags":[],"config":0,"compile_kind":0}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
This file has an mtime of when this was started.
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{"$message_type":"diagnostic","message":"Error loading target specification: Could not find specification for target \"../customos\". Run `rustc --print target-list` for a list of built-in targets","code":null,"level":"error","spans":[],"children":[],"rendered":"\u001b[0m\u001b[1m\u001b[38;5;9merror\u001b[0m\u001b[0m\u001b[1m: Error loading target specification: Could not find specification for target \"../customos\". Run `rustc --print target-list` for a list of built-in targets\u001b[0m\n\n"}
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
85b0379a2e964349
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
{"rustc":5637828655848808591,"features":"","declared_features":"","target":0,"profile":0,"path":0,"deps":[[16831489395241507197,"build_script_build",false,15090704965883138604],[4566724075159146729,"build_script_build",false,12086878114467551400]],"local":[{"RerunIfChanged":{"output":"../customos/debug/build/foundryos_kernel-15da3dc5b1d972d1/output","paths":["linker-x86_64.ld"]}}],"rustflags":[],"config":0,"compile_kind":0}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
This file has an mtime of when this was started.
|
|
||||||
@@ -1,151 +0,0 @@
|
|||||||
cargo::rerun-if-changed=build.rs
|
|
||||||
cargo::rerun-if-changed=configure.rs
|
|
||||||
cargo::rustc-check-cfg=cfg(__ashldi3, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__ashlsi3, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__ashrdi3, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__ashrsi3, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__bswapsi2, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__bswapdi2, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__bswapti2, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__divdi3, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__divsi3, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__divmoddi4, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__divmodsi4, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__divmodsi4, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__divmodti4, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__lshrdi3, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__lshrsi3, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__moddi3, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__modsi3, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__muldi3, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__udivdi3, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__udivmoddi4, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__udivmodsi4, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__udivsi3, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__umoddi3, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__umodsi3, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_cas1_relax, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_cas1_acq, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_cas1_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_cas1_acq_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_cas2_relax, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_cas2_acq, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_cas2_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_cas2_acq_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_cas4_relax, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_cas4_acq, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_cas4_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_cas4_acq_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_cas8_relax, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_cas8_acq, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_cas8_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_cas8_acq_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_cas16_relax, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_cas16_acq, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_cas16_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_cas16_acq_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldadd1_relax, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldadd1_acq, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldadd1_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldadd1_acq_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldadd2_relax, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldadd2_acq, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldadd2_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldadd2_acq_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldadd4_relax, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldadd4_acq, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldadd4_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldadd4_acq_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldadd8_relax, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldadd8_acq, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldadd8_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldadd8_acq_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldclr1_relax, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldclr1_acq, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldclr1_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldclr1_acq_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldclr2_relax, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldclr2_acq, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldclr2_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldclr2_acq_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldclr4_relax, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldclr4_acq, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldclr4_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldclr4_acq_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldclr8_relax, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldclr8_acq, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldclr8_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldclr8_acq_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldeor1_relax, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldeor1_acq, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldeor1_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldeor1_acq_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldeor2_relax, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldeor2_acq, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldeor2_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldeor2_acq_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldeor4_relax, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldeor4_acq, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldeor4_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldeor4_acq_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldeor8_relax, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldeor8_acq, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldeor8_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldeor8_acq_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldset1_relax, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldset1_acq, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldset1_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldset1_acq_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldset2_relax, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldset2_acq, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldset2_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldset2_acq_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldset4_relax, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldset4_acq, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldset4_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldset4_acq_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldset8_relax, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldset8_acq, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldset8_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_ldset8_acq_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_swp1_relax, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_swp1_acq, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_swp1_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_swp1_acq_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_swp2_relax, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_swp2_acq, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_swp2_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_swp2_acq_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_swp4_relax, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_swp4_acq, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_swp4_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_swp4_acq_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_swp8_relax, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_swp8_acq, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_swp8_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(__aarch64_swp8_acq_rel, values("optimized-c"))
|
|
||||||
cargo::rustc-check-cfg=cfg(target_feature, values("vis3"))
|
|
||||||
cargo::rustc-check-cfg=cfg(feature, values("checked"))
|
|
||||||
cargo::rustc-check-cfg=cfg(assert_no_panic)
|
|
||||||
cargo::rustc-check-cfg=cfg(f16_enabled)
|
|
||||||
cargo::rustc-check-cfg=cfg(f128_enabled)
|
|
||||||
cargo::rustc-cfg=f16_enabled
|
|
||||||
cargo::rustc-cfg=f128_enabled
|
|
||||||
cargo:rustc-check-cfg=cfg(intrinsics_enabled)
|
|
||||||
cargo:rustc-check-cfg=cfg(arch_enabled)
|
|
||||||
cargo:rustc-check-cfg=cfg(optimizations_enabled)
|
|
||||||
cargo:rustc-check-cfg=cfg(feature, values("unstable-public-internals"))
|
|
||||||
cargo:rustc-cfg=intrinsics_enabled
|
|
||||||
cargo:rustc-cfg=arch_enabled
|
|
||||||
cargo:rustc-check-cfg=cfg(optimizations_enabled)
|
|
||||||
cargo:rustc-check-cfg=cfg(x86_no_sse)
|
|
||||||
cargo:rustc-env=CFG_CARGO_FEATURES=["compiler-builtins", "core", "default", "mem", "rustc-dep-of-std"]
|
|
||||||
cargo:rustc-env=CFG_OPT_LEVEL=0
|
|
||||||
cargo:rustc-env=CFG_TARGET_FEATURES=["x87"]
|
|
||||||
cargo:rustc-cfg=feature="unstable-intrinsics"
|
|
||||||
cargo:compiler-rt=/home/zxq5/.cargo/bin/registry/src/index.crates.io-1949cf8c6b5b557f/compiler_builtins-0.1.146/compiler-rt
|
|
||||||
cargo::rustc-check-cfg=cfg(feature, values("mem-unaligned"))
|
|
||||||
cargo:rustc-cfg=feature="mem-unaligned"
|
|
||||||
cargo::rustc-check-cfg=cfg(thumb)
|
|
||||||
cargo::rustc-check-cfg=cfg(thumb_1)
|
|
||||||
cargo::rustc-check-cfg=cfg(kernel_user_helpers)
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/home/zxq5/Projects/OSDev/FoundryOS/kernel/./target/../customos/debug/build/compiler_builtins-7ff902764ead3159/out
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
This file has an mtime of when this was started.
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
cargo:rustc-link-arg=-Tlinker-x86_64.ld
|
|
||||||
cargo:rerun-if-changed=linker-x86_64.ld
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/home/zxq5/Projects/OSDev/FoundryOS/kernel/./target/../customos/debug/build/foundryos_kernel-15da3dc5b1d972d1/out
|
|
||||||
@@ -9,9 +9,10 @@ ENTRY(kmain)
|
|||||||
/* process. */
|
/* process. */
|
||||||
PHDRS
|
PHDRS
|
||||||
{
|
{
|
||||||
text PT_LOAD;
|
limine_requests PT_LOAD;
|
||||||
rodata PT_LOAD;
|
text PT_LOAD;
|
||||||
data PT_LOAD;
|
rodata PT_LOAD;
|
||||||
|
data PT_LOAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
@@ -22,6 +23,18 @@ SECTIONS
|
|||||||
/* that is the beginning of the region. */
|
/* that is the beginning of the region. */
|
||||||
. = 0xffffffff80000000;
|
. = 0xffffffff80000000;
|
||||||
|
|
||||||
|
/* Define a section to contain the Limine requests and assign it to its own PHDR */
|
||||||
|
|
||||||
|
.limine_requests : {
|
||||||
|
KEEP(*(.limine_requests_start))
|
||||||
|
KEEP(*(.limine_requests))
|
||||||
|
KEEP(*(.limine_requests_end))
|
||||||
|
} :limine_requests
|
||||||
|
|
||||||
|
/* Move to the next memory page for .text */
|
||||||
|
|
||||||
|
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||||
|
|
||||||
.text : {
|
.text : {
|
||||||
*(.text .text.*)
|
*(.text .text.*)
|
||||||
} :text
|
} :text
|
||||||
@@ -38,12 +51,6 @@ SECTIONS
|
|||||||
|
|
||||||
.data : {
|
.data : {
|
||||||
*(.data .data.*)
|
*(.data .data.*)
|
||||||
|
|
||||||
/* Place the sections that contain the Limine requests as part of the .data */
|
|
||||||
/* output section. */
|
|
||||||
KEEP(*(.requests_start_marker))
|
|
||||||
KEEP(*(.requests))
|
|
||||||
KEEP(*(.requests_end_marker))
|
|
||||||
} :data
|
} :data
|
||||||
|
|
||||||
/* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */
|
/* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */
|
||||||
@@ -60,4 +67,4 @@ SECTIONS
|
|||||||
*(.eh_frame*)
|
*(.eh_frame*)
|
||||||
*(.note .note.*)
|
*(.note .note.*)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
[toolchain]
|
|
||||||
channel = "nightly"
|
|
||||||
targets = ["rust-src", "llvm-tools-preview", "rustfmt", "clippy"]
|
|
||||||
components = []
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
pub mod x86_64;
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
#![allow(unused)] // TODO: Remove this when ready.
|
||||||
|
use core::arch::x86_64::__cpuid;
|
||||||
|
|
||||||
|
use x86_64::{
|
||||||
|
PhysAddr, VirtAddr,
|
||||||
|
structures::paging::{Mapper, Size4KiB},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::serial_print;
|
||||||
|
|
||||||
|
use super::{cpu::model_specific_registers::*, mem::memmap::PHYSICAL_MEMORY_OFFSET};
|
||||||
|
|
||||||
|
const IA32_APIC_BASE_MSR: u32 = 0x1b;
|
||||||
|
const IA32_APIC_BASE_MSR_BSP: u64 = 0x100;
|
||||||
|
const IA32_APIC_BASE_MSR_ENABLE: u64 = 0x800;
|
||||||
|
const IA32_APIC_BASE_MSR_DISABLE: u64 = !IA32_APIC_BASE_MSR_ENABLE;
|
||||||
|
|
||||||
|
const CPUID_FEAT_EDX_APIC: u64 = 1 << 9; // the cpuid instruction will return this flag if it supports APIC
|
||||||
|
|
||||||
|
// const APIC_VIRTUAL_ADDRESS: Lazy<VirtAddr> = Lazy::new(|| {
|
||||||
|
// let apic_base = get_apic_base();
|
||||||
|
// let virt_addr = unsafe { phys_to_virt(apic_base) };
|
||||||
|
|
||||||
|
// virt_addr
|
||||||
|
// });
|
||||||
|
|
||||||
|
fn set_apic_base_enable(apic: PhysAddr) {
|
||||||
|
let rax = (apic.as_u64() & 0xfffff0000) | IA32_APIC_BASE_MSR_ENABLE;
|
||||||
|
cpu_set_msr(IA32_APIC_BASE_MSR, rax);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_apic_base_disable(apic: PhysAddr) {
|
||||||
|
let rax = (apic.as_u64() & 0xfffff0000) & IA32_APIC_BASE_MSR_DISABLE;
|
||||||
|
cpu_set_msr(IA32_APIC_BASE_MSR, rax);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_apic_base() -> PhysAddr {
|
||||||
|
let mut value: u64 = 0;
|
||||||
|
cpu_get_msr(IA32_APIC_BASE_MSR, &mut value);
|
||||||
|
PhysAddr::new(value & 0xfffff0000)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_apic_register(apic_base: &VirtAddr, reg: u8, value: u32) {
|
||||||
|
let apic_base = apic_base.as_u64();
|
||||||
|
let reg_addr = (apic_base & 0xFFFFF0000) + reg as u64;
|
||||||
|
unsafe { *(reg_addr as *mut u32) = value };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_apic_register(apic_base: &VirtAddr, reg: u8) -> u32 {
|
||||||
|
let apic_base = apic_base.as_u64();
|
||||||
|
|
||||||
|
serial_print!("got apic base");
|
||||||
|
|
||||||
|
let reg_addr = (apic_base & 0xFFFFF0000) + reg as u64;
|
||||||
|
unsafe { *(reg_addr as *const u32) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_apic() -> bool {
|
||||||
|
let res = unsafe { __cpuid(1) };
|
||||||
|
res.edx as u64 & CPUID_FEAT_EDX_APIC != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
unsafe fn phys_to_virt(phys: PhysAddr) -> VirtAddr {
|
||||||
|
let phys = phys.as_u64();
|
||||||
|
phys.checked_add(*PHYSICAL_MEMORY_OFFSET).map_or_else(
|
||||||
|
|| {
|
||||||
|
serial_print!("THIS IS A PROBLEM");
|
||||||
|
panic!("overflow")
|
||||||
|
},
|
||||||
|
|virt| {
|
||||||
|
serial_print!("map worked!");
|
||||||
|
VirtAddr::new(virt)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enable_apic(
|
||||||
|
_mapper: &mut impl Mapper<Size4KiB>,
|
||||||
|
// TODO: Fix this function.
|
||||||
|
// frame_allocator: &mut FoundryOSFrameAllocator,
|
||||||
|
) {
|
||||||
|
unimplemented!();
|
||||||
|
|
||||||
|
// let apic_phys_addr = get_apic_base();
|
||||||
|
// set_apic_base_enable(apic_phys_addr);
|
||||||
|
// map virt address of apic
|
||||||
|
|
||||||
|
// let apic_virt = unsafe { phys_to_virt(apic_phys_addr) };
|
||||||
|
// let page: Page<Size4KiB> = Page::containing_address(apic_virt);
|
||||||
|
// let frame: PhysFrame<Size4KiB> = PhysFrame::containing_address(apic_phys_addr);
|
||||||
|
// let flags: PageTableFlags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE;
|
||||||
|
|
||||||
|
// unsafe {
|
||||||
|
// match mapper.map_to(page, frame, flags, frame_allocator) {
|
||||||
|
// Ok(_) => {}
|
||||||
|
// Err(why) => panic!("failed to map apic: {:?}", why),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // FIXME: this causes a page fault
|
||||||
|
// // TODO: map to virtual memor
|
||||||
|
|
||||||
|
// let reg = read_apic_register(&apic_virt, 0xF0);
|
||||||
|
|
||||||
|
// serial_print!("ok2");
|
||||||
|
|
||||||
|
// write_apic_register(&apic_virt, 0xF0, reg | 0x100);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Apic {}
|
||||||
|
|
||||||
|
pub enum ApicVector {}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
pub mod model_specific_registers {
|
||||||
|
use core::arch::x86_64::__cpuid;
|
||||||
|
use spin::Lazy;
|
||||||
|
use x86_64::registers::model_specific::Msr;
|
||||||
|
|
||||||
|
const _CPUID_FLAG_MSR: u32 = 1 << 5;
|
||||||
|
static _EDX: Lazy<u32> = Lazy::new(|| unsafe { __cpuid(1).edx });
|
||||||
|
|
||||||
|
pub fn _cpu_has_msr() -> bool {
|
||||||
|
*_EDX & _CPUID_FLAG_MSR != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cpu_get_msr(msr: u32, value: &mut u64) {
|
||||||
|
let msr = Msr::new(msr);
|
||||||
|
unsafe {
|
||||||
|
*value = msr.read();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cpu_set_msr(msr: u32, value: u64) {
|
||||||
|
let mut msr = Msr::new(msr);
|
||||||
|
unsafe {
|
||||||
|
msr.write(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
use x86_64::{
|
||||||
|
instructions::tables::load_tss,
|
||||||
|
registers::segmentation::{Segment, CS, DS, ES, SS},
|
||||||
|
structures::{
|
||||||
|
gdt::{Descriptor, GlobalDescriptorTable, SegmentSelector},
|
||||||
|
tss::TaskStateSegment,
|
||||||
|
},
|
||||||
|
VirtAddr,
|
||||||
|
};
|
||||||
|
|
||||||
|
use spin::Lazy;
|
||||||
|
|
||||||
|
pub const DOUBLE_FAULT_1ST_INDEX: u16 = 0;
|
||||||
|
|
||||||
|
static TSS: Lazy<TaskStateSegment> = Lazy::new(|| {
|
||||||
|
let mut tss = TaskStateSegment::new();
|
||||||
|
tss.interrupt_stack_table[DOUBLE_FAULT_1ST_INDEX as usize] = {
|
||||||
|
const STACK_SIZE: usize = 4096 * 8;
|
||||||
|
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
|
||||||
|
|
||||||
|
let stack_start = VirtAddr::from_ptr(&raw const STACK);
|
||||||
|
|
||||||
|
stack_start + STACK_SIZE.try_into().unwrap()
|
||||||
|
};
|
||||||
|
tss
|
||||||
|
});
|
||||||
|
|
||||||
|
static GDT: Lazy<(GlobalDescriptorTable, Selectors)> = Lazy::new(|| {
|
||||||
|
let mut gdt = GlobalDescriptorTable::new();
|
||||||
|
let code_selector = gdt.append(Descriptor::kernel_code_segment());
|
||||||
|
let data_selector = gdt.append(Descriptor::kernel_data_segment());
|
||||||
|
|
||||||
|
let user_code_selector = gdt.append(Descriptor::user_code_segment());
|
||||||
|
let user_data_selector = gdt.append(Descriptor::user_data_segment());
|
||||||
|
|
||||||
|
let tss_selector = gdt.append(Descriptor::tss_segment(&TSS));
|
||||||
|
|
||||||
|
(
|
||||||
|
gdt,
|
||||||
|
Selectors {
|
||||||
|
code_selector,
|
||||||
|
data_selector,
|
||||||
|
_user_code_selector: user_code_selector,
|
||||||
|
_user_data_selector: user_data_selector,
|
||||||
|
tss_selector,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
struct Selectors {
|
||||||
|
code_selector: SegmentSelector,
|
||||||
|
data_selector: SegmentSelector,
|
||||||
|
_user_code_selector: SegmentSelector,
|
||||||
|
_user_data_selector: SegmentSelector,
|
||||||
|
tss_selector: SegmentSelector,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init() {
|
||||||
|
GDT.0.load();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
CS::set_reg(GDT.1.code_selector);
|
||||||
|
load_tss(GDT.1.tss_selector);
|
||||||
|
|
||||||
|
DS::set_reg(self::GDT.1.data_selector);
|
||||||
|
ES::set_reg(self::GDT.1.data_selector);
|
||||||
|
SS::set_reg(self::GDT.1.data_selector);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,153 @@
|
|||||||
|
// use libk::drivers::mem::{FRAME_ALLOCATOR, OFFSET_PAGE_TABLE};
|
||||||
|
use libk::prelude::*;
|
||||||
|
use pic8259::ChainedPics;
|
||||||
|
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode};
|
||||||
|
|
||||||
|
use spin::{Lazy, Mutex};
|
||||||
|
|
||||||
|
use super::gdt;
|
||||||
|
|
||||||
|
static IDT: Lazy<InterruptDescriptorTable> = Lazy::new(|| {
|
||||||
|
let mut idt = InterruptDescriptorTable::new();
|
||||||
|
idt.breakpoint.set_handler_fn(breakpoint_handler);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
idt.double_fault
|
||||||
|
.set_handler_fn(double_fault_handler)
|
||||||
|
.set_stack_index(gdt::DOUBLE_FAULT_1ST_INDEX);
|
||||||
|
}
|
||||||
|
|
||||||
|
idt.general_protection_fault
|
||||||
|
.set_handler_fn(general_protection_fault_handler);
|
||||||
|
idt.page_fault.set_handler_fn(page_fault_handler);
|
||||||
|
|
||||||
|
idt[InterruptIndex::Timer.as_u8()].set_handler_fn(timer_interrupt_handler);
|
||||||
|
idt[InterruptIndex::Keyboard.as_u8()].set_handler_fn(keyboard_interrupt_handler);
|
||||||
|
idt
|
||||||
|
});
|
||||||
|
|
||||||
|
pub const PIC_1_OFFSET: u8 = 32;
|
||||||
|
pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8;
|
||||||
|
|
||||||
|
pub static PICS: Mutex<ChainedPics> =
|
||||||
|
Mutex::new(unsafe { ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) });
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum InterruptIndex {
|
||||||
|
Timer = PIC_1_OFFSET,
|
||||||
|
Keyboard,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InterruptIndex {
|
||||||
|
const fn as_u8(self) -> u8 {
|
||||||
|
self as u8
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _as_usize(self) -> usize {
|
||||||
|
usize::from(self.as_u8())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init_idt() {
|
||||||
|
IDT.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enable_pic() {
|
||||||
|
unsafe {
|
||||||
|
PICS.lock().initialize();
|
||||||
|
PICS.lock().write_masks(0xfc, 0xff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[expect(unused)]
|
||||||
|
pub fn disable_pic() {
|
||||||
|
unsafe {
|
||||||
|
PICS.lock().disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "x86-interrupt" fn breakpoint_handler(stack_frame: InterruptStackFrame) {
|
||||||
|
serial_println!("Exception: Breakpoint\n{:#?}", stack_frame);
|
||||||
|
println_log!("Exception: Breakpoint\n{:#?}", stack_frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "x86-interrupt" fn general_protection_fault_handler(
|
||||||
|
stack_frame: InterruptStackFrame,
|
||||||
|
_error_code: u64,
|
||||||
|
) {
|
||||||
|
serial_println!("Exception: General Protection Fault\n{:#?}", stack_frame);
|
||||||
|
panic!("Exception: General Protection Fault\n{:#?}", stack_frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "x86-interrupt" fn double_fault_handler(
|
||||||
|
stack_frame: InterruptStackFrame,
|
||||||
|
_error_code: u64,
|
||||||
|
) -> ! {
|
||||||
|
serial_println!("Exception: Double Fault\n{:#?}", stack_frame);
|
||||||
|
panic!("Exception: Double Fault\n{:#?}", stack_frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: InterruptStackFrame) {
|
||||||
|
use pc_keyboard::{HandleControl, Keyboard, ScancodeSet1, layouts};
|
||||||
|
// use pc_keyboard::DecodedKey;
|
||||||
|
use spin::Mutex;
|
||||||
|
use x86_64::instructions::port::Port;
|
||||||
|
|
||||||
|
static KEYBOARD: Lazy<Mutex<Keyboard<layouts::Uk105Key, ScancodeSet1>>> = Lazy::new(|| {
|
||||||
|
Mutex::new(Keyboard::new(
|
||||||
|
ScancodeSet1::new(),
|
||||||
|
layouts::Uk105Key,
|
||||||
|
HandleControl::Ignore,
|
||||||
|
))
|
||||||
|
});
|
||||||
|
|
||||||
|
let _keyboard = KEYBOARD.lock();
|
||||||
|
let mut port = Port::new(0x60);
|
||||||
|
|
||||||
|
let scancode: u8 = unsafe { port.read() };
|
||||||
|
libk::drivers::io::keyboard::add_scancode(scancode);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
PICS.lock()
|
||||||
|
.notify_end_of_interrupt(InterruptIndex::Keyboard.as_u8());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: InterruptStackFrame) {
|
||||||
|
unsafe {
|
||||||
|
PICS.lock()
|
||||||
|
.notify_end_of_interrupt(InterruptIndex::Timer.as_u8());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "x86-interrupt" fn page_fault_handler(
|
||||||
|
_stack_frame: InterruptStackFrame,
|
||||||
|
_error_code: PageFaultErrorCode,
|
||||||
|
) {
|
||||||
|
todo!("Get this working again.")
|
||||||
|
// serial_println!("Exception: Page Fault");
|
||||||
|
// serial_println!("Accessed Address: {:?}", Cr2::read());
|
||||||
|
// serial_println!("Error Code: {:?}", error_code);
|
||||||
|
// serial_println!("{:#?}", stack_frame);
|
||||||
|
|
||||||
|
// if let Some(frame_allocator) = FRAME_ALLOCATOR.get() {
|
||||||
|
// let mut f = frame_allocator.lock();
|
||||||
|
|
||||||
|
// let frame = f.allocate_frame().unwrap();
|
||||||
|
// let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE;
|
||||||
|
// let page: Page<Size4KiB> = Page::containing_address(Cr2::read().unwrap());
|
||||||
|
|
||||||
|
// unsafe {
|
||||||
|
// let mut mapper = OFFSET_PAGE_TABLE.get().unwrap().lock();
|
||||||
|
|
||||||
|
// match mapper.map_to(page, frame, flags, &mut *f) {
|
||||||
|
// Ok(_) => {}
|
||||||
|
// Err(why) => panic!("failed to map page: {:?}", why),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// MapperFlushAll::new().flush_all();
|
||||||
|
// } else {
|
||||||
|
// panic!("failed to get frame allocator");
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
//! Sets up a memory map using Limine.
|
||||||
|
|
||||||
|
use limine::{
|
||||||
|
request::{HhdmRequest, KernelAddressRequest, MemoryMapRequest},
|
||||||
|
response::MemoryMapResponse,
|
||||||
|
};
|
||||||
|
use spin::Lazy;
|
||||||
|
|
||||||
|
#[used]
|
||||||
|
#[unsafe(link_section = ".requests")]
|
||||||
|
static MEMORY_MAP_REQUEST: MemoryMapRequest = MemoryMapRequest::new();
|
||||||
|
|
||||||
|
#[used]
|
||||||
|
#[unsafe(link_section = ".requests")]
|
||||||
|
static HIGHER_HALF_DIRECT_MAP_REQUEST: HhdmRequest = HhdmRequest::new();
|
||||||
|
|
||||||
|
#[used]
|
||||||
|
#[unsafe(link_section = ".requests")]
|
||||||
|
static KERNEL_ADDRESS_REQUEST: KernelAddressRequest = KernelAddressRequest::new();
|
||||||
|
|
||||||
|
/// ```rs
|
||||||
|
/// let virt_addr = phys_addr + offset;
|
||||||
|
/// let phys_addr = virt_addr - offset; // (given VA is in the HHDM). Do not use for executable code.
|
||||||
|
/// ```
|
||||||
|
pub static PHYSICAL_MEMORY_OFFSET: Lazy<u64> = Lazy::new(|| {
|
||||||
|
HIGHER_HALF_DIRECT_MAP_REQUEST
|
||||||
|
.get_response()
|
||||||
|
.unwrap()
|
||||||
|
.offset()
|
||||||
|
});
|
||||||
|
|
||||||
|
/// Converts virtual addresses in the kernel to a physical address like this:
|
||||||
|
/// ```rs
|
||||||
|
/// let phys_addr = virt_addr - virtual_base + physical_base;
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Returns (virtual_base, physical_base)
|
||||||
|
pub static _KERNEL_PHYSICAL_MEMORY_OFFSET: Lazy<(u64, u64)> = Lazy::new(|| {
|
||||||
|
let resp = KERNEL_ADDRESS_REQUEST.get_response().unwrap();
|
||||||
|
|
||||||
|
// These are base addresses, using Limine's built in page table.
|
||||||
|
(resp.virtual_base(), resp.physical_base())
|
||||||
|
});
|
||||||
|
|
||||||
|
/// Fetches the memory map from Limine.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the memory map was not found in MEMORY_MAP_REQUEST.
|
||||||
|
pub fn get_memory_map() -> &'static MemoryMapResponse {
|
||||||
|
MEMORY_MAP_REQUEST.get_response().map_or_else(
|
||||||
|
|| unreachable!("Could not fetch memory map from Limine."),
|
||||||
|
|memory_map| memory_map,
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
pub mod memmap;
|
||||||
|
pub mod pmm;
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
pub mod apic;
|
||||||
|
pub mod cpu;
|
||||||
|
pub mod gdt;
|
||||||
|
pub mod interrupts;
|
||||||
|
pub mod mem;
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![feature(abi_x86_interrupt)]
|
||||||
|
#![warn(
|
||||||
|
clippy::correctness,
|
||||||
|
clippy::nursery,
|
||||||
|
clippy::unnecessary_cast,
|
||||||
|
clippy::all,
|
||||||
|
clippy::suspicious,
|
||||||
|
clippy::perf,
|
||||||
|
rustdoc::missing_errors_doc,
|
||||||
|
rustdoc::missing_panics_doc
|
||||||
|
)]
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
|
// use arch::x86_64::apic::enable_apic;
|
||||||
|
use core::arch::asm;
|
||||||
|
// use libk::drivers::mem::pmm;
|
||||||
|
use limine::BaseRevision;
|
||||||
|
|
||||||
|
// use libk::drivers::alloc::allocator::init_heap;
|
||||||
|
use libk::prelude::*;
|
||||||
|
|
||||||
|
mod arch;
|
||||||
|
|
||||||
|
/// Sets the base revision to the latest revision supported by the crate.
|
||||||
|
/// See specification for further info.
|
||||||
|
/// Be sure to mark all limine requests with #[used], otherwise they may be removed by the compiler.
|
||||||
|
#[used]
|
||||||
|
// The .requests section allows limine to find the requests faster and more safely.
|
||||||
|
#[unsafe(link_section = ".requests")]
|
||||||
|
static BASE_REVISION: BaseRevision = BaseRevision::new();
|
||||||
|
|
||||||
|
#[panic_handler]
|
||||||
|
fn rust_panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
|
println!("Kernel panic: {}", _info);
|
||||||
|
serial_println!("Kernel panic: {}", _info);
|
||||||
|
hcf();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hcf() -> ! {
|
||||||
|
loop {
|
||||||
|
unsafe {
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
asm!("hlt");
|
||||||
|
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
|
||||||
|
asm!("wfi");
|
||||||
|
#[cfg(target_arch = "loongarch64")]
|
||||||
|
asm!("idle 0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn boot() -> Result<(), &'static str> {
|
||||||
|
if !BASE_REVISION.is_supported() {
|
||||||
|
return Err("base revision not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
use arch::x86_64::{gdt, interrupts, mem::memmap};
|
||||||
|
|
||||||
|
let _memory_map = memmap::get_memory_map();
|
||||||
|
|
||||||
|
print_log!(" Initialising Serial... ");
|
||||||
|
if libk::drivers::io::serial::init().is_err() {
|
||||||
|
println_log!("[Not Detected]")
|
||||||
|
} else {
|
||||||
|
println_log!("[Success]");
|
||||||
|
}
|
||||||
|
|
||||||
|
print_log!(" Setting Up Global Descriptor Table... ");
|
||||||
|
gdt::init();
|
||||||
|
println_log!("[Success]");
|
||||||
|
|
||||||
|
print_log!(" Setting Up Interrupt Descriptor Table... ");
|
||||||
|
interrupts::init_idt();
|
||||||
|
println_log!("[Success]");
|
||||||
|
|
||||||
|
print_log!(" Initialising Memory Subsystem... ");
|
||||||
|
// let physical_memory_offset = VirtAddr::new(*memmap::PHYSICAL_MEMORY_OFFSET);
|
||||||
|
// pmm::init_page_table(physical_memory_offset);
|
||||||
|
println_log!("[Success]");
|
||||||
|
|
||||||
|
print_log!(" Setting Up Page Table... ");
|
||||||
|
// pmm::init_frame_allocator(memory_map);
|
||||||
|
println_log!("[Success]");
|
||||||
|
|
||||||
|
print_log!(" Initialising Heap... ");
|
||||||
|
// TODO: Reenable the heap.
|
||||||
|
// if init_heap().is_err() {
|
||||||
|
// return Err("Failed to initialise heap: error");
|
||||||
|
// }
|
||||||
|
println_log!("[Success]");
|
||||||
|
|
||||||
|
print_log!(" Enabling PICs... ");
|
||||||
|
interrupts::enable_pic();
|
||||||
|
println_log!("[Success]");
|
||||||
|
|
||||||
|
// print_log!(" Disabling PICs... ");
|
||||||
|
// interrupts::disable_pic();
|
||||||
|
// println_log!("[Success]");
|
||||||
|
//
|
||||||
|
// print_log!(" Initialising APIC");
|
||||||
|
// enable_apic(&mut l4_table, &mut frame_allocator);
|
||||||
|
// println_log!("[Success]");
|
||||||
|
|
||||||
|
print_log!(" Enabling Interrupts... ");
|
||||||
|
x86_64::instructions::interrupts::enable();
|
||||||
|
println_log!("[Success]");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
+30
-57
@@ -1,67 +1,40 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use core::arch::asm;
|
extern crate alloc;
|
||||||
|
|
||||||
use limine::request::{FramebufferRequest, RequestsEndMarker, RequestsStartMarker};
|
use libk::{
|
||||||
use limine::BaseRevision;
|
drivers::{
|
||||||
|
async_io::task::{Executor, Task},
|
||||||
|
io,
|
||||||
|
},
|
||||||
|
prelude::*,
|
||||||
|
util::shell::shell,
|
||||||
|
};
|
||||||
|
|
||||||
/// Sets the base revision to the latest revision supported by the crate.
|
#[unsafe(no_mangle)]
|
||||||
/// See specification for further info.
|
extern "C" fn kmain() -> ! {
|
||||||
/// Be sure to mark all limine requests with #[used], otherwise they may be removed by the compiler.
|
println_log!(" [ Initialising Kernel Systems ] ");
|
||||||
#[used]
|
if let Err(err) = foundry_os::boot() {
|
||||||
// The .requests section allows limine to find the requests faster and more safely.
|
panic!("{}", err);
|
||||||
#[link_section = ".requests"]
|
|
||||||
static BASE_REVISION: BaseRevision = BaseRevision::new();
|
|
||||||
|
|
||||||
#[used]
|
|
||||||
#[link_section = ".requests"]
|
|
||||||
static FRAMEBUFFER_REQUEST: FramebufferRequest = FramebufferRequest::new();
|
|
||||||
|
|
||||||
/// Define the stand and end markers for Limine requests.
|
|
||||||
#[used]
|
|
||||||
#[link_section = ".requests_start_marker"]
|
|
||||||
static _START_MARKER: RequestsStartMarker = RequestsStartMarker::new();
|
|
||||||
#[used]
|
|
||||||
#[link_section = ".requests_end_marker"]
|
|
||||||
static _END_MARKER: RequestsEndMarker = RequestsEndMarker::new();
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
unsafe extern "C" fn kmain() -> ! {
|
|
||||||
// All limine requests must also be referenced in a called function, otherwise they may be
|
|
||||||
// removed by the linker.
|
|
||||||
assert!(BASE_REVISION.is_supported());
|
|
||||||
|
|
||||||
if let Some(framebuffer_response) = FRAMEBUFFER_REQUEST.get_response() {
|
|
||||||
if let Some(framebuffer) = framebuffer_response.framebuffers().next() {
|
|
||||||
for i in 0..100_u64 {
|
|
||||||
// Calculate the pixel offset using the framebuffer information we obtained above.
|
|
||||||
// We skip `i` scanlines (pitch is provided in bytes) and add `i * 4` to skip `i` pixels forward.
|
|
||||||
let pixel_offset = i * framebuffer.pitch() + i * 4;
|
|
||||||
|
|
||||||
// Write 0xFFFFFFFF to the provided pixel offset to fill it white.
|
|
||||||
*(framebuffer.addr().add(pixel_offset as usize) as *mut u32) = 0xFFFFFFFF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hcf();
|
println_log!("[ Kernel Initialised Successfully ] ");
|
||||||
}
|
|
||||||
|
|
||||||
#[panic_handler]
|
let dimensions = io::ascii::screensize_chars();
|
||||||
fn rust_panic(_info: &core::panic::PanicInfo) -> ! {
|
let dimensions2 = io::framebuffer::display::screensize_px();
|
||||||
hcf();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn hcf() -> ! {
|
println!("Dimensions: {}x{} (px)", dimensions2.0, dimensions2.1);
|
||||||
loop {
|
println!("Dimensions: {}x{} (chars)", dimensions.0, dimensions.1);
|
||||||
unsafe {
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
let mut executor = Executor::new();
|
||||||
asm!("hlt");
|
|
||||||
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
|
let mut v = Vec::with_capacity(1000 * 1000);
|
||||||
asm!("wfi");
|
for i in 0..1000 * 1000 {
|
||||||
#[cfg(target_arch = "loongarch64")]
|
v.push(i);
|
||||||
asm!("idle 0");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
println!("v.len(): {}", v.len());
|
||||||
|
|
||||||
|
executor.spawn(Task::new(shell()));
|
||||||
|
executor.run();
|
||||||
|
}
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
{"rustc_fingerprint":10191676143533991604,"outputs":{"17747080675513052775":{"success":true,"status":"","code":0,"stdout":"rustc 1.87.0-nightly (827a0d638 2025-02-18)\nbinary: rustc\ncommit-hash: 827a0d638dabc9a22c56f9c37a557568f86ac76c\ncommit-date: 2025-02-18\nhost: x86_64-unknown-linux-gnu\nrelease: 1.87.0-nightly\nLLVM version: 20.1.0\n","stderr":""},"7971740275564407648":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/zxq5/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu\noff\npacked\nunpacked\n___\ndebug_assertions\nfmt_debug=\"full\"\noverflow_checks\npanic=\"unwind\"\nproc_macro\nrelocation_model=\"pic\"\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_feature=\"x87\"\ntarget_has_atomic\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_has_atomic_equal_alignment=\"16\"\ntarget_has_atomic_equal_alignment=\"32\"\ntarget_has_atomic_equal_alignment=\"64\"\ntarget_has_atomic_equal_alignment=\"8\"\ntarget_has_atomic_equal_alignment=\"ptr\"\ntarget_has_atomic_load_store\ntarget_has_atomic_load_store=\"16\"\ntarget_has_atomic_load_store=\"32\"\ntarget_has_atomic_load_store=\"64\"\ntarget_has_atomic_load_store=\"8\"\ntarget_has_atomic_load_store=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_thread_local\ntarget_vendor=\"unknown\"\nub_checks\nunix\n","stderr":""},"16938275954012004043":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.a\n/home/zxq5/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu\noff\n___\ndebug_assertions\nfmt_debug=\"full\"\noverflow_checks\npanic=\"abort\"\nproc_macro\nrelocation_model=\"static\"\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_feature=\"x87\"\ntarget_has_atomic\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_has_atomic_equal_alignment=\"16\"\ntarget_has_atomic_equal_alignment=\"32\"\ntarget_has_atomic_equal_alignment=\"64\"\ntarget_has_atomic_equal_alignment=\"8\"\ntarget_has_atomic_equal_alignment=\"ptr\"\ntarget_has_atomic_load_store\ntarget_has_atomic_load_store=\"16\"\ntarget_has_atomic_load_store=\"32\"\ntarget_has_atomic_load_store=\"64\"\ntarget_has_atomic_load_store=\"8\"\ntarget_has_atomic_load_store=\"ptr\"\ntarget_os=\"none\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nub_checks\n","stderr":"warning: target feature `sse2` must be enabled to ensure that the ABI of the current target can be implemented correctly\n |\n = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!\n = note: for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>\n\nwarning: dropping unsupported crate type `dylib` for target `../customos`\n\nwarning: dropping unsupported crate type `cdylib` for target `../customos`\n\nwarning: dropping unsupported crate type `proc-macro` for target `../customos`\n\nwarning: 4 warnings emitted\n\n"}},"successes":{}}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
Signature: 8a477f597d28d172789f06886806bc55
|
|
||||||
# This file is a cache directory tag created by cargo.
|
|
||||||
# For information about cache directory tags see https://bford.info/cachedir/
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
7de8642d21f1fe21
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
{"rustc":5637828655848808591,"features":"[\"compiler-builtins\", \"core\", \"default\", \"mem\", \"rustc-dep-of-std\"]","declared_features":"[\"c\", \"cc\", \"compiler-builtins\", \"core\", \"default\", \"mangled-names\", \"mem\", \"no-asm\", \"no-f16-f128\", \"public-test-deps\", \"rustc-dep-of-std\"]","target":5408242616063297496,"profile":15657897354478470176,"path":1296201966205883023,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/compiler_builtins-96bb72fd3eed954b/dep-build-script-build-script-build","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}
|
|
||||||
BIN
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
This file has an mtime of when this was started.
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
a81848289b37bda7
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
{"rustc":5637828655848808591,"features":"[]","declared_features":"[]","target":5408242616063297496,"profile":8731458305071235362,"path":11588123521703303381,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/foundryos_kernel-4c0b4334571dcf0e/dep-build-script-build-script-build","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}
|
|
||||||
BIN
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
This file has an mtime of when this was started.
|
|
||||||
Binary file not shown.
BIN
Binary file not shown.
-6
@@ -1,6 +0,0 @@
|
|||||||
/home/zxq5/Projects/OSDev/FoundryOS/kernel/./target/debug/build/compiler_builtins-96bb72fd3eed954b/build_script_build-96bb72fd3eed954b: /home/zxq5/.cargo/bin/registry/src/index.crates.io-1949cf8c6b5b557f/compiler_builtins-0.1.146/build.rs /home/zxq5/.cargo/bin/registry/src/index.crates.io-1949cf8c6b5b557f/compiler_builtins-0.1.146/configure.rs
|
|
||||||
|
|
||||||
/home/zxq5/Projects/OSDev/FoundryOS/kernel/./target/debug/build/compiler_builtins-96bb72fd3eed954b/build_script_build-96bb72fd3eed954b.d: /home/zxq5/.cargo/bin/registry/src/index.crates.io-1949cf8c6b5b557f/compiler_builtins-0.1.146/build.rs /home/zxq5/.cargo/bin/registry/src/index.crates.io-1949cf8c6b5b557f/compiler_builtins-0.1.146/configure.rs
|
|
||||||
|
|
||||||
/home/zxq5/.cargo/bin/registry/src/index.crates.io-1949cf8c6b5b557f/compiler_builtins-0.1.146/build.rs:
|
|
||||||
/home/zxq5/.cargo/bin/registry/src/index.crates.io-1949cf8c6b5b557f/compiler_builtins-0.1.146/configure.rs:
|
|
||||||
Binary file not shown.
BIN
Binary file not shown.
-5
@@ -1,5 +0,0 @@
|
|||||||
/home/zxq5/Projects/OSDev/FoundryOS/kernel/./target/debug/build/foundryos_kernel-4c0b4334571dcf0e/build_script_build-4c0b4334571dcf0e: kernel/build.rs
|
|
||||||
|
|
||||||
/home/zxq5/Projects/OSDev/FoundryOS/kernel/./target/debug/build/foundryos_kernel-4c0b4334571dcf0e/build_script_build-4c0b4334571dcf0e.d: kernel/build.rs
|
|
||||||
|
|
||||||
kernel/build.rs:
|
|
||||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"llvm-target": "x86_64-unknown-none",
|
||||||
|
"data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
|
||||||
|
"arch": "x86_64",
|
||||||
|
"target-endian": "little",
|
||||||
|
"target-pointer-width": "64",
|
||||||
|
"target-c-int-width": "32",
|
||||||
|
"os": "none",
|
||||||
|
"executables": true,
|
||||||
|
"linker-flavor": "ld.lld",
|
||||||
|
"linker": "rust-lld",
|
||||||
|
"panic-strategy": "abort",
|
||||||
|
"disable-redzone": true,
|
||||||
|
"features": "-mmx,-sse,+soft-float",
|
||||||
|
"rustc-abi": "x86-softfloat",
|
||||||
|
"relocation-model": "static",
|
||||||
|
"code-model": "kernel",
|
||||||
|
"pre-link-args": {
|
||||||
|
"ld.lld": [
|
||||||
|
"--script=kernel/linker.ld",
|
||||||
|
"-nostdlib",
|
||||||
|
"--no-dynamic-linker",
|
||||||
|
"-static",
|
||||||
|
"--no-pie",
|
||||||
|
"--gc-sections",
|
||||||
|
"--build-id=none",
|
||||||
|
"-z",
|
||||||
|
"max-page-size=0x1000"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
[package]
|
||||||
|
name = "libk"
|
||||||
|
publish = ["gitea"]
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
description = "A library crate used to write the kernel for Foundry OS."
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
limine = "0.3.1"
|
||||||
|
x86_64 = "0.15.2"
|
||||||
|
crossbeam = { version = "0.8.4", default-features = false, features = [
|
||||||
|
"alloc",
|
||||||
|
"crossbeam-queue",
|
||||||
|
] }
|
||||||
|
pc-keyboard = "0.8.0"
|
||||||
|
spin = "0.9.8"
|
||||||
|
futures-util = { version = "0.3.31", default-features = false, features = [
|
||||||
|
"alloc",
|
||||||
|
] }
|
||||||
|
linked_list_allocator = "0.10.5"
|
||||||
|
libm = { path = "../libm" }
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# libk is for the code that did not make the kernel*
|
||||||
|
|
||||||
|
\*crate, lol.
|
||||||
|
|
||||||
|
libk is an attempt to move away from the godforsaken git submodules that plagued our forefathers. Now we have a crate containing a bunch of code that didn't quite make the core kernel crate, which should be:
|
||||||
|
|
||||||
|
* simpler to maintain
|
||||||
|
* has a catchier name
|
||||||
|
* less fighting with Cargo.toml manifests
|
||||||
|
|
||||||
|
## TODO:
|
||||||
|
|
||||||
|
A lot of things must be improved and worked on, feel free to add extra TODOs below.
|
||||||
|
|
||||||
|
[] Create a kernel logging abstraction similar to Linux. (this should probably just use the serial drivers)
|
||||||
|
|
||||||
|
The rationale behind this is that we want some sort of debug log/tracing support so we aren't just printf debugging forever.
|
||||||
|
|
||||||
|
## Authors
|
||||||
|
|
||||||
|
Again, write your name below if you like:
|
||||||
|
|
||||||
|
* @zxq5 (wrote most of the libraries as of 23/02/25)
|
||||||
|
* @nullndvoid (made this lushious library crate)
|
||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
|||||||
|
pub mod task;
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
//! Allows creation of asynchronous IO bound tasks.
|
||||||
|
//!
|
||||||
|
//! Written by @zxq5 for the most part with code from
|
||||||
|
//! [here](https://github.com/phil-opp/blog_os/).
|
||||||
|
//!
|
||||||
|
use crate::prelude::*;
|
||||||
|
use alloc::collections::BTreeMap;
|
||||||
|
use alloc::sync::Arc;
|
||||||
|
use alloc::task::Wake;
|
||||||
|
use core::{
|
||||||
|
future::Future,
|
||||||
|
pin::Pin,
|
||||||
|
sync::atomic::AtomicU64,
|
||||||
|
task::{Context, Poll, Waker},
|
||||||
|
};
|
||||||
|
use crossbeam::queue::ArrayQueue;
|
||||||
|
use x86_64::instructions::interrupts::{self, enable_and_hlt};
|
||||||
|
|
||||||
|
pub struct Task {
|
||||||
|
id: TaskId,
|
||||||
|
future: Pin<Box<dyn Future<Output = ()>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Task {
|
||||||
|
pub fn new(future: impl Future<Output = ()> + 'static) -> Self {
|
||||||
|
Self {
|
||||||
|
id: TaskId::new(),
|
||||||
|
future: Box::pin(future),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll(&mut self, context: &mut Context) -> Poll<()> {
|
||||||
|
self.future.as_mut().poll(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
struct TaskId(u64);
|
||||||
|
|
||||||
|
impl TaskId {
|
||||||
|
fn new() -> Self {
|
||||||
|
static NEXT: AtomicU64 = AtomicU64::new(0);
|
||||||
|
Self(NEXT.fetch_add(1, core::sync::atomic::Ordering::Relaxed))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Executor {
|
||||||
|
tasks: BTreeMap<TaskId, Task>,
|
||||||
|
task_queue: Arc<ArrayQueue<TaskId>>,
|
||||||
|
waker_cache: BTreeMap<TaskId, Waker>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Executor {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
tasks: BTreeMap::new(),
|
||||||
|
task_queue: Arc::new(ArrayQueue::new(100)),
|
||||||
|
waker_cache: BTreeMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn spawn(&mut self, task: Task) {
|
||||||
|
let task_id = task.id;
|
||||||
|
if self.tasks.insert(task.id, task).is_some() {
|
||||||
|
panic!("task with same id already in tasks");
|
||||||
|
}
|
||||||
|
self.task_queue.push(task_id).expect("queue full");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_ready_tasks(&mut self) {
|
||||||
|
// destructure `self` to avoid borrow checker errors
|
||||||
|
let Self {
|
||||||
|
tasks,
|
||||||
|
task_queue,
|
||||||
|
waker_cache,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
while let Some(task_id) = task_queue.pop() {
|
||||||
|
let task = match tasks.get_mut(&task_id) {
|
||||||
|
Some(task) => task,
|
||||||
|
None => continue, // task no longer exists
|
||||||
|
};
|
||||||
|
let waker = waker_cache
|
||||||
|
.entry(task_id)
|
||||||
|
.or_insert_with(|| TaskWaker::new_waker(task_id, task_queue.clone()));
|
||||||
|
let mut context = Context::from_waker(waker);
|
||||||
|
match task.poll(&mut context) {
|
||||||
|
Poll::Ready(()) => {
|
||||||
|
// task done -> remove it and its cached waker
|
||||||
|
tasks.remove(&task_id);
|
||||||
|
waker_cache.remove(&task_id);
|
||||||
|
}
|
||||||
|
Poll::Pending => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run(&mut self) -> ! {
|
||||||
|
loop {
|
||||||
|
self.run_ready_tasks();
|
||||||
|
self.sleep_if_idle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sleep_if_idle(&self) {
|
||||||
|
interrupts::disable();
|
||||||
|
if self.task_queue.is_empty() {
|
||||||
|
enable_and_hlt();
|
||||||
|
} else {
|
||||||
|
interrupts::enable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Executor {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TaskWaker {
|
||||||
|
task_id: TaskId,
|
||||||
|
task_queue: Arc<ArrayQueue<TaskId>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TaskWaker {
|
||||||
|
fn wake_task(&self) {
|
||||||
|
self.task_queue.push(self.task_id).expect("task_queue full");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_waker(task_id: TaskId, task_queue: Arc<ArrayQueue<TaskId>>) -> Waker {
|
||||||
|
Waker::from(Arc::new(Self {
|
||||||
|
task_id,
|
||||||
|
task_queue,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Wake for TaskWaker {
|
||||||
|
fn wake(self: Arc<Self>) {
|
||||||
|
self.wake_task();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wake_by_ref(self: &Arc<Self>) {
|
||||||
|
self.wake_task();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,235 @@
|
|||||||
|
use core::fmt;
|
||||||
|
use spin::{Lazy, Mutex};
|
||||||
|
use x86_64::instructions::interrupts;
|
||||||
|
|
||||||
|
use super::framebuffer::{colour::Colour, display::FRAMEBUFFER_WRITER};
|
||||||
|
|
||||||
|
use crate::resources::font::{FONT_SPLEEN_8X16, Font};
|
||||||
|
|
||||||
|
static FONT_WIDTH: u32 = 8;
|
||||||
|
static FONT_HEIGHT: u32 = 16;
|
||||||
|
|
||||||
|
pub static WRITER: Lazy<Mutex<Writer>> = Lazy::new(|| Mutex::new(Writer::new()));
|
||||||
|
|
||||||
|
pub fn screensize_chars() -> (u32, u32) {
|
||||||
|
let writer = WRITER.lock();
|
||||||
|
(writer.screen_width, writer.screen_height)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Writer {
|
||||||
|
font: &'static Font,
|
||||||
|
/// Measured in chars not pixels.
|
||||||
|
screen_width: u32,
|
||||||
|
/// Measured in chars not pixels.
|
||||||
|
screen_height: u32,
|
||||||
|
/// 16 pixels tall.
|
||||||
|
text_line: u32,
|
||||||
|
/// 8 pixels wide.
|
||||||
|
text_col: u32,
|
||||||
|
|
||||||
|
fg_color: Colour,
|
||||||
|
bg_color: Colour,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Writer {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Writer {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
FRAMEBUFFER_WRITER.lock().as_mut().map_or_else(
|
||||||
|
|| {
|
||||||
|
panic!("Framebuffer writer not initialized.");
|
||||||
|
},
|
||||||
|
|writer| Self {
|
||||||
|
font: &FONT_SPLEEN_8X16,
|
||||||
|
screen_width: writer.width() / 8,
|
||||||
|
screen_height: writer.height() / 16,
|
||||||
|
text_line: 0,
|
||||||
|
text_col: 0,
|
||||||
|
fg_color: Colour::White,
|
||||||
|
bg_color: Colour::Black,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn set_font(&mut self, font: &'static Font) {
|
||||||
|
self.font = font;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This is sent when the user types a backspace.
|
||||||
|
const BACKSPACE: u8 = 8;
|
||||||
|
|
||||||
|
pub fn write_glyph(&mut self, c: u8) {
|
||||||
|
if c == b'\n' {
|
||||||
|
self.newline();
|
||||||
|
return;
|
||||||
|
} else if c == Self::BACKSPACE {
|
||||||
|
self.backspace();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the character data from the font array. -- each byte is a row of pixels
|
||||||
|
let data: &[u8] = &self.font.glyphs[c as usize];
|
||||||
|
|
||||||
|
if let Some(writer) = FRAMEBUFFER_WRITER.lock().as_mut() {
|
||||||
|
for (row, line) in data.iter().enumerate().take(16) {
|
||||||
|
for col in 0..8 {
|
||||||
|
let pixel_x: u32 = self.text_col * FONT_WIDTH + col;
|
||||||
|
let pixel_y: u32 = self.text_line * FONT_HEIGHT + row as u32;
|
||||||
|
|
||||||
|
if line & (0x80 >> col) != 0 {
|
||||||
|
// Write the foreground color
|
||||||
|
writer.write_pixel(pixel_x as usize, pixel_y as usize, self.fg_color);
|
||||||
|
} else {
|
||||||
|
// Write the background color
|
||||||
|
writer.write_pixel(pixel_x as usize, pixel_y as usize, self.bg_color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go to next position
|
||||||
|
if self.text_col + 1 >= self.screen_width {
|
||||||
|
self.newline();
|
||||||
|
} else {
|
||||||
|
self.text_col += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn dimensions(&self) -> (u32, u32) {
|
||||||
|
(self.screen_width, self.screen_height)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn next_char(&mut self) {
|
||||||
|
self.text_col += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn newline(&mut self) {
|
||||||
|
self.text_col = 0;
|
||||||
|
|
||||||
|
if self.text_line + 1 >= self.screen_height {
|
||||||
|
self.text_line = 0;
|
||||||
|
} else {
|
||||||
|
self.text_line += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Handles the backspace character. TODO: Implement VT-100 style terminal control
|
||||||
|
/// codes alongside a shell. Not simple.
|
||||||
|
pub fn backspace(&mut self) {
|
||||||
|
if self.text_col > 0 {
|
||||||
|
self.text_col -= 1;
|
||||||
|
// Blank out the previous char.
|
||||||
|
self.write_glyph(b' ');
|
||||||
|
self.text_col -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_string(&mut self, s: &str) {
|
||||||
|
for c in s.chars() {
|
||||||
|
self.write_glyph(c as u8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn set_colour(&mut self, fg: Colour, bg: Colour) {
|
||||||
|
self.fg_color = fg;
|
||||||
|
self.bg_color = bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn reset_colour(&mut self) {
|
||||||
|
self.fg_color = Colour::White;
|
||||||
|
self.bg_color = Colour::Black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl core::fmt::Write for Writer {
|
||||||
|
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||||
|
self.write_string(s);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(args: fmt::Arguments, fg: Colour, bg: Colour) {
|
||||||
|
use core::fmt::Write;
|
||||||
|
|
||||||
|
interrupts::without_interrupts(|| {
|
||||||
|
let mut writer = WRITER.lock();
|
||||||
|
writer.set_colour(fg, bg);
|
||||||
|
writer.write_fmt(args).unwrap();
|
||||||
|
writer.reset_colour();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn _print(args: fmt::Arguments) {
|
||||||
|
x86_64::instructions::interrupts::without_interrupts(|| {
|
||||||
|
write(args, Colour::White, Colour::Black);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn _print_err(args: fmt::Arguments) {
|
||||||
|
x86_64::instructions::interrupts::without_interrupts(|| {
|
||||||
|
write(args, Colour::Red, Colour::Black);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn _print_log(args: fmt::Arguments) {
|
||||||
|
x86_64::instructions::interrupts::without_interrupts(|| {
|
||||||
|
write(args, Colour::Yellow, Colour::Black);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_screen() {
|
||||||
|
interrupts::without_interrupts(|| {
|
||||||
|
let mut writer = WRITER.lock();
|
||||||
|
writer.text_line = 0;
|
||||||
|
writer.text_col = 0;
|
||||||
|
|
||||||
|
if let Some(writer) = FRAMEBUFFER_WRITER.lock().as_mut() {
|
||||||
|
writer.clear();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset_cursor() {
|
||||||
|
interrupts::without_interrupts(|| {
|
||||||
|
let mut writer = WRITER.lock();
|
||||||
|
writer.text_line = 0;
|
||||||
|
writer.text_col = 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! println_log {
|
||||||
|
() => ($crate::print_log!("\n"));
|
||||||
|
($($arg:tt)*) => ($crate::print_log!("{}\n", format_args!($($arg)*)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! print_log {
|
||||||
|
($($arg:tt)*) => ($crate::_print_log(format_args!($($arg)*)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! println {
|
||||||
|
() => ($crate::print!("\n"));
|
||||||
|
($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! print {
|
||||||
|
($($arg:tt)*) => ($crate::_print(format_args!($($arg)*)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! printlnerr {
|
||||||
|
() => ($crate::printerr!("\n"));
|
||||||
|
($($arg:tt)*) => ($crate::printerr!("{}\n", format_args!($($arg)*)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! printerr {
|
||||||
|
($($arg:tt)*) => ($crate::_print_err(format_args!($($arg)*)));
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
#[repr(u32)]
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
|
pub enum Colour {
|
||||||
|
ARGB(u8, u8, u8, u8),
|
||||||
|
RGB(u8, u8, u8),
|
||||||
|
HexARGB(u32),
|
||||||
|
Black = 0x000000FF,
|
||||||
|
Blue = 0x0000FFFF,
|
||||||
|
Green = 0x00FF00FF,
|
||||||
|
Cyan = 0x00FFFFFF,
|
||||||
|
Red = 0xFF0000FF,
|
||||||
|
Magenta = 0xFF00FFFF,
|
||||||
|
Yellow = 0xFFFF00FF,
|
||||||
|
White = 0xFFFFFFFF,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::use_self)]
|
||||||
|
impl From<Colour> for u32 {
|
||||||
|
fn from(val: Colour) -> Self {
|
||||||
|
match val {
|
||||||
|
Colour::ARGB(a, r, g, b) => {
|
||||||
|
(a as u32) << 24 | (r as u32) << 16 | (g as u32) << 8 | (b as u32)
|
||||||
|
}
|
||||||
|
Colour::RGB(r, g, b) => ((r as u32) << 16) | (g as u32) << 8 | (b as u32),
|
||||||
|
Colour::HexARGB(hex) => hex,
|
||||||
|
Colour::Black => 0xFF000000,
|
||||||
|
Colour::Blue => 0xFF0000FF,
|
||||||
|
Colour::Green => 0xFF00FF00,
|
||||||
|
Colour::Cyan => 0xFF00FFFF,
|
||||||
|
Colour::Red => 0xFFFF0000,
|
||||||
|
Colour::Magenta => 0xFFFF00FF,
|
||||||
|
Colour::Yellow => 0xFFFFFF00,
|
||||||
|
Colour::White => 0xFFFFFFFF,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl core::fmt::Display for Colour {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::ARGB(r, g, b, a) => write!(f, "RGBA(#{:x}{:x}{:x}{:x})", r, g, b, a),
|
||||||
|
Self::RGB(r, g, b) => write!(f, "RGB(#{:x}{:x}{:x})", r, g, b),
|
||||||
|
Self::HexARGB(hex) => write!(f, "Hex(#{:x})", hex),
|
||||||
|
Self::Black => write!(f, "Black"),
|
||||||
|
Self::Blue => write!(f, "Blue"),
|
||||||
|
Self::Green => write!(f, "Green"),
|
||||||
|
Self::Cyan => write!(f, "Cyan"),
|
||||||
|
Self::Red => write!(f, "Red"),
|
||||||
|
Self::Magenta => write!(f, "Magenta"),
|
||||||
|
Self::Yellow => write!(f, "Yellow"),
|
||||||
|
Self::White => write!(f, "White"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
use limine::request::FramebufferRequest;
|
||||||
|
|
||||||
|
#[used]
|
||||||
|
#[unsafe(link_section = ".requests")]
|
||||||
|
static FRAMEBUFFER_REQUEST: FramebufferRequest = FramebufferRequest::new();
|
||||||
|
|
||||||
|
use super::colour::Colour;
|
||||||
|
use core::panic;
|
||||||
|
|
||||||
|
use limine::framebuffer::Framebuffer;
|
||||||
|
use spin::{Lazy, Mutex};
|
||||||
|
|
||||||
|
pub static FRAMEBUFFER_WRITER: Lazy<Mutex<Option<FramebufferWriter>>> = Lazy::new(|| {
|
||||||
|
Mutex::new(FRAMEBUFFER_REQUEST.get_response().map_or_else(
|
||||||
|
|| {
|
||||||
|
panic!("Framebuffer request failed");
|
||||||
|
},
|
||||||
|
|framebuffer_response| {
|
||||||
|
let framebuffer = framebuffer_response.framebuffers().next().unwrap();
|
||||||
|
Some(FramebufferWriter::new(framebuffer))
|
||||||
|
},
|
||||||
|
))
|
||||||
|
});
|
||||||
|
|
||||||
|
/// The updated writer stores necessary fields from the [Framebuffer].
|
||||||
|
/// This ensures that the contained types are Send, as Framebuffer was
|
||||||
|
/// not marked as Send.
|
||||||
|
///
|
||||||
|
/// It also avoids the requirement for lifetimes.
|
||||||
|
///
|
||||||
|
/// Note this does not implement Writer as these functions only handle drawing pixels.
|
||||||
|
pub struct FramebufferWriter {
|
||||||
|
pitch: u64,
|
||||||
|
bpp: u16,
|
||||||
|
addr: *mut u8,
|
||||||
|
width: u64,
|
||||||
|
height: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for FramebufferWriter {}
|
||||||
|
unsafe impl Sync for FramebufferWriter {}
|
||||||
|
|
||||||
|
impl FramebufferWriter {
|
||||||
|
pub fn new(framebuffer: Framebuffer) -> Self {
|
||||||
|
Self {
|
||||||
|
pitch: framebuffer.pitch(),
|
||||||
|
bpp: framebuffer.bpp(),
|
||||||
|
addr: framebuffer.addr(),
|
||||||
|
width: framebuffer.width(),
|
||||||
|
height: framebuffer.height(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_pixel(&self, x: usize, y: usize, color: Colour) {
|
||||||
|
let pitch = self.pitch as usize;
|
||||||
|
let bpp = (self.bpp / 8) as usize;
|
||||||
|
let pixel_offset = y * pitch + x * bpp;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
*(self.addr.add(pixel_offset) as *mut u32) = color.into();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_frame(&self, buffer: &[Colour; 1280 * 800]) {
|
||||||
|
for (y, row) in buffer.chunks(1280).enumerate() {
|
||||||
|
for (x, pixel) in row.iter().enumerate() {
|
||||||
|
self.write_pixel(x, y, *pixel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn width(&self) -> u32 {
|
||||||
|
self.width as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn height(&self) -> u32 {
|
||||||
|
self.height as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear(&self) {
|
||||||
|
let width = self.width as usize;
|
||||||
|
let height = self.height as usize;
|
||||||
|
|
||||||
|
for y in 0..height {
|
||||||
|
for x in 0..width {
|
||||||
|
self.write_pixel(x, y, Colour::Black);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn screensize_px() -> (u32, u32) {
|
||||||
|
FRAMEBUFFER_WRITER
|
||||||
|
.lock()
|
||||||
|
.as_mut()
|
||||||
|
.map_or_else(|| (0, 0), |writer| (writer.width(), writer.height()))
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
pub mod colour;
|
||||||
|
pub mod display;
|
||||||
@@ -0,0 +1,206 @@
|
|||||||
|
use core::{
|
||||||
|
pin::Pin,
|
||||||
|
task::{Context, Poll},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crossbeam::queue::ArrayQueue;
|
||||||
|
use futures_util::{Stream, StreamExt, task::AtomicWaker};
|
||||||
|
use pc_keyboard::{
|
||||||
|
DecodedKey, HandleControl, KeyCode, Keyboard, ScancodeSet1,
|
||||||
|
layouts::{self, Uk105Key},
|
||||||
|
};
|
||||||
|
use spin::{Lazy, Mutex, Once};
|
||||||
|
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
static KBD_QUEUE: Once<ArrayQueue<u8>> = Once::new();
|
||||||
|
static WAKER: AtomicWaker = AtomicWaker::new();
|
||||||
|
|
||||||
|
pub static KEYBOARD: Lazy<Mutex<Keyboard<Uk105Key, ScancodeSet1>>> = Lazy::new(|| {
|
||||||
|
Mutex::new(Keyboard::new(
|
||||||
|
ScancodeSet1::new(),
|
||||||
|
// TODO: Expose an API to change the default KB layout.
|
||||||
|
layouts::Uk105Key,
|
||||||
|
HandleControl::Ignore,
|
||||||
|
))
|
||||||
|
});
|
||||||
|
pub static SCANCODE_STREAM: Lazy<Mutex<ScancodeStream>> =
|
||||||
|
Lazy::new(|| Mutex::new(ScancodeStream::new()));
|
||||||
|
|
||||||
|
pub fn add_scancode(scancode: u8) {
|
||||||
|
if let Some(queue) = KBD_QUEUE.get() {
|
||||||
|
if queue.push(scancode).is_err() {
|
||||||
|
println!("WARNING: scancode queue full; dropping keyboard input");
|
||||||
|
} else {
|
||||||
|
WAKER.wake();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!("WARNING: scancode queue not initialized");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ScancodeStream {
|
||||||
|
_private: (),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ScancodeStream {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
KBD_QUEUE.call_once(|| ArrayQueue::new(5));
|
||||||
|
Self { _private: () }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_next(&mut self) -> Option<u8> {
|
||||||
|
KBD_QUEUE.get().and_then(|queue| queue.pop())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ScancodeStream {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Stream for ScancodeStream {
|
||||||
|
type Item = u8;
|
||||||
|
|
||||||
|
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||||
|
let queue = KBD_QUEUE.get().unwrap();
|
||||||
|
|
||||||
|
if let Some(scancode) = queue.pop() {
|
||||||
|
return Poll::Ready(Some(scancode));
|
||||||
|
}
|
||||||
|
|
||||||
|
WAKER.register(cx.waker());
|
||||||
|
WAKER.register(cx.waker());
|
||||||
|
|
||||||
|
queue.pop().map_or(Poll::Pending, |scancode| {
|
||||||
|
WAKER.take();
|
||||||
|
Poll::Ready(Some(scancode))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_keystroke_async() -> KeyStroke {
|
||||||
|
loop {
|
||||||
|
if let Some(scancode) = SCANCODE_STREAM.lock().next().await {
|
||||||
|
if let Ok(keystroke) = KeyStroke::try_from(scancode) {
|
||||||
|
return keystroke;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_keystroke_optional() -> Option<KeyStroke> {
|
||||||
|
if let Some(scancode) = SCANCODE_STREAM.lock().try_next() {
|
||||||
|
if let Ok(keystroke) = KeyStroke::try_from(scancode) {
|
||||||
|
return Some(keystroke);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum KeyStroke {
|
||||||
|
Char(char),
|
||||||
|
Ctrl,
|
||||||
|
RCtrl,
|
||||||
|
Alt,
|
||||||
|
RAlt,
|
||||||
|
Shift,
|
||||||
|
RShift,
|
||||||
|
Meta,
|
||||||
|
RMeta,
|
||||||
|
Backspace,
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
Up,
|
||||||
|
Down,
|
||||||
|
None,
|
||||||
|
Enter,
|
||||||
|
Escape,
|
||||||
|
Del,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KeyStroke {
|
||||||
|
pub const fn from_keycode(key: KeyCode) -> Self {
|
||||||
|
match key {
|
||||||
|
KeyCode::LControl => Self::Ctrl,
|
||||||
|
KeyCode::RControl => Self::RCtrl,
|
||||||
|
KeyCode::LAlt => Self::Alt,
|
||||||
|
KeyCode::RAlt2 => Self::RAlt,
|
||||||
|
KeyCode::LShift => Self::Shift,
|
||||||
|
KeyCode::RShift => Self::RShift,
|
||||||
|
KeyCode::LWin => Self::Meta,
|
||||||
|
KeyCode::RWin => Self::RMeta,
|
||||||
|
KeyCode::Backspace => Self::Backspace,
|
||||||
|
KeyCode::ArrowLeft => Self::Left,
|
||||||
|
KeyCode::ArrowRight => Self::Right,
|
||||||
|
KeyCode::ArrowUp => Self::Up,
|
||||||
|
KeyCode::ArrowDown => Self::Down,
|
||||||
|
KeyCode::Return => Self::Enter,
|
||||||
|
KeyCode::Escape => Self::Escape,
|
||||||
|
KeyCode::Delete => Self::Del,
|
||||||
|
_ => Self::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<u8> for KeyStroke {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(code: u8) -> Result<Self, Self::Error> {
|
||||||
|
let mut keyboard = KEYBOARD.lock();
|
||||||
|
|
||||||
|
let key = match keyboard.add_byte(code) {
|
||||||
|
Ok(Some(event)) => match keyboard.process_keyevent(event) {
|
||||||
|
Some(key) => key,
|
||||||
|
_ => return Err(()),
|
||||||
|
},
|
||||||
|
_ => return Err(()),
|
||||||
|
};
|
||||||
|
|
||||||
|
match key {
|
||||||
|
DecodedKey::Unicode(ch) => Ok(Self::Char(ch)),
|
||||||
|
DecodedKey::RawKey(key) => match Self::from_keycode(key) {
|
||||||
|
Self::None => Err(()),
|
||||||
|
key => Ok(key),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryInto<char> for KeyStroke {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_into(self) -> Result<char, Self::Error> {
|
||||||
|
match self {
|
||||||
|
Self::Char(c) => Ok(c),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl core::fmt::Display for KeyStroke {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Char(c) => write!(f, "{}", c),
|
||||||
|
Self::Ctrl => write!(f, "CTRL"),
|
||||||
|
Self::RCtrl => write!(f, "RCtrl"),
|
||||||
|
Self::Alt => write!(f, "ALT"),
|
||||||
|
Self::RAlt => write!(f, "RAlt"),
|
||||||
|
Self::Shift => write!(f, "SHIFT"),
|
||||||
|
Self::RShift => write!(f, "RShift"),
|
||||||
|
Self::Meta => write!(f, "META"),
|
||||||
|
Self::RMeta => write!(f, "RMeta"),
|
||||||
|
Self::Backspace => write!(f, "BACKSPACE"),
|
||||||
|
Self::Left => write!(f, "LEFT"),
|
||||||
|
Self::Right => write!(f, "RIGHT"),
|
||||||
|
Self::Up => write!(f, "UP"),
|
||||||
|
Self::Down => write!(f, "DOWN"),
|
||||||
|
Self::Enter => write!(f, "ENTER"),
|
||||||
|
Self::Escape => write!(f, "ESCAPE"),
|
||||||
|
Self::None => write!(f, "NONE"),
|
||||||
|
Self::Del => write!(f, "DEL"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
pub mod ascii;
|
||||||
|
pub mod framebuffer;
|
||||||
|
pub mod keyboard;
|
||||||
|
pub mod port;
|
||||||
|
pub mod serial;
|
||||||
|
|
||||||
|
// Re-exported macro definitions.
|
||||||
|
|
||||||
|
pub use crate::print;
|
||||||
|
pub use crate::print_log;
|
||||||
|
pub use crate::printerr;
|
||||||
|
pub use crate::println;
|
||||||
|
pub use crate::println_log;
|
||||||
|
pub use crate::printlnerr;
|
||||||
|
|
||||||
|
pub use crate::serial_print;
|
||||||
|
pub use crate::serial_println;
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user