1#![no_implicit_prelude]
21
22extern crate core;
23extern crate rpsp;
24
25use core::cell::UnsafeCell;
26use core::convert::From;
27use core::default::Default;
28use core::fmt::{self, Debug, Formatter};
29use core::result::Result::{self, Err};
30use core::slice::{from_raw_parts, from_raw_parts_mut};
31
32use rpsp::io;
33
34use crate::fs::{Block, Volume};
35
36const PART_START: usize = 0x1BEusize;
37
38pub enum DeviceError {
39 Timeout,
41 NotAFile,
42 NotFound,
43 EndOfFile,
44 NotReadable,
45 NotWritable,
46 UnexpectedEoF,
47 NotADirectory,
48 NonEmptyDirectory,
49
50 BadData,
52 NoSpace,
53 ReadError,
54 WriteError,
55 Hardware(u8),
56
57 Overflow,
59 InvalidIndex,
60 InvalidOptions,
61
62 NameTooLong,
64 InvalidChain,
65 InvalidVolume,
66 InvalidCluster,
67 InvalidChecksum,
68 InvalidPartition,
69 InvalidFileSystem,
70 UnsupportedVolume(u8),
71 UnsupportedFileSystem,
72}
73
74pub struct Storage<B: BlockDevice> {
75 dev: UnsafeCell<B>,
76}
77
78pub type Error = io::Error<DeviceError>;
79
80pub trait BlockDevice {
81 fn blocks(&mut self) -> Result<u32, DeviceError>;
82 fn write(&mut self, b: &[Block], start: u32) -> Result<(), DeviceError>;
83 fn read(&mut self, b: &mut [Block], start: u32) -> Result<(), DeviceError>;
84
85 #[inline]
86 fn write_single(&mut self, b: &Block, start: u32) -> Result<(), DeviceError> {
87 let v = unsafe { from_raw_parts(b, 1) };
88 self.write(v, start)
89 }
90 #[inline]
91 fn read_single(&mut self, b: &mut Block, start: u32) -> Result<(), DeviceError> {
92 let v = unsafe { from_raw_parts_mut(b, 1) };
93 self.read(v, start)
94 }
95}
96
97impl<B: BlockDevice> Storage<B> {
98 #[inline(always)]
99 pub fn new(dev: B) -> Storage<B> {
100 Storage { dev: UnsafeCell::new(dev) }
101 }
102
103 #[inline(always)]
104 pub fn device(&self) -> &mut B {
105 unsafe { &mut *self.dev.get() }
106 }
107 #[inline(always)]
108 pub fn root<'a>(&'a self) -> Result<Volume<'a, B>, DeviceError> {
109 self.volume(0)
110 }
111 pub fn volume<'a>(&'a self, index: usize) -> Result<Volume<'a, B>, DeviceError> {
112 if index > 3 {
113 return Err(DeviceError::NotFound);
114 }
115 let mut b = Block::default();
116 self.read_single(&mut b, 0)?;
117 if le_u16(&b[0x1FE..]) != 0xAA55 {
118 return Err(DeviceError::InvalidPartition);
119 }
120 let i = PART_START + (0x10 * index);
121 if i + 12 > Block::SIZE {
122 return Err(DeviceError::NotFound);
123 }
124 if b[i] & 0x7F != 0 {
125 return Err(DeviceError::InvalidPartition);
126 }
127 match b[i + 4] {
128 0x6 | 0xB | 0xE | 0xC | 0x16 | 0x1B | 0x1E | 0x66 | 0x76 | 0x83 | 0x92 | 0x97 | 0x98 | 0x9A | 0xD0 | 0xE4 | 0xE6 | 0xEF | 0xF4 | 0xF6 => (),
131 _ => return Err(DeviceError::UnsupportedVolume(b[i + 4])),
132 }
133 let (s, n) = (le_u32(&b[i + 8..]), le_u32(&b[i + 12..]));
134 Volume::parse(self, b, s, n)
135 }
136
137 #[inline(always)]
138 pub(super) fn write(&self, b: &[Block], start: u32) -> Result<(), DeviceError> {
139 self.device().write(b, start)
140 }
141 #[inline(always)]
142 pub(super) fn read(&self, b: &mut [Block], start: u32) -> Result<(), DeviceError> {
143 self.device().read(b, start)
144 }
145 #[inline(always)]
146 pub(super) fn write_single(&self, b: &Block, start: u32) -> Result<(), DeviceError> {
147 self.device().write_single(b, start)
148 }
149 #[inline(always)]
150 pub(super) fn read_single(&self, b: &mut Block, start: u32) -> Result<(), DeviceError> {
151 self.device().read_single(b, start)
152 }
153}
154
155impl From<DeviceError> for Error {
156 #[inline]
157 fn from(v: DeviceError) -> Error {
158 match v {
159 DeviceError::Timeout => Error::Timeout,
160 DeviceError::EndOfFile => Error::EndOfFile,
161 DeviceError::ReadError => Error::ReadError,
162 DeviceError::WriteError => Error::WriteError,
163 DeviceError::UnexpectedEoF => Error::UnexpectedEof,
164 DeviceError::NoSpace => Error::NoSpace,
165 DeviceError::NotAFile => Error::NotAFile,
166 DeviceError::NotFound => Error::NotFound,
167 DeviceError::Overflow => Error::Overflow,
168 DeviceError::NotReadable => Error::NotReadable,
169 DeviceError::NotWritable => Error::NotWritable,
170 DeviceError::NotADirectory => Error::NotADirectory,
171 DeviceError::NonEmptyDirectory => Error::NonEmptyDirectory,
172 DeviceError::InvalidIndex => Error::InvalidIndex,
173 DeviceError::InvalidOptions => Error::InvalidOptions,
174 _ => Error::Other(v),
175 }
176 }
177}
178
179#[cfg(feature = "debug")]
180impl Debug for DeviceError {
181 #[inline]
182 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
183 match self {
184 DeviceError::Timeout => f.write_str("Timeout"),
185 DeviceError::NotAFile => f.write_str("NotAFile"),
186 DeviceError::NotFound => f.write_str("NotFound"),
187 DeviceError::EndOfFile => f.write_str("EndOfFile"),
188 DeviceError::NotReadable => f.write_str("NotReadable"),
189 DeviceError::NotWritable => f.write_str("NotWritable"),
190 DeviceError::UnexpectedEoF => f.write_str("UnexpectedEoF"),
191 DeviceError::NotADirectory => f.write_str("NotADirectory"),
192 DeviceError::NonEmptyDirectory => f.write_str("NonEmptyDirectory"),
193 DeviceError::BadData => f.write_str("BadData"),
194 DeviceError::NoSpace => f.write_str("NoSpace"),
195 DeviceError::ReadError => f.write_str("ReadError"),
196 DeviceError::WriteError => f.write_str("WriteError"),
197 DeviceError::Hardware(v) => f.debug_tuple("Hardware").field(v).finish(),
198 DeviceError::Overflow => f.write_str("Overflow"),
199 DeviceError::InvalidIndex => f.write_str("InvalidIndex"),
200 DeviceError::InvalidOptions => f.write_str("InvalidOptions"),
201 DeviceError::NameTooLong => f.write_str("NameTooLong"),
202 DeviceError::InvalidChain => f.write_str("InvalidChain"),
203 DeviceError::InvalidVolume => f.write_str("InvalidVolume"),
204 DeviceError::InvalidCluster => f.write_str("InvalidCluster"),
205 DeviceError::InvalidChecksum => f.write_str("InvalidChecksum"),
206 DeviceError::InvalidPartition => f.write_str("InvalidPartition"),
207 DeviceError::InvalidFileSystem => f.write_str("InvalidFileSystem"),
208 DeviceError::UnsupportedVolume(v) => f.debug_tuple("UnsupportedVolume").field(v).finish(),
209 DeviceError::UnsupportedFileSystem => f.write_str("UnsupportedFileSystem"),
210 }
211 }
212}
213#[cfg(not(feature = "debug"))]
214impl Debug for DeviceError {
215 #[inline(always)]
216 fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result {
217 Result::Ok(())
218 }
219}
220
221#[inline(always)]
222pub(super) fn le_u16(b: &[u8]) -> u16 {
223 (b[0] as u16) | (b[1] as u16) << 8
224}
225#[inline(always)]
226pub(super) fn le_u32(b: &[u8]) -> u32 {
227 (b[0] as u32) | (b[1] as u32) << 8 | (b[2] as u32) << 16 | (b[3] as u32) << 24
228}
229#[inline]
230pub(super) fn to_le_u16(v: u16, b: &mut [u8]) {
231 b[0] = v as u8;
232 b[1] = (v >> 8) as u8;
233}
234#[inline]
235pub(super) fn to_le_u32(v: u32, b: &mut [u8]) {
236 b[0] = v as u8;
237 b[1] = (v >> 8) as u8;
238 b[2] = (v >> 16) as u8;
239 b[3] = (v >> 24) as u8;
240}