Skip to main content

atmos/kernel/fs/
block.rs

1// block.rs - Block Device Abstraction, RAM Disk Backend, and Mirrored (Redundant) Layer
2#![allow(dead_code)]
3#![allow(static_mut_refs)]
4
5extern crate alloc;
6use super::checksum::crc32;
7use alloc::vec::Vec;
8
9pub const SECTOR_SIZE: usize = 512;
10pub const DATA_SIZE_PER_SECTOR: usize = 508; // 512 - 4 (CRC32)
11
12/// 抽象ブロックデバイスの動作を規定するトレイト
13pub trait BlockDevice {
14    /// デバイスの総セクタ数を取得します
15    fn total_sectors(&self) -> usize;
16
17    /// 生セクタ (512バイト) の読み込みを行います (チェックサム検証なし)
18    fn read_raw_sector(&mut self, sector: usize, buf: &mut [u8]) -> Result<(), &'static str>;
19
20    /// 生セクタ (512バイト) の書き込みを行います (チェックサム検証なし)
21    fn write_raw_sector(&mut self, sector: usize, buf: &[u8]) -> Result<(), &'static str>;
22
23    /// データの二重化(ミラーリング)が必要な外部記憶デバイスかどうか
24    fn should_mirror(&self) -> bool {
25        false
26    }
27}
28
29/// メモリ上にファイルシステム全体を格納する仮想RAMディスク
30pub struct RAMDisk {
31    base_ptr: *mut u8,
32    size_bytes: usize,
33    sectors: usize,
34    _allocated: Option<Vec<u8>>,
35}
36
37unsafe impl Send for RAMDisk {}
38unsafe impl Sync for RAMDisk {}
39
40impl RAMDisk {
41    /// ヒープからメモリを確保する仮想RAMディスク(単体テストや小規模環境用)
42    pub fn new(size_bytes: usize) -> Self {
43        let mut storage = alloc::vec![0u8; size_bytes];
44        let base_ptr = storage.as_mut_ptr();
45        let sectors = size_bytes / SECTOR_SIZE;
46        Self {
47            base_ptr,
48            size_bytes,
49            sectors,
50            _allocated: Some(storage),
51        }
52    }
53
54    /// 物理メモリ上の特定領域(ヒープ外の専用RAM領域)を直接使用するRAMディスク(実機カーネル用)
55    ///
56    /// # Safety
57    /// `base_addr` から `size_bytes` の領域が他モジュールと重複せず、排他的に使用可能である必要があります。
58    pub unsafe fn from_raw_memory(base_addr: usize, size_bytes: usize) -> Self {
59        let base_ptr = base_addr as *mut u8;
60        let sectors = size_bytes / SECTOR_SIZE;
61        Self {
62            base_ptr,
63            size_bytes,
64            sectors,
65            _allocated: None,
66        }
67    }
68}
69
70impl BlockDevice for RAMDisk {
71    fn total_sectors(&self) -> usize {
72        self.sectors
73    }
74
75    fn read_raw_sector(&mut self, sector: usize, buf: &mut [u8]) -> Result<(), &'static str> {
76        if sector >= self.sectors || buf.len() < SECTOR_SIZE {
77            return Err("read_raw_sector: sector out of range or buffer too small");
78        }
79        let offset = sector * SECTOR_SIZE;
80        unsafe {
81            let src = self.base_ptr.add(offset);
82            core::ptr::copy_nonoverlapping(src, buf.as_mut_ptr(), SECTOR_SIZE);
83        }
84        Ok(())
85    }
86
87    fn write_raw_sector(&mut self, sector: usize, buf: &[u8]) -> Result<(), &'static str> {
88        if sector >= self.sectors || buf.len() < SECTOR_SIZE {
89            return Err("write_raw_sector: sector out of range or buffer too small");
90        }
91        let offset = sector * SECTOR_SIZE;
92        unsafe {
93            let dst = self.base_ptr.add(offset);
94            core::ptr::copy_nonoverlapping(buf.as_ptr(), dst, SECTOR_SIZE);
95        }
96        Ok(())
97    }
98
99    fn should_mirror(&self) -> bool {
100        // RAMディスクは揮発性メモリのため二重化不要(RAM容量を100%有効活用)
101        false
102    }
103}
104
105/// データの二重化 (ミラーリング) & 自動自己修復 (Self-Healing) を提供する上位ブロックデバイス層
106/// SDカード等の外部不揮発性ストレージでは二重化を行い、
107/// RAMディスク等の揮発性メモリでは多重化を行わずに全RAM容量を有効活用する。
108pub struct MirroredBlockDevice<B: BlockDevice> {
109    backend: B,
110    mirrored: bool,
111    usable_sectors: usize,
112}
113
114impl<B: BlockDevice> MirroredBlockDevice<B> {
115    pub fn new(backend: B) -> Self {
116        let mirrored = backend.should_mirror();
117        let usable_sectors = if mirrored {
118            backend.total_sectors() / 2
119        } else {
120            backend.total_sectors()
121        };
122        Self {
123            backend,
124            mirrored,
125            usable_sectors,
126        }
127    }
128
129    pub fn new_mirrored(backend: B) -> Self {
130        let usable_sectors = backend.total_sectors() / 2;
131        Self {
132            backend,
133            mirrored: true,
134            usable_sectors,
135        }
136    }
137
138    pub fn new_single(backend: B) -> Self {
139        let usable_sectors = backend.total_sectors();
140        Self {
141            backend,
142            mirrored: false,
143            usable_sectors,
144        }
145    }
146
147    pub fn is_mirrored(&self) -> bool {
148        self.mirrored
149    }
150
151    pub fn total_usable_sectors(&self) -> usize {
152        self.usable_sectors
153    }
154
155    /// チェックサム (CRC32) 付きでデータをセクタに書き込みします
156    pub fn write_sector(&mut self, sector: usize, data: &[u8]) -> Result<(), &'static str> {
157        if sector >= self.usable_sectors || data.len() > DATA_SIZE_PER_SECTOR {
158            return Err("write_sector: sector out of range or data too large");
159        }
160
161        // 512バイトの書き込み用一時バッファを用意
162        let mut buf = [0u8; SECTOR_SIZE];
163        buf[..data.len()].copy_from_slice(data);
164
165        // データのチェックサムを計算し、セクタの末尾4バイトに格納
166        let crc = crc32(&buf[..DATA_SIZE_PER_SECTOR]);
167        let crc_bytes = crc.to_le_bytes();
168        buf[DATA_SIZE_PER_SECTOR..SECTOR_SIZE].copy_from_slice(&crc_bytes);
169
170        // 1. プライマリ領域に書き込み
171        self.backend.write_raw_sector(sector, &buf)?;
172
173        // 2. ミラーリング有効時(SD/SSD等の外部記憶)のみセカンダリ領域に同一データを書き込み
174        if self.mirrored {
175            self.backend
176                .write_raw_sector(sector + self.usable_sectors, &buf)?;
177        }
178
179        Ok(())
180    }
181
182    /// チェックサム (CRC32) 検証付きでセクタからデータを読み込みます (外部記憶ミラーリング時は破損から自動修復)
183    pub fn read_sector(&mut self, sector: usize, data: &mut [u8]) -> Result<(), &'static str> {
184        if sector >= self.usable_sectors || data.len() < DATA_SIZE_PER_SECTOR {
185            return Err("read_sector: sector out of range or buffer too small");
186        }
187
188        let mut buf = [0u8; SECTOR_SIZE];
189
190        // 1. プライマリ領域からの読み込み試行
191        if self.backend.read_raw_sector(sector, &mut buf).is_ok() {
192            let crc_stored = u32::from_le_bytes([
193                buf[DATA_SIZE_PER_SECTOR],
194                buf[DATA_SIZE_PER_SECTOR + 1],
195                buf[DATA_SIZE_PER_SECTOR + 2],
196                buf[DATA_SIZE_PER_SECTOR + 3],
197            ]);
198            let crc_calc = crc32(&buf[..DATA_SIZE_PER_SECTOR]);
199
200            if crc_stored == crc_calc {
201                // プライマリデータは健全
202                data[..DATA_SIZE_PER_SECTOR].copy_from_slice(&buf[..DATA_SIZE_PER_SECTOR]);
203                return Ok(());
204            } else if self.mirrored {
205                crate::warn!(
206                    "CRC mismatch on Primary Sector {}. Initiating Self-Healing...",
207                    sector
208                );
209            } else {
210                crate::warn!(
211                    "CRC mismatch on Sector {}. RAMDisk is unmirrored.",
212                    sector
213                );
214                return Err("read_sector: crc mismatch");
215            }
216        }
217
218        // 2. ミラーリング有効時かつプライマリが破損していた場合、セカンダリ (ミラー) 領域から読み込み
219        if self.mirrored {
220            let mirror_sector = sector + self.usable_sectors;
221            if self
222                .backend
223                .read_raw_sector(mirror_sector, &mut buf)
224                .is_ok()
225            {
226                let crc_stored = u32::from_le_bytes([
227                    buf[DATA_SIZE_PER_SECTOR],
228                    buf[DATA_SIZE_PER_SECTOR + 1],
229                    buf[DATA_SIZE_PER_SECTOR + 2],
230                    buf[DATA_SIZE_PER_SECTOR + 3],
231                ]);
232                let crc_calc = crc32(&buf[..DATA_SIZE_PER_SECTOR]);
233
234                if crc_stored == crc_calc {
235                    crate::info!(
236                        "Mirror Sector {} is healthy. Healing Primary Sector {}...",
237                        mirror_sector,
238                        sector
239                    );
240                    if let Err(e) = self.backend.write_raw_sector(sector, &buf) {
241                        crate::warn!(
242                            "[BLOCK] 自己修復の書き戻しに失敗 sector={} mirror_sector={} err={:?}",
243                            sector,
244                            mirror_sector,
245                            e
246                        );
247                    }
248
249                    data[..DATA_SIZE_PER_SECTOR].copy_from_slice(&buf[..DATA_SIZE_PER_SECTOR]);
250                    return Ok(());
251                }
252            }
253
254            // 両系とも破損していた場合
255            crate::error!(
256                "Dual-redundancy failure on Sector {}. Data is unrecoverable!",
257                sector
258            );
259            return Err("read_sector: both primary and mirror corrupted");
260        }
261
262        Err("read_sector: read failed")
263    }
264
265    /// デバッグ検証用: 意図的に特定の生セクタを破壊します (自己修復のテストに使用)
266    pub fn force_corrupt_raw_sector(&mut self, sector: usize) -> Result<(), &'static str> {
267        if sector >= self.backend.total_sectors() {
268            return Err("force_corrupt: sector out of range");
269        }
270        let corrupt_buf = [0u8; SECTOR_SIZE]; // ゼロクリアで完全に上書き破壊
271        self.backend.write_raw_sector(sector, &corrupt_buf)
272    }
273}
274
275/// オンボードのブート用 microSD カード (SDHOST 制御) 用のブロックデバイス実装
276pub struct SDCard {
277    offset_sectors: usize,
278}
279
280impl SDCard {
281    pub fn new() -> Result<Self, &'static str> {
282        // SDHOST コントローラと物理カードの初期化を実行
283        crate::kernel::sdhost::init()?;
284        // オフセットは 256 MiB (256 * 1024 * 1024 / 512 = 524,288 セクタ)
285        let sd = Self {
286            offset_sectors: 524288,
287        };
288
289        // 【2026-07-26】コントローラの初期化に成功しても、データ転送経路
290        // (CMD17/CMD24 と FIFO 処理)が機能していなければファイルシステムは
291        // 使い物にならない。実際、SDHOST のレスポンス種別フラグ修正で
292        // ACMD41 は通るようになったものの読み書きは依然として成立せず、
293        // それまで働いていた RAMDisk フォールバックが無効化されて
294        // **かえって機能後退**する状態になった。
295        // 初期化直後に読み出しを 1 回試し、成立しなければエラーを返して
296        // 従来どおり RAMDisk へフォールバックさせる。
297        Self::probe_data_path(&sd)?;
298        Ok(sd)
299    }
300
301    /// データ転送経路が最低限機能しているかの疎通確認(読み出し 1 セクタ)。
302    fn probe_data_path(sd: &Self) -> Result<(), &'static str> {
303        let mut buf = [0u8; 512];
304        crate::kernel::sdhost::read_sector(sd.offset_sectors, &mut buf)
305            .map_err(|_| "SDHOST: data path probe failed (read)")
306    }
307}
308
309impl BlockDevice for SDCard {
310    fn total_sectors(&self) -> usize {
311        let total = crate::kernel::sdhost::get_total_sectors();
312        // ブート領域 (256MiB) を差し引いた残りの全セクタ数を SylFS に公開
313        total.saturating_sub(self.offset_sectors)
314    }
315
316    fn read_raw_sector(&mut self, sector: usize, buf: &mut [u8]) -> Result<(), &'static str> {
317        let target_sector = sector + self.offset_sectors;
318        crate::kernel::sdhost::read_sector(target_sector, buf)
319    }
320
321    fn write_raw_sector(&mut self, sector: usize, buf: &[u8]) -> Result<(), &'static str> {
322        let target_sector = sector + self.offset_sectors;
323        // 防御的セキュリティ: 誤ってブート用 FAT32 パーティション領域 (先頭 256MiB) を破壊する書き込みをブロック
324        if target_sector < self.offset_sectors {
325            return Err("SDCard write blocked: Attempted to write to boot/OS partition area!");
326        }
327        crate::kernel::sdhost::write_sector(target_sector, buf)
328    }
329
330    fn should_mirror(&self) -> bool {
331        // SDカード・外部SSD等の不揮発性ストレージはビット破損や物理不良対策のため二重化(ミラーリング)する
332        true
333    }
334}
335
336/// 実行環境に応じて RAMDisk と SDCard を安全に切り替えるためのデバイスラッパー
337pub enum BackendDevice {
338    RAM(RAMDisk),
339    SD(SDCard),
340}
341
342impl BlockDevice for BackendDevice {
343    fn total_sectors(&self) -> usize {
344        match self {
345            BackendDevice::RAM(d) => d.total_sectors(),
346            BackendDevice::SD(d) => d.total_sectors(),
347        }
348    }
349
350    fn read_raw_sector(&mut self, sector: usize, buf: &mut [u8]) -> Result<(), &'static str> {
351        match self {
352            BackendDevice::RAM(d) => d.read_raw_sector(sector, buf),
353            BackendDevice::SD(d) => d.read_raw_sector(sector, buf),
354        }
355    }
356
357    fn write_raw_sector(&mut self, sector: usize, buf: &[u8]) -> Result<(), &'static str> {
358        match self {
359            BackendDevice::RAM(d) => d.write_raw_sector(sector, buf),
360            BackendDevice::SD(d) => d.write_raw_sector(sector, buf),
361        }
362    }
363
364    fn should_mirror(&self) -> bool {
365        match self {
366            BackendDevice::RAM(d) => d.should_mirror(),
367            BackendDevice::SD(d) => d.should_mirror(),
368        }
369    }
370}