Initial commit
This commit is contained in:
commit
8c29ffea06
9
.cargo/config.toml
Normal file
9
.cargo/config.toml
Normal file
@ -0,0 +1,9 @@
|
||||
[unstable]
|
||||
build-std-features = ["compiler-builtins-mem"]
|
||||
build-std = ["core", "compiler_builtins", "alloc"]
|
||||
|
||||
[build]
|
||||
target = "x86_64-unknown-none.json"
|
||||
|
||||
[install]
|
||||
root = "../kernel/sysroot"
|
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
target
|
367
Cargo.lock
generated
Normal file
367
Cargo.lock
generated
Normal file
@ -0,0 +1,367 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bit_field"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cobs"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15"
|
||||
|
||||
[[package]]
|
||||
name = "core2"
|
||||
version = "0.4.0"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-queue"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cd42583b04998a5363558e5f9291ee5a5ff6b49944332103f251e7479a82aa7"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive-try-from-primitive"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "302ccf094df1151173bb6f5a2282fcd2f45accd5eae1bdf82dcbfefbc501ad5c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dev_driver_rpc"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"postcard",
|
||||
"serde",
|
||||
"spin",
|
||||
"std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "elfloader"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a249d6a9d50f3bf5a3cb7bfd75e84989cad89c6c77b5996c8b084e844146ff04"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"log",
|
||||
"xmas-elf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "file_rpc"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"postcard",
|
||||
"serde",
|
||||
"spin",
|
||||
"std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.132"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
|
||||
|
||||
[[package]]
|
||||
name = "linked_list_allocator"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "636c3bc929db632724303109c88d5d559a2a60f62243bb041387f03fa081d94a"
|
||||
dependencies = [
|
||||
"spinning_top",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e"
|
||||
|
||||
[[package]]
|
||||
name = "postcard"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c2b180dc0bade59f03fd005cb967d3f1e5f69b13922dad0cd6e047cb8af2363"
|
||||
dependencies = [
|
||||
"cobs",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.144"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.144"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spinning_top"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75adad84ee84b521fb2cca2d4fd0f1dab1d8d026bda3c5bea4ca63b5f9f9293c"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "std"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"core2",
|
||||
"crossbeam-queue",
|
||||
"derive-try-from-primitive",
|
||||
"elfloader",
|
||||
"hashbrown",
|
||||
"linked_list_allocator",
|
||||
"postcard",
|
||||
"serde",
|
||||
"spin",
|
||||
"x86_64 0.14.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.99"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13"
|
||||
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 = "test_proc"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"dev_driver_rpc",
|
||||
"file_rpc",
|
||||
"postcard",
|
||||
"serde",
|
||||
"spin",
|
||||
"std",
|
||||
"tap",
|
||||
"x86_64 0.14.10 (git+https://github.com/pjht/x86_64)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "volatile"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3ca98349dda8a60ae74e04fd90c7fb4d6a4fbe01e6d3be095478aa0b76f6c0c"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "x86_64"
|
||||
version = "0.14.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "100555a863c0092238c2e0e814c1096c1e5cf066a309c696a87e907b5f8c5d69"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"bitflags",
|
||||
"rustversion",
|
||||
"volatile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x86_64"
|
||||
version = "0.14.10"
|
||||
source = "git+https://github.com/pjht/x86_64#5d941e68fa70779e07576d42a9f49bc89afdb9ed"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"bitflags",
|
||||
"rustversion",
|
||||
"volatile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xmas-elf"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d29b4d8e7beaceb4e77447ba941a7600d23d0319ab52da0461abea214832d5a"
|
||||
dependencies = [
|
||||
"zero",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zero"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f1bc8a6b2005884962297587045002d8cfb8dcec9db332f4ca216ddc5de82c5"
|
23
Cargo.toml
Normal file
23
Cargo.toml
Normal file
@ -0,0 +1,23 @@
|
||||
[package]
|
||||
name = "test_proc"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
dev_driver_rpc = { version = "0.1.0", path = "../dev_driver_rpc" }
|
||||
postcard = { version = "1.0.2", default-features = false, features = ["alloc"] }
|
||||
serde = { version = "1.0.144", default-features = false, features = ["alloc", "derive"] }
|
||||
std = { path = "../std" }
|
||||
bitflags = "1.3.2"
|
||||
spin = "0.9.4"
|
||||
tap = "1.0.1"
|
||||
x86_64 = { git = "https://github.com/pjht/x86_64", features = ["experimental"] }
|
||||
file_rpc = { version = "0.1.0", path = "../file_rpc" }
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
2
rust-toolchain.toml
Normal file
2
rust-toolchain.toml
Normal file
@ -0,0 +1,2 @@
|
||||
[toolchain]
|
||||
channel = "nightly"
|
412
src/ata.rs
Normal file
412
src/ata.rs
Normal file
@ -0,0 +1,412 @@
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use bitflags::bitflags;
|
||||
use spin::{Lazy, Mutex};
|
||||
use std::io::{self, Read, Seek};
|
||||
use tap::Tap;
|
||||
use x86_64::instructions::port::{
|
||||
PortRead, PortSafe, PortSafeReadOnly, PortSafeWriteOnly, PortWrite,
|
||||
};
|
||||
|
||||
bitflags! {
|
||||
pub struct RawError: u8 {
|
||||
const AMNF = 0b0000_0001;
|
||||
const TKZNF = 0b0000_0010;
|
||||
const ABRT = 0b0000_0100;
|
||||
const MCR = 0b0000_1000;
|
||||
const IDNF = 0b0001_0000;
|
||||
const MC = 0b0010_0000;
|
||||
const UNC = 0b0100_0000;
|
||||
const BBK = 0b1000_0000;
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RawError> for Error {
|
||||
fn from(err: RawError) -> Self {
|
||||
if err.contains(RawError::AMNF) {
|
||||
Self::AddressMarkNotFound
|
||||
} else if err.contains(RawError::TKZNF) {
|
||||
Self::TrackZeroNotFound
|
||||
} else if err.contains(RawError::ABRT) {
|
||||
Self::AbortedCommand
|
||||
} else if err.contains(RawError::MCR) {
|
||||
Self::MediaChangeRequest
|
||||
} else if err.contains(RawError::IDNF) {
|
||||
Self::IDMarkNotFound
|
||||
} else if err.contains(RawError::MC) {
|
||||
Self::MediaChanged
|
||||
} else if err.contains(RawError::UNC) {
|
||||
Self::UncorrectableData
|
||||
} else if err.contains(RawError::BBK) {
|
||||
Self::BadBlock
|
||||
} else {
|
||||
Self::Generic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PortRead for RawError {
|
||||
unsafe fn read_from_port(port: u16) -> Self {
|
||||
unsafe { Self::from_bits_unchecked(u8::read_from_port(port)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl PortWrite for RawError {
|
||||
unsafe fn write_to_port(port: u16, value: Self) {
|
||||
unsafe { u8::write_to_port(port, value.bits) };
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct Status: u8 {
|
||||
const ERR = 0b0000_0001;
|
||||
const DRQ = 0b0000_1000;
|
||||
const SRV = 0b0001_0000;
|
||||
const DF = 0b0010_0000;
|
||||
const RDY = 0b0100_0000;
|
||||
const BSY = 0b1000_0000;
|
||||
}
|
||||
}
|
||||
|
||||
impl PortRead for Status {
|
||||
unsafe fn read_from_port(port: u16) -> Self {
|
||||
unsafe { Self::from_bits_unchecked(u8::read_from_port(port)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl PortWrite for Status {
|
||||
unsafe fn write_to_port(port: u16, value: Self) {
|
||||
unsafe { u8::write_to_port(port, value.bits) };
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct DeviceControl: u8 {
|
||||
const N_IEN = 0b0000_0010;
|
||||
const SRST = 0b0000_0100;
|
||||
const HOB = 0b1000_0000;
|
||||
}
|
||||
}
|
||||
|
||||
impl PortRead for DeviceControl {
|
||||
unsafe fn read_from_port(port: u16) -> Self {
|
||||
unsafe { Self::from_bits_unchecked(u8::read_from_port(port)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl PortWrite for DeviceControl {
|
||||
unsafe fn write_to_port(port: u16, value: Self) {
|
||||
unsafe { u8::write_to_port(port, value.bits) };
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[repr(transparent)]
|
||||
pub struct DriveHead: u8 {
|
||||
const DT0 = 0b0000_0001;
|
||||
const DT1 = 0b0000_0010;
|
||||
const DT2 = 0b0000_0100;
|
||||
const DT3 = 0b0000_1000;
|
||||
const DRV = 0b0001_0000;
|
||||
const LBA = 0b0100_0000;
|
||||
}
|
||||
}
|
||||
|
||||
impl DriveHead {
|
||||
fn set_head_block(&mut self, data: u8) {
|
||||
assert!(data < 16);
|
||||
self.bits = (self.bits & 0xF0) | data;
|
||||
}
|
||||
}
|
||||
|
||||
impl PortRead for DriveHead {
|
||||
unsafe fn read_from_port(port: u16) -> Self {
|
||||
unsafe { Self::from_bits_unchecked(u8::read_from_port(port)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl PortWrite for DriveHead {
|
||||
unsafe fn write_to_port(port: u16, value: Self) {
|
||||
unsafe { u8::write_to_port(port, value.bits) };
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum DriveNumber {
|
||||
Master = 0,
|
||||
Slave = 1,
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
#[allow(unused)]
|
||||
enum Command {
|
||||
Identify = 0xEC,
|
||||
IdentifyPacket = 0xA1,
|
||||
ReadSectors = 0x20,
|
||||
WriteSectors = 0x30,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Error {
|
||||
NonexistentDrive,
|
||||
Generic,
|
||||
AbortedCommand,
|
||||
TrackZeroNotFound,
|
||||
AddressMarkNotFound,
|
||||
MediaChangeRequest,
|
||||
IDMarkNotFound,
|
||||
MediaChanged,
|
||||
UncorrectableData,
|
||||
BadBlock,
|
||||
}
|
||||
|
||||
impl From<Error> for io::Error {
|
||||
fn from(_: Error) -> Self {
|
||||
Self::new(io::ErrorKind::Other, "ATA read error")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
pub enum DriveKind {
|
||||
ATA,
|
||||
ATAPI,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum IdentifyError {
|
||||
SATADrive,
|
||||
Error(Error),
|
||||
}
|
||||
|
||||
impl From<Error> for IdentifyError {
|
||||
fn from(err: Error) -> Self {
|
||||
Self::Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Bus {
|
||||
data: PortSafe<u16>,
|
||||
error: PortSafeReadOnly<RawError>,
|
||||
sector_count: PortSafe<u8>,
|
||||
sector_num_lba_lo: PortSafe<u8>,
|
||||
cyl_low_lba_mid: PortSafe<u8>,
|
||||
cyl_high_lba_hi: PortSafe<u8>,
|
||||
drive_head: PortSafe<DriveHead>,
|
||||
status: PortSafeReadOnly<Status>,
|
||||
command: PortSafeWriteOnly<u8>,
|
||||
selected_drive: Option<DriveNumber>, // None represents the initial state with an unknown drive selected
|
||||
}
|
||||
|
||||
impl Bus {
|
||||
/// SAFETY
|
||||
/// io_base must be a valid base for the ATA bus's IO registers
|
||||
const unsafe fn new(io_base: u16) -> Self {
|
||||
unsafe {
|
||||
Self {
|
||||
data: PortSafe::new(io_base),
|
||||
error: PortSafeReadOnly::new(io_base + 1),
|
||||
sector_count: PortSafe::new(io_base + 2),
|
||||
sector_num_lba_lo: PortSafe::new(io_base + 3),
|
||||
cyl_low_lba_mid: PortSafe::new(io_base + 4),
|
||||
cyl_high_lba_hi: PortSafe::new(io_base + 5),
|
||||
drive_head: PortSafe::new(io_base + 6),
|
||||
status: PortSafeReadOnly::new(io_base + 7),
|
||||
command: PortSafeWriteOnly::new(io_base + 7),
|
||||
selected_drive: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn select(&mut self, drive: DriveNumber, lba: bool, data: u8) {
|
||||
if self.selected_drive != Some(drive) {
|
||||
self.drive_head.write(DriveHead::empty().tap_mut(|v| {
|
||||
v.set(DriveHead::DRV, drive == DriveNumber::Slave);
|
||||
v.set(DriveHead::LBA, lba);
|
||||
v.set_head_block(data);
|
||||
}));
|
||||
for _ in 0..14 {
|
||||
self.status.read();
|
||||
}
|
||||
self.selected_drive = Some(drive);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_data(&mut self) -> Result<[u16; 256], Error> {
|
||||
self.poll()?;
|
||||
let mut arr = [0; 256];
|
||||
arr.fill_with(|| self.data.read());
|
||||
Ok(arr)
|
||||
}
|
||||
|
||||
fn poll(&mut self) -> Result<(), Error> {
|
||||
while self.status.read().contains(Status::BSY) {}
|
||||
while !(self.status.read().intersects(Status::DRQ | Status::ERR)) {}
|
||||
self.error()
|
||||
}
|
||||
|
||||
fn send_command(&mut self, command: Command) {
|
||||
self.command.write(command as u8);
|
||||
}
|
||||
|
||||
pub fn identify(&mut self) -> Result<(DriveKind, [u16; 256]), IdentifyError> {
|
||||
self.command.write(Command::Identify as u8);
|
||||
if self.status.read().bits() == 0 {
|
||||
return Err(IdentifyError::Error(Error::NonexistentDrive));
|
||||
};
|
||||
self.poll()?;
|
||||
if self.status.read().contains(Status::ERR) {
|
||||
if self.cyl_low_lba_mid.read() == 0x14 && self.cyl_high_lba_hi.read() == 0xEB {
|
||||
self.command.write(Command::IdentifyPacket as u8);
|
||||
if self.status.read().bits() == 0 {
|
||||
return Err(IdentifyError::Error(Error::NonexistentDrive));
|
||||
};
|
||||
Ok((DriveKind::ATAPI, self.read_data()?))
|
||||
} else {
|
||||
Err(IdentifyError::SATADrive)
|
||||
}
|
||||
} else {
|
||||
Ok((DriveKind::ATA, self.read_data()?))
|
||||
}
|
||||
}
|
||||
|
||||
fn error(&mut self) -> Result<(), Error> {
|
||||
if self.status.read().contains(Status::ERR) {
|
||||
panic!("Drive Error: {:?}", Error::from(self.error.read()));
|
||||
Err(self.error.read().into())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
// SAFETY
|
||||
// This is safe because 0x1F0 is the standard primary bus base address
|
||||
static PRIMARY_BUS: Mutex<Bus> = Mutex::new(unsafe { Bus::new(0x1F0) });
|
||||
#[allow(unused)]
|
||||
// SAFETY
|
||||
// This is safe because 0x170 is the standard secondary bus base address
|
||||
static SECONDARY_BUS: Mutex<Bus> = Mutex::new(unsafe { Bus::new(0x170) });
|
||||
|
||||
#[allow(unused)]
|
||||
pub static PRIMARY_MASTER: Lazy<Result<Device, NewDeviceError>> =
|
||||
Lazy::new(|| Device::new(&PRIMARY_BUS, DriveNumber::Master));
|
||||
#[allow(unused)]
|
||||
pub static PRIMARY_SLAVE: Lazy<Result<Device, NewDeviceError>> =
|
||||
Lazy::new(|| Device::new(&PRIMARY_BUS, DriveNumber::Slave));
|
||||
#[allow(unused)]
|
||||
pub static SECONDARY_MASTER: Lazy<Result<Device, NewDeviceError>> =
|
||||
Lazy::new(|| Device::new(&SECONDARY_BUS, DriveNumber::Master));
|
||||
#[allow(unused)]
|
||||
pub static SECONDARY_SLAVE: Lazy<Result<Device, NewDeviceError>> =
|
||||
Lazy::new(|| Device::new(&SECONDARY_BUS, DriveNumber::Slave));
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Device {
|
||||
bus: &'static Mutex<Bus>,
|
||||
drive_number: DriveNumber,
|
||||
lba: bool,
|
||||
pos: u64,
|
||||
len: u64,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum NewDeviceError {
|
||||
IdentifyError(IdentifyError),
|
||||
ATAPIDevice,
|
||||
}
|
||||
|
||||
impl Device {
|
||||
fn new(bus: &'static Mutex<Bus>, drive_number: DriveNumber) -> Result<Self, NewDeviceError> {
|
||||
bus.lock().select(drive_number, true, 0);
|
||||
let id_result = bus
|
||||
.lock()
|
||||
.identify()
|
||||
.map_err(NewDeviceError::IdentifyError)?;
|
||||
if let (DriveKind::ATA, ident_data) = id_result {
|
||||
Ok(Self {
|
||||
bus,
|
||||
drive_number,
|
||||
lba: true,
|
||||
pos: 0,
|
||||
len: (u64::from(ident_data[60]) * 512),
|
||||
})
|
||||
} else {
|
||||
Err(NewDeviceError::ATAPIDevice)
|
||||
}
|
||||
}
|
||||
|
||||
fn select(&self, data: u8) {
|
||||
self.bus.lock().select(self.drive_number, self.lba, data);
|
||||
}
|
||||
}
|
||||
|
||||
impl Read for Device {
|
||||
#[allow(clippy::similar_names)]
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
let avail_len = u64::min(u64::min(self.len - self.pos, buf.len() as u64), 512 * 250);
|
||||
if avail_len == 0 {
|
||||
return Ok(0);
|
||||
}
|
||||
let sector = self.pos / 512;
|
||||
assert!(sector < 0x1_0000_0000_0000);
|
||||
let offset = (self.pos % 512) as usize;
|
||||
let length = avail_len as usize + offset;
|
||||
let num_sectors = length.div_ceil(512);
|
||||
assert!(num_sectors < 256);
|
||||
if sector < 0x1000_0000 {
|
||||
self.select(((sector & 0xF00_0000) >> 24) as u8);
|
||||
let mut bus = self.bus.lock();
|
||||
bus.sector_count.write(num_sectors as u8);
|
||||
bus.sector_num_lba_lo.write(sector as u8);
|
||||
bus.cyl_low_lba_mid.write((sector >> 8) as u8);
|
||||
bus.cyl_high_lba_hi.write((sector >> 16) as u8);
|
||||
bus.send_command(Command::ReadSectors);
|
||||
} else {
|
||||
unimplemented!();
|
||||
}
|
||||
let mut byte_num = 0;
|
||||
let mut i = 0;
|
||||
for _ in 0..num_sectors {
|
||||
for byte in self
|
||||
.bus
|
||||
.lock()
|
||||
.read_data()?
|
||||
.into_iter()
|
||||
.flat_map(u16::to_le_bytes)
|
||||
{
|
||||
if byte_num >= offset && byte_num < (offset + buf.len()) {
|
||||
buf[i] = byte;
|
||||
i += 1;
|
||||
}
|
||||
byte_num += 1;
|
||||
}
|
||||
}
|
||||
self.pos += avail_len as u64;
|
||||
Ok(avail_len as usize)
|
||||
}
|
||||
}
|
||||
|
||||
impl Seek for Device {
|
||||
fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
|
||||
match pos {
|
||||
io::SeekFrom::Start(x) => self.pos = x,
|
||||
io::SeekFrom::End(_) => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"End seek not implemented yet",
|
||||
))
|
||||
}
|
||||
io::SeekFrom::Current(x) => match x.cmp(&0) {
|
||||
Ordering::Equal => (),
|
||||
Ordering::Greater => self.pos += x.unsigned_abs(),
|
||||
Ordering::Less => self.pos -= x.unsigned_abs(),
|
||||
},
|
||||
};
|
||||
Ok(self.pos)
|
||||
}
|
||||
}
|
91
src/main.rs
Normal file
91
src/main.rs
Normal file
@ -0,0 +1,91 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(int_roundings)]
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
mod ata;
|
||||
|
||||
use ata::{
|
||||
Device, NewDeviceError, PRIMARY_MASTER, PRIMARY_SLAVE, SECONDARY_MASTER, SECONDARY_SLAVE,
|
||||
};
|
||||
use dev_driver_rpc::Server as DevServer;
|
||||
use file_rpc::Server as FileServer;
|
||||
use std::{
|
||||
io::{self, Read, Seek, SeekFrom},
|
||||
ipc,
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
struct Serv;
|
||||
|
||||
fn get_drive_from_number(num: u64) -> Result<Device, NewDeviceError> {
|
||||
match num {
|
||||
0 => *PRIMARY_MASTER,
|
||||
1 => *PRIMARY_SLAVE,
|
||||
2 => *SECONDARY_MASTER,
|
||||
3 => *SECONDARY_SLAVE,
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
|
||||
impl DevServer for Serv {
|
||||
fn open(&self, path: &str) -> Result<u64, io::Error> {
|
||||
match path {
|
||||
"sda" => {
|
||||
if PRIMARY_MASTER.is_ok() {
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(io::ErrorKind::NotFound.into())
|
||||
}
|
||||
}
|
||||
"sdb" => {
|
||||
if PRIMARY_SLAVE.is_ok() {
|
||||
Ok(1)
|
||||
} else {
|
||||
Err(io::ErrorKind::NotFound.into())
|
||||
}
|
||||
}
|
||||
"sdc" => {
|
||||
if SECONDARY_MASTER.is_ok() {
|
||||
Ok(2)
|
||||
} else {
|
||||
Err(io::ErrorKind::NotFound.into())
|
||||
}
|
||||
}
|
||||
"sdd" => {
|
||||
if SECONDARY_SLAVE.is_ok() {
|
||||
Ok(3)
|
||||
} else {
|
||||
Err(io::ErrorKind::NotFound.into())
|
||||
}
|
||||
}
|
||||
_ => Err(io::ErrorKind::NotFound.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl FileServer for Serv {
|
||||
fn read(&self, fd: u64, pos: u64, len: usize) -> Result<Vec<u8>, io::Error> {
|
||||
let mut buf = Vec::new();
|
||||
buf.resize(len, 0);
|
||||
let mut drive = get_drive_from_number(fd).unwrap();
|
||||
// dbg!(pos, len);
|
||||
drive.seek(SeekFrom::Start(pos))?;
|
||||
drive.read(&mut buf)?;
|
||||
// dbg!(&buf[0..usize::min(len, 16)]);
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
fn write(&self, _fd: u64, _pos: u64, _data: &[u8]) -> Result<(), io::Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn close(&self, _fd: u64) {}
|
||||
}
|
||||
|
||||
main!({
|
||||
dev_driver_rpc::register_server(Box::new(Serv));
|
||||
file_rpc::register_server(Box::new(Serv));
|
||||
loop {
|
||||
ipc::process_messages()
|
||||
}
|
||||
});
|
15
x86_64-unknown-none.json
Normal file
15
x86_64-unknown-none.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"llvm-target": "x86_64-unknown-none",
|
||||
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
|
||||
"arch": "x86_64",
|
||||
"target-endian": "little",
|
||||
"target-pointer-width": "64",
|
||||
"target-c-int-width": "32",
|
||||
"os": "none",
|
||||
"executables": true,
|
||||
"linker-flavor": "ld.lld",
|
||||
"linker": "rust-lld",
|
||||
"panic-strategy": "abort",
|
||||
"disable-redzone": true,
|
||||
"features": "-mmx,-sse,+soft-float"
|
||||
}
|
Loading…
Reference in New Issue
Block a user