diff --git a/Cargo.lock b/Cargo.lock index 8c602a0414..c325744907 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,8 +4,9 @@ name = "ahcid" version = "0.1.0" dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "partitionlib 0.1.0 (git+https://gitlab.redox-os.org/redox-os/partitionlib.git)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -61,7 +62,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bitflags" -version = "1.1.0" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "build_const" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -98,7 +104,15 @@ name = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crc" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -157,7 +171,7 @@ name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -171,6 +185,17 @@ name = "futures" version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "gpt" +version = "0.6.3" +source = "git+https://github.com/4lDO2/gpt#20160d7089faa44c3566cad0fa6e49b2824b599c" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "httparse" version = "1.3.4" @@ -238,7 +263,7 @@ dependencies = [ name = "ixgbed" version = "1.0.0" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "netutils 0.1.0 (git+https://gitlab.redox-os.org/redox-os/netutils.git)", "redox_event 0.1.0 (git+https://gitlab.redox-os.org/redox-os/event.git)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", @@ -536,6 +561,16 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "partitionlib" +version = "0.1.0" +source = "git+https://gitlab.redox-os.org/redox-os/partitionlib.git#ae8157fde75ac3589b7e8ff831bbba538b8009d8" +dependencies = [ + "gpt 0.6.3 (git+https://github.com/4lDO2/gpt)", + "scroll 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pbr" version = "1.0.1" @@ -563,7 +598,7 @@ dependencies = [ name = "pcid" version = "0.1.0" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", @@ -596,6 +631,14 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro2" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ps2d" version = "0.1.0" @@ -614,6 +657,14 @@ dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quote" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand" version = "0.6.5" @@ -815,6 +866,24 @@ name = "scopeguard" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "scroll" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "scroll_derive 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scroll_derive" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "sct" version = "0.4.0" @@ -829,7 +898,7 @@ name = "sdl2" version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -912,6 +981,16 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syn" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "termion" version = "1.5.3" @@ -1135,6 +1214,11 @@ name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "untrusted" version = "0.6.2" @@ -1155,6 +1239,14 @@ name = "utf8parse" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "uuid" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "vboxd" version = "0.1.0" @@ -1260,13 +1352,15 @@ dependencies = [ "checksum autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "22130e92352b948e7e82a49cdb0aa94f2211761117f29e052dd397c1ac33542b" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" -"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" +"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +"checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" "checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" "checksum cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "ce400c638d48ee0e9ab75aef7997609ec57367ccfe1463f21bf53c3eca67bf46" "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" "checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" "checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" "checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" @@ -1275,6 +1369,7 @@ dependencies = [ "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "45dc39533a6cae6da2b56da48edae506bb767ec07370f86f70fc062e9d435869" +"checksum gpt 0.6.3 (git+https://github.com/4lDO2/gpt)" = "" "checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" "checksum hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" "checksum hyper-rustls 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "71f7b2e5858ab9e19771dc361159f09ee5031734a6f7471fe0947db0238d92b7" @@ -1310,12 +1405,15 @@ dependencies = [ "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum partitionlib 0.1.0 (git+https://gitlab.redox-os.org/redox-os/partitionlib.git)" = "" "checksum pbr 1.0.1 (git+https://github.com/a8m/pb)" = "" "checksum pbr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "deb73390ab68d81992bd994d145f697451bb0b54fd39738e72eef32458ad6907" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +"checksum proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0319972dcae462681daf4da1adeeaa066e3ebd29c69be96c6abb1259d2ee2bcc" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" @@ -1338,6 +1436,8 @@ dependencies = [ "checksum safemem 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e133ccc4f4d1cd4f89cc8a7ff618287d56dc7f638b8e38fc32c5fdcadc339dd5" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" +"checksum scroll 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "abb2332cb595d33f7edd5700f4cbf94892e680c7f0ae56adab58a35190b66cb1" +"checksum scroll_derive 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8584eea9b9ff42825b46faf46a8c24d2cff13ec152fa2a50df788b87c07ee28" "checksum sct 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb8f61f9e6eadd062a71c380043d28036304a4706b3c4dd001ff3387ed00745a" "checksum sdl2 0.32.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d051a07231e303f5f719da78cb6f7394f6d5b54f733aef5b0b447804a83edd7b" "checksum sdl2-sys 0.32.6 (registry+https://github.com/rust-lang/crates.io-index)" = "34e71125077d297d57e4c1acfe8981b5bdfbf5a20e7b589abfdcb33bf1127f86" @@ -1351,6 +1451,7 @@ dependencies = [ "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum stb_truetype 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "69b7df505db8e81d54ff8be4693421e5b543e08214bd8d99eb761fcb4d5668ba" "checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +"checksum syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4ff033220a41d1a57d8125eab57bf5263783dfdcc18688b1dacc6ce9651ef8" "checksum termion 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a8fb22f7cde82c8220e5aeacb3258ed7ce996142c77cba193f203515e26c330" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum tokio 0.1.13 (git+https://gitlab.redox-os.org/redox-os/tokio)" = "" @@ -1372,9 +1473,11 @@ dependencies = [ "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" "checksum utf8parse 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8772a4ccbb4e89959023bc5b7cb8623a795caa7092d99f3aa9501b9484d4557d" +"checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum vte 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4f42f536e22f7fcbb407639765c8fd78707a33109301f834a594758bedd6e8cf" "checksum webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "17d7967316d8411ca3b01821ee6c332bde138ba4363becdb492f12e514daa17f" diff --git a/ahcid/.gitignore b/ahcid/.gitignore new file mode 100644 index 0000000000..ea8c4bf7f3 --- /dev/null +++ b/ahcid/.gitignore @@ -0,0 +1 @@ +/target diff --git a/ahcid/Cargo.toml b/ahcid/Cargo.toml index 789f7e0b38..bfd9f21315 100644 --- a/ahcid/Cargo.toml +++ b/ahcid/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" edition = "2018" [dependencies] -bitflags = "0.7" -redox_syscall = "0.1" +bitflags = "1.2" byteorder = "1.2" +partitionlib = { git = "https://gitlab.redox-os.org/redox-os/partitionlib.git" } +redox_syscall = "0.1" diff --git a/ahcid/src/scheme.rs b/ahcid/src/scheme.rs index 28684b2cbc..1e13a744f3 100644 --- a/ahcid/src/scheme.rs +++ b/ahcid/src/scheme.rs @@ -1,25 +1,152 @@ use std::collections::BTreeMap; use std::{cmp, str}; +use std::convert::{TryFrom, TryInto}; use std::fmt::Write; -use std::io::Read; +use std::io::prelude::*; +use std::io::SeekFrom; +use std::io; + use syscall::{ - Error, EACCES, EBADF, EINVAL, EISDIR, ENOENT, Result, + Error, EACCES, EBADF, EINVAL, EISDIR, ENOENT, EOVERFLOW, Result, Io, SchemeBlockMut, Stat, MODE_DIR, MODE_FILE, O_DIRECTORY, O_STAT, SEEK_CUR, SEEK_END, SEEK_SET}; use crate::ahci::Disk; use crate::ahci::hba::HbaMem; +use partitionlib::{LogicalBlockSize, PartitionTable}; + #[derive(Clone)] enum Handle { - List(Vec, usize), - Disk(usize, usize) + List(Vec, usize), // Dir contents buffer, position + Disk(usize, usize), // Disk index, position + Partition(usize, u32, usize), // Disk index, partition index, position +} + +pub struct DiskWrapper { + disk: Box, + pt: Option, +} + +impl DiskWrapper { + fn pt(disk: &mut dyn Disk) -> Option { + let bs = match disk.block_length() { + Ok(512) => LogicalBlockSize::Lb512, + Ok(4096) => LogicalBlockSize::Lb4096, + _ => return None, + }; + struct Device<'a, 'b> { disk: &'a mut dyn Disk, offset: u64, block_bytes: &'b mut [u8] } + + impl<'a, 'b> Seek for Device<'a, 'b> { + fn seek(&mut self, from: SeekFrom) -> io::Result { + let size = i64::try_from(self.disk.size()).or(Err(io::Error::new(io::ErrorKind::Other, "Disk larger than 2^63 - 1 bytes")))?; + + self.offset = match from { + SeekFrom::Start(new_pos) => cmp::min(self.disk.size(), new_pos), + SeekFrom::Current(new_pos) => cmp::max(0, cmp::min(size, self.offset as i64 + new_pos)) as u64, + SeekFrom::End(new_pos) => cmp::max(0, cmp::min(size + new_pos, size)) as u64, + }; + + Ok(self.offset) + } + } + // Perhaps this impl should be used in the rest of the scheme. + impl<'a, 'b> Read for Device<'a, 'b> { + fn read(&mut self, mut buf: &mut [u8]) -> io::Result { + // TODO: Yield sometimes, perhaps after a few blocks or something. + use std::ops::{Add, Div, Rem}; + + fn div_round_up(a: T, b: T) -> T + where + T: Add + Div + Rem + PartialEq + From + Copy + { + if a % b != T::from(0u8) { + a / b + T::from(1u8) + } else { + a / b + } + } + + let orig_buf_len = buf.len(); + + let blksize = self.disk.block_length().map_err(|err| io::Error::from_raw_os_error(err.errno))?; + + let start_block = self.offset / u64::from(blksize); + let end_block = div_round_up(self.offset + buf.len() as u64, u64::from(blksize)); // The first block not in the range + + let offset_from_start_block: u64 = self.offset % u64::from(blksize); + let offset_to_end_block: u64 = u64::from(blksize) - (self.offset + buf.len() as u64) % u64::from(blksize); + + let first_whole_block = start_block + if offset_from_start_block > 0 { 1 } else { 0 }; + let last_whole_block = end_block - if offset_to_end_block > 0 { 1 } else { 0 } - 1; + + let whole_blocks_to_read = last_whole_block - first_whole_block + 1; + + for block in start_block..end_block { + // TODO: Async/await? I mean, shouldn't AHCI be async? + + loop { + let block = self.offset / u64::from(blksize); + + match self.disk.read(block, self.block_bytes) { + Ok(Some(bytes)) => { + assert_eq!(bytes, self.block_bytes.len()); + assert_eq!(bytes, blksize as usize); + break; + } + Ok(None) => continue, + Err(err) => return Err(io::Error::from_raw_os_error(err.errno)), + } + } + + let (bytes_to_read, src_buf): (u64, &[u8]) = if block == start_block { + (u64::from(blksize) - offset_from_start_block, &self.block_bytes[offset_from_start_block as usize..]) + } else if block == end_block { + (u64::from(blksize) - offset_to_end_block, &self.block_bytes[..offset_to_end_block as usize]) + } else { + (blksize.into(), &self.block_bytes[..]) + }; + let bytes_to_read = std::cmp::min(bytes_to_read as usize, buf.len()); + buf[..bytes_to_read].copy_from_slice(&src_buf[..bytes_to_read]); + buf = &mut buf[..bytes_to_read]; + } + + let bytes_read = std::cmp::min(orig_buf_len, whole_blocks_to_read as usize * blksize as usize + offset_from_start_block as usize + offset_to_end_block as usize); + self.offset += bytes_read as u64; + + Ok(bytes_read) + } + } + + let mut block_bytes = [0u8; 4096]; + + partitionlib::get_partitions(&mut Device { disk, offset: 0, block_bytes: &mut block_bytes[..bs.into()] }, bs).ok().flatten() + } + fn new(mut disk: Box) -> Self { + Self { + pt: Self::pt(&mut *disk), + disk, + } + } +} + +impl std::ops::Deref for DiskWrapper { + type Target = dyn Disk; + + fn deref(&self) -> &Self::Target { + &*self.disk + } +} +impl std::ops::DerefMut for DiskWrapper { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut *self.disk + } } pub struct DiskScheme { scheme_name: String, hba_mem: &'static mut HbaMem, - disks: Box<[Box]>, + disks: Box<[DiskWrapper]>, handles: BTreeMap, next_id: usize } @@ -29,7 +156,7 @@ impl DiskScheme { DiskScheme { scheme_name: scheme_name, hba_mem: hba_mem, - disks: disks.into_boxed_slice(), + disks: disks.into_iter().map(DiskWrapper::new).collect::>().into_boxed_slice(), handles: BTreeMap::new(), next_id: 0 } @@ -65,8 +192,15 @@ impl SchemeBlockMut for DiskScheme { if flags & O_DIRECTORY == O_DIRECTORY || flags & O_STAT == O_STAT { let mut list = String::new(); - for i in 0..self.disks.len() { - write!(list, "{}\n", i).unwrap(); + for (disk_index, disk) in self.disks.iter().enumerate() { + write!(list, "{}\n", disk_index).unwrap(); + + if disk.pt.is_none() { + continue + } + for part_index in 0..disk.pt.as_ref().unwrap().partitions.len() { + write!(list, "{}p{}\n", disk_index, part_index).unwrap(); + } } let id = self.next_id; @@ -76,6 +210,28 @@ impl SchemeBlockMut for DiskScheme { } else { Err(Error::new(EISDIR)) } + } else if let Some(p_pos) = path_str.chars().position(|c| c == 'p') { + let disk_id_str = &path_str[..p_pos]; + if p_pos + 1 >= path_str.len() { + return Err(Error::new(ENOENT)); + } + let part_id_str = &path_str[p_pos + 1..]; + let i = disk_id_str.parse::().or(Err(Error::new(ENOENT)))?; + let p = part_id_str.parse::().or(Err(Error::new(ENOENT)))?; + + if let Some(disk) = self.disks.get(i) { + if disk.pt.is_none() || disk.pt.as_ref().unwrap().partitions.get(p as usize).is_none() { + return Err(Error::new(ENOENT)); + } + let id = self.next_id; + self.next_id += 1; + + self.handles.insert(id, Handle::Partition(i, p, 0)); + + Ok(Some(id)) + } else { + Err(Error::new(ENOENT)) + } } else { let i = path_str.parse::().or(Err(Error::new(ENOENT)))?; @@ -120,6 +276,21 @@ impl SchemeBlockMut for DiskScheme { let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?; stat.st_mode = MODE_FILE; stat.st_size = disk.size(); + stat.st_blksize = disk.block_length()?; + Ok(Some(0)) + } + Handle::Partition(disk_id, part_num, _) => { + let disk = self.disks.get_mut(disk_id).ok_or(Error::new(EBADF))?; + let size = { + let pt = disk.pt.as_ref().ok_or(Error::new(EBADF))?; + let partition = pt.partitions.get(part_num as usize).ok_or(Error::new(EBADF))?; + partition.size + }; + + stat.st_mode = MODE_FILE; // TODO: Block device? + stat.st_size = size * u64::from(disk.block_length()?); + stat.st_blksize = disk.block_length()?; + stat.st_blocks = size; Ok(Some(0)) } } @@ -155,6 +326,16 @@ impl SchemeBlockMut for DiskScheme { j += 1; } } + Handle::Partition(disk_num, part_num, _) => { + let path = format!("{}p{}", disk_num, part_num); + let path_bytes = path.as_bytes(); + j = 0; + while i < buf.len() && j < path_bytes.len() { + buf[i] = path_bytes[j]; + i += 1; + j += 1; + } + } } Ok(Some(i)) @@ -162,7 +343,7 @@ impl SchemeBlockMut for DiskScheme { fn read(&mut self, id: usize, buf: &mut [u8]) -> Result> { match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? { - Handle::List(ref mut handle, ref mut size) => { + Handle::List(ref handle, ref mut size) => { let count = (&handle[*size..]).read(buf).unwrap(); *size += count; Ok(Some(count)) @@ -177,6 +358,30 @@ impl SchemeBlockMut for DiskScheme { Ok(None) } } + Handle::Partition(disk_num, part_num, ref mut position) => { + let disk = self.disks.get_mut(disk_num).ok_or(Error::new(EBADF))?; + let blksize = disk.block_length()?; + + // validate that we're actually reading within the bounds of the partition + let rel_block = *position as u64 / blksize as u64; + + let abs_block = { + let pt = disk.pt.as_ref().ok_or(Error::new(EBADF))?; + let partition = pt.partitions.get(part_num as usize).ok_or(Error::new(EBADF))?; + + let abs_block = partition.start_lba + rel_block; + if rel_block >= partition.size { + return Err(Error::new(EOVERFLOW)); + } + abs_block + }; + + if let Some(count) = disk.read(abs_block, buf)? { + Ok(Some(count)) + } else { + Ok(None) + } + } } } @@ -195,6 +400,30 @@ impl SchemeBlockMut for DiskScheme { Ok(None) } } + Handle::Partition(disk_num, part_num, ref mut position) => { + let disk = self.disks.get_mut(disk_num).ok_or(Error::new(EBADF))?; + let blksize = disk.block_length()?; + + // validate that we're actually reading within the bounds of the partition + let rel_block = *position as u64 / blksize as u64; + + let abs_block = { + let pt = disk.pt.as_ref().ok_or(Error::new(EBADF))?; + let partition = pt.partitions.get(part_num as usize).ok_or(Error::new(EBADF))?; + + let abs_block = partition.start_lba + rel_block; + if rel_block >= partition.size { + return Err(Error::new(EOVERFLOW)); + } + abs_block + }; + + if let Some(count) = disk.write(abs_block, buf)? { + Ok(Some(count)) + } else { + Ok(None) + } + } } } @@ -223,6 +452,19 @@ impl SchemeBlockMut for DiskScheme { Ok(Some(*size)) } + Handle::Partition(disk_num, part_num, ref mut position) => { + let disk = self.disks.get_mut(disk_num).ok_or(Error::new(EBADF))?; + let block_count = disk.pt.as_ref().ok_or(Error::new(EBADF))?.partitions.get(part_num as usize).ok_or(Error::new(EBADF))?.size; + let len = u64::from(disk.block_length()?) * block_count; + + *position = match whence { + SEEK_SET => cmp::min(len as usize, pos) as usize, // Why isn't pos u64? + SEEK_CUR => cmp::max(0, cmp::min(len as isize, *position as isize + pos as isize)) as usize, + SEEK_END => cmp::max(0, cmp::min(len as isize, len as isize + pos as isize)) as usize, + _ => return Err(Error::new(EINVAL)), + }; + Ok(Some(*position as usize)) + } } }