commit
1c92cacbc3
@ -1,10 +1,2 @@
|
||||
[unstable]
|
||||
build-std = ["core", "compiler_builtins"]
|
||||
build-std-features = ["compiler-builtins-mem"]
|
||||
|
||||
[build]
|
||||
target = "i686-unknown-linux-gnu"
|
||||
|
||||
[target.i686-unknown-linux-gnu]
|
||||
linker = "i686-elf-ld"
|
||||
ar = "i686-elf-ar"
|
||||
bindeps = true
|
||||
580
Cargo.lock
generated
580
Cargo.lock
generated
@ -3,10 +3,25 @@
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "bit_field"
|
||||
version = "0.10.2"
|
||||
name = "anyhow"
|
||||
version = "1.0.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
|
||||
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "1.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit_field"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
@ -15,28 +30,571 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "cure"
|
||||
name = "bitflags"
|
||||
version = "2.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394"
|
||||
|
||||
[[package]]
|
||||
name = "bitvec"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
|
||||
dependencies = [
|
||||
"funty",
|
||||
"radium",
|
||||
"tap",
|
||||
"wyz",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bootloader"
|
||||
version = "0.11.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61e418d2f8952e4a6d935d23ea038daed2fe7707b0118923f91e83bf1fbe64b3"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bootloader-boot-config",
|
||||
"fatfs",
|
||||
"gpt",
|
||||
"llvm-tools",
|
||||
"mbrman",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bootloader-boot-config"
|
||||
version = "0.11.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6cfbe7f4a5d9843a9a310712e64691f3c474546f02bed7a53ed81775a681d18e"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bootloader_api"
|
||||
version = "0.11.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba1a4adcd36a49a08c4fb8c13c132fb1ea01a59681b305b46625095318328455"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
|
||||
|
||||
[[package]]
|
||||
name = "crc"
|
||||
version = "3.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675"
|
||||
dependencies = [
|
||||
"crc-catalog",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc-catalog"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
|
||||
|
||||
[[package]]
|
||||
name = "cure-builder"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"x86",
|
||||
"bootloader",
|
||||
"cure-kernel",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cure-kernel"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bootloader_api",
|
||||
"lazy_static",
|
||||
"raw-cpuid",
|
||||
"spin 0.10.0",
|
||||
"x86_64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
||||
|
||||
[[package]]
|
||||
name = "fatfs"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05669f8e7e2d7badc545c513710f0eba09c2fbef683eb859fd79c46c355048e0"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"byteorder",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "funty"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"r-efi",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gpt"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8283e7331b8c93b9756e0cfdbcfb90312852f953c6faf9bf741e684cc3b6ad69"
|
||||
dependencies = [
|
||||
"bitflags 2.9.4",
|
||||
"crc",
|
||||
"log",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
dependencies = [
|
||||
"spin 0.9.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.177"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
|
||||
|
||||
[[package]]
|
||||
name = "llvm-tools"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "955be5d0ca0465caf127165acb47964f911e2bc26073e865deb8be7189302faf"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
|
||||
dependencies = [
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
|
||||
|
||||
[[package]]
|
||||
name = "mbrman"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1fc3bff63c208d4a14301c6cb807af2d1a0760052584ce3f9a737b55fb85498"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bitvec",
|
||||
"serde",
|
||||
"serde-big-array",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.101"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi"
|
||||
version = "5.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
||||
|
||||
[[package]]
|
||||
name = "radium"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
|
||||
|
||||
[[package]]
|
||||
name = "raw-cpuid"
|
||||
version = "10.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x86"
|
||||
version = "0.52.0"
|
||||
name = "rustix"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2781db97787217ad2a2845c396a5efe286f87467a5810836db6d74926e94a385"
|
||||
checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e"
|
||||
dependencies = [
|
||||
"bitflags 2.9.4",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-big-array"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.145"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"ryu",
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tap"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.23.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16"
|
||||
dependencies = [
|
||||
"fastrand",
|
||||
"getrandom",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.18.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "volatile"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "442887c63f2c839b346c192d047a7c87e73d0689c9157b00b53dcc27dd5ea793"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.14.7+wasi-0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c"
|
||||
dependencies = [
|
||||
"wasip2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasip2"
|
||||
version = "1.0.1+wasi-0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
|
||||
dependencies = [
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"rustversion",
|
||||
"wasm-bindgen-macro",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
|
||||
|
||||
[[package]]
|
||||
name = "wyz"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
|
||||
dependencies = [
|
||||
"tap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x86_64"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f042214de98141e9c8706e8192b73f56494087cc55ebec28ce10f26c5c364ae"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"bitflags",
|
||||
"raw-cpuid",
|
||||
"bitflags 2.9.4",
|
||||
"rustversion",
|
||||
"volatile",
|
||||
]
|
||||
|
||||
26
Cargo.toml
26
Cargo.toml
@ -1,27 +1,9 @@
|
||||
[package]
|
||||
name = "cure"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
path = "src/lib.rs"
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = ["kernel", "builder"]
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
opt-level = 0
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
opt-level = 2
|
||||
|
||||
[package.metadata.bootimage]
|
||||
test-args = ["-device", "isa-debug-exit,iobase=0xf4,iosize=0x04", "-serial", "stdio", "-display", "none"]
|
||||
test-success-exit-code = 33
|
||||
|
||||
[features]
|
||||
default = []
|
||||
debug = []
|
||||
|
||||
[dependencies]
|
||||
x86 = "0.52.0"
|
||||
panic = "abort"
|
||||
@ -1,10 +1,10 @@
|
||||
# -- 基本設定 --
|
||||
romimage: file=/usr/local/share/bochs/BIOS-bochs-latest, address=0xfffe0000
|
||||
vgaromimage: file=/usr/local/share/bochs/VGABIOS-lgpl-latest
|
||||
# romimage: file=/usr/local/share/bochs/BIOS-bochs-latest, address=0xfffe0000
|
||||
# vgaromimage: file=/usr/local/share/bochs/VGABIOS-lgpl-latest
|
||||
|
||||
boot: cdrom
|
||||
boot: disk
|
||||
ata0-master: type=disk, path="build/cure-bios.img", mode=flat
|
||||
|
||||
ata0-master: type=cdrom, path="build/cure.iso", status=inserted
|
||||
|
||||
memory: guest=1024, host=1024
|
||||
|
||||
|
||||
14
builder/Cargo.toml
Normal file
14
builder/Cargo.toml
Normal file
@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "cure-builder"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
||||
[build-dependencies]
|
||||
bootloader = "0.11.12"
|
||||
|
||||
[build-dependencies.cure-kernel]
|
||||
path = "../kernel"
|
||||
artifact = "bin"
|
||||
target = "x86_64-unknown-none"
|
||||
28
builder/build.rs
Normal file
28
builder/build.rs
Normal file
@ -0,0 +1,28 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
let kernel_path = PathBuf::from(
|
||||
std::env::var("CARGO_BIN_FILE_CURE_KERNEL_cure-kernel")
|
||||
.expect("CARGO_BIN_FILE_CURE_KERNEL_cure-kernel not set")
|
||||
);
|
||||
|
||||
println!("cargo:warning=Kernel path: {:?}", kernel_path);
|
||||
|
||||
let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap());
|
||||
|
||||
let bios_path = out_dir.join("cure-bios.img");
|
||||
bootloader::BiosBoot::new(&kernel_path)
|
||||
.create_disk_image(&bios_path)
|
||||
.expect("Failed to create BIOS disk image");
|
||||
|
||||
let uefi_path = out_dir.join("cure-uefi.img");
|
||||
bootloader::UefiBoot::new(&kernel_path)
|
||||
.create_disk_image(&uefi_path)
|
||||
.expect("Failed to create UEFI disk image");
|
||||
|
||||
println!("cargo:warning=✓ BIOS image: {:?}", bios_path);
|
||||
println!("cargo:warning=✓ UEFI image: {:?}", uefi_path);
|
||||
|
||||
println!("cargo:rustc-env=BIOS_IMAGE={}", bios_path.display());
|
||||
println!("cargo:rustc-env=UEFI_IMAGE={}", uefi_path.display());
|
||||
}
|
||||
4
builder/src/main.rs
Normal file
4
builder/src/main.rs
Normal file
@ -0,0 +1,4 @@
|
||||
fn main() {
|
||||
println!("Build completed successfully!");
|
||||
println!("Disk images created in target directory");
|
||||
}
|
||||
6
kernel/.cargo/config.toml
Normal file
6
kernel/.cargo/config.toml
Normal file
@ -0,0 +1,6 @@
|
||||
[unstable]
|
||||
bindeps = true
|
||||
|
||||
[target.x86_64-unknown-none]
|
||||
build-std = ["core", "compiler_builtins"]
|
||||
build-std-features = ["compiler-builtins-mem"]
|
||||
15
kernel/Cargo.toml
Normal file
15
kernel/Cargo.toml
Normal file
@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "cure-kernel"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
bootloader_api = "0.11.12"
|
||||
lazy_static = { version = "1.5.0", features = ["spin_no_std"] }
|
||||
x86_64 = { version = "0.15.2", features = ["instructions"] }
|
||||
spin = "0.10.0"
|
||||
raw-cpuid = "10.7.0"
|
||||
|
||||
[package.metadata.bootloader]
|
||||
map-physical-memory = true
|
||||
physical-memory-offset = "0xFFFF800000000000"
|
||||
@ -1,23 +1,12 @@
|
||||
// src/hal/cpu.rs
|
||||
use x86::controlregs::{
|
||||
cr0,
|
||||
cr0_write,
|
||||
cr2,
|
||||
cr2_write,
|
||||
cr3,
|
||||
cr3_write,
|
||||
cr4,
|
||||
cr4_write,
|
||||
Cr0,
|
||||
Cr4
|
||||
};
|
||||
use x86::time::rdtsc;
|
||||
use x86::cpuid;
|
||||
use core::hint::spin_loop;
|
||||
use x86::irq::{enable, disable};
|
||||
use x86::halt;
|
||||
// kernel/src/hal/cpu.rs
|
||||
use x86_64::registers::control::{Cr0, Cr0Flags, Cr2, Cr3, Cr4, Cr4Flags};
|
||||
use x86_64::instructions::{interrupts, hlt};
|
||||
use core::arch::asm;
|
||||
use x86_64::VirtAddr;
|
||||
|
||||
/// 64 位元暫存器類型
|
||||
#[allow(dead_code)]
|
||||
pub type Reg64 = u64;
|
||||
/// 32 位元暫存器類型
|
||||
#[allow(dead_code)]
|
||||
pub type Reg32 = u32;
|
||||
@ -25,18 +14,26 @@ pub type Reg32 = u32;
|
||||
#[allow(dead_code)]
|
||||
pub type Reg16 = u16;
|
||||
|
||||
/// 通用目的暫存器結構
|
||||
/// 通用目的暫存器結構 (64-bit)
|
||||
#[allow(dead_code)]
|
||||
#[repr(C, packed)]
|
||||
pub struct GpRegs {
|
||||
pub eax: Reg32,
|
||||
pub ebx: Reg32,
|
||||
pub ecx: Reg32,
|
||||
pub edx: Reg32,
|
||||
pub edi: Reg32,
|
||||
pub ebp: Reg32,
|
||||
pub esi: Reg32,
|
||||
pub esp: Reg32,
|
||||
pub rax: Reg64,
|
||||
pub rbx: Reg64,
|
||||
pub rcx: Reg64,
|
||||
pub rdx: Reg64,
|
||||
pub rdi: Reg64,
|
||||
pub rbp: Reg64,
|
||||
pub rsi: Reg64,
|
||||
pub rsp: Reg64,
|
||||
pub r8: Reg64,
|
||||
pub r9: Reg64,
|
||||
pub r10: Reg64,
|
||||
pub r11: Reg64,
|
||||
pub r12: Reg64,
|
||||
pub r13: Reg64,
|
||||
pub r14: Reg64,
|
||||
pub r15: Reg64,
|
||||
}
|
||||
|
||||
/// 段暫存器結構
|
||||
@ -51,77 +48,66 @@ pub struct SgReg {
|
||||
pub cs: Reg16,
|
||||
}
|
||||
|
||||
/// Write cr4.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// use x86::controlregs::*;
|
||||
/// unsafe {
|
||||
/// let cr4 = cr4();
|
||||
/// let cr4 = cr4 | Cr4::CR4_ENABLE_PSE;
|
||||
/// cr4_write(cr4);
|
||||
/// }
|
||||
/// ```
|
||||
// ============ 控制寄存器 ============
|
||||
|
||||
/// 讀取 CR0 暫存器
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_r_cr0() -> Cr0 {
|
||||
unsafe { cr0() }
|
||||
pub fn cpu_r_cr0() -> Cr0Flags {
|
||||
Cr0::read()
|
||||
}
|
||||
|
||||
/// 讀取 CR2 暫存器
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_r_cr2() -> usize {
|
||||
unsafe { cr2() }
|
||||
pub fn cpu_r_cr2() -> u64 {
|
||||
Cr2::read_raw()
|
||||
}
|
||||
|
||||
/// 讀取 CR3 暫存器
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_r_cr3() -> u64 {
|
||||
unsafe { cr3() }
|
||||
Cr3::read().0.start_address().as_u64()
|
||||
}
|
||||
|
||||
/// 讀取 CR4 暫存器
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_r_cr4() -> Cr4 {
|
||||
unsafe { cr4() }
|
||||
pub fn cpu_r_cr4() -> Cr4Flags {
|
||||
Cr4::read()
|
||||
}
|
||||
|
||||
/// 寫入 CR0 暫存器
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_w_cr0(val: Cr0) {
|
||||
unsafe { cr0_write(val); }
|
||||
}
|
||||
|
||||
/// 寫入 CR2 暫存器
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_w_cr2(val: u64) {
|
||||
unsafe { cr2_write(val); }
|
||||
pub fn cpu_w_cr0(val: Cr0Flags) {
|
||||
unsafe { Cr0::write(val); }
|
||||
}
|
||||
|
||||
/// 寫入 CR3 暫存器
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_w_cr3(val: u64) {
|
||||
unsafe { cr3_write(val); }
|
||||
use x86_64::{PhysAddr, structures::paging::PhysFrame};
|
||||
|
||||
let frame = PhysFrame::containing_address(PhysAddr::new(val));
|
||||
unsafe {
|
||||
Cr3::write(frame, Cr3::read().1);
|
||||
}
|
||||
}
|
||||
|
||||
/// 寫入 CR4 暫存器
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_w_cr4(val: Cr4) {
|
||||
unsafe { cr4_write(val); }
|
||||
pub fn cpu_w_cr4(val: Cr4Flags) {
|
||||
unsafe { Cr4::write(val); }
|
||||
}
|
||||
|
||||
/// 獲取 CPU 型號
|
||||
///
|
||||
// ============ CPU 資訊 ============
|
||||
|
||||
/// 獲取 CPU 供應商 ID
|
||||
///
|
||||
/// # 參數
|
||||
/// * `model_out` - 輸出緩衝區,至少需要 13 bytes
|
||||
/// # 返回
|
||||
@ -131,17 +117,18 @@ pub fn cpu_get_model(model_out: &mut [u8]) -> &str {
|
||||
if model_out.len() < 13 {
|
||||
return "Buffer too small";
|
||||
}
|
||||
|
||||
// 使用 cpuid 取得廠商 ID
|
||||
let vendor_id = cpuid::CpuId::new().get_vendor_info();
|
||||
|
||||
if let Some(vendor) = vendor_id {
|
||||
|
||||
// 使用 raw_cpuid crate
|
||||
use raw_cpuid::CpuId;
|
||||
let cpuid = CpuId::new();
|
||||
|
||||
if let Some(vendor) = cpuid.get_vendor_info() {
|
||||
let vendor_string = vendor.as_str();
|
||||
let bytes = vendor_string.as_bytes();
|
||||
let copy_len = core::cmp::min(bytes.len(), model_out.len() - 1);
|
||||
|
||||
|
||||
model_out[..copy_len].copy_from_slice(&bytes[..copy_len]);
|
||||
model_out[copy_len] = 0; // null
|
||||
model_out[copy_len] = 0; // null terminator
|
||||
|
||||
match core::str::from_utf8(&model_out[..copy_len]) {
|
||||
Ok(s) => s,
|
||||
@ -157,15 +144,16 @@ pub fn cpu_get_model(model_out: &mut [u8]) -> &str {
|
||||
/// 檢查是否支持品牌字串
|
||||
#[allow(dead_code)]
|
||||
pub fn cpu_brand_string_supported() -> bool {
|
||||
let cpuid = cpuid::CpuId::new();
|
||||
use raw_cpuid::CpuId;
|
||||
let cpuid = CpuId::new();
|
||||
cpuid.get_processor_brand_string().is_some()
|
||||
}
|
||||
|
||||
/// 獲取 CPU 品牌字串
|
||||
///
|
||||
///
|
||||
/// # 參數
|
||||
/// * `brand_out` - 輸出緩衝區,至少需要 49 bytes
|
||||
///
|
||||
///
|
||||
/// # 返回
|
||||
/// 字符串切片,表示 CPU 品牌
|
||||
#[allow(dead_code)]
|
||||
@ -173,21 +161,19 @@ pub fn cpu_get_brand(brand_out: &mut [u8]) -> &str {
|
||||
if brand_out.len() < 49 {
|
||||
return "Buffer too small";
|
||||
}
|
||||
|
||||
let cpuid = cpuid::CpuId::new();
|
||||
|
||||
|
||||
use raw_cpuid::CpuId;
|
||||
let cpuid = CpuId::new();
|
||||
|
||||
if let Some(brand) = cpuid.get_processor_brand_string() {
|
||||
let brand_string = brand.as_str();
|
||||
let bytes = brand_string.as_bytes();
|
||||
let copy_len = core::cmp::min(bytes.len(), brand_out.len() - 1);
|
||||
|
||||
|
||||
brand_out[..copy_len].copy_from_slice(&bytes[..copy_len]);
|
||||
brand_out[copy_len] = 0; // null
|
||||
|
||||
match core::str::from_utf8(&brand_out[..copy_len]) {
|
||||
Ok(s) => s,
|
||||
Err(_) => "Invalid UTF-8"
|
||||
}
|
||||
brand_out[copy_len] = 0; // null terminator
|
||||
|
||||
core::str::from_utf8(&brand_out[..copy_len]).unwrap_or_else(|_| "Invalid UTF-8")
|
||||
} else {
|
||||
brand_out[0] = b'?';
|
||||
brand_out[1] = 0;
|
||||
@ -195,53 +181,99 @@ pub fn cpu_get_brand(brand_out: &mut [u8]) -> &str {
|
||||
}
|
||||
}
|
||||
|
||||
// ============ CPU 指令 ============
|
||||
|
||||
/// 讀取 CPU 時間戳計數器 (TSC)
|
||||
///
|
||||
///
|
||||
/// # 返回
|
||||
/// 時間戳計數值
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_rdtsc() -> u64 {
|
||||
unsafe { rdtsc() }
|
||||
unsafe {
|
||||
let low: u32;
|
||||
let high: u32;
|
||||
asm!(
|
||||
"rdtsc",
|
||||
out("eax") low,
|
||||
out("edx") high,
|
||||
options(nomem, nostack, preserves_flags)
|
||||
);
|
||||
((high as u64) << 32) | (low as u64)
|
||||
}
|
||||
}
|
||||
|
||||
/// 執行 CPU 暫停指令
|
||||
///
|
||||
/// 在等待時減少 CPU 功耗
|
||||
/// 執行 CPU 暫停指令 (減少功耗)
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_pause() {
|
||||
spin_loop();
|
||||
core::hint::spin_loop();
|
||||
}
|
||||
|
||||
/// 停止 CPU 執行,直到下一個中斷發生
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_halt() {
|
||||
unsafe { halt(); }
|
||||
hlt();
|
||||
}
|
||||
|
||||
/// 停止 CPU 並進入低功耗模式
|
||||
/// 停止 CPU 並進入低功耗模式 (等同於 cpu_halt)
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_idle() {
|
||||
unsafe { halt(); }
|
||||
hlt();
|
||||
}
|
||||
|
||||
/// 啟用中斷
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_enable_interrupts() {
|
||||
unsafe {
|
||||
enable();
|
||||
}
|
||||
interrupts::enable();
|
||||
}
|
||||
|
||||
/// 禁用中斷
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_disable_interrupts() {
|
||||
unsafe {
|
||||
disable();
|
||||
}
|
||||
interrupts::disable();
|
||||
}
|
||||
|
||||
/// 檢查中斷是否啟用
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_interrupts_enabled() -> bool {
|
||||
interrupts::are_enabled()
|
||||
}
|
||||
|
||||
/// 在禁用中斷的情況下執行閉包
|
||||
///
|
||||
/// # 範例
|
||||
/// ```
|
||||
/// cpu_without_interrupts(|| {
|
||||
/// // 臨界區代碼
|
||||
/// // 中斷被禁用
|
||||
/// });
|
||||
/// // 中斷恢復到之前的狀態
|
||||
/// ```
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_without_interrupts<F, R>(f: F) -> R
|
||||
where
|
||||
F: FnOnce() -> R,
|
||||
{
|
||||
interrupts::without_interrupts(f)
|
||||
}
|
||||
|
||||
/// 無條件觸發斷點異常 (用於調試)
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_breakpoint() {
|
||||
x86_64::instructions::interrupts::int3();
|
||||
}
|
||||
|
||||
/// 讀取 RFLAGS 寄存器
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_read_flags() -> u64 {
|
||||
x86_64::registers::rflags::read().bits()
|
||||
}
|
||||
@ -1,13 +1,8 @@
|
||||
// src/hal/io.rs
|
||||
use x86::io::{inb, inl, outb, outl};
|
||||
|
||||
// :e - 32 位寄存器(如 eax, edx 等)
|
||||
// :x - 16 位寄存器(如 ax, dx 等)
|
||||
// :l - 8 位低位寄存器(如 al, dl 等)
|
||||
// :h - 8 位高位寄存器(如 ah, dh 等)
|
||||
// kernel/src/hal/io.rs
|
||||
use x86_64::instructions::port::{Port, PortReadOnly, PortWriteOnly};
|
||||
|
||||
/// 向 I/O 端口寫入一個字節
|
||||
///
|
||||
///
|
||||
/// # 參數
|
||||
/// * `port` - 端口號
|
||||
/// * `value` - 要寫入的值
|
||||
@ -15,25 +10,12 @@ use x86::io::{inb, inl, outb, outl};
|
||||
#[inline]
|
||||
pub fn io_port_wb(port: u16, value: u8) {
|
||||
unsafe {
|
||||
outb(port, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// 向 I/O 端口寫入一個雙字
|
||||
///
|
||||
/// # 參數
|
||||
/// * `port` - 端口號
|
||||
/// * `value` - 要寫入的值
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn io_port_wl(port: u16, value: u32) {
|
||||
unsafe {
|
||||
outl(port, value);
|
||||
Port::new(port).write(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// 從 I/O 端口讀取一個字節
|
||||
///
|
||||
///
|
||||
/// # 參數
|
||||
/// * `port` - 端口號
|
||||
/// # 返回
|
||||
@ -42,26 +24,12 @@ pub fn io_port_wl(port: u16, value: u32) {
|
||||
#[inline]
|
||||
pub fn io_port_rb(port: u16) -> u8 {
|
||||
unsafe {
|
||||
inb(port)
|
||||
Port::new(port).read()
|
||||
}
|
||||
}
|
||||
|
||||
/// 從 I/O 端口讀取一個雙字
|
||||
///
|
||||
/// # 參數
|
||||
/// * `port` - 端口號
|
||||
/// # 返回
|
||||
/// 讀取到的值
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn io_port_rl(port: u16) -> u32 {
|
||||
unsafe {
|
||||
inl(port)
|
||||
}
|
||||
}
|
||||
|
||||
/// 向 I/O 端口寫入一個字
|
||||
///
|
||||
/// 向 I/O 端口寫入一個字 (16-bit)
|
||||
///
|
||||
/// # 參數
|
||||
/// * `port` - 端口號
|
||||
/// * `value` - 要寫入的值
|
||||
@ -69,12 +37,12 @@ pub fn io_port_rl(port: u16) -> u32 {
|
||||
#[inline]
|
||||
pub fn io_port_ww(port: u16, value: u16) {
|
||||
unsafe {
|
||||
x86::io::outw(port, value);
|
||||
Port::new(port).write(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// 從 I/O 端口讀取一個字
|
||||
///
|
||||
/// 從 I/O 端口讀取一個字 (16-bit)
|
||||
///
|
||||
/// # 參數
|
||||
/// * `port` - 端口號
|
||||
/// # 返回
|
||||
@ -83,6 +51,33 @@ pub fn io_port_ww(port: u16, value: u16) {
|
||||
#[inline]
|
||||
pub fn io_port_rw(port: u16) -> u16 {
|
||||
unsafe {
|
||||
x86::io::inw(port)
|
||||
Port::new(port).read()
|
||||
}
|
||||
}
|
||||
|
||||
/// 向 I/O 端口寫入一個雙字 (32-bit)
|
||||
///
|
||||
/// # 參數
|
||||
/// * `port` - 端口號
|
||||
/// * `value` - 要寫入的值
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn io_port_wl(port: u16, value: u32) {
|
||||
unsafe {
|
||||
Port::new(port).write(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// 從 I/O 端口讀取一個雙字 (32-bit)
|
||||
///
|
||||
/// # 參數
|
||||
/// * `port` - 端口號
|
||||
/// # 返回
|
||||
/// 讀取到的值
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn io_port_rl(port: u16) -> u32 {
|
||||
unsafe {
|
||||
Port::new(port).read()
|
||||
}
|
||||
}
|
||||
@ -10,7 +10,6 @@ pub use cpu::cpu_r_cr0;
|
||||
pub use cpu::cpu_r_cr2;
|
||||
pub use cpu::cpu_r_cr3;
|
||||
pub use cpu::cpu_w_cr0;
|
||||
pub use cpu::cpu_w_cr2;
|
||||
pub use cpu::cpu_w_cr3;
|
||||
pub use cpu::cpu_get_model;
|
||||
pub use cpu::cpu_brand_string_supported;
|
||||
128
kernel/src/kernel/asm/x86/gdt.rs
Normal file
128
kernel/src/kernel/asm/x86/gdt.rs
Normal file
@ -0,0 +1,128 @@
|
||||
// kernel/src/kernel/asm/x86/gdt.rs
|
||||
use x86_64::structures::gdt::{GlobalDescriptorTable, Descriptor, SegmentSelector};
|
||||
use x86_64::structures::tss::TaskStateSegment;
|
||||
use x86_64::instructions::segmentation::{Segment, CS, DS, ES, SS};
|
||||
use x86_64::instructions::tables::load_tss;
|
||||
use x86_64::VirtAddr;
|
||||
use lazy_static::lazy_static;
|
||||
use crate::kprintln;
|
||||
|
||||
pub const DOUBLE_FAULT_IST_INDEX: u16 = 0;
|
||||
|
||||
lazy_static! {
|
||||
static ref TSS: TaskStateSegment = {
|
||||
let mut tss = TaskStateSegment::new();
|
||||
|
||||
unsafe { tss.interrupt_stack_table[DOUBLE_FAULT_IST_INDEX as usize] = {
|
||||
const STACK_SIZE: usize = 4096 * 5; // 20KB
|
||||
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
|
||||
|
||||
let stack_start = VirtAddr::new(&raw const STACK as *const _ as u64);
|
||||
let stack_end = stack_start + STACK_SIZE as u64;
|
||||
|
||||
stack_end
|
||||
}; }
|
||||
|
||||
unsafe { tss.privilege_stack_table[0] = {
|
||||
const STACK_SIZE: usize = 4096 * 5; // 20KB
|
||||
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
|
||||
|
||||
let stack_start = VirtAddr::new(&raw const STACK as *const _ as u64);
|
||||
let stack_end = stack_start + STACK_SIZE as u64;
|
||||
|
||||
stack_end
|
||||
}; }
|
||||
|
||||
tss
|
||||
};
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref GDT: (GlobalDescriptorTable, Selectors) = {
|
||||
let mut gdt = GlobalDescriptorTable::new();
|
||||
|
||||
// 0x00: Null
|
||||
|
||||
// 0x08 ring 0
|
||||
let kernel_code_selector = gdt.append(Descriptor::kernel_code_segment());
|
||||
|
||||
// 0x10 ring 0
|
||||
let kernel_data_selector = gdt.append(Descriptor::kernel_data_segment());
|
||||
|
||||
// 0x18 ring 3
|
||||
let user_code_selector = gdt.append(Descriptor::user_code_segment());
|
||||
|
||||
// 0x20 ring 3
|
||||
let user_data_selector = gdt.append(Descriptor::user_data_segment());
|
||||
|
||||
// 0x28 Task seg
|
||||
let tss_selector = gdt.append(Descriptor::tss_segment(&TSS));
|
||||
|
||||
(
|
||||
gdt,
|
||||
Selectors {
|
||||
kernel_code_selector,
|
||||
kernel_data_selector,
|
||||
user_code_selector,
|
||||
user_data_selector,
|
||||
tss_selector,
|
||||
},
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Selectors {
|
||||
pub kernel_code_selector: SegmentSelector,
|
||||
pub kernel_data_selector: SegmentSelector,
|
||||
pub user_code_selector: SegmentSelector,
|
||||
pub user_data_selector: SegmentSelector,
|
||||
pub tss_selector: SegmentSelector,
|
||||
}
|
||||
|
||||
pub fn get_selectors() -> Selectors {
|
||||
GDT.1
|
||||
}
|
||||
|
||||
pub fn user_code_selector() -> SegmentSelector {
|
||||
GDT.1.user_code_selector
|
||||
}
|
||||
|
||||
pub fn user_data_selector() -> SegmentSelector {
|
||||
GDT.1.user_data_selector
|
||||
}
|
||||
|
||||
pub fn kernel_code_selector() -> SegmentSelector {
|
||||
GDT.1.kernel_code_selector
|
||||
}
|
||||
|
||||
pub fn kernel_data_selector() -> SegmentSelector {
|
||||
GDT.1.kernel_data_selector
|
||||
}
|
||||
|
||||
// 初始化 GDT
|
||||
pub fn init() {
|
||||
GDT.0.load();
|
||||
|
||||
unsafe {
|
||||
CS::set_reg(GDT.1.kernel_code_selector);
|
||||
|
||||
DS::set_reg(GDT.1.kernel_data_selector);
|
||||
ES::set_reg(GDT.1.kernel_data_selector);
|
||||
SS::set_reg(GDT.1.kernel_data_selector);
|
||||
|
||||
// 加載 TSS
|
||||
load_tss(GDT.1.tss_selector);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_info() {
|
||||
let selectors = get_selectors();
|
||||
|
||||
kprintln!("GDT Information:");
|
||||
kprintln!(" Kernel Code: {:#x} (ring 0)", selectors.kernel_code_selector.0);
|
||||
kprintln!(" Kernel Data: {:#x} (ring 0)", selectors.kernel_data_selector.0);
|
||||
kprintln!(" User Code: {:#x} (ring 3)", selectors.user_code_selector.0);
|
||||
kprintln!(" User Data: {:#x} (ring 3)", selectors.user_data_selector.0);
|
||||
kprintln!(" TSS: {:#x}", selectors.tss_selector.0);
|
||||
}
|
||||
49
kernel/src/kernel/asm/x86/idt.rs
Normal file
49
kernel/src/kernel/asm/x86/idt.rs
Normal file
@ -0,0 +1,49 @@
|
||||
// kernel/src/kernel/asm/x86/idt.rs
|
||||
use x86_64::structures::idt::{InterruptDescriptorTable};
|
||||
use lazy_static::lazy_static;
|
||||
use crate::kprintln;
|
||||
use super::interrupt::*;
|
||||
|
||||
lazy_static! {
|
||||
static ref IDT: InterruptDescriptorTable = {
|
||||
let mut idt = InterruptDescriptorTable::new();
|
||||
|
||||
idt.breakpoint.set_handler_fn(breakpoint_handler);
|
||||
idt.divide_error.set_handler_fn(divide_error_handler);
|
||||
idt.debug.set_handler_fn(debug_handler);
|
||||
idt.non_maskable_interrupt.set_handler_fn(nmi_handler);
|
||||
idt.overflow.set_handler_fn(overflow_handler);
|
||||
idt.bound_range_exceeded.set_handler_fn(bound_range_handler);
|
||||
idt.invalid_opcode.set_handler_fn(invalid_opcode_handler);
|
||||
idt.device_not_available.set_handler_fn(device_not_available_handler);
|
||||
|
||||
unsafe {
|
||||
idt.double_fault
|
||||
.set_handler_fn(double_fault_handler)
|
||||
.set_stack_index(crate::kernel::asm::x86::gdt::DOUBLE_FAULT_IST_INDEX);
|
||||
}
|
||||
|
||||
idt.invalid_tss.set_handler_fn(invalid_tss_handler);
|
||||
idt.segment_not_present.set_handler_fn(segment_not_present_handler);
|
||||
idt.stack_segment_fault.set_handler_fn(stack_segment_fault_handler);
|
||||
idt.general_protection_fault.set_handler_fn(general_protection_fault_handler);
|
||||
idt.page_fault.set_handler_fn(page_fault_handler);
|
||||
idt.x87_floating_point.set_handler_fn(x87_floating_point_handler);
|
||||
idt.alignment_check.set_handler_fn(alignment_check_handler);
|
||||
idt.machine_check.set_handler_fn(machine_check_handler);
|
||||
idt.simd_floating_point.set_handler_fn(simd_floating_point_handler);
|
||||
idt.virtualization.set_handler_fn(virtualization_handler);
|
||||
|
||||
idt
|
||||
};
|
||||
}
|
||||
|
||||
pub fn init() {
|
||||
IDT.load();
|
||||
}
|
||||
|
||||
pub fn print_info() {
|
||||
kprintln!("IDT Information:");
|
||||
kprintln!(" IDT loaded and active");
|
||||
kprintln!(" Exception handlers registered");
|
||||
}
|
||||
211
kernel/src/kernel/asm/x86/interrupt.rs
Normal file
211
kernel/src/kernel/asm/x86/interrupt.rs
Normal file
@ -0,0 +1,211 @@
|
||||
// kernel/src/kernel/asm/x86/interrupt.rs
|
||||
use x86_64::structures::idt::{InterruptStackFrame, PageFaultErrorCode};
|
||||
use crate::kprintln;
|
||||
|
||||
/// Divide Error (#DE)
|
||||
pub extern "x86-interrupt" fn divide_error_handler(stack_frame: InterruptStackFrame) {
|
||||
kprintln!();
|
||||
kprintln!("EXCEPTION: DIVIDE ERROR (#DE)");
|
||||
kprintln!("{:#?}", stack_frame);
|
||||
loop {
|
||||
crate::hal::cpu::cpu_halt();
|
||||
}
|
||||
}
|
||||
|
||||
/// Debug Exception (#DB)
|
||||
pub extern "x86-interrupt" fn debug_handler(stack_frame: InterruptStackFrame) {
|
||||
kprintln!();
|
||||
kprintln!("EXCEPTION: DEBUG (#DB)");
|
||||
kprintln!("{:#?}", stack_frame);
|
||||
}
|
||||
|
||||
/// Non-Maskable Interrupt (NMI)
|
||||
pub extern "x86-interrupt" fn nmi_handler(stack_frame: InterruptStackFrame) {
|
||||
kprintln!();
|
||||
kprintln!("EXCEPTION: NON-MASKABLE INTERRUPT (NMI)");
|
||||
kprintln!("{:#?}", stack_frame);
|
||||
}
|
||||
|
||||
/// Breakpoint (#BP)
|
||||
pub extern "x86-interrupt" fn breakpoint_handler(stack_frame: InterruptStackFrame) {
|
||||
kprintln!();
|
||||
kprintln!("EXCEPTION: BREAKPOINT (#BP)");
|
||||
kprintln!("{:#?}", stack_frame);
|
||||
}
|
||||
|
||||
/// Overflow (#OF)
|
||||
pub extern "x86-interrupt" fn overflow_handler(stack_frame: InterruptStackFrame) {
|
||||
kprintln!();
|
||||
kprintln!("EXCEPTION: OVERFLOW (#OF)");
|
||||
kprintln!("{:#?}", stack_frame);
|
||||
loop {
|
||||
crate::hal::cpu::cpu_halt();
|
||||
}
|
||||
}
|
||||
|
||||
/// Bound Range Exceeded (#BR)
|
||||
pub extern "x86-interrupt" fn bound_range_handler(stack_frame: InterruptStackFrame) {
|
||||
kprintln!();
|
||||
kprintln!("EXCEPTION: BOUND RANGE EXCEEDED (#BR)");
|
||||
kprintln!("{:#?}", stack_frame);
|
||||
loop {
|
||||
crate::hal::cpu::cpu_halt();
|
||||
}
|
||||
}
|
||||
|
||||
/// Invalid Opcode (#UD)
|
||||
pub extern "x86-interrupt" fn invalid_opcode_handler(stack_frame: InterruptStackFrame) {
|
||||
kprintln!();
|
||||
kprintln!("EXCEPTION: INVALID OPCODE (#UD)");
|
||||
kprintln!("{:#?}", stack_frame);
|
||||
loop {
|
||||
crate::hal::cpu::cpu_halt();
|
||||
}
|
||||
}
|
||||
|
||||
/// Device Not Available (#NM)
|
||||
pub extern "x86-interrupt" fn device_not_available_handler(stack_frame: InterruptStackFrame) {
|
||||
kprintln!();
|
||||
kprintln!("EXCEPTION: DEVICE NOT AVAILABLE (#NM)");
|
||||
kprintln!("{:#?}", stack_frame);
|
||||
loop {
|
||||
crate::hal::cpu::cpu_halt();
|
||||
}
|
||||
}
|
||||
|
||||
/// Double Fault (#DF)
|
||||
pub extern "x86-interrupt" fn double_fault_handler(
|
||||
stack_frame: InterruptStackFrame,
|
||||
error_code: u64,
|
||||
) -> ! {
|
||||
panic!("EXCEPTION: DOUBLE FAULT (#DF)\nError Code: {}\n{:#?}", error_code, stack_frame);
|
||||
}
|
||||
|
||||
/// Invalid TSS (#TS)
|
||||
pub extern "x86-interrupt" fn invalid_tss_handler(
|
||||
stack_frame: InterruptStackFrame,
|
||||
error_code: u64,
|
||||
) {
|
||||
kprintln!();
|
||||
kprintln!("EXCEPTION: INVALID TSS (#TS)");
|
||||
kprintln!("Error Code: {:#x}", error_code);
|
||||
kprintln!("{:#?}", stack_frame);
|
||||
loop {
|
||||
crate::hal::cpu::cpu_halt();
|
||||
}
|
||||
}
|
||||
|
||||
/// Segment Not Present (#NP)
|
||||
pub extern "x86-interrupt" fn segment_not_present_handler(
|
||||
stack_frame: InterruptStackFrame,
|
||||
error_code: u64,
|
||||
) {
|
||||
kprintln!();
|
||||
kprintln!("EXCEPTION: SEGMENT NOT PRESENT (#NP)");
|
||||
kprintln!("Error Code: {:#x}", error_code);
|
||||
kprintln!("{:#?}", stack_frame);
|
||||
loop {
|
||||
crate::hal::cpu::cpu_halt();
|
||||
}
|
||||
}
|
||||
|
||||
/// Stack Segment Fault (#SS)
|
||||
pub extern "x86-interrupt" fn stack_segment_fault_handler(
|
||||
stack_frame: InterruptStackFrame,
|
||||
error_code: u64,
|
||||
) {
|
||||
kprintln!();
|
||||
kprintln!("EXCEPTION: STACK SEGMENT FAULT (#SS)");
|
||||
kprintln!("Error Code: {:#x}", error_code);
|
||||
kprintln!("{:#?}", stack_frame);
|
||||
loop {
|
||||
crate::hal::cpu::cpu_halt();
|
||||
}
|
||||
}
|
||||
|
||||
/// General Protection Fault (#GP)
|
||||
pub extern "x86-interrupt" fn general_protection_fault_handler(
|
||||
stack_frame: InterruptStackFrame,
|
||||
error_code: u64,
|
||||
) {
|
||||
kprintln!();
|
||||
kprintln!("EXCEPTION: GENERAL PROTECTION FAULT (#GP)");
|
||||
kprintln!("Error Code: {:#x}", error_code);
|
||||
kprintln!("{:#?}", stack_frame);
|
||||
loop {
|
||||
crate::hal::cpu::cpu_halt();
|
||||
}
|
||||
}
|
||||
|
||||
/// Page Fault (#PF)
|
||||
pub extern "x86-interrupt" fn page_fault_handler(
|
||||
stack_frame: InterruptStackFrame,
|
||||
error_code: PageFaultErrorCode,
|
||||
) {
|
||||
use x86_64::registers::control::Cr2;
|
||||
|
||||
kprintln!();
|
||||
kprintln!("EXCEPTION: PAGE FAULT (#PF)");
|
||||
kprintln!("Accessed Address: {:?}", Cr2::read());
|
||||
kprintln!("Error Code: {:?}", error_code);
|
||||
kprintln!(" - Present: {}", error_code.contains(PageFaultErrorCode::PROTECTION_VIOLATION));
|
||||
kprintln!(" - Write: {}", error_code.contains(PageFaultErrorCode::CAUSED_BY_WRITE));
|
||||
kprintln!(" - User: {}", error_code.contains(PageFaultErrorCode::USER_MODE));
|
||||
kprintln!(" - Reserved Write: {}", error_code.contains(PageFaultErrorCode::MALFORMED_TABLE));
|
||||
kprintln!(" - Instruction Fetch: {}", error_code.contains(PageFaultErrorCode::INSTRUCTION_FETCH));
|
||||
kprintln!("{:#?}", stack_frame);
|
||||
loop {
|
||||
crate::hal::cpu::cpu_halt();
|
||||
}
|
||||
}
|
||||
|
||||
/// x87 Floating-Point Exception (#MF)
|
||||
pub extern "x86-interrupt" fn x87_floating_point_handler(stack_frame: InterruptStackFrame) {
|
||||
kprintln!();
|
||||
kprintln!("EXCEPTION: x87 FLOATING POINT (#MF)");
|
||||
kprintln!("{:#?}", stack_frame);
|
||||
loop {
|
||||
crate::hal::cpu::cpu_halt();
|
||||
}
|
||||
}
|
||||
|
||||
/// Alignment Check (#AC)
|
||||
pub extern "x86-interrupt" fn alignment_check_handler(
|
||||
stack_frame: InterruptStackFrame,
|
||||
error_code: u64,
|
||||
) {
|
||||
kprintln!();
|
||||
kprintln!("EXCEPTION: ALIGNMENT CHECK (#AC)");
|
||||
kprintln!("Error Code: {:#x}", error_code);
|
||||
kprintln!("{:#?}", stack_frame);
|
||||
loop {
|
||||
crate::hal::cpu::cpu_halt();
|
||||
}
|
||||
}
|
||||
|
||||
/// Machine Check (#MC)
|
||||
pub extern "x86-interrupt" fn machine_check_handler(stack_frame: InterruptStackFrame) -> ! {
|
||||
panic!("EXCEPTION: MACHINE CHECK (#MC)\n{:#?}", stack_frame);
|
||||
}
|
||||
|
||||
/// SIMD Floating-Point Exception (#XM/#XF)
|
||||
pub extern "x86-interrupt" fn simd_floating_point_handler(stack_frame: InterruptStackFrame) {
|
||||
kprintln!();
|
||||
kprintln!("EXCEPTION: SIMD FLOATING POINT (#XM/#XF)");
|
||||
kprintln!("{:#?}", stack_frame);
|
||||
loop {
|
||||
crate::hal::cpu::cpu_halt();
|
||||
}
|
||||
}
|
||||
|
||||
/// Virtualization Exception (#VE)
|
||||
pub extern "x86-interrupt" fn virtualization_handler(stack_frame: InterruptStackFrame) {
|
||||
kprintln!();
|
||||
kprintln!("EXCEPTION: VIRTUALIZATION (#VE)");
|
||||
kprintln!("{:#?}", stack_frame);
|
||||
loop {
|
||||
crate::hal::cpu::cpu_halt();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Timer interrupt, Keyboard interrupt
|
||||
@ -1,4 +1,4 @@
|
||||
pub mod gdt;
|
||||
pub mod idt;
|
||||
pub mod interrupt;
|
||||
pub mod segment;
|
||||
// pub mod segment;
|
||||
@ -1,4 +1,3 @@
|
||||
pub mod kernel;
|
||||
pub mod tty;
|
||||
pub mod asm;
|
||||
|
||||
133
kernel/src/kernel/tty/font.rs
Normal file
133
kernel/src/kernel/tty/font.rs
Normal file
@ -0,0 +1,133 @@
|
||||
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub static FONT_BASIC: [[u8; 16]; 128] = [
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x00,
|
||||
[ 0x00, 0x00, 0x7E, 0x81, 0xA5, 0x81, 0x81, 0xBD, 0x99, 0x81, 0x81, 0x7E, 0x00, 0x00, 0x00, 0x00, ], //0x01,
|
||||
[ 0x00, 0x00, 0x7E, 0xFF, 0xDB, 0xFF, 0xFF, 0xC3, 0xE7, 0xFF, 0xFF, 0x7E, 0x00, 0x00, 0x00, 0x00, ], //0x02,
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x6C, 0xFE, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, ], //0x03,
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x04,
|
||||
[ 0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0xE7, 0xE7, 0xE7, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, ], //0x05,
|
||||
[ 0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, ], //0x06,
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x07,
|
||||
[ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ], //0x08,
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x09,
|
||||
[ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ], //0x0A,
|
||||
[ 0x00, 0x00, 0x1E, 0x0E, 0x1A, 0x32, 0x78, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00, ], //0x0B,
|
||||
[ 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, ], //0x0C,
|
||||
[ 0x00, 0x00, 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x30, 0x30, 0x70, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00, ], //0x0D,
|
||||
[ 0x00, 0x00, 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x67, 0xE7, 0xE6, 0xC0, 0x00, 0x00, 0x00, ], //0x0E,
|
||||
[ 0x00, 0x00, 0x00, 0x18, 0x18, 0xDB, 0x3C, 0xE7, 0x3C, 0xDB, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, ], //0x0F,
|
||||
[ 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFE, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, ], //0x10,
|
||||
[ 0x00, 0x02, 0x06, 0x0E, 0x1E, 0x3E, 0xFE, 0x3E, 0x1E, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, ], //0x11,
|
||||
[ 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x12,
|
||||
[ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, ], //0x13,
|
||||
[ 0x00, 0x00, 0x7F, 0xDB, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, 0x00, 0x00, ], //0x14,
|
||||
[ 0x00, 0x7C, 0xC6, 0x60, 0x38, 0x6C, 0xC6, 0xC6, 0x6C, 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00, ], //0x15,
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, ], //0x16,
|
||||
[ 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00, ], //0x17,
|
||||
[ 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, ], //0x18,
|
||||
[ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, ], //0x19,
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x1A,
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x1B, esc
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x1C,
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6C, 0xFE, 0x6C, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x1D,
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7C, 0x7C, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x1E,
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x7C, 0x7C, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x1F,
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x20, ' '
|
||||
[ 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, ], //0x21, '!'
|
||||
[ 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x22, '"'
|
||||
[ 0x00, 0x00, 0x00, 0x6C, 0x6C, 0xFE, 0x6C, 0x6C, 0x6C, 0xFE, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, ], //0x23, '#'
|
||||
[ 0x18, 0x18, 0x7C, 0xC6, 0xC2, 0xC0, 0x7C, 0x06, 0x06, 0x86, 0xC6, 0x7C, 0x18, 0x18, 0x00, 0x00, ], //0x24, '$'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0xC2, 0xC6, 0x0C, 0x18, 0x30, 0x60, 0xC6, 0x86, 0x00, 0x00, 0x00, 0x00, ], //0x25, '%'
|
||||
[ 0x00, 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, ], //0x26, '&'
|
||||
[ 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x27, '''
|
||||
[ 0x00, 0x00, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00, ], //0x28, '('
|
||||
[ 0x00, 0x00, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, ], //0x29, ')'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x2A, '*'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x2B, '+'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, ], //0x2C, '
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x2D, '-'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, ], //0x2E, '.'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, ], //0x2F, '/'
|
||||
[ 0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xD6, 0xD6, 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, ], //0x30, '0'
|
||||
[ 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00, ], //0x31, '1'
|
||||
[ 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, ], //0x32, '2'
|
||||
[ 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x33, '3'
|
||||
[ 0x00, 0x00, 0x0C, 0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x0C, 0x0C, 0x1E, 0x00, 0x00, 0x00, 0x00, ], //0x34, '4'
|
||||
[ 0x00, 0x00, 0xFE, 0xC0, 0xC0, 0xC0, 0xFC, 0x06, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x35, '5'
|
||||
[ 0x00, 0x00, 0x38, 0x60, 0xC0, 0xC0, 0xFC, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x36, '6'
|
||||
[ 0x00, 0x00, 0xFE, 0xC6, 0x06, 0x06, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, ], //0x37, '7'
|
||||
[ 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x38, '8'
|
||||
[ 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x06, 0x0C, 0x78, 0x00, 0x00, 0x00, 0x00, ], //0x39, '9'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x3A, ':'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, ], //0x3B, ';'
|
||||
[ 0x00, 0x00, 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, ], //0x3C, '<'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x3D, '='
|
||||
[ 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, ], //0x3E, '>'
|
||||
[ 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x0C, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, ], //0x3F, '?'
|
||||
[ 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xDE, 0xDE, 0xDE, 0xDC, 0xC0, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x40, '@'
|
||||
[ 0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, ], //0x41, 'A'
|
||||
[ 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00, ], //0x42, 'B'
|
||||
[ 0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xC0, 0xC0, 0xC2, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, ], //0x43, 'C'
|
||||
[ 0x00, 0x00, 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00, 0x00, 0x00, 0x00, ], //0x44, 'D'
|
||||
[ 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00, ], //0x45, 'E'
|
||||
[ 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, ], //0x46, 'F'
|
||||
[ 0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xDE, 0xC6, 0xC6, 0x66, 0x3A, 0x00, 0x00, 0x00, 0x00, ], //0x47, 'G'
|
||||
[ 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, ], //0x48, 'H'
|
||||
[ 0x00, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, ], //0x49, 'I'
|
||||
[ 0x00, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00, ], //0x4A, 'J'
|
||||
[ 0x00, 0x00, 0xE6, 0x66, 0x66, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, ], //0x4B, 'K'
|
||||
[ 0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00, ], //0x4C, 'L'
|
||||
[ 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, ], //0x4D, 'M'
|
||||
[ 0x00, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE, 0xCE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, ], //0x4E, 'N'
|
||||
[ 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x4F, 'O'
|
||||
[ 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, ], //0x50, 'P'
|
||||
[ 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xDE, 0x7C, 0x0C, 0x0E, 0x00, 0x00, ], //0x51, 'Q'
|
||||
[ 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, ], //0x52, 'R'
|
||||
[ 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x60, 0x38, 0x0C, 0x06, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x53, 'S'
|
||||
[ 0x00, 0x00, 0x7E, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, ], //0x54, 'T'
|
||||
[ 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x55, 'U'
|
||||
[ 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, ], //0x56, 'V'
|
||||
[ 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xD6, 0xD6, 0xFE, 0xEE, 0x6C, 0x00, 0x00, 0x00, 0x00, ], //0x57, 'W'
|
||||
[ 0x00, 0x00, 0xC6, 0xC6, 0x6C, 0x7C, 0x38, 0x38, 0x7C, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, ], //0x58, 'X'
|
||||
[ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, ], //0x59, 'Y'
|
||||
[ 0x00, 0x00, 0xFE, 0xC6, 0x86, 0x0C, 0x18, 0x30, 0x60, 0xC2, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, ], //0x5A, 'Z'
|
||||
[ 0x00, 0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0x00, 0x00, 0x00, 0x00, ], //0x5B, '['
|
||||
[ 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, ], //0x5C, '\'
|
||||
[ 0x00, 0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0x00, 0x00, 0x00, 0x00, ], //0x5D, ']'
|
||||
[ 0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x5E, '^'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, ], //0x5F, '_'
|
||||
[ 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x60, '`'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, ], //0x61, 'a'
|
||||
[ 0x00, 0x00, 0xE0, 0x60, 0x60, 0x78, 0x6C, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x62, 'b'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x63, 'c'
|
||||
[ 0x00, 0x00, 0x1C, 0x0C, 0x0C, 0x3C, 0x6C, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, ], //0x64, 'd'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x65, 'e'
|
||||
[ 0x00, 0x00, 0x38, 0x6C, 0x64, 0x60, 0xF0, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, ], //0x66, 'f'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xCC, 0x78, 0x00, ], //0x67, 'g'
|
||||
[ 0x00, 0x00, 0xE0, 0x60, 0x60, 0x6C, 0x76, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, ], //0x68, 'h'
|
||||
[ 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, ], //0x69, 'i'
|
||||
[ 0x00, 0x00, 0x06, 0x06, 0x00, 0x0E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3C, 0x00, ], //0x6A, 'j'
|
||||
[ 0x00, 0x00, 0xE0, 0x60, 0x60, 0x66, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, ], //0x6B, 'k'
|
||||
[ 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, ], //0x6C, 'l'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xFE, 0xD6, 0xD6, 0xD6, 0xD6, 0xC6, 0x00, 0x00, 0x00, 0x00, ], //0x6D, 'm'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, ], //0x6E, 'n'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x6F, 'o'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00, ], //0x70, 'p'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0x0C, 0x1E, 0x00, ], //0x71, 'q'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x76, 0x66, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, ], //0x72, 'r'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x60, 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x73, 's'
|
||||
[ 0x00, 0x00, 0x10, 0x30, 0x30, 0xFC, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00, ], //0x74, 't'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, ], //0x75, 'u'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, ], //0x76, 'v'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xD6, 0xD6, 0xD6, 0xFE, 0x6C, 0x00, 0x00, 0x00, 0x00, ], //0x77, 'w'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x38, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00, ], //0x78, 'x'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0xF8, 0x00, ], //0x79, 'y'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xCC, 0x18, 0x30, 0x60, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, ], //0x7A, 'z'
|
||||
[ 0x00, 0x00, 0x0E, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0E, 0x00, 0x00, 0x00, 0x00, ], //0x7B, '['
|
||||
[ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, ], //0x7C, '|'
|
||||
[ 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, ], //0x7D, ']'
|
||||
[ 0x00, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x7E, '~'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x7F, delete
|
||||
];
|
||||
4
kernel/src/kernel/tty/mod.rs
Normal file
4
kernel/src/kernel/tty/mod.rs
Normal file
@ -0,0 +1,4 @@
|
||||
// src/kernel/tty/mod.rs
|
||||
|
||||
pub mod tty;
|
||||
pub mod font;
|
||||
186
kernel/src/kernel/tty/tty.rs
Normal file
186
kernel/src/kernel/tty/tty.rs
Normal file
@ -0,0 +1,186 @@
|
||||
use bootloader_api::info::{FrameBuffer, FrameBufferInfo, PixelFormat};
|
||||
use crate::kernel::tty::font::FONT_BASIC;
|
||||
use core::ptr::{addr_of, addr_of_mut};
|
||||
|
||||
pub struct TTYState {
|
||||
framebuffer: *mut u8,
|
||||
fb_len: usize,
|
||||
info: Option<FrameBufferInfo>,
|
||||
cursor_x: usize,
|
||||
cursor_y: usize,
|
||||
}
|
||||
|
||||
impl TTYState {
|
||||
const fn new() -> Self {
|
||||
Self {
|
||||
framebuffer: core::ptr::null_mut(),
|
||||
fb_len: 0,
|
||||
info: None,
|
||||
cursor_x: 0,
|
||||
cursor_y: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static mut TTY_STATE: TTYState = TTYState::new();
|
||||
|
||||
pub fn init(framebuffer: &'static mut FrameBuffer) {
|
||||
let info = framebuffer.info();
|
||||
let buffer = framebuffer.buffer_mut();
|
||||
|
||||
unsafe {
|
||||
let state = &mut *addr_of_mut!(TTY_STATE);
|
||||
state.framebuffer = buffer.as_mut_ptr();
|
||||
state.fb_len = buffer.len();
|
||||
state.info = Some(info);
|
||||
state.cursor_x = 0;
|
||||
state.cursor_y = 0;
|
||||
}
|
||||
|
||||
clear(0x000000);
|
||||
}
|
||||
|
||||
pub fn clear(color: u32) {
|
||||
unsafe {
|
||||
let state = &*addr_of!(TTY_STATE);
|
||||
|
||||
if state.framebuffer.is_null() {
|
||||
return;
|
||||
}
|
||||
|
||||
let info = match state.info.as_ref() {
|
||||
Some(i) => i,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let (r, g, b) = u32_to_rgb(color);
|
||||
let buffer = core::slice::from_raw_parts_mut(state.framebuffer, state.fb_len);
|
||||
|
||||
for pixel in buffer.chunks_exact_mut(info.bytes_per_pixel) {
|
||||
write_pixel(info, pixel, r, g, b);
|
||||
}
|
||||
|
||||
let state_mut = &mut *addr_of_mut!(TTY_STATE);
|
||||
state_mut.cursor_x = 0;
|
||||
state_mut.cursor_y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
fn write_pixel(info: &FrameBufferInfo, pixel: &mut [u8], r: u8, g: u8, b: u8) {
|
||||
match info.pixel_format {
|
||||
PixelFormat::Rgb => {
|
||||
pixel[0] = r;
|
||||
pixel[1] = g;
|
||||
pixel[2] = b;
|
||||
}
|
||||
PixelFormat::Bgr => {
|
||||
pixel[0] = b;
|
||||
pixel[1] = g;
|
||||
pixel[2] = r;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_pixel(x: usize, y: usize, color: u32) {
|
||||
unsafe {
|
||||
let state = &*addr_of!(TTY_STATE);
|
||||
|
||||
if state.framebuffer.is_null() {
|
||||
return;
|
||||
}
|
||||
|
||||
let info = match state.info.as_ref() {
|
||||
Some(i) => i,
|
||||
None => return,
|
||||
};
|
||||
|
||||
if x >= info.width || y >= info.height {
|
||||
return;
|
||||
}
|
||||
|
||||
let pixel_offset = (y * info.stride + x) * info.bytes_per_pixel;
|
||||
let (r, g, b) = u32_to_rgb(color);
|
||||
|
||||
let buffer = core::slice::from_raw_parts_mut(state.framebuffer, state.fb_len);
|
||||
|
||||
if let Some(pixel) = buffer.get_mut(pixel_offset..pixel_offset + info.bytes_per_pixel) {
|
||||
write_pixel(info, pixel, r, g, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_char(c: char, color: u32) {
|
||||
const CHAR_WIDTH: usize = 8;
|
||||
const CHAR_HEIGHT: usize = 16;
|
||||
|
||||
unsafe {
|
||||
let state = &*addr_of!(TTY_STATE);
|
||||
|
||||
if state.framebuffer.is_null() {
|
||||
return;
|
||||
}
|
||||
|
||||
let info = match state.info.as_ref() {
|
||||
Some(i) => i,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let state_mut = &mut *addr_of_mut!(TTY_STATE);
|
||||
|
||||
if c == '\n' {
|
||||
state_mut.cursor_x = 0;
|
||||
state_mut.cursor_y += CHAR_HEIGHT;
|
||||
return;
|
||||
}
|
||||
|
||||
if state_mut.cursor_x + CHAR_WIDTH > info.width {
|
||||
state_mut.cursor_x = 0;
|
||||
state_mut.cursor_y += CHAR_HEIGHT;
|
||||
}
|
||||
|
||||
if state_mut.cursor_y + CHAR_HEIGHT > info.height {
|
||||
state_mut.cursor_y = 0;
|
||||
}
|
||||
|
||||
let idx = c as usize;
|
||||
if idx >= FONT_BASIC.len() {
|
||||
return;
|
||||
}
|
||||
let glyph = &FONT_BASIC[idx];
|
||||
|
||||
let cursor_x = state_mut.cursor_x;
|
||||
let cursor_y = state_mut.cursor_y;
|
||||
|
||||
for (y, row) in glyph.iter().enumerate() {
|
||||
for x in 0..8 {
|
||||
if (row >> (7 - x)) & 1 == 1 {
|
||||
draw_pixel(cursor_x + x, cursor_y + y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state_mut.cursor_x += CHAR_WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_str(s: &str, color: u32) {
|
||||
for c in s.chars() {
|
||||
draw_char(c, color);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tty_put_str(s: &str, color: Option<u32>) {
|
||||
if let Some(c) = color {
|
||||
write_str(s, c);
|
||||
} else {
|
||||
write_str(s, 0xFFFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
fn u32_to_rgb(color: u32) -> (u8, u8, u8) {
|
||||
let r = ((color >> 16) & 0xFF) as u8;
|
||||
let g = ((color >> 8) & 0xFF) as u8;
|
||||
let b = (color & 0xFF) as u8;
|
||||
(r, g, b)
|
||||
}
|
||||
@ -7,7 +7,7 @@ pub struct Writer;
|
||||
|
||||
impl fmt::Write for Writer {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
tty::tty_put_str(s);
|
||||
tty::tty_put_str(s, None);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -23,7 +23,11 @@ macro_rules! print {
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! println {
|
||||
() => ($crate::print!("\n"));
|
||||
($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*)));
|
||||
macro_rules! kprintln {
|
||||
() => {
|
||||
$crate::libs::libc::print::_print(format_args!("\n"))
|
||||
};
|
||||
($($arg:tt)*) => {
|
||||
$crate::libs::libc::print::_print(format_args!("{}\n", format_args!($($arg)*)))
|
||||
};
|
||||
}
|
||||
0
kernel/src/logger.rs
Normal file
0
kernel/src/logger.rs
Normal file
83
kernel/src/main.rs
Normal file
83
kernel/src/main.rs
Normal file
@ -0,0 +1,83 @@
|
||||
// kernel/src/main.rs
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(abi_x86_interrupt)]
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
use bootloader_api::{entry_point, BootInfo};
|
||||
|
||||
mod kernel;
|
||||
mod hal;
|
||||
mod libs;
|
||||
mod logger;
|
||||
|
||||
use kernel::tty::tty;
|
||||
use kernel::asm::x86::{gdt, idt};
|
||||
use hal::cpu;
|
||||
|
||||
|
||||
entry_point!(kernel_main);
|
||||
|
||||
fn kernel_main(boot_info: &'static mut BootInfo) -> ! {
|
||||
if let Some(framebuffer) = boot_info.framebuffer.as_mut() {
|
||||
tty::init(framebuffer);
|
||||
tty::clear(0x000000);
|
||||
|
||||
kprintln!("CureOS Booting...");
|
||||
kprintln!("Framebuffer initialized");
|
||||
|
||||
kprintln!("Initializing GDT...");
|
||||
gdt::init();
|
||||
kprintln!("GDT initialized");
|
||||
gdt::print_info();
|
||||
kprintln!();
|
||||
|
||||
kprintln!("Initializing IDT...");
|
||||
idt::init();
|
||||
kprintln!("IDT initialized");
|
||||
idt::print_info();
|
||||
kprintln!();
|
||||
|
||||
kprintln!("Welcome to CureOS!");
|
||||
|
||||
let mut brand_buf = [0u8; 64];
|
||||
let mut model_buf = [0u8; 16];
|
||||
kprintln!("CPU: {} ({})",
|
||||
cpu::cpu_get_brand(&mut brand_buf),
|
||||
cpu::cpu_get_model(&mut model_buf)
|
||||
);
|
||||
|
||||
kprintln!();
|
||||
kprintln!("Control Registers:");
|
||||
kprintln!(" CR0: 0x{:016x}", hal::cpu::cpu_r_cr0().bits());
|
||||
kprintln!(" CR2: 0x{:016x}", hal::cpu::cpu_r_cr2());
|
||||
kprintln!(" CR3: 0x{:016x}", hal::cpu::cpu_r_cr3());
|
||||
kprintln!(" CR4: 0x{:016x}", hal::cpu::cpu_r_cr4().bits());
|
||||
|
||||
kprintln!();
|
||||
kprintln!("Kernel initialized successfully!");
|
||||
|
||||
} else {
|
||||
loop {
|
||||
hal::cpu::cpu_halt();
|
||||
}
|
||||
}
|
||||
|
||||
loop {
|
||||
hal::cpu::cpu_halt();
|
||||
}
|
||||
}
|
||||
#[cfg(not(test))]
|
||||
#[panic_handler]
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
kprintln!();
|
||||
kprintln!("================================");
|
||||
kprintln!(" KERNEL PANIC!" );
|
||||
kprintln!("================================");
|
||||
kprintln!();
|
||||
kprintln!("{}", info);
|
||||
|
||||
loop {
|
||||
hal::cpu::cpu_halt();
|
||||
}
|
||||
}
|
||||
225
makefile
225
makefile
@ -3,75 +3,188 @@ include config/make-os
|
||||
include config/make-cc
|
||||
include config/make-debug-tool
|
||||
|
||||
# Rust 構建配置
|
||||
BUILD_MODE := release
|
||||
CARGO_FLAGS :=
|
||||
RUST_TARGET := i686-unknown-linux-gnu
|
||||
CARGO_FLAGS := --release
|
||||
ifeq ($(BUILD_MODE),debug)
|
||||
CARGO_FLAGS :=
|
||||
endif
|
||||
|
||||
INCLUDES := $(patsubst %, -I%, $(INCLUDES_DIR))
|
||||
SOURCE_FILES := $(shell find -name "*.[cS]")
|
||||
SRC := $(patsubst ./%, $(OBJECT_DIR)/%.o, $(SOURCE_FILES))
|
||||
# 目標和輸出
|
||||
RUST_TARGET := x86_64-unknown-none
|
||||
BUILDER_PKG := cure-builder
|
||||
DISK_IMAGE := cure-os.img
|
||||
|
||||
$(OBJECT_DIR):
|
||||
@mkdir -p $(OBJECT_DIR)
|
||||
# 顏色輸出
|
||||
COLOR_RESET := \033[0m
|
||||
COLOR_GREEN := \033[32m
|
||||
COLOR_YELLOW := \033[33m
|
||||
COLOR_BLUE := \033[34m
|
||||
COLOR_RED := \033[31m
|
||||
|
||||
.PHONY: all rust-build run clean debug-bochs debug-qemu help all-debug
|
||||
|
||||
# 創建目錄(先清理)
|
||||
$(BUILD_DIR):
|
||||
@rm -rf $(BUILD_DIR)
|
||||
@mkdir -p $(BUILD_DIR)
|
||||
|
||||
$(BIN_DIR):
|
||||
@mkdir -p $(BIN_DIR)
|
||||
|
||||
$(ISO_DIR):
|
||||
@mkdir -p $(ISO_DIR)
|
||||
@mkdir -p $(ISO_BOOT_DIR)
|
||||
@mkdir -p $(ISO_GRUB_DIR)
|
||||
# 默認目標
|
||||
all: clean-build rust-build copy-artifacts
|
||||
|
||||
rust-kernel:
|
||||
@echo "Building Rust kernel..."
|
||||
@cargo build $(CARGO_FLAGS)
|
||||
|
||||
$(OBJECT_DIR)/%.S.o: %.S
|
||||
@mkdir -p $(@D)
|
||||
@echo "Compiling: $< -> $@"
|
||||
@$(CC) $(INCLUDES) -c $< -o $@
|
||||
|
||||
$(OBJECT_DIR)/%.c.o: %.c
|
||||
@mkdir -p $(@D)
|
||||
@echo "Compiling: $< -> $@"
|
||||
@$(CC) $(INCLUDES) -c $< -o $@ $(CFLAGS)
|
||||
|
||||
$(BIN_DIR)/$(OS_BIN): $(OBJECT_DIR) $(BIN_DIR) rust-kernel $(SRC)
|
||||
@echo "Linking..."
|
||||
@cp target/$(RUST_TARGET)/$(BUILD_MODE)/libcure.a $(OBJECT_DIR)/
|
||||
@$(CC) -T linker.ld -o $(BIN_DIR)/$(OS_BIN) $(SRC) $(OBJECT_DIR)/libcure.a $(LDFLAGS)
|
||||
|
||||
$(BUILD_DIR)/$(OS_ISO): $(ISO_DIR) $(BIN_DIR)/$(OS_BIN) GRUB_TEMPLATE
|
||||
@./config-grub.sh ${OS_NAME} $(ISO_GRUB_DIR)/grub.cfg
|
||||
@cp $(BIN_DIR)/$(OS_BIN) $(ISO_BOOT_DIR)
|
||||
@grub-mkrescue -o $(BUILD_DIR)/$(OS_ISO) $(ISO_DIR)
|
||||
|
||||
all: clean $(BUILD_DIR)/$(OS_ISO)
|
||||
|
||||
all-debug: BUILD_MODE := debug
|
||||
all-debug: CARGO_FLAGS := --features debug
|
||||
all-debug: O := -Og
|
||||
all-debug: CFLAGS := -g -std=gnu99 -ffreestanding $(O) $(W) $(ARCH_OPT)
|
||||
all-debug: LDFLAGS := -g -ffreestanding $(O) -nostdlib -lgcc
|
||||
all-debug: clean $(BUILD_DIR)/$(OS_ISO)
|
||||
@echo "Dumping the disassembled kernel code to $(BUILD_DIR)/dump.txt"
|
||||
@$(OBJDUMP) -D $(BIN_DIR)/$(OS_BIN) > $(BUILD_DIR)/dump.txt
|
||||
|
||||
clean:
|
||||
# 清理 build 目錄
|
||||
clean-build:
|
||||
@echo "$(COLOR_YELLOW)Cleaning build directory...$(COLOR_RESET)"
|
||||
@rm -rf $(BUILD_DIR)
|
||||
|
||||
# 構建內核
|
||||
rust-build:
|
||||
@echo "$(COLOR_BLUE)Building CureOS...$(COLOR_RESET)"
|
||||
@cargo build -p $(BUILDER_PKG) $(CARGO_FLAGS)
|
||||
@echo "$(COLOR_GREEN)✓ Build complete$(COLOR_RESET)"
|
||||
|
||||
# 複製構建產物到 build/ 目錄
|
||||
copy-artifacts: $(BUILD_DIR) $(BIN_DIR)
|
||||
@echo "$(COLOR_BLUE)Copying build artifacts...$(COLOR_RESET)"
|
||||
@BIOS_IMG=$$(find target -name "cure-bios.img" -type f | head -1); \
|
||||
UEFI_IMG=$$(find target -name "cure-uefi.img" -type f | head -1); \
|
||||
KERNEL_BIN=$$(find target/$(RUST_TARGET)/$(BUILD_MODE) -name "cure-kernel" -type f | head -1); \
|
||||
if [ -n "$$BIOS_IMG" ]; then \
|
||||
echo "$(COLOR_YELLOW) → $(BUILD_DIR)/cure-bios.img$(COLOR_RESET)"; \
|
||||
cp "$$BIOS_IMG" $(BUILD_DIR)/cure-bios.img; \
|
||||
fi; \
|
||||
if [ -n "$$UEFI_IMG" ]; then \
|
||||
echo "$(COLOR_YELLOW) → $(BUILD_DIR)/cure-uefi.img$(COLOR_RESET)"; \
|
||||
cp "$$UEFI_IMG" $(BUILD_DIR)/cure-uefi.img; \
|
||||
fi; \
|
||||
if [ -n "$$KERNEL_BIN" ]; then \
|
||||
echo "$(COLOR_YELLOW) → $(BIN_DIR)/$(OS_BIN)$(COLOR_RESET)"; \
|
||||
cp "$$KERNEL_BIN" $(BIN_DIR)/$(OS_BIN); \
|
||||
fi
|
||||
|
||||
@echo "$(COLOR_GREEN)✓ Artifacts copied$(COLOR_RESET)"
|
||||
|
||||
# Debug 構建(包含 dump)
|
||||
all-debug: BUILD_MODE := debug
|
||||
all-debug: CARGO_FLAGS :=
|
||||
all-debug: clean-build rust-build copy-artifacts dump
|
||||
|
||||
# 生成反彙編 dump
|
||||
dump:
|
||||
@echo "$(COLOR_BLUE)Generating disassembly dump...$(COLOR_RESET)"
|
||||
@if [ -f "$(BIN_DIR)/$(OS_BIN)" ]; then \
|
||||
echo "$(COLOR_YELLOW)Dumping to $(BUILD_DIR)/dump.txt$(COLOR_RESET)"; \
|
||||
objdump -D $(BIN_DIR)/$(OS_BIN) > $(BUILD_DIR)/dump.txt; \
|
||||
echo "$(COLOR_GREEN)✓ Dump complete$(COLOR_RESET)"; \
|
||||
else \
|
||||
echo "$(COLOR_RED)Error: Kernel binary not found$(COLOR_RESET)"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
# 完全清理
|
||||
clean:
|
||||
@echo "$(COLOR_YELLOW)Cleaning all build artifacts...$(COLOR_RESET)"
|
||||
@cargo clean
|
||||
@rm -rf $(BUILD_DIR)
|
||||
@rm -f $(DISK_IMAGE) bochs.log serial.log serial-debug.log bochs-debug.log
|
||||
@echo "$(COLOR_GREEN)✓ Clean complete$(COLOR_RESET)"
|
||||
|
||||
run: $(BUILD_DIR)/$(OS_ISO)
|
||||
@qemu-system-i386 -smp 1 -m 1G -rtc base=utc -cdrom $(BUILD_DIR)/$(OS_ISO) -monitor telnet::$(QEMU_MON_PORT),server,nowait &
|
||||
@sleep 1
|
||||
@telnet 127.0.0.1 $(QEMU_MON_PORT)
|
||||
# 使用 QEMU 運行
|
||||
run: all
|
||||
@echo "$(COLOR_BLUE)Running with QEMU...$(COLOR_RESET)"
|
||||
@qemu-system-x86_64 -drive format=raw,file=$(BUILD_DIR)/cure-bios.img \
|
||||
-m 128M \
|
||||
-serial stdio
|
||||
|
||||
# 使用 Bochs 運行
|
||||
run-bochs: all
|
||||
@echo "$(COLOR_BLUE)Running with Bochs...$(COLOR_RESET)"
|
||||
@bochs -q -f bochs.cfg
|
||||
|
||||
# QEMU 調試模式
|
||||
debug-qemu: all-debug
|
||||
@$(OBJCOPY) --only-keep-debug $(BIN_DIR)/$(OS_BIN) $(BUILD_DIR)/kernel.dbg
|
||||
@qemu-system-i386 -smp 1 -m 1G -rtc base=utc -s -S -cdrom $(BUILD_DIR)/$(OS_ISO) -monitor telnet::$(QEMU_MON_PORT),server,nowait &
|
||||
@echo "$(COLOR_BLUE)Starting QEMU in debug mode...$(COLOR_RESET)"
|
||||
@qemu-system-x86_64 -drive format=raw,file=$(BUILD_DIR)/cure-bios.img \
|
||||
-m 128M \
|
||||
-serial stdio \
|
||||
-s -S &
|
||||
@sleep 1
|
||||
@$(QEMU_MON_TERM) -e "telnet 127.0.0.1 $(QEMU_MON_PORT)"
|
||||
@gdb -s $(BUILD_DIR)/kernel.dbg -ex "target remote localhost:1234"
|
||||
@echo ""
|
||||
@echo "$(COLOR_YELLOW)QEMU waiting for debugger...$(COLOR_RESET)"
|
||||
@echo "$(COLOR_YELLOW)Run in another terminal:$(COLOR_RESET)"
|
||||
@echo " gdb $(BIN_DIR)/$(OS_BIN)"
|
||||
@echo " (gdb) target remote :1234"
|
||||
@echo " (gdb) continue"
|
||||
@echo ""
|
||||
|
||||
# Bochs 調試模式
|
||||
debug-bochs: all-debug
|
||||
@bochs -q -f bochs.cfg
|
||||
@echo "$(COLOR_BLUE)Running Bochs in debug mode...$(COLOR_RESET)"
|
||||
@echo "$(COLOR_YELLOW)Dump file available at: $(BUILD_DIR)/dump.txt$(COLOR_RESET)"
|
||||
@bochs -q -f bochs.cfg
|
||||
|
||||
# 顯示構建產物位置
|
||||
show-artifacts:
|
||||
@echo "$(COLOR_BLUE)Build artifacts:$(COLOR_RESET)"
|
||||
@echo " Build directory: $(BUILD_DIR)/"
|
||||
@echo " Binary directory: $(BIN_DIR)/"
|
||||
@echo ""
|
||||
@if [ -d $(BUILD_DIR) ]; then \
|
||||
echo "$(COLOR_GREEN)Files in $(BUILD_DIR):$(COLOR_RESET)"; \
|
||||
ls -lh $(BUILD_DIR)/ 2>/dev/null || echo " (empty)"; \
|
||||
else \
|
||||
echo "$(COLOR_YELLOW) (directory doesn't exist)$(COLOR_RESET)"; \
|
||||
fi
|
||||
@echo ""
|
||||
@if [ -d $(BIN_DIR) ]; then \
|
||||
echo "$(COLOR_GREEN)Files in $(BIN_DIR):$(COLOR_RESET)"; \
|
||||
ls -lh $(BIN_DIR)/ 2>/dev/null || echo " (empty)"; \
|
||||
else \
|
||||
echo "$(COLOR_YELLOW) (directory doesn't exist)$(COLOR_RESET)"; \
|
||||
fi
|
||||
|
||||
# 檢查構建
|
||||
check:
|
||||
@echo "$(COLOR_BLUE)Checking code...$(COLOR_RESET)"
|
||||
@cargo check -p cure-kernel
|
||||
@cargo check -p $(BUILDER_PKG)
|
||||
@echo "$(COLOR_GREEN)✓ Check complete$(COLOR_RESET)"
|
||||
|
||||
# 格式化代碼
|
||||
fmt:
|
||||
@echo "$(COLOR_BLUE)Formatting code...$(COLOR_RESET)"
|
||||
@cargo fmt
|
||||
@echo "$(COLOR_GREEN)✓ Format complete$(COLOR_RESET)"
|
||||
|
||||
# Clippy 檢查
|
||||
clippy:
|
||||
@echo "$(COLOR_BLUE)Running clippy...$(COLOR_RESET)"
|
||||
@cargo clippy
|
||||
@echo "$(COLOR_GREEN)✓ Clippy complete$(COLOR_RESET)"
|
||||
|
||||
# 幫助信息
|
||||
help:
|
||||
@echo "$(COLOR_BLUE)CureOS Makefile Commands:$(COLOR_RESET)"
|
||||
@echo ""
|
||||
@echo " $(COLOR_GREEN)make all$(COLOR_RESET) - Clean build/ then build (release)"
|
||||
@echo " $(COLOR_GREEN)make all-debug$(COLOR_RESET) - Clean build/ then build (debug + dump)"
|
||||
@echo " $(COLOR_GREEN)make dump$(COLOR_RESET) - Generate disassembly dump"
|
||||
@echo " $(COLOR_GREEN)make run$(COLOR_RESET) - Build and run with QEMU"
|
||||
@echo " $(COLOR_GREEN)make run-bochs$(COLOR_RESET) - Build and run with Bochs"
|
||||
@echo " $(COLOR_GREEN)make debug-qemu$(COLOR_RESET) - Debug build and run with QEMU+GDB"
|
||||
@echo " $(COLOR_GREEN)make debug-bochs$(COLOR_RESET) - Debug build and run with Bochs"
|
||||
@echo " $(COLOR_GREEN)make clean$(COLOR_RESET) - Clean all build artifacts"
|
||||
@echo " $(COLOR_GREEN)make clean-build$(COLOR_RESET) - Clean build/ directory only"
|
||||
@echo " $(COLOR_GREEN)make show-artifacts$(COLOR_RESET) - Show build output locations"
|
||||
@echo " $(COLOR_GREEN)make check$(COLOR_RESET) - Check code"
|
||||
@echo " $(COLOR_GREEN)make fmt$(COLOR_RESET) - Format code"
|
||||
@echo " $(COLOR_GREEN)make clippy$(COLOR_RESET) - Run clippy"
|
||||
@echo " $(COLOR_GREEN)make help$(COLOR_RESET) - Show this help"
|
||||
@echo ""
|
||||
@echo "$(COLOR_YELLOW)Debug artifacts:$(COLOR_RESET)"
|
||||
@echo " - $(BUILD_DIR)/dump.txt - Kernel disassembly (debug mode only)"
|
||||
@echo " - $(BIN_DIR)/$(OS_BIN) - Kernel binary (for GDB)"
|
||||
@echo ""
|
||||
0
GRUB_TEMPLATE → old/GRUB_TEMPLATE
Executable file → Normal file
0
GRUB_TEMPLATE → old/GRUB_TEMPLATE
Executable file → Normal file
0
config-grub.sh → old/config-grub.sh
Executable file → Normal file
0
config-grub.sh → old/config-grub.sh
Executable file → Normal file
0
linker.ld → old/linker.ld
Executable file → Normal file
0
linker.ld → old/linker.ld
Executable file → Normal file
98
old/makefile
Normal file
98
old/makefile
Normal file
@ -0,0 +1,98 @@
|
||||
include config/make-locations
|
||||
include config/make-os
|
||||
include config/make-debug-tool
|
||||
|
||||
BUILD_MODE := release
|
||||
CARGO_FLAGS := --release
|
||||
|
||||
# Rust target for bootloader
|
||||
RUST_TARGET := x86_64-unknown-none
|
||||
|
||||
.PHONY: all all-debug clean run debug-qemu debug-bochs rust-kernel
|
||||
|
||||
$(BUILD_DIR):
|
||||
@mkdir -p $(BUILD_DIR)
|
||||
|
||||
$(BIN_DIR):
|
||||
@mkdir -p $(BIN_DIR)
|
||||
|
||||
$(ISO_DIR):
|
||||
@mkdir -p $(ISO_DIR)
|
||||
@mkdir -p $(ISO_BOOT_DIR)
|
||||
@mkdir -p $(ISO_GRUB_DIR)
|
||||
|
||||
# 構建 Rust kernel + bootloader,提取 bin 文件
|
||||
rust-kernel: $(BUILD_DIR) $(BIN_DIR)
|
||||
@echo "Building Rust kernel with bootloader..."
|
||||
@cargo build -p cure-builder $(CARGO_FLAGS)
|
||||
@echo "Finding kernel binary..."
|
||||
@KERNEL_BIN=$$(find target/$(RUST_TARGET)/$(BUILD_MODE) -name "cure-kernel" -type f | head -1); \
|
||||
if [ -z "$$KERNEL_BIN" ]; then \
|
||||
echo "Error: Kernel binary not found!"; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
echo "Copying kernel binary to $(BIN_DIR)/$(OS_BIN)"; \
|
||||
cp "$$KERNEL_BIN" $(BIN_DIR)/$(OS_BIN)
|
||||
|
||||
# 創建 ISO(使用 GRUB Multiboot2)
|
||||
$(BUILD_DIR)/$(OS_ISO): $(ISO_DIR) rust-kernel
|
||||
@echo "Creating ISO image..."
|
||||
@./config-grub.sh $(OS_NAME) $(ISO_GRUB_DIR)/grub.cfg
|
||||
@cp $(BIN_DIR)/$(OS_BIN) $(ISO_BOOT_DIR)/$(OS_BIN)
|
||||
@echo "Running grub-mkrescue..."
|
||||
@grub-mkrescue -o $(BUILD_DIR)/$(OS_ISO) $(ISO_DIR) 2>&1 || \
|
||||
(echo "Error: grub-mkrescue failed. Installing grub-pc-bin..."; \
|
||||
sudo apt install -y grub-pc-bin xorriso mtools && \
|
||||
grub-mkrescue -o $(BUILD_DIR)/$(OS_ISO) $(ISO_DIR))
|
||||
@echo "ISO created at $(BUILD_DIR)/$(OS_ISO)"
|
||||
|
||||
all: $(BUILD_DIR)/$(OS_ISO)
|
||||
|
||||
all-debug: BUILD_MODE := debug
|
||||
all-debug: CARGO_FLAGS :=
|
||||
all-debug: $(BUILD_DIR)/$(OS_ISO)
|
||||
@echo "Debug build completed"
|
||||
|
||||
clean:
|
||||
@rm -rf $(BUILD_DIR)
|
||||
@cargo clean
|
||||
@echo "Cleaned build artifacts"
|
||||
|
||||
# 使用 QEMU 運行 ISO
|
||||
run: $(BUILD_DIR)/$(OS_ISO)
|
||||
@echo "Running $(OS_ISO) with QEMU..."
|
||||
@qemu-system-x86_64 -cdrom $(BUILD_DIR)/$(OS_ISO) -m 512M -serial stdio
|
||||
|
||||
# 使用 Bochs 運行 ISO
|
||||
run-bochs: $(BUILD_DIR)/$(OS_ISO)
|
||||
@echo "Running ISO with Bochs..."
|
||||
@bochs -q -f bochs.cfg
|
||||
|
||||
# QEMU 調試模式
|
||||
debug-qemu: all-debug
|
||||
@echo "Starting QEMU in debug mode..."
|
||||
@qemu-system-x86_64 -cdrom $(BUILD_DIR)/$(OS_ISO) -m 512M \
|
||||
-serial stdio -s -S &
|
||||
@sleep 1
|
||||
@echo "QEMU waiting for GDB connection on localhost:1234"
|
||||
@echo "Run: gdb target/$(RUST_TARGET)/debug/cure-kernel"
|
||||
@echo "Then: (gdb) target remote localhost:1234"
|
||||
|
||||
# Bochs 調試模式
|
||||
debug-bochs: all-debug
|
||||
@echo "Running Bochs in debug mode..."
|
||||
@bochs -q -f bochs.cfg
|
||||
|
||||
# 幫助信息
|
||||
help:
|
||||
@echo "CureOS Build System"
|
||||
@echo ""
|
||||
@echo "Targets:"
|
||||
@echo " all - Build ISO image (release mode)"
|
||||
@echo " all-debug - Build ISO image (debug mode)"
|
||||
@echo " clean - Clean all build artifacts"
|
||||
@echo " run - Build and run ISO with QEMU"
|
||||
@echo " run-bochs - Build and run ISO with Bochs"
|
||||
@echo " debug-qemu - Run QEMU in debug mode"
|
||||
@echo " debug-bochs - Run Bochs in debug mode"
|
||||
@echo " help - Show this help message"
|
||||
@ -1,63 +0,0 @@
|
||||
#include "multiboot.h"
|
||||
|
||||
.section .multiboot
|
||||
/* Define type as 32 bit */
|
||||
.long MB_MAGIC
|
||||
.long MB_ALIGNED_4K_MEM_MAP
|
||||
.long CHECKSUM(MB_ALIGNED_4K_MEM_MAP)
|
||||
|
||||
/* .bss: stack */
|
||||
.section .bss
|
||||
/* According to System V ABI, the stack must be aligned at 16 bytes boundary.*/
|
||||
.align 16 /* Not divisible by 16, move forward until divisible */
|
||||
stack_bottom:
|
||||
.skip 32708, 0
|
||||
stack_top:
|
||||
|
||||
/* .text: put executable code */
|
||||
.section .text
|
||||
.global start_
|
||||
start_:
|
||||
cli
|
||||
|
||||
movl $stack_top, %esp
|
||||
/*
|
||||
TODO: kernel init
|
||||
Load GDT
|
||||
Load IDT
|
||||
Enable paging
|
||||
*/
|
||||
call _kernel_init
|
||||
|
||||
/* install gdt */
|
||||
call _load_gdt
|
||||
// call _init_gdt
|
||||
// subl $0x6, %esp
|
||||
// movl $_GDT, 2(%esp)
|
||||
// movw _GDT_LIMIT, %ax
|
||||
// movw %ax, (%esp)
|
||||
// lgdt (%esp)
|
||||
// addl $0x6, %esp
|
||||
|
||||
/* processing register (CS, ES, SS, DS, FS, GS) */
|
||||
movw KERNEL_DATA_SEL, %cx /* 0x10 in binary representation is 0001 0000. If you right-shift this number by 3 bits, you will get 0000 0010, so the index is 2. */
|
||||
movw %cx, %es
|
||||
movw %cx, %ds
|
||||
movw %cx, %fs
|
||||
movw %cx, %gs
|
||||
movw %cx, %ss
|
||||
|
||||
/* Change CS:IP */
|
||||
pushw KERNEL_CODE_SEL /* 0x08 in binary representation is 0000 1000. If you right-shift this number by 3 bits, you will get 0000 0001, so the index is 1. */
|
||||
pushl $_after_gdt
|
||||
retf
|
||||
|
||||
_after_gdt:
|
||||
pushl %ebx
|
||||
|
||||
call _load_idt
|
||||
call _kernel_main
|
||||
|
||||
j_:
|
||||
hlt
|
||||
jmp j_
|
||||
@ -1,4 +0,0 @@
|
||||
// Define constants in multiboot
|
||||
#define MB_MAGIC 0x1BADB002
|
||||
#define MB_ALIGNED_4K_MEM_MAP 0x03
|
||||
#define CHECKSUM(flags) - (MB_MAGIC + flags)
|
||||
@ -1,112 +0,0 @@
|
||||
// src/kernel/asm/x86/gdt.rs
|
||||
use core::mem;
|
||||
use core::ptr;
|
||||
use x86::segmentation::{self, Descriptor, DataSegmentType, CodeSegmentType, SegmentSelector};
|
||||
use x86::segmentation::{SegmentDescriptorBuilder, BuildDescriptor};
|
||||
use x86::dtables::{DescriptorTablePointer, lgdt};
|
||||
use x86::Ring;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub const SEG_DATA_RD: u64 = 0x00; // Read-Only
|
||||
#[allow(dead_code)]
|
||||
pub const SEG_DATA_RDA: u64 = 0x01; // Read-Only, accessed
|
||||
#[allow(dead_code)]
|
||||
pub const SEG_DATA_RDWR: u64 = 0x02; // Read/Write
|
||||
#[allow(dead_code)]
|
||||
pub const SEG_DATA_RDWRA: u64 = 0x03; // Read/Write, accessed
|
||||
#[allow(dead_code)]
|
||||
pub const SEG_DATA_RDEXPD: u64 = 0x04; // Read-Only, expand-down
|
||||
#[allow(dead_code)]
|
||||
pub const SEG_DATA_RDEXPDA: u64 = 0x05; // Read-Only, expand-down, accessed
|
||||
#[allow(dead_code)]
|
||||
pub const SEG_DATA_RDWREXPD: u64 = 0x06; // Read/Write, expand-down
|
||||
#[allow(dead_code)]
|
||||
pub const SEG_DATA_RDWREXPDA: u64 = 0x07; // Read/Write, expand-down, accessed
|
||||
#[allow(dead_code)]
|
||||
pub const SEG_CODE_EX: u64 = 0x08; // Execute-Only
|
||||
#[allow(dead_code)]
|
||||
pub const SEG_CODE_EXA: u64 = 0x09; // Execute-Only, accessed
|
||||
#[allow(dead_code)]
|
||||
pub const SEG_CODE_EXRD: u64 = 0x0A; // Execute/Read
|
||||
#[allow(dead_code)]
|
||||
pub const SEG_CODE_EXRDA: u64 = 0x0B; // Execute/Read, accessed
|
||||
#[allow(dead_code)]
|
||||
pub const SEG_CODE_EXC: u64 = 0x0C; // Execute-Only, conforming
|
||||
#[allow(dead_code)]
|
||||
pub const SEG_CODE_EXCA: u64 = 0x0D; // Execute-Only, conforming, accessed
|
||||
#[allow(dead_code)]
|
||||
pub const SEG_CODE_EXRDC: u64 = 0x0E; // Execute/Read, conforming
|
||||
#[allow(dead_code)]
|
||||
pub const SEG_CODE_EXRDCA: u64 = 0x0F; // Execute/Read, conforming, accessed
|
||||
|
||||
pub const GDT_ENTRY_COUNT: usize = 5;
|
||||
|
||||
#[no_mangle]
|
||||
pub static mut _GDT: [Descriptor; GDT_ENTRY_COUNT] = [Descriptor::NULL; GDT_ENTRY_COUNT];
|
||||
|
||||
#[no_mangle]
|
||||
pub static mut _GDT_LIMIT: u16 = (mem::size_of::<[Descriptor; GDT_ENTRY_COUNT]>() - 1) as u16;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn _init_gdt() {
|
||||
unsafe {
|
||||
_GDT[0] = Descriptor::NULL;
|
||||
|
||||
_GDT[1] = segmentation::DescriptorBuilder::code_descriptor(
|
||||
0,
|
||||
0xFFFFF,
|
||||
CodeSegmentType::ExecuteRead
|
||||
)
|
||||
.present()
|
||||
.dpl(Ring::Ring0)
|
||||
.db()
|
||||
.limit_granularity_4kb()
|
||||
.finish();
|
||||
|
||||
_GDT[2] = segmentation::DescriptorBuilder::data_descriptor(
|
||||
0,
|
||||
0xFFFFF,
|
||||
DataSegmentType::ReadWrite
|
||||
)
|
||||
.present()
|
||||
.dpl(Ring::Ring0)
|
||||
.db()
|
||||
.limit_granularity_4kb()
|
||||
.finish();
|
||||
|
||||
_GDT[3] = segmentation::DescriptorBuilder::code_descriptor(
|
||||
0,
|
||||
0xFFFFF,
|
||||
CodeSegmentType::ExecuteRead
|
||||
)
|
||||
.present()
|
||||
.dpl(Ring::Ring3)
|
||||
.db()
|
||||
.limit_granularity_4kb()
|
||||
.finish();
|
||||
|
||||
_GDT[4] = segmentation::DescriptorBuilder::data_descriptor(
|
||||
0,
|
||||
0xFFFFF,
|
||||
DataSegmentType::ReadWrite
|
||||
)
|
||||
.present()
|
||||
.dpl(Ring::Ring3)
|
||||
.db()
|
||||
.limit_granularity_4kb()
|
||||
.finish();
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn _load_gdt() {
|
||||
unsafe {
|
||||
_init_gdt();
|
||||
|
||||
let gdtr = DescriptorTablePointer {
|
||||
limit: _GDT_LIMIT,
|
||||
base: ptr::addr_of!(_GDT),
|
||||
};
|
||||
lgdt(&gdtr);
|
||||
}
|
||||
}
|
||||
@ -1,179 +0,0 @@
|
||||
// src/kernel/asm/x86/idt.rs
|
||||
use core::mem;
|
||||
use core::ptr;
|
||||
use x86::dtables::{DescriptorTablePointer, lidt};
|
||||
use x86::segmentation::{
|
||||
self,
|
||||
SegmentSelector,
|
||||
Descriptor,
|
||||
SystemDescriptorTypes32,
|
||||
DescriptorBuilder,
|
||||
BuildDescriptor
|
||||
};
|
||||
use x86::Ring;
|
||||
use x86::irq::{self, EXCEPTIONS};
|
||||
use x86::segmentation::GateDescriptorBuilder;
|
||||
use x86::segmentation::TaskGateDescriptorBuilder;
|
||||
use crate::kernel::asm::x86::{interrupt, segment};
|
||||
|
||||
pub const IDT_ENTRY_COUNT: usize = 256;
|
||||
|
||||
#[no_mangle]
|
||||
pub static mut _IDT: [Descriptor; IDT_ENTRY_COUNT] = [Descriptor::NULL; IDT_ENTRY_COUNT];
|
||||
|
||||
#[no_mangle]
|
||||
pub static mut _IDT_LIMIT: u16 = (mem::size_of::<[Descriptor; IDT_ENTRY_COUNT]>() - 1) as u16;
|
||||
|
||||
pub type InterruptHandler = unsafe extern "C" fn() -> ();
|
||||
pub type ExceptionHandlerWithErrorCode = fn(error_code: u32) -> ();
|
||||
|
||||
#[no_mangle]
|
||||
pub fn _set_interrupt_handler(vector: u8, selector: SegmentSelector, handler: InterruptHandler, dpl: Ring) {
|
||||
unsafe {
|
||||
let desc = DescriptorBuilder::interrupt_descriptor(selector, handler as u32)
|
||||
.present()
|
||||
.dpl(dpl)
|
||||
.finish();
|
||||
|
||||
_IDT[vector as usize] = desc;
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn _set_interrupt_err_handler(vector: u8, selector: SegmentSelector, handler: ExceptionHandlerWithErrorCode, dpl: Ring) {
|
||||
unsafe {
|
||||
let desc = DescriptorBuilder::interrupt_descriptor(selector, handler as u32)
|
||||
.present()
|
||||
.dpl(dpl)
|
||||
.finish();
|
||||
|
||||
_IDT[vector as usize] = desc;
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn _set_trap_handler(vector: u8, selector: SegmentSelector, handler: InterruptHandler, dpl: Ring) {
|
||||
unsafe {
|
||||
let desc = DescriptorBuilder::trap_gate_descriptor(selector, handler as u32)
|
||||
.present()
|
||||
.dpl(dpl)
|
||||
.finish();
|
||||
|
||||
_IDT[vector as usize] = desc;
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn _set_task_gate(vector: u8, tss_selector: SegmentSelector, dpl: Ring) {
|
||||
unsafe {
|
||||
let desc = DescriptorBuilder::task_gate_descriptor(tss_selector)
|
||||
.present()
|
||||
.dpl(dpl)
|
||||
.finish();
|
||||
|
||||
_IDT[vector as usize] = desc;
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn _init_idt() {
|
||||
unsafe {
|
||||
for i in 0..IDT_ENTRY_COUNT {
|
||||
_IDT[i] = Descriptor::NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn _load_idt() {
|
||||
unsafe {
|
||||
_init_idt();
|
||||
|
||||
let idtr = DescriptorTablePointer {
|
||||
limit: _IDT_LIMIT,
|
||||
base: ptr::addr_of!(_IDT) as *const _,
|
||||
};
|
||||
lidt(&idtr);
|
||||
|
||||
_setup_idt();
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn _setup_idt() {
|
||||
extern "C" {
|
||||
fn _asm_isr0();
|
||||
fn _asm_isr1();
|
||||
fn _asm_isr2();
|
||||
fn _asm_isr3();
|
||||
fn _asm_isr4();
|
||||
fn _asm_isr5();
|
||||
fn _asm_isr6();
|
||||
fn _asm_isr7();
|
||||
fn _asm_isr8();
|
||||
fn _asm_isr9();
|
||||
fn _asm_isr10();
|
||||
fn _asm_isr11();
|
||||
fn _asm_isr12();
|
||||
fn _asm_isr13();
|
||||
fn _asm_isr14();
|
||||
fn _asm_isr15();
|
||||
fn _asm_isr16();
|
||||
fn _asm_isr17();
|
||||
fn _asm_isr18();
|
||||
fn _asm_isr19();
|
||||
fn _asm_isr20();
|
||||
fn _asm_isr21();
|
||||
fn _asm_isr22();
|
||||
fn _asm_isr23();
|
||||
fn _asm_isr24();
|
||||
fn _asm_isr25();
|
||||
fn _asm_isr26();
|
||||
fn _asm_isr27();
|
||||
fn _asm_isr28();
|
||||
fn _asm_isr29();
|
||||
fn _asm_isr30();
|
||||
fn _asm_isr31();
|
||||
}
|
||||
|
||||
_set_interrupt_handler(irq::DIVIDE_ERROR_VECTOR, segment::KERNEL_CODE_SELECTOR, _asm_isr0, Ring::Ring0);
|
||||
_set_interrupt_handler(irq::DEBUG_VECTOR, segment::KERNEL_CODE_SELECTOR, _asm_isr1, Ring::Ring0);
|
||||
_set_interrupt_handler(irq::NONMASKABLE_INTERRUPT_VECTOR, segment::KERNEL_CODE_SELECTOR, _asm_isr2, Ring::Ring0);
|
||||
_set_interrupt_handler(irq::BREAKPOINT_VECTOR, segment::KERNEL_CODE_SELECTOR, _asm_isr3, Ring::Ring0);
|
||||
_set_interrupt_handler(irq::OVERFLOW_VECTOR, segment::KERNEL_CODE_SELECTOR, _asm_isr4, Ring::Ring0);
|
||||
_set_interrupt_handler(irq::BOUND_RANGE_EXCEEDED_VECTOR, segment::KERNEL_CODE_SELECTOR, _asm_isr5, Ring::Ring0);
|
||||
_set_interrupt_handler(irq::INVALID_OPCODE_VECTOR, segment::KERNEL_CODE_SELECTOR, _asm_isr6, Ring::Ring0);
|
||||
_set_interrupt_handler(irq::DEVICE_NOT_AVAILABLE_VECTOR, segment::KERNEL_CODE_SELECTOR, _asm_isr7, Ring::Ring0);
|
||||
_set_interrupt_handler(irq::DOUBLE_FAULT_VECTOR, segment::KERNEL_CODE_SELECTOR, _asm_isr8, Ring::Ring0);
|
||||
_set_interrupt_handler(irq::COPROCESSOR_SEGMENT_OVERRUN_VECTOR, segment::KERNEL_CODE_SELECTOR, _asm_isr9, Ring::Ring0);
|
||||
_set_interrupt_handler(irq::INVALID_TSS_VECTOR, segment::KERNEL_CODE_SELECTOR, _asm_isr10, Ring::Ring0);
|
||||
_set_interrupt_handler(irq::SEGMENT_NOT_PRESENT_VECTOR, segment::KERNEL_CODE_SELECTOR, _asm_isr11, Ring::Ring0);
|
||||
_set_interrupt_handler(irq::STACK_SEGEMENT_FAULT_VECTOR, segment::KERNEL_CODE_SELECTOR, _asm_isr12, Ring::Ring0);
|
||||
_set_interrupt_handler(irq::GENERAL_PROTECTION_FAULT_VECTOR, segment::KERNEL_CODE_SELECTOR, _asm_isr13, Ring::Ring0);
|
||||
_set_interrupt_handler(irq::PAGE_FAULT_VECTOR, segment::KERNEL_CODE_SELECTOR, _asm_isr14, Ring::Ring0);
|
||||
_set_interrupt_handler(15, segment::KERNEL_CODE_SELECTOR, _asm_isr15, Ring::Ring0);
|
||||
_set_interrupt_handler(irq::X87_FPU_VECTOR, segment::KERNEL_CODE_SELECTOR, _asm_isr16, Ring::Ring0);
|
||||
_set_interrupt_handler(irq::ALIGNMENT_CHECK_VECTOR, segment::KERNEL_CODE_SELECTOR, _asm_isr17, Ring::Ring0);
|
||||
_set_interrupt_handler(irq::MACHINE_CHECK_VECTOR, segment::KERNEL_CODE_SELECTOR, _asm_isr18, Ring::Ring0);
|
||||
_set_interrupt_handler(irq::SIMD_FLOATING_POINT_VECTOR, segment::KERNEL_CODE_SELECTOR, _asm_isr19, Ring::Ring0);
|
||||
_set_interrupt_handler(irq::VIRTUALIZATION_VECTOR, segment::KERNEL_CODE_SELECTOR, _asm_isr20, Ring::Ring0);
|
||||
|
||||
_set_interrupt_handler(21, segment::KERNEL_CODE_SELECTOR, _asm_isr21, Ring::Ring0);
|
||||
_set_interrupt_handler(22, segment::KERNEL_CODE_SELECTOR, _asm_isr22, Ring::Ring0);
|
||||
_set_interrupt_handler(23, segment::KERNEL_CODE_SELECTOR, _asm_isr23, Ring::Ring0);
|
||||
_set_interrupt_handler(24, segment::KERNEL_CODE_SELECTOR, _asm_isr24, Ring::Ring0);
|
||||
_set_interrupt_handler(25, segment::KERNEL_CODE_SELECTOR, _asm_isr25, Ring::Ring0);
|
||||
_set_interrupt_handler(26, segment::KERNEL_CODE_SELECTOR, _asm_isr26, Ring::Ring0);
|
||||
_set_interrupt_handler(27, segment::KERNEL_CODE_SELECTOR, _asm_isr27, Ring::Ring0);
|
||||
_set_interrupt_handler(28, segment::KERNEL_CODE_SELECTOR, _asm_isr28, Ring::Ring0);
|
||||
_set_interrupt_handler(29, segment::KERNEL_CODE_SELECTOR, _asm_isr29, Ring::Ring0);
|
||||
_set_interrupt_handler(30, segment::KERNEL_CODE_SELECTOR, _asm_isr30, Ring::Ring0);
|
||||
_set_interrupt_handler(31, segment::KERNEL_CODE_SELECTOR, _asm_isr31, Ring::Ring0);
|
||||
|
||||
|
||||
// for i in 32..IDT_ENTRY_COUNT as u8 {
|
||||
// _set_interrupt_handler(i, segment::KERNEL_CODE_SELECTOR, interrupt::default_interrupt_handler, Ring::Ring0);
|
||||
// }
|
||||
|
||||
// crate::println!("IDT initialized with {} entries", IDT_ENTRY_COUNT);
|
||||
}
|
||||
@ -1,58 +0,0 @@
|
||||
.macro isr_template vector, no_error_code=1
|
||||
.global _asm_isr\vector
|
||||
.type _asm_isr\vector, @function
|
||||
_asm_isr\vector:
|
||||
.if \no_error_code
|
||||
pushl $0x0
|
||||
.endif
|
||||
pushl $\vector
|
||||
jmp interrupt_wrapper
|
||||
.endm
|
||||
|
||||
.section .text
|
||||
isr_template 0
|
||||
isr_template 1
|
||||
isr_template 2
|
||||
isr_template 3
|
||||
isr_template 4
|
||||
isr_template 5
|
||||
isr_template 6
|
||||
isr_template 7
|
||||
isr_template 8, 0
|
||||
isr_template 9
|
||||
isr_template 10, 0
|
||||
isr_template 11, 0
|
||||
isr_template 12, 0
|
||||
isr_template 13, 0
|
||||
isr_template 14, 0
|
||||
isr_template 15
|
||||
isr_template 16
|
||||
isr_template 17, 0
|
||||
isr_template 18
|
||||
isr_template 19
|
||||
isr_template 20
|
||||
isr_template 21
|
||||
isr_template 22
|
||||
isr_template 23
|
||||
isr_template 24
|
||||
isr_template 25
|
||||
isr_template 26
|
||||
isr_template 27
|
||||
isr_template 28
|
||||
isr_template 29
|
||||
isr_template 30
|
||||
isr_template 31
|
||||
|
||||
interrupt_wrapper:
|
||||
|
||||
movl %esp, %eax
|
||||
andl $0xfffffff0, %esp
|
||||
subl $16, %esp
|
||||
movl %eax, (%esp)
|
||||
|
||||
call interrupt_handler
|
||||
pop %eax
|
||||
movl %eax, %esp
|
||||
addl $8, %esp
|
||||
|
||||
iret
|
||||
@ -1,248 +0,0 @@
|
||||
use core::mem;
|
||||
use core::ptr;
|
||||
use x86::segmentation::{SegmentSelector, Descriptor};
|
||||
use x86::Ring;
|
||||
use x86::irq::{self, PageFaultError, EXCEPTIONS};
|
||||
use crate::{print, println};
|
||||
use crate::hal::cpu;
|
||||
|
||||
#[repr(C, packed)]
|
||||
pub struct IsrParam {
|
||||
vector: u32,
|
||||
err_code: u32,
|
||||
eip: u32,
|
||||
cs: u32,
|
||||
eflags: u32,
|
||||
esp: u32,
|
||||
ss: u32,
|
||||
}
|
||||
|
||||
impl IsrParam {
|
||||
pub fn vector(&self) -> u32 {
|
||||
return self.vector;
|
||||
}
|
||||
|
||||
pub fn err_code(&self) -> u32 {
|
||||
// unsafe {
|
||||
// let ptr = ptr::addr_of!(self.err_code);
|
||||
// ptr::read_unaligned(ptr)
|
||||
// }
|
||||
return self.err_code;
|
||||
}
|
||||
|
||||
pub fn eip(&self) -> u32 {
|
||||
return self.eip;
|
||||
}
|
||||
|
||||
pub fn cs(&self) -> u32 {
|
||||
return self.cs;
|
||||
}
|
||||
|
||||
pub fn eflags(&self) -> u32 {
|
||||
return self.eflags;
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn interrupt_handler(param: *const IsrParam) {
|
||||
// param.as_ref().expect("中斷參數為 null")
|
||||
let param_ref = unsafe { param.as_ref().unwrap() };
|
||||
|
||||
match param_ref.vector {
|
||||
0 => divide_error_handler(param_ref),
|
||||
1 => debug_error_handler(param_ref),
|
||||
2 => nonmaskable_interrupt_handler(param_ref),
|
||||
3 => breakpoint_handler(param_ref),
|
||||
4 => overflow_handler(param_ref),
|
||||
|
||||
5 => bound_range_exceeded_handler(param_ref),
|
||||
6 => invalid_opcode_handler(param_ref),
|
||||
7 => device_not_available_handler(param_ref),
|
||||
8 => double_fault_handler(param_ref),
|
||||
9 => coprocessor_segment_overrun_handler(param_ref),
|
||||
|
||||
10 => invalid_tss_handler(param_ref),
|
||||
11 => segment_not_present_handler(param_ref),
|
||||
12 => stack_segment_fault_handler(param_ref),
|
||||
13 => general_protection_handler(param_ref),
|
||||
14 => page_fault_handler(param_ref),
|
||||
// 15 => reserved_handler(param_ref),
|
||||
16 => x87_fpu_floating_point_handler(param_ref),
|
||||
17 => alignment_check_handler(param_ref),
|
||||
18 => machine_check_handler(param_ref),
|
||||
19 => simd_floating_point_handler(param_ref),
|
||||
20 => virtualization_handler(param_ref),
|
||||
// 21 => reserved_handler(param_ref),
|
||||
// 22 => reserved_handler(param_ref),
|
||||
// 23 => reserved_handler(param_ref),
|
||||
// 24 => reserved_handler(param_ref),
|
||||
// 25 => reserved_handler(param_ref),
|
||||
// 26 => reserved_handler(param_ref),
|
||||
// 27 => reserved_handler(param_ref),
|
||||
// 28 => reserved_handler(param_ref),
|
||||
// 29 => reserved_handler(param_ref),
|
||||
// 30 => reserved_handler(param_ref),
|
||||
// 31 => reserved_handler(param_ref),
|
||||
|
||||
_ => reserved_handler(param_ref),
|
||||
}
|
||||
}
|
||||
|
||||
fn print_exception(param: &IsrParam) {
|
||||
let vector = param.vector();
|
||||
|
||||
if vector < 32 {
|
||||
let ex = &EXCEPTIONS[vector as usize];
|
||||
println!("CPU Exception: {}", ex);
|
||||
println!("EIP: 0x{:x}, CS: 0x{:x}, EFLAGS: 0x{:x}", param.eip(), param.cs(), param.eflags());
|
||||
|
||||
let error_code = param.err_code();
|
||||
|
||||
if error_code != 0 {
|
||||
println!("Error code: 0x{:x}", error_code);
|
||||
|
||||
if vector == irq::PAGE_FAULT_VECTOR.into() {
|
||||
let cr2 = cpu::cpu_r_cr2() ;
|
||||
let pf_error = PageFaultError::from_bits_truncate(error_code);
|
||||
|
||||
println!("Fault address: 0x{:x}", cr2);
|
||||
println!("Fault details:\n{}", pf_error);
|
||||
}
|
||||
}
|
||||
|
||||
// if let Some(addr) = fault_addr {
|
||||
// println!("Fault address: 0x{:x}", addr);
|
||||
// }
|
||||
} else {
|
||||
println!("Unhandled interrupt: Vector {}", vector);
|
||||
}
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
/// isr0
|
||||
#[no_mangle]
|
||||
pub fn divide_error_handler(param: &IsrParam) {
|
||||
print_exception(param)
|
||||
}
|
||||
|
||||
/// isr1
|
||||
#[no_mangle]
|
||||
pub fn debug_error_handler(param: &IsrParam) {
|
||||
print_exception(param)
|
||||
}
|
||||
|
||||
/// isr2
|
||||
#[no_mangle]
|
||||
pub fn nonmaskable_interrupt_handler(param: &IsrParam) {
|
||||
print_exception(param)
|
||||
}
|
||||
|
||||
/// isr3
|
||||
#[no_mangle]
|
||||
pub fn breakpoint_handler(param: &IsrParam) {
|
||||
print_exception(param)
|
||||
}
|
||||
|
||||
/// isr4
|
||||
#[no_mangle]
|
||||
pub fn overflow_handler(param: &IsrParam) {
|
||||
print_exception(param)
|
||||
}
|
||||
|
||||
/// isr5
|
||||
#[no_mangle]
|
||||
pub fn bound_range_exceeded_handler(param: &IsrParam) {
|
||||
print_exception(param)
|
||||
}
|
||||
|
||||
/// isr6
|
||||
#[no_mangle]
|
||||
pub fn invalid_opcode_handler(param: &IsrParam) {
|
||||
print_exception(param)
|
||||
}
|
||||
|
||||
/// isr7
|
||||
#[no_mangle]
|
||||
pub fn device_not_available_handler(param: &IsrParam) {
|
||||
print_exception(param)
|
||||
}
|
||||
|
||||
/// isr8
|
||||
#[no_mangle]
|
||||
pub fn double_fault_handler(param: &IsrParam) {
|
||||
print_exception(param)
|
||||
}
|
||||
|
||||
/// isr9
|
||||
#[no_mangle]
|
||||
pub fn coprocessor_segment_overrun_handler(param: &IsrParam) {
|
||||
print_exception(param)
|
||||
}
|
||||
|
||||
/// isr10
|
||||
#[no_mangle]
|
||||
pub fn invalid_tss_handler(param: &IsrParam) {
|
||||
print_exception(param)
|
||||
}
|
||||
|
||||
/// isr11
|
||||
#[no_mangle]
|
||||
pub fn segment_not_present_handler(param: &IsrParam) {
|
||||
print_exception(param)
|
||||
}
|
||||
|
||||
/// isr12
|
||||
#[no_mangle]
|
||||
pub fn stack_segment_fault_handler(param: &IsrParam) {
|
||||
print_exception(param)
|
||||
}
|
||||
|
||||
/// isr13
|
||||
#[no_mangle]
|
||||
pub fn general_protection_handler(param: &IsrParam) {
|
||||
print_exception(param)
|
||||
}
|
||||
|
||||
/// isr14
|
||||
#[no_mangle]
|
||||
pub fn page_fault_handler(param: &IsrParam) {
|
||||
print_exception(param)
|
||||
}
|
||||
|
||||
/// isr16
|
||||
#[no_mangle]
|
||||
pub fn x87_fpu_floating_point_handler(param: &IsrParam) {
|
||||
print_exception(param)
|
||||
}
|
||||
|
||||
/// isr17
|
||||
#[no_mangle]
|
||||
pub fn alignment_check_handler(param: &IsrParam) {
|
||||
print_exception(param)
|
||||
}
|
||||
|
||||
/// isr18
|
||||
#[no_mangle]
|
||||
pub fn machine_check_handler(param: &IsrParam) {
|
||||
print_exception(param)
|
||||
}
|
||||
|
||||
/// isr19
|
||||
#[no_mangle]
|
||||
pub fn simd_floating_point_handler(param: &IsrParam) {
|
||||
print_exception(param)
|
||||
}
|
||||
|
||||
/// isr20
|
||||
#[no_mangle]
|
||||
pub fn virtualization_handler(param: &IsrParam) {
|
||||
print_exception(param)
|
||||
}
|
||||
|
||||
|
||||
/// isr15, 21-31
|
||||
#[no_mangle]
|
||||
pub fn reserved_handler(param: &IsrParam) {
|
||||
print_exception(param)
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
use x86::segmentation::SegmentSelector;
|
||||
use x86::Ring;
|
||||
|
||||
pub const NULL_SELECTOR: SegmentSelector = SegmentSelector::new(0, Ring::Ring0);
|
||||
pub const KERNEL_CODE_SELECTOR: SegmentSelector = SegmentSelector::new(1, Ring::Ring0);
|
||||
pub const KERNEL_DATA_SELECTOR: SegmentSelector = SegmentSelector::new(2, Ring::Ring0);
|
||||
pub const USER_CODE_SELECTOR: SegmentSelector = SegmentSelector::new(3, Ring::Ring3);
|
||||
pub const USER_DATA_SELECTOR: SegmentSelector = SegmentSelector::new(4, Ring::Ring3);
|
||||
|
||||
#[no_mangle]
|
||||
pub static NULL_SEL: u16 = NULL_SELECTOR.bits();
|
||||
#[no_mangle]
|
||||
pub static KERNEL_CODE_SEL: u16 = KERNEL_CODE_SELECTOR.bits();
|
||||
#[no_mangle]
|
||||
pub static KERNEL_DATA_SEL: u16 = KERNEL_DATA_SELECTOR.bits();
|
||||
#[no_mangle]
|
||||
pub static USER_CODE_SEL: u16 = USER_CODE_SELECTOR.bits();
|
||||
#[no_mangle]
|
||||
pub static USER_DATA_SEL: u16 = USER_DATA_SELECTOR.bits();
|
||||
@ -1,78 +0,0 @@
|
||||
// src/kernel/kernel.rs
|
||||
use core::arch::asm;
|
||||
use crate::kernel::tty::tty;
|
||||
use crate::hal::cpu;
|
||||
use crate::{print, println};
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn _kernel_init() {
|
||||
// TODO: 加載 GDT OK
|
||||
// TODO: 加載 IDT OK
|
||||
// TODO: 啟用分頁
|
||||
tty::tty_init(tty::VGA_BUFFER_PADDR);
|
||||
tty::tty_set_theme(tty::VGA_COLOR_WHITE, tty::VGA_COLOR_BLACK);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn _kernel_post_init() {
|
||||
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn _kernel_main() {
|
||||
|
||||
println!("Loading....!");
|
||||
|
||||
// tty::tty_clear();
|
||||
|
||||
println!("Welcome to Cure OS!");
|
||||
|
||||
println!("{0} + {1} = {0}", 1, 2);
|
||||
|
||||
let name = "111";
|
||||
let age = 25;
|
||||
println!("{}, {}", name, age);
|
||||
|
||||
let value = 42;
|
||||
println!("10: {}, 16: {:x}", value, value);
|
||||
|
||||
let mut brand_buffer = [0u8; 64];
|
||||
println!("{}", cpu::cpu_get_brand(&mut brand_buffer));
|
||||
println!("{}", cpu::cpu_get_model(&mut brand_buffer));
|
||||
|
||||
unsafe {
|
||||
let eflags: u32;
|
||||
asm!("pushfd; pop {}", out(reg) eflags);
|
||||
println!("Current EFLAGS: 0x{:x}", eflags);
|
||||
}
|
||||
|
||||
// unsafe {
|
||||
// core::arch::asm!(
|
||||
// "movl $0, %eax",
|
||||
// "movl $0, %ebx",
|
||||
// "divl %ebx",
|
||||
// options(att_syntax)
|
||||
// );
|
||||
// }
|
||||
|
||||
unsafe {
|
||||
asm!(
|
||||
"mov ax, 0x27",
|
||||
"mov ds, ax",
|
||||
options(nostack)
|
||||
);
|
||||
}
|
||||
|
||||
// cpu::cpu_enable_interrupts();
|
||||
|
||||
// unsafe {
|
||||
// core::arch::asm!(
|
||||
// "int $13",
|
||||
// options(att_syntax)
|
||||
// );
|
||||
// }
|
||||
|
||||
loop {
|
||||
cpu::cpu_idle();
|
||||
}
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
// src/kernel/tty/mod.rs
|
||||
|
||||
pub mod tty;
|
||||
|
||||
pub use tty::tty_init;
|
||||
pub use tty::tty_set_buffer;
|
||||
pub use tty::tty_set_theme;
|
||||
pub use tty::tty_put_char;
|
||||
pub use tty::tty_put_str;
|
||||
pub use tty::tty_scroll_up;
|
||||
pub use tty::tty_clear;
|
||||
pub use tty::tty_clear_line;
|
||||
pub use tty::tty_set_cpos;
|
||||
pub use tty::tty_get_cpos;
|
||||
pub use tty::tty_get_theme;
|
||||
@ -1,252 +0,0 @@
|
||||
// src/kernel/tty/tty.rs
|
||||
|
||||
use crate::hal::io;
|
||||
use core::ptr::NonNull;
|
||||
|
||||
/// VGA 屬性類型 (16位)
|
||||
#[allow(dead_code)]
|
||||
pub type VgaAttribute = u16;
|
||||
|
||||
// VGA 顏色常量
|
||||
#[allow(dead_code)]
|
||||
pub const VGA_COLOR_BLACK: u8 = 0;
|
||||
#[allow(dead_code)]
|
||||
pub const VGA_COLOR_BLUE: u8 = 1;
|
||||
#[allow(dead_code)]
|
||||
pub const VGA_COLOR_GREEN: u8 = 2;
|
||||
#[allow(dead_code)]
|
||||
pub const VGA_COLOR_CYAN: u8 = 3;
|
||||
#[allow(dead_code)]
|
||||
pub const VGA_COLOR_RED: u8 = 4;
|
||||
#[allow(dead_code)]
|
||||
pub const VGA_COLOR_MAGENTA: u8 = 5;
|
||||
#[allow(dead_code)]
|
||||
pub const VGA_COLOR_BROWN: u8 = 6;
|
||||
#[allow(dead_code)]
|
||||
pub const VGA_COLOR_LIGHT_GREY: u8 = 7;
|
||||
#[allow(dead_code)]
|
||||
pub const VGA_COLOR_DARK_GREY: u8 = 8;
|
||||
#[allow(dead_code)]
|
||||
pub const VGA_COLOR_LIGHT_BLUE: u8 = 9;
|
||||
#[allow(dead_code)]
|
||||
pub const VGA_COLOR_LIGHT_GREEN: u8 = 10;
|
||||
#[allow(dead_code)]
|
||||
pub const VGA_COLOR_LIGHT_CYAN: u8 = 11;
|
||||
#[allow(dead_code)]
|
||||
pub const VGA_COLOR_LIGHT_RED: u8 = 12;
|
||||
#[allow(dead_code)]
|
||||
pub const VGA_COLOR_LIGHT_MAGENTA: u8 = 13;
|
||||
#[allow(dead_code)]
|
||||
pub const VGA_COLOR_LIGHT_BROWN: u8 = 14;
|
||||
#[allow(dead_code)]
|
||||
pub const VGA_COLOR_WHITE: u8 = 15;
|
||||
#[allow(dead_code)]
|
||||
pub const VGA_BUFFER_PADDR: usize = 0xB8000;
|
||||
|
||||
#[allow(dead_code)]
|
||||
const TTY_WIDTH: usize = 80;
|
||||
#[allow(dead_code)]
|
||||
const TTY_HEIGHT: usize = 25;
|
||||
#[allow(dead_code)]
|
||||
const VGA_CTRL_PORT: u16 = 0x3D4;
|
||||
#[allow(dead_code)]
|
||||
const VGA_DATA_PORT: u16 = 0x3D5;
|
||||
|
||||
// 全局 TTY 狀態
|
||||
pub struct TTYState {
|
||||
vga_buffer: Option<NonNull<VgaAttribute>>,
|
||||
theme_color: VgaAttribute,
|
||||
x: usize,
|
||||
y: usize,
|
||||
}
|
||||
|
||||
impl TTYState {
|
||||
const fn new() -> Self {
|
||||
Self {
|
||||
vga_buffer: None,
|
||||
theme_color: (VGA_COLOR_BLACK as VgaAttribute) << 8,
|
||||
x: 0,
|
||||
y: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static mut TTY_STATE: TTYState = TTYState::new();
|
||||
|
||||
// #[no_mangle]
|
||||
// fn update_cursor() {
|
||||
// unsafe {
|
||||
// let pos = TTY_STATE.y * TTY_WIDTH + TTY_STATE.x;
|
||||
|
||||
// io::io_port_wb(VGA_CTRL_PORT, 0x0F);
|
||||
// io::io_port_wb(VGA_DATA_PORT, (pos & 0xFF) as u8);
|
||||
// io::io_port_wb(VGA_CTRL_PORT, 0x0E);
|
||||
// io::io_port_wb(VGA_DATA_PORT, ((pos >> 8) & 0xFF) as u8);
|
||||
// }
|
||||
// }
|
||||
|
||||
/// 初始化 TTY
|
||||
// vga_buf: *mut u8
|
||||
#[no_mangle]
|
||||
pub fn tty_init(vga_buf: usize) {
|
||||
unsafe {
|
||||
TTY_STATE.vga_buffer = NonNull::new(vga_buf as *mut VgaAttribute);
|
||||
tty_clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// 設置 VGA 緩衝區
|
||||
#[no_mangle]
|
||||
pub fn tty_set_buffer(vga_buf: usize) {
|
||||
unsafe {
|
||||
TTY_STATE.vga_buffer = NonNull::new(vga_buf as *mut VgaAttribute);
|
||||
}
|
||||
}
|
||||
|
||||
/// 設置主題顏色(前景色和背景色)
|
||||
#[no_mangle]
|
||||
pub fn tty_set_theme(fg: u8, bg: u8) {
|
||||
unsafe {
|
||||
TTY_STATE.theme_color = ((bg << 4 | fg) as VgaAttribute) << 8;
|
||||
}
|
||||
}
|
||||
|
||||
/// 向 TTY 輸出單個字符
|
||||
///
|
||||
/// # 注意
|
||||
/// - 僅支援 ASCII 範圍 (0-255) 的字符
|
||||
/// - 多字節 Unicode 字符會被截斷為低 8 位
|
||||
/// - '\t' 擴展為 4 個空格
|
||||
/// - '\n' 換行並將游標移至行首
|
||||
/// - '\r' 將游標移至行首
|
||||
#[no_mangle]
|
||||
pub fn tty_put_char(chr: char) {
|
||||
unsafe {
|
||||
if let Some(vga_ptr) = TTY_STATE.vga_buffer {
|
||||
match chr {
|
||||
'\t' => {
|
||||
TTY_STATE.x += 4;
|
||||
}
|
||||
'\n' => {
|
||||
TTY_STATE.y += 1;
|
||||
TTY_STATE.x = 0;
|
||||
}
|
||||
'\r' => {
|
||||
TTY_STATE.x = 0;
|
||||
}
|
||||
_ => {
|
||||
let offset = TTY_STATE.x + TTY_STATE.y * TTY_WIDTH;
|
||||
// VGA 文本模式僅支持 8 位字符
|
||||
*vga_ptr.as_ptr().add(offset) = TTY_STATE.theme_color | (chr as u8) as VgaAttribute;
|
||||
TTY_STATE.x += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if TTY_STATE.x >= TTY_WIDTH {
|
||||
TTY_STATE.x = 0;
|
||||
TTY_STATE.y += 1;
|
||||
}
|
||||
|
||||
if TTY_STATE.y >= TTY_HEIGHT {
|
||||
tty_scroll_up();
|
||||
}
|
||||
|
||||
// update_cursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 向 TTY 輸出字符串
|
||||
///
|
||||
/// # 注意
|
||||
/// - 字符串中的多字節 Unicode 字符會被截斷為低 8 位
|
||||
/// - 支持 Rust 字符串切片 (&str)
|
||||
#[no_mangle]
|
||||
pub fn tty_put_str(s: &str) {
|
||||
for chr in s.chars() {
|
||||
tty_put_char(chr);
|
||||
}
|
||||
}
|
||||
|
||||
/// 向上滾動一行
|
||||
#[no_mangle]
|
||||
pub fn tty_scroll_up() {
|
||||
unsafe {
|
||||
if let Some(vga_ptr) = TTY_STATE.vga_buffer {
|
||||
let last_line = TTY_WIDTH * (TTY_HEIGHT - 1);
|
||||
let buffer_ptr = vga_ptr.as_ptr();
|
||||
|
||||
// 將所有行向上移動一行
|
||||
core::ptr::copy(
|
||||
buffer_ptr.add(TTY_WIDTH),
|
||||
buffer_ptr,
|
||||
last_line
|
||||
);
|
||||
|
||||
// 清空最後一行
|
||||
for i in 0..TTY_WIDTH {
|
||||
*buffer_ptr.add(i + last_line) = TTY_STATE.theme_color;
|
||||
}
|
||||
|
||||
TTY_STATE.y = if TTY_STATE.y == 0 { 0 } else { TTY_HEIGHT - 1 };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 清空屏幕
|
||||
#[no_mangle]
|
||||
pub fn tty_clear() {
|
||||
unsafe {
|
||||
if let Some(vga_ptr) = TTY_STATE.vga_buffer {
|
||||
let buffer_ptr = vga_ptr.as_ptr();
|
||||
|
||||
for i in 0..(TTY_WIDTH * TTY_HEIGHT) {
|
||||
*buffer_ptr.add(i) = TTY_STATE.theme_color;
|
||||
}
|
||||
|
||||
TTY_STATE.x = 0;
|
||||
TTY_STATE.y = 0;
|
||||
// update_cursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 清空指定行
|
||||
#[no_mangle]
|
||||
pub fn tty_clear_line(y: usize) {
|
||||
unsafe {
|
||||
if let Some(vga_ptr) = TTY_STATE.vga_buffer {
|
||||
let buffer_ptr = vga_ptr.as_ptr();
|
||||
|
||||
for i in 0..TTY_WIDTH {
|
||||
*buffer_ptr.add(i + y * TTY_WIDTH) = TTY_STATE.theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 設置游標位置
|
||||
#[no_mangle]
|
||||
pub fn tty_set_cpos(x: usize, y: usize) {
|
||||
unsafe {
|
||||
TTY_STATE.x = x % TTY_WIDTH;
|
||||
TTY_STATE.y = y % TTY_HEIGHT;
|
||||
// update_cursor();
|
||||
}
|
||||
}
|
||||
|
||||
/// 獲取游標位置
|
||||
#[no_mangle]
|
||||
pub fn tty_get_cpos() -> (usize, usize) {
|
||||
unsafe {
|
||||
(TTY_STATE.x, TTY_STATE.y)
|
||||
}
|
||||
}
|
||||
|
||||
/// 獲取當前主題顏色
|
||||
#[no_mangle]
|
||||
pub fn tty_get_theme() -> VgaAttribute {
|
||||
unsafe {
|
||||
TTY_STATE.theme_color
|
||||
}
|
||||
}
|
||||
13
src/lib.rs
13
src/lib.rs
@ -1,13 +0,0 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
mod kernel;
|
||||
mod hal;
|
||||
mod libs;
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(_info: &PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user