Compare commits
114 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9ed3b73df8 | |||
| ad5edb57db | |||
| 394e932b9c | |||
| fdd556f742 | |||
| 4bad44e475 | |||
| 096a66adbb | |||
| 53d325749d | |||
| 8a3e9e3afc | |||
| e38c20dbd3 | |||
| c8bb85364c | |||
| fe18004f7d | |||
| 192100be7a | |||
| 2915d0c879 | |||
| 9852cb14eb | |||
| db8dbff9f2 | |||
| 2178215a01 | |||
| 821759ec63 | |||
| 0b3dbed4be | |||
| 3b6e272fd2 | |||
| 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.json"
|
||||||
|
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
+14
@@ -0,0 +1,14 @@
|
|||||||
|
<?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" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/libk/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/libm/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
+11
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"rust-analyzer.cargo.allTargets": false,
|
||||||
|
"rust-analyzer.cargo.target": "x86_64-kernel.json",
|
||||||
|
"[rust]": {
|
||||||
|
"editor.defaultFormatter": "rust-lang.rust-analyzer",
|
||||||
|
"editor.formatOnSave": true
|
||||||
|
},
|
||||||
|
"rust-analyzer.check.command": "clippy",
|
||||||
|
"rust-analyzer.procMacro.attributes.enable": true,
|
||||||
|
"rust-analyzer.cargo.buildScripts.enable": true
|
||||||
|
}
|
||||||
Generated
+259
-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,133 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
|
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "foundryos_kernel"
|
name = "cc"
|
||||||
|
version = "1.2.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c"
|
||||||
|
dependencies = [
|
||||||
|
"shlex",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-queue",
|
||||||
|
"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",
|
||||||
|
"crossbeam",
|
||||||
|
"futures-util",
|
||||||
|
"libm",
|
||||||
"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 = "libm"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"darling",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -23,3 +158,126 @@ checksum = "9ca87cab008b8efeebdbe037cd4d1438037d48c5cb6fed939ffa5aa06315a321"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[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 = "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", "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
+3
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"cssTheme": "Dark Moss"
|
||||||
|
}
|
||||||
+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
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"id": "obsidian-excalidraw-plugin",
|
||||||
|
"name": "Excalidraw",
|
||||||
|
"version": "2.8.3",
|
||||||
|
"minAppVersion": "1.1.6",
|
||||||
|
"description": "An Obsidian plugin to edit and view Excalidraw drawings",
|
||||||
|
"author": "Zsolt Viczian",
|
||||||
|
"authorUrl": "https://www.zsolt.blog",
|
||||||
|
"fundingUrl": "https://ko-fi.com/zsolt",
|
||||||
|
"helpUrl": "https://github.com/zsviczian/obsidian-excalidraw-plugin#readme",
|
||||||
|
"isDesktopOnly": false
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
Vendored
+185
@@ -0,0 +1,185 @@
|
|||||||
|
{
|
||||||
|
"main": {
|
||||||
|
"id": "20da7b1c0adc4114",
|
||||||
|
"type": "split",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "c178a2dff57ae0aa",
|
||||||
|
"type": "tabs",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "6d395e6a4c72e1c8",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "markdown",
|
||||||
|
"state": {
|
||||||
|
"file": "Planning & To-Dos.md",
|
||||||
|
"mode": "source",
|
||||||
|
"source": false
|
||||||
|
},
|
||||||
|
"icon": "lucide-file",
|
||||||
|
"title": "Planning & To-Dos"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"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": "",
|
||||||
|
"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": 307.5
|
||||||
|
},
|
||||||
|
"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,
|
||||||
|
"collapsed": true
|
||||||
|
},
|
||||||
|
"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,
|
||||||
|
"command-palette:Open command palette": false,
|
||||||
|
"templates:Insert template": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"active": "6d395e6a4c72e1c8",
|
||||||
|
"lastOpenFiles": [
|
||||||
|
"Usage/Building The Kernel.md",
|
||||||
|
"Planning & To-Dos.md",
|
||||||
|
"structure/idk.canvas",
|
||||||
|
"structure/kernel.md",
|
||||||
|
"structure/libk.md",
|
||||||
|
"structure/libm.md",
|
||||||
|
"structure/libk",
|
||||||
|
"structure",
|
||||||
|
"Usage",
|
||||||
|
"Welcome.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,134 @@
|
|||||||
|
> [!todo] Testing
|
||||||
|
> - [ ] setup custom test frameworks (Use CrystalOS-V2 as a reference)
|
||||||
|
> - [ ] write a sub-crate for tests
|
||||||
|
> - [ ] implement several unit tests on things that we are likely to break often
|
||||||
|
> - [ ] setup Git CI/CD pipeline with testing
|
||||||
|
> - [ ] figure out how to run QEMU in the test environment
|
||||||
|
> - [ ] write a script to run tests
|
||||||
|
> - [ ] a release should only be published if all tests pass
|
||||||
|
>
|
||||||
|
> [!todo] HAL (Hardware Abstraction Layer)
|
||||||
|
> - [ ] use either traits or cfg attributes to support more than just x86_64
|
||||||
|
> - [ ] prefer writing cross platform code (I am aware I made the problem slightly worse by merging libk with the kernel sources)
|
||||||
|
>
|
||||||
|
> [!todo] Allocator
|
||||||
|
> - [ ] learn about several allocator designs and decide on the optimal one
|
||||||
|
> - [ ] implementation
|
||||||
|
> - [ ] implement an allocate method
|
||||||
|
> - [ ] implement a deallocate method
|
||||||
|
> - [ ] set the global allocator
|
||||||
|
> - [ ] testing
|
||||||
|
> - [ ] write unit tests
|
||||||
|
> - [ ] many allocations
|
||||||
|
> - [ ] large allocations
|
||||||
|
> - [ ] allocating more memory than is available
|
||||||
|
> - [ ] pass unit tests
|
||||||
|
|
||||||
|
> [!todo] Threading
|
||||||
|
> - [ ] implement thread switching functionality
|
||||||
|
> - [ ] switch stacks
|
||||||
|
> - [ ] implement multi-threading
|
||||||
|
> - [ ] figure out how to turn on another core
|
||||||
|
> - [ ] Scheduler
|
||||||
|
> - [ ] which task goes on which thread?
|
||||||
|
> - [ ] round robin / time slicing algorithm
|
||||||
|
> - [ ] switch tasks on a given core
|
||||||
|
> - [ ] push registers
|
||||||
|
> - [ ] switch stacks
|
||||||
|
> - [ ] ensure the scheduler knows where to find the stack for each thread
|
||||||
|
> - [ ] move a given task to a new core
|
||||||
|
> - [ ] differentiate between kernel threads and user threads
|
||||||
|
> - [ ] create syscall to create a new thread
|
||||||
|
|
||||||
|
> [!todo] Filesystem
|
||||||
|
> - [ ] AHCI Implementation
|
||||||
|
> - [ ] figure out what hard drives are attached
|
||||||
|
> - [ ] read data
|
||||||
|
> - [ ] write data
|
||||||
|
> - [ ] FAT32 Implementation
|
||||||
|
> - [ ] parse FAT header
|
||||||
|
> - [ ] figure out where files are / what files are what
|
||||||
|
> - [ ] parse file metadata / figure out type of file
|
||||||
|
> - [ ] reading the entirety of a file into memory
|
||||||
|
> - [ ] *(extension)* ext2 Implementation
|
||||||
|
> - [ ] Syscall API
|
||||||
|
> - [ ] provide a user program with file read / write access given a filename
|
||||||
|
> - [ ] translate a filename into a disk location of data & the size of the data
|
||||||
|
> - [ ] provide an interface to read from a file or write to a file
|
||||||
|
|
||||||
|
> [!todo] APIC
|
||||||
|
> - [ ] Enable APIC
|
||||||
|
> - [x] Get apic location from MSR
|
||||||
|
> - [x] Enable APIC bit flag
|
||||||
|
> - [x] Disable Legacy PIC
|
||||||
|
> - [ ] Map physical APIC address to virtual memory
|
||||||
|
>
|
||||||
|
>> [!error]
|
||||||
|
>> Page fault exception occurs when APIC is activated
|
||||||
|
>
|
||||||
|
>- [ ] Setup Interrupt handlers to handle interrupts generated by the APIC
|
||||||
|
> - [ ] Timer Interrupts
|
||||||
|
> - [ ] Keyboard Interrupts
|
||||||
|
|
||||||
|
> [!todo] Userspace (req: Threading, Filesystem)
|
||||||
|
> - [ ] Load program into memory from disk
|
||||||
|
> - [ ] requires:
|
||||||
|
> - [ ] Program Loader
|
||||||
|
> - [ ] Parse ELF File
|
||||||
|
> - [ ] Load file into memory
|
||||||
|
> - [ ] Filesystem
|
||||||
|
> - [ ] Scheduler (to start and manage the process)
|
||||||
|
> - [ ] Start a user process
|
||||||
|
> - [ ] switch stacks
|
||||||
|
> - [ ] jump to user code
|
||||||
|
|
||||||
|
>[!todo] User Interface
|
||||||
|
>- This will be a library so that programs in userspace can provide a user interface rather than relying on text commands from a basic terminal
|
||||||
|
>- features required:
|
||||||
|
> - [ ] Rendering frames to a display buffer
|
||||||
|
> - [ ] requires: Frame rendering Syscall
|
||||||
|
> - [ ] I/O
|
||||||
|
> - [ ] syncio
|
||||||
|
> - [ ] keystrokes
|
||||||
|
> - [ ] asyncio
|
||||||
|
> - [ ] keystrokes
|
||||||
|
> - [ ] requires: I/O Syscalls
|
||||||
|
> - [ ] Window struct
|
||||||
|
> - [ ] stores it's size and location
|
||||||
|
> - [ ] handles rendering pixels to the screen
|
||||||
|
> - [ ] Widgets
|
||||||
|
> - [ ] textbox / label
|
||||||
|
> - [ ] single line text input
|
||||||
|
> - [ ] how do we capture keyboard inputs?
|
||||||
|
> - [ ] multiline text input
|
||||||
|
> - [ ] how do we capture keyboard inputs?
|
||||||
|
> - [ ] button
|
||||||
|
> - [ ] dialog
|
||||||
|
> - [ ] box widget
|
||||||
|
> - [ ] figure out how to nest other widgets inside it
|
||||||
|
>```rust
|
||||||
|
>pub struct Window {
|
||||||
|
> position;
|
||||||
|
> dimensions;
|
||||||
|
>}
|
||||||
|
>
|
||||||
|
>impl Window {
|
||||||
|
> fn display(&self, frame: &Frame) -> Result<(), RenderError>;
|
||||||
|
>}
|
||||||
|
>
|
||||||
|
>pub struct Frame<'a> {
|
||||||
|
> window: &'a Window,
|
||||||
|
> data: <"... a suitable type to store pixels">
|
||||||
|
>}
|
||||||
|
>
|
||||||
|
>impl<'a> Frame<'a> {
|
||||||
|
> pub fn display(&self) -> Result<(), RenderError> {
|
||||||
|
> self.window.display(self)
|
||||||
|
> }
|
||||||
|
>}
|
||||||
|
>
|
||||||
|
> pub trait Widget {
|
||||||
|
> fn render(&self) -> Frame;
|
||||||
|
> }
|
||||||
|
>```
|
||||||
|
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"nodes":[
|
||||||
|
{"id":"8391ed519ab6cb3d","type":"group","x":-920,"y":600,"width":1595,"height":360,"label":"Hardware Layer"},
|
||||||
|
{"id":"967decfbdbf166e2","type":"group","x":-920,"y":120,"width":1595,"height":320,"label":"Kernel Layer (kernelspace)"},
|
||||||
|
{"id":"efd3cf75db396678","type":"group","x":-920,"y":-280,"width":1595,"height":240,"label":"System Layer (userspace)"},
|
||||||
|
{"id":"d577e6c4fa3d7479","type":"group","x":-920,"y":-600,"width":1595,"height":140,"label":"User Layer (userspace)"},
|
||||||
|
{"id":"549099b4188ff073","type":"text","text":"Interrupt handling & initialisation","x":-204,"y":320,"width":250,"height":60,"color":"2"},
|
||||||
|
{"id":"d0c73e9e86edba62","type":"text","text":"Kernel #kernel","x":-220,"y":260,"width":281,"height":140,"color":"2"},
|
||||||
|
{"id":"4fdc8ae730503ad0","type":"text","text":"libk #kernel","x":-880,"y":260,"width":280,"height":140,"color":"2"},
|
||||||
|
{"id":"4839a4f4f0980254","type":"text","text":"System Libraries #userspace","x":-220,"y":-240,"width":281,"height":160,"color":"3"},
|
||||||
|
{"id":"ba48ee2ccc891a62","type":"text","text":"Scheduler","x":-880,"y":160,"width":280,"height":60,"color":"2"},
|
||||||
|
{"id":"3d31fc276e0ba4a0","type":"text","text":"UI Shell #userspace","x":-880,"y":-560,"width":280,"height":60,"color":"4"},
|
||||||
|
{"id":"6b5e17c10589a7b6","type":"text","text":"Generic Application #userspace","x":-219,"y":-560,"width":281,"height":60,"color":"4"},
|
||||||
|
{"id":"0a47f47a2c7b3609","type":"text","text":"CPU #hardware","x":-880,"y":640,"width":280,"height":280,"color":"1"},
|
||||||
|
{"id":"a7002e4427f0540d","type":"text","text":"lib_io","x":-200,"y":-160,"width":122,"height":60,"color":"3"},
|
||||||
|
{"id":"e09d0bccffd19ed9","type":"text","text":"lib_ui","x":-78,"y":-160,"width":118,"height":60,"color":"3"},
|
||||||
|
{"id":"cbfeda8989b260d8","type":"text","text":"Userspace Drivers #userspace","x":360,"y":-240,"width":281,"height":160,"color":"3"},
|
||||||
|
{"id":"3acced35498279a0","type":"text","text":"Hardware #hardware\n- Display\n- Hard drives\n- Keyboard\n- Mouse","x":360,"y":640,"width":281,"height":280,"color":"1"},
|
||||||
|
{"id":"31548bb91b4977eb","type":"text","text":"Syscall API","x":-219,"y":160,"width":281,"height":60,"color":"2"},
|
||||||
|
{"id":"110b7bee2ba99819","type":"text","text":"Drivers & low level kernel libraries","x":-860,"y":320,"width":240,"height":60,"color":"2"}
|
||||||
|
],
|
||||||
|
"edges":[
|
||||||
|
{"id":"6a8d6b7540c2898d","fromNode":"3d31fc276e0ba4a0","fromSide":"right","toNode":"4839a4f4f0980254","toSide":"left","color":"3"},
|
||||||
|
{"id":"57aedf427a150ff1","fromNode":"6b5e17c10589a7b6","fromSide":"bottom","toNode":"4839a4f4f0980254","toSide":"top","color":"3","label":"Applications are statically \nlinked to system libraries"},
|
||||||
|
{"id":"d292a19f88032809","fromNode":"4839a4f4f0980254","fromSide":"bottom","toNode":"31548bb91b4977eb","toSide":"top","color":"2","label":"system libraries make syscalls"},
|
||||||
|
{"id":"8b437f1c08e1caf2","fromNode":"ba48ee2ccc891a62","fromSide":"top","toNode":"3d31fc276e0ba4a0","toSide":"bottom","color":"4","label":"Scheduler Starts\nUI in userspace"},
|
||||||
|
{"id":"3e2c6f6d5dcd7613","fromNode":"4839a4f4f0980254","fromSide":"right","toNode":"cbfeda8989b260d8","toSide":"left","color":"3"},
|
||||||
|
{"id":"88f6e95c288c933d","fromNode":"31548bb91b4977eb","fromSide":"top","toNode":"4839a4f4f0980254","toSide":"bottom","color":"2"},
|
||||||
|
{"id":"156c8a89b537e219","fromNode":"cbfeda8989b260d8","fromSide":"left","toNode":"4839a4f4f0980254","toSide":"right","color":"3","label":"some libs talk to\nhardware through\nuserspace drivers"},
|
||||||
|
{"id":"0d04c5b0f76a5d9b","fromNode":"cbfeda8989b260d8","fromSide":"bottom","toNode":"3acced35498279a0","toSide":"top","fromEnd":"arrow","color":"1","label":"Userspace drivers can talk\ndirectly to hardware so\nin the case of a driver crash\nthe kernel is unaffected"},
|
||||||
|
{"id":"e9f1afb45bf17b77","fromNode":"4fdc8ae730503ad0","fromSide":"bottom","toNode":"3acced35498279a0","toSide":"left","fromEnd":"arrow","color":"1","label":"Libk handles most hardware\ninteraction, keeping the core kernel codebase as minimal\nas possible"},
|
||||||
|
{"id":"99414d640e519c8c","fromNode":"4fdc8ae730503ad0","fromSide":"right","toNode":"d0c73e9e86edba62","toSide":"left","fromEnd":"arrow","color":"2","label":"kernel static linked to libk\nmost kernel functionality\nisfound in libk"},
|
||||||
|
{"id":"85cd865c914dd125","fromNode":"549099b4188ff073","fromSide":"top","toNode":"d0c73e9e86edba62","toSide":"top","color":"2"},
|
||||||
|
{"id":"e882694ec774c0d6","fromNode":"4fdc8ae730503ad0","fromSide":"top","toNode":"ba48ee2ccc891a62","toSide":"bottom","color":"2"},
|
||||||
|
{"id":"c689b667be8cdfab","fromNode":"d0c73e9e86edba62","fromSide":"top","toNode":"31548bb91b4977eb","toSide":"bottom","color":"2"},
|
||||||
|
{"id":"0c9da0cce11e4bd1","fromNode":"ba48ee2ccc891a62","fromSide":"bottom","toNode":"4fdc8ae730503ad0","toSide":"top","color":"2"},
|
||||||
|
{"id":"c45efb0ad498f8a8","fromNode":"ba48ee2ccc891a62","fromSide":"right","toNode":"6b5e17c10589a7b6","toSide":"left","color":"4","label":"Scheduler\nstarts applications"},
|
||||||
|
{"id":"aee2cd6ef9682f0f","fromNode":"31548bb91b4977eb","fromSide":"left","toNode":"ba48ee2ccc891a62","toSide":"right","color":"2","label":"system libs can talk to\nthe scheduler to manage\nprocesses"},
|
||||||
|
{"id":"b1b2b96d8ac2b490","fromNode":"4fdc8ae730503ad0","fromSide":"bottom","toNode":"0a47f47a2c7b3609","toSide":"top","fromEnd":"arrow","color":"1"}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
- contains all proc macros for building the kernel
|
||||||
|
|
||||||
|
## Current Features
|
||||||
|
### font importer:
|
||||||
|
- a macro that takes a filename to a font file and turns it into a font.
|
||||||
|
```rust
|
||||||
|
pub struct Font {
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
length: u16,
|
||||||
|
data: [[u8; 16]; 512],
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static FONT_CP850_8X16: Font =
|
||||||
|
Font::new(include_font!("./libk/resources/font/cp850-8x16.psf"));
|
||||||
|
```
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
[build]
|
|
||||||
target = "../customos"
|
|
||||||
target-dir = "./target"
|
|
||||||
|
|
||||||
[unstable]
|
|
||||||
build-std = ["core", "compiler_builtins"]
|
|
||||||
build-std-features = ["compiler-builtins-mem"]
|
|
||||||
+28
-3
@@ -1,7 +1,32 @@
|
|||||||
[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"
|
||||||
|
libm = { version = "0.1.0", path = "../libm" }
|
||||||
|
crossbeam = { version = "0.8.4", default-features = false, features = [
|
||||||
|
# "alloc",
|
||||||
|
"crossbeam-queue",
|
||||||
|
] }
|
||||||
|
futures-util = { version = "0.3.31", default-features = false, features = [
|
||||||
|
# "alloc",
|
||||||
|
] }
|
||||||
|
|
||||||
|
[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.*)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Binary file not shown.
Binary file not shown.
@@ -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,104 @@
|
|||||||
|
#![expect(unused)]
|
||||||
|
use core::arch::x86_64::__cpuid;
|
||||||
|
|
||||||
|
use spin::Lazy;
|
||||||
|
// use libk::drivers::memory::{FRAME_ALLOCATOR, FoundryOSFrameAllocator,
|
||||||
|
// OFFSET_PAGE_TABLE};
|
||||||
|
use x86_64::{
|
||||||
|
PhysAddr, VirtAddr,
|
||||||
|
structures::paging::{Page, PageTableFlags, PhysFrame, Size4KiB},
|
||||||
|
};
|
||||||
|
|
||||||
|
// use crate::serial_print;
|
||||||
|
|
||||||
|
use super::{cpu::msr::*, 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
|
||||||
|
|
||||||
|
static APIC_VIRTUAL_ADDRESS: Lazy<VirtAddr> = Lazy::new(|| {
|
||||||
|
let apic_base = get_apic_base();
|
||||||
|
|
||||||
|
unsafe { phys_to_virt(apic_base) }
|
||||||
|
});
|
||||||
|
|
||||||
|
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 };
|
||||||
|
}
|
||||||
|
|
||||||
|
const 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(|| panic!(" overflow"), VirtAddr::new)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enable_apic() {
|
||||||
|
// let mut mapper = OFFSET_PAGE_TABLE.get().unwrap().lock();
|
||||||
|
// let mut frame_allocator = FRAME_ALLOCATOR.get().unwrap().lock();
|
||||||
|
|
||||||
|
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, &mut *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_VIRTUAL_ADDRESS, 0xF0);
|
||||||
|
|
||||||
|
// serial_print!("ok2");
|
||||||
|
|
||||||
|
write_apic_register(&apic_virt, 0xF0, reg | 0x100);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Apic {}
|
||||||
|
|
||||||
|
pub enum ApicVector {}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
pub mod msr;
|
||||||
|
pub mod port;
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
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,38 @@
|
|||||||
|
//! Functions for IO using ports.
|
||||||
|
use core::arch::asm;
|
||||||
|
|
||||||
|
/// Take a byte in from a port.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// This might have side effects so it is marked unsafe just in case.
|
||||||
|
#[inline(always)]
|
||||||
|
pub unsafe fn inb(port: u16) -> u8 {
|
||||||
|
let value: u8;
|
||||||
|
unsafe {
|
||||||
|
asm!(
|
||||||
|
"in al, dx",
|
||||||
|
out("al") value,
|
||||||
|
in("dx") port,
|
||||||
|
options(nomem, nostack, preserves_flags)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Take a byte in from a port.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// This might have side effects so it is marked unsafe just in case.
|
||||||
|
#[inline(always)]
|
||||||
|
pub unsafe fn outb(port: u16, value: u8) {
|
||||||
|
unsafe {
|
||||||
|
asm!(
|
||||||
|
"out dx, al",
|
||||||
|
in("dx") port,
|
||||||
|
in("al") value,
|
||||||
|
options(nomem, nostack, preserves_flags)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
pub mod pic;
|
||||||
|
pub mod serial;
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
#![allow(clippy::missing_safety_doc)]
|
||||||
|
use x86_64::instructions::port::Port;
|
||||||
|
|
||||||
|
const CMD_INIT: u8 = 0x11;
|
||||||
|
const CMD_END_OF_INT: u8 = 0x20;
|
||||||
|
const MODE_8086: u8 = 0x01;
|
||||||
|
|
||||||
|
struct Pic {
|
||||||
|
offset: u8,
|
||||||
|
data: Port<u8>,
|
||||||
|
command: Port<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pic {
|
||||||
|
/// Are we in charge of handling the specified interrupt?
|
||||||
|
/// (Each PIC handles 8 interrupts.)
|
||||||
|
const fn handles_interrupt(&self, interrupt_id: u8) -> bool {
|
||||||
|
self.offset <= interrupt_id && interrupt_id < self.offset + 8
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Notify us that an interrupt has been handled and that we're ready
|
||||||
|
/// for more.
|
||||||
|
unsafe fn end_of_interrupt(&mut self) {
|
||||||
|
unsafe { self.command.write(CMD_END_OF_INT) };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reads the interrupt mask of this PIC.
|
||||||
|
unsafe fn read_mask(&mut self) -> u8 {
|
||||||
|
unsafe { self.data.read() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Writes the interrupt mask of this PIC.
|
||||||
|
unsafe fn write_mask(&mut self, mask: u8) {
|
||||||
|
unsafe { self.data.write(mask) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A pair of chained PICs. This is the standard setup on x86.
|
||||||
|
pub struct ChainedPics {
|
||||||
|
pics: [Pic; 2],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ChainedPics {
|
||||||
|
/// Creates a new [`ChainedPics`].
|
||||||
|
pub const fn new(offset1: u8, offset2: u8) -> Self {
|
||||||
|
Self {
|
||||||
|
pics: [
|
||||||
|
Pic {
|
||||||
|
offset: offset1,
|
||||||
|
command: Port::new(0x20),
|
||||||
|
data: Port::new(0x21),
|
||||||
|
},
|
||||||
|
Pic {
|
||||||
|
offset: offset2,
|
||||||
|
command: Port::new(0xA0),
|
||||||
|
data: Port::new(0xA1),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn new_contiguous(primary_offset: u8) -> Self {
|
||||||
|
Self::new(primary_offset, primary_offset + 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the initialize of this [`ChainedPics`].
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// .
|
||||||
|
pub unsafe fn initialize(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
let mut wait_port: Port<u8> = Port::new(0x80);
|
||||||
|
let mut wait = || wait_port.write(0);
|
||||||
|
|
||||||
|
// Save our original interrupt masks, because I'm too lazy to
|
||||||
|
// figure out reasonable values. We'll restore these when we're
|
||||||
|
// done.
|
||||||
|
let saved_masks = self.read_masks();
|
||||||
|
|
||||||
|
// Tell each PIC that we're going to send it a three-byte
|
||||||
|
// initialization sequence on its data port.
|
||||||
|
self.pics[0].command.write(CMD_INIT);
|
||||||
|
wait();
|
||||||
|
self.pics[1].command.write(CMD_INIT);
|
||||||
|
wait();
|
||||||
|
|
||||||
|
// Byte 1: Set up our base offsets.
|
||||||
|
self.pics[0].data.write(self.pics[0].offset);
|
||||||
|
wait();
|
||||||
|
self.pics[1].data.write(self.pics[1].offset);
|
||||||
|
wait();
|
||||||
|
|
||||||
|
// Byte 2: Configure chaining between PIC1 and PIC2.
|
||||||
|
self.pics[0].data.write(4);
|
||||||
|
wait();
|
||||||
|
self.pics[1].data.write(2);
|
||||||
|
wait();
|
||||||
|
|
||||||
|
// Byte 3: Set our mode.
|
||||||
|
self.pics[0].data.write(MODE_8086);
|
||||||
|
wait();
|
||||||
|
self.pics[1].data.write(MODE_8086);
|
||||||
|
wait();
|
||||||
|
|
||||||
|
// Restore our saved masks.
|
||||||
|
self.write_masks(saved_masks[0], saved_masks[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reads the interrupt masks of both PICs.
|
||||||
|
pub unsafe fn read_masks(&mut self) -> [u8; 2] {
|
||||||
|
unsafe { [self.pics[0].read_mask(), self.pics[1].read_mask()] }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Writes the interrupt masks of both PICs.
|
||||||
|
pub unsafe fn write_masks(&mut self, mask1: u8, mask2: u8) {
|
||||||
|
unsafe {
|
||||||
|
self.pics[0].write_mask(mask1);
|
||||||
|
self.pics[1].write_mask(mask2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Disables both PICs by masking all interrupts.
|
||||||
|
pub unsafe fn disable(&mut self) {
|
||||||
|
unsafe { self.write_masks(u8::MAX, u8::MAX) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Do we handle this interrupt?
|
||||||
|
pub fn handles_interrupt(&self, interrupt_id: u8) -> bool {
|
||||||
|
self.pics.iter().any(|p| p.handles_interrupt(interrupt_id))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Figure out which (if any) PICs in our chain need to know about this
|
||||||
|
/// interrupt. This is tricky, because all interrupts from `pics[1]`
|
||||||
|
/// get chained through `pics[0]`.
|
||||||
|
pub unsafe fn notify_end_of_interrupt(&mut self, interrupt_id: u8) {
|
||||||
|
if self.handles_interrupt(interrupt_id) {
|
||||||
|
if self.pics[1].handles_interrupt(interrupt_id) {
|
||||||
|
unsafe {
|
||||||
|
self.pics[1].end_of_interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
self.pics[0].end_of_interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,153 @@
|
|||||||
|
use crate::arch::x86_64::cpu::port::{inb, outb};
|
||||||
|
use core::{
|
||||||
|
fmt,
|
||||||
|
sync::atomic::{AtomicUsize, Ordering},
|
||||||
|
};
|
||||||
|
use spin::{Lazy, Mutex};
|
||||||
|
use x86_64::instructions::interrupts;
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! serial_print {
|
||||||
|
($($arg:tt)*) => ($crate::arch::x86_64::dev::serial::_serial_write(format_args!($($arg)*)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! serial_println {
|
||||||
|
() => ($crate::serial_print!("\n"));
|
||||||
|
($($arg:tt)*) => (serial_print!("{}\n", format_args!($($arg)*)));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn _serial_write(args: fmt::Arguments) {
|
||||||
|
use core::fmt::Write;
|
||||||
|
|
||||||
|
interrupts::without_interrupts(|| {
|
||||||
|
if let Some(writer) = WRITER.lock().as_mut() {
|
||||||
|
writer.write_fmt(args).unwrap();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn serial_read() -> &'static str {
|
||||||
|
serial_println!("getting value!");
|
||||||
|
|
||||||
|
interrupts::without_interrupts(|| {
|
||||||
|
if let Some(reader) = READER.lock().as_mut() {
|
||||||
|
serial_println!("stuff happnin.");
|
||||||
|
reader.read_str_to_buffer();
|
||||||
|
} else {
|
||||||
|
serial_println!("failed to get writer");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
serial_println!("eee");
|
||||||
|
|
||||||
|
let i = BUFFER_LEN.load(Ordering::SeqCst);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
if i != 0 {
|
||||||
|
core::str::from_utf8(&BUFFER[..i - 1]).unwrap()
|
||||||
|
} else {
|
||||||
|
serial_println!("empty string");
|
||||||
|
""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static PORT: u16 = 0x3f8;
|
||||||
|
static mut BUFFER: [u8; 256] = [0; 256];
|
||||||
|
static BUFFER_LEN: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
|
static READER: Lazy<Mutex<Option<Reader>>> = Lazy::new(|| Mutex::new(None));
|
||||||
|
static WRITER: Lazy<Mutex<Option<Writer>>> = Lazy::new(|| Mutex::new(None));
|
||||||
|
|
||||||
|
struct Reader;
|
||||||
|
|
||||||
|
struct Writer;
|
||||||
|
|
||||||
|
impl fmt::Write for Writer {
|
||||||
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||||
|
for c in s.chars() {
|
||||||
|
self.write_byte(c as u8);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Writer {
|
||||||
|
unsafe fn write_success(&self) -> bool {
|
||||||
|
unsafe { inb(PORT + 5) & 0x20 != 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_byte(&self, data: u8) {
|
||||||
|
unsafe {
|
||||||
|
while !self.write_success() {}
|
||||||
|
outb(PORT, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init() -> Result<(), &'static str> {
|
||||||
|
test()?;
|
||||||
|
|
||||||
|
if READER.lock().is_none() {
|
||||||
|
*READER.lock() = Some(Reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
if WRITER.lock().is_none() {
|
||||||
|
*WRITER.lock() = Some(Writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn test() -> Result<(), &'static str> {
|
||||||
|
unsafe { outb(PORT + 1, 0x00) }; // Disable all interrupts
|
||||||
|
unsafe { outb(PORT + 3, 0x80) }; // Enable DLAB (set baud rate divisor)
|
||||||
|
unsafe { outb(PORT, 0x03) }; // Set divisor to 3 (lo byte) 38400 baud
|
||||||
|
unsafe { outb(PORT + 1, 0x00) }; // (hi byte)
|
||||||
|
unsafe { outb(PORT + 3, 0x03) }; // 8 bits, no parity, one stop bit
|
||||||
|
unsafe { outb(PORT + 2, 0xC7) }; // Enable FIFO, clear them, with 14-bytethreshold
|
||||||
|
unsafe { outb(PORT + 4, 0x0B) }; // IRQs enabled, RTS/DSR set
|
||||||
|
unsafe { outb(PORT + 4, 0x1E) }; // Set in loopback mode, test the serial chip
|
||||||
|
unsafe { outb(PORT, 0xAE) }; // Test serial chip (send byte 0xAE and check if serial returns same byte)
|
||||||
|
|
||||||
|
if unsafe { inb(PORT) } != 0xAE {
|
||||||
|
return Err("Serial test failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe { outb(PORT + 4, 0x0F) };
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Reader {
|
||||||
|
pub fn read_str_to_buffer(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
while !self.read_ready() {}
|
||||||
|
|
||||||
|
BUFFER_LEN.store(0, Ordering::SeqCst);
|
||||||
|
|
||||||
|
while BUFFER_LEN.load(Ordering::SeqCst) < 256 {
|
||||||
|
let c = self.read();
|
||||||
|
BUFFER[BUFFER_LEN.load(Ordering::SeqCst)] = c;
|
||||||
|
if c as char == '\r' {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
BUFFER_LEN.fetch_add(1, Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
|
||||||
|
serial_println!("returning")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn read_ready(&self) -> bool {
|
||||||
|
unsafe { inb(PORT + 5) & 1 != 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read(&self) -> u8 {
|
||||||
|
unsafe {
|
||||||
|
while !self.read_ready() {}
|
||||||
|
inb(PORT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
use x86_64::{
|
||||||
|
VirtAddr,
|
||||||
|
instructions::tables::load_tss,
|
||||||
|
registers::segmentation::{CS, DS, ES, SS, Segment},
|
||||||
|
structures::{
|
||||||
|
gdt::{Descriptor, GlobalDescriptorTable, SegmentSelector},
|
||||||
|
tss::TaskStateSegment,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
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,165 @@
|
|||||||
|
use pic8259::ChainedPics;
|
||||||
|
use x86_64::structures::idt::{
|
||||||
|
InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode,
|
||||||
|
};
|
||||||
|
|
||||||
|
use spin::{Lazy, Mutex};
|
||||||
|
|
||||||
|
use crate::print_log;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn disable_pic() {
|
||||||
|
unsafe {
|
||||||
|
PICS.lock().disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const 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,
|
||||||
|
) {
|
||||||
|
x86_64::instructions::interrupts::without_interrupts(|| {
|
||||||
|
print_log!("{:?}", _stack_frame)
|
||||||
|
});
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
PICS.lock()
|
||||||
|
.notify_end_of_interrupt(InterruptIndex::Timer.as_u8());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const extern "x86-interrupt" fn page_fault_handler(
|
||||||
|
_stack_frame: InterruptStackFrame,
|
||||||
|
_error_code: PageFaultErrorCode,
|
||||||
|
) {
|
||||||
|
// 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,54 @@
|
|||||||
|
//! 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,6 @@
|
|||||||
|
pub mod apic;
|
||||||
|
pub mod cpu;
|
||||||
|
pub mod dev;
|
||||||
|
pub mod gdt;
|
||||||
|
pub mod interrupts;
|
||||||
|
pub mod memmap;
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
#[repr(u32)]
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
|
// Some predefined colours as well as custom colours in the proper format. This
|
||||||
|
// assumes that the framebuffer uses 32bpp, something which we will assert on
|
||||||
|
// initialisation.
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[expect(
|
||||||
|
clippy::use_self,
|
||||||
|
reason = "Self is uglier and more verbose than `u32`"
|
||||||
|
)]
|
||||||
|
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,46 @@
|
|||||||
|
#![allow(unused)]
|
||||||
|
use libm::include_font;
|
||||||
|
|
||||||
|
pub const FONT_SPLEEN_8X16: Font =
|
||||||
|
Font::new(include_font!("../../resources/font/spleen-8x16.psf"));
|
||||||
|
|
||||||
|
pub const FONT_CP850_8X16: Font =
|
||||||
|
Font::new(include_font!("../../resources/font/cp850-8x16.psf"));
|
||||||
|
|
||||||
|
pub struct Font {
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
length: u16,
|
||||||
|
data: [[u8; 16]; 512],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Font {
|
||||||
|
pub const fn new(data: [[u8; 16]; 512]) -> Self {
|
||||||
|
Self {
|
||||||
|
width: 8,
|
||||||
|
height: 16,
|
||||||
|
length: data.len() as u16,
|
||||||
|
data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn glyph_for(&self, c: u16) -> &[u8] {
|
||||||
|
if c > self.length {
|
||||||
|
return &self.data[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
&self.data[c as usize]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn width(&self) -> usize {
|
||||||
|
self.width
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn height(&self) -> usize {
|
||||||
|
self.height
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn default() -> &'static Self {
|
||||||
|
&FONT_SPLEEN_8X16
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,158 @@
|
|||||||
|
//! Handles setting up the framebuffer passed to us by Limine.
|
||||||
|
#![expect(unused)]
|
||||||
|
use crate::DEFAULT_FONT;
|
||||||
|
|
||||||
|
use super::{colour::Colour, font::Font};
|
||||||
|
|
||||||
|
use limine::framebuffer::Framebuffer;
|
||||||
|
use limine::request::FramebufferRequest;
|
||||||
|
use spin::{Lazy, Mutex};
|
||||||
|
|
||||||
|
#[used]
|
||||||
|
#[unsafe(link_section = ".requests")]
|
||||||
|
/// The Limine framebuffer request.
|
||||||
|
static FRAMEBUFFER_REQUEST: FramebufferRequest = FramebufferRequest::new();
|
||||||
|
|
||||||
|
/// A mutex used for writing to the framebuffer, in most cases we can abstract
|
||||||
|
/// this behind calls to println! etc.
|
||||||
|
pub static FRAMEBUFFER_WRITER: Lazy<Mutex<Option<FramebufferWriter>>> = Lazy::new(
|
||||||
|
|| {
|
||||||
|
Mutex::new(FRAMEBUFFER_REQUEST.get_response().map_or_else(
|
||||||
|
|| {
|
||||||
|
unreachable!("Framebuffer request failed, got None.");
|
||||||
|
},
|
||||||
|
|framebuffer_response| {
|
||||||
|
let framebuffer =
|
||||||
|
framebuffer_response.framebuffers().next()
|
||||||
|
.expect("Expected to find at least one framebuffer in response, got zero.");
|
||||||
|
Some(FramebufferWriter::new(framebuffer, Colour::Black))
|
||||||
|
},
|
||||||
|
))
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
/// 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,
|
||||||
|
/// Number of bits used per pixel, we expect 32 so this will be asserted
|
||||||
|
/// when we initialise the framebuffer.
|
||||||
|
bpp: u16,
|
||||||
|
/// A raw pointer to the framebuffer.
|
||||||
|
addr: *mut u8,
|
||||||
|
/// The width of the screen in pixels.
|
||||||
|
width: u64,
|
||||||
|
/// The height of the screen in pixels.
|
||||||
|
height: u64,
|
||||||
|
/// The default background colour of the Framebuffer.
|
||||||
|
background_colour: Colour,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Marker trait required for sending the writer across threads, which will
|
||||||
|
/// probably come in handy later.
|
||||||
|
unsafe impl Send for FramebufferWriter {}
|
||||||
|
/// Marker trait required for sharing the writer across threads, which will
|
||||||
|
/// probably come in handy later.
|
||||||
|
///
|
||||||
|
/// # Note
|
||||||
|
///
|
||||||
|
/// We wrap this in a Mutex later so this should handle synchronising accesses.
|
||||||
|
unsafe impl Sync for FramebufferWriter {}
|
||||||
|
|
||||||
|
impl FramebufferWriter {
|
||||||
|
/// Creates a new [`FramebufferWriter`] with the specified background
|
||||||
|
/// colour.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the bits per pixel for the framebuffer is not 32 bits per
|
||||||
|
/// pixel, because we didn't exactly handle other cases.
|
||||||
|
pub fn new(framebuffer: Framebuffer, background_colour: Colour) -> Self {
|
||||||
|
// We don't handle other cases, this should not trigger on most newer
|
||||||
|
// hardware.
|
||||||
|
assert!(framebuffer.bpp() == 32);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
pitch: framebuffer.pitch(),
|
||||||
|
bpp: framebuffer.bpp(),
|
||||||
|
addr: framebuffer.addr(),
|
||||||
|
width: framebuffer.width(),
|
||||||
|
height: framebuffer.height(),
|
||||||
|
background_colour,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Writes a pixel with `colour` to the screen at the given `(x, y)`
|
||||||
|
/// coordinates (in pixels).
|
||||||
|
pub fn write_pixel(&self, x: usize, y: usize, colour: Colour) {
|
||||||
|
let pitch = self.pitch as usize;
|
||||||
|
let bpp = (self.bpp / 8) as usize;
|
||||||
|
let pixel_offset = y * pitch + x * bpp;
|
||||||
|
|
||||||
|
// Safety: We assume the pointer to the framebuffer is valid, which it likely
|
||||||
|
// is because we copy it from the Limine request.
|
||||||
|
unsafe {
|
||||||
|
*(self.addr.add(pixel_offset) as *mut u32) = colour.into();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Writes a 2D slice `buffer` to the screen. This should be less than the
|
||||||
|
/// size of the screen in dimensions, but does not neccessarily fill the
|
||||||
|
/// whole screen.
|
||||||
|
pub fn render_frame(&self, buffer: &[&[Colour]]) {
|
||||||
|
// TODO: this should return errors.
|
||||||
|
for (y, &row) in buffer.iter().enumerate() {
|
||||||
|
if y >= self.height() as usize {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (x, pixel) in row.iter().enumerate() {
|
||||||
|
if x >= self.width() as usize {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
self.write_pixel(x, y, *pixel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the width of the framebuffer in pixels.
|
||||||
|
pub const fn width(&self) -> u32 {
|
||||||
|
self.width as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the height of the framebuffer in pixels.
|
||||||
|
pub const fn height(&self) -> u32 {
|
||||||
|
self.height as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the new default background colour.
|
||||||
|
pub const fn set_default_background_colour(&mut self, bg: Colour) {
|
||||||
|
self.background_colour = bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clears the screen and sets the background to the default colour.
|
||||||
|
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 {
|
||||||
|
// Write the background in the preferred background colour.
|
||||||
|
self.write_pixel(x, y, self.background_colour);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the screen size in pixels or (0, 0) if something went wrong.
|
||||||
|
pub fn screensize_px() -> (u32, u32) {
|
||||||
|
FRAMEBUFFER_WRITER
|
||||||
|
.lock()
|
||||||
|
.as_mut()
|
||||||
|
.map_or_else(|| (0, 0), |writer| (writer.width(), writer.height()))
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
pub mod colour;
|
||||||
|
pub mod font;
|
||||||
|
pub mod framebuffer;
|
||||||
|
pub mod writer;
|
||||||
@@ -0,0 +1,248 @@
|
|||||||
|
//! Formerly called ascii.rs, this file defines helper functions for drawing
|
||||||
|
//! characters to the screen.
|
||||||
|
|
||||||
|
use core::fmt;
|
||||||
|
use spin::{Lazy, Mutex};
|
||||||
|
use x86_64::instructions::interrupts;
|
||||||
|
|
||||||
|
use super::{colour::Colour, font::Font, framebuffer::FRAMEBUFFER_WRITER};
|
||||||
|
|
||||||
|
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: &crate::DEFAULT_FONT,
|
||||||
|
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.glyph_for(c as u16);
|
||||||
|
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn _print(args: fmt::Arguments) {
|
||||||
|
x86_64::instructions::interrupts::without_interrupts(|| {
|
||||||
|
write(args, Colour::White, Colour::Black);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn _print_err(args: fmt::Arguments) {
|
||||||
|
x86_64::instructions::interrupts::without_interrupts(|| {
|
||||||
|
write(args, Colour::Red, Colour::Black);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
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::graphics::writer::_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::graphics::writer::_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::graphics::writer::_print_err(format_args!($($arg)*)));
|
||||||
|
}
|
||||||
@@ -0,0 +1,209 @@
|
|||||||
|
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};
|
||||||
|
|
||||||
|
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 @@
|
|||||||
|
// pub mod keyboard;
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
#![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
|
||||||
|
)]
|
||||||
|
|
||||||
|
use arch::x86_64::dev::serial;
|
||||||
|
use arch::x86_64::{gdt, interrupts};
|
||||||
|
use core::arch::asm;
|
||||||
|
use graphics::font::{FONT_SPLEEN_8X16, Font};
|
||||||
|
use limine::BaseRevision;
|
||||||
|
|
||||||
|
pub mod arch;
|
||||||
|
pub mod graphics;
|
||||||
|
pub mod io;
|
||||||
|
|
||||||
|
/// 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();
|
||||||
|
|
||||||
|
/// The default font used when setting up the framebuffer code.
|
||||||
|
pub const DEFAULT_FONT: Font = FONT_SPLEEN_8X16;
|
||||||
|
|
||||||
|
#[panic_handler]
|
||||||
|
fn rust_panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
|
hcf();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hcf() -> ! {
|
||||||
|
loop {
|
||||||
|
unsafe {
|
||||||
|
asm!("hlt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn boot() -> Result<(), &'static str> {
|
||||||
|
if !BASE_REVISION.is_supported() {
|
||||||
|
return Err("Base Revision was not supported.");
|
||||||
|
}
|
||||||
|
|
||||||
|
print_log!(" Setting up Serial Communication... ");
|
||||||
|
|
||||||
|
if serial::init().is_err() {
|
||||||
|
println_log!("[Not Detected]")
|
||||||
|
} else {
|
||||||
|
println_log!("[Success]")
|
||||||
|
}
|
||||||
|
|
||||||
|
print_log!(" Setting up GDT... ");
|
||||||
|
gdt::init();
|
||||||
|
println_log!("[Success]");
|
||||||
|
|
||||||
|
interrupts::enable_pic();
|
||||||
|
// interrupts::disable_pic();
|
||||||
|
|
||||||
|
print_log!(" Initialising interrupts... ");
|
||||||
|
interrupts::init_idt();
|
||||||
|
println_log!("[Success]");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
+6
-61
@@ -1,67 +1,12 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use core::arch::asm;
|
use foundry_os::boot;
|
||||||
|
|
||||||
use limine::request::{FramebufferRequest, RequestsEndMarker, RequestsStartMarker};
|
#[unsafe(no_mangle)]
|
||||||
use limine::BaseRevision;
|
extern "C" fn kmain() -> ! {
|
||||||
|
_ = boot();
|
||||||
|
|
||||||
/// Sets the base revision to the latest revision supported by the crate.
|
#[allow(clippy::empty_loop)]
|
||||||
/// See specification for further info.
|
loop {}
|
||||||
/// 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.
|
|
||||||
#[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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[panic_handler]
|
|
||||||
fn rust_panic(_info: &core::panic::PanicInfo) -> ! {
|
|
||||||
hcf();
|
|
||||||
}
|
|
||||||
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user