Forráskód Böngészése

fix(block): improve block's partprobe to register whole disk partition, and sort fdt's device node by start address

Heinz 7 hónapja
szülő
commit
c0ffa04589
5 módosított fájl, 93 hozzáadás és 29 törlés
  1. 4 2
      Makefile.src
  2. 6 3
      src/driver/virtio.rs
  3. 1 1
      src/fs/ext4.rs
  4. 80 14
      src/kernel/block.rs
  5. 2 9
      src/lib.rs

+ 4 - 2
Makefile.src

@@ -46,8 +46,10 @@ BINARY_DIR := $(BINARY_DIR_BASE)/$(MODE)
 QEMU_ARGS += \
 	-machine virt -kernel $(BINARY_DIR)/eonix_kernel \
 	-device virtio-blk-device,drive=disk0,bus=virtio-mmio-bus.0 \
+	-device virtio-blk-device,drive=disk1,bus=virtio-mmio-bus.1 \
 	-device virtio-net-device,netdev=mynet0 \
-	-drive id=disk0,file=test/sdcard-rv.img,format=raw,if=none \
+	-drive id=disk0,file=build/boot-riscv64.img,format=raw,if=none \
+	-drive id=disk1,file=test/sdcard-rv.img,format=raw,if=none \
 	-netdev user,id=mynet0 \
 	-rtc base=utc
 
@@ -122,7 +124,7 @@ build/kernel.sym: $(BINARY_DIR)/eonix_kernel
 
 build/fs-%.img: user-programs/init_script_%.sh script/build-img.sh $(USER_PROGRAMS)
 	ARCH=$* OUTPUT=$@ sh script/build-img.sh
-	
+
 build/mbr.bin: $(BINARY_DIR)/eonix_kernel
 	cargo objcopy -q $(CARGO_FLAGS) -- -O binary -j .mbr build/mbr.bin
 

+ 6 - 3
src/driver/virtio.rs

@@ -7,7 +7,7 @@ use crate::kernel::{
     block::{make_device, BlockDevice},
     mem::{AsMemoryBlock, MemoryBlock, Page},
 };
-use alloc::sync::Arc;
+use alloc::{sync::Arc, vec::Vec};
 use core::num::NonZero;
 use eonix_hal::{arch_exported::fdt::FDT, mm::ArchPhysAccess};
 use eonix_log::{println_info, println_warn};
@@ -84,7 +84,7 @@ unsafe impl Hal for HAL {
 
 pub fn init_virtio_devices() {
     let mut disk_id = 0;
-    for reg in FDT
+    let mut virtio_devices: Vec<_> = FDT
         .all_nodes()
         .filter(|node| {
             node.compatible()
@@ -92,7 +92,10 @@ pub fn init_virtio_devices() {
         })
         .filter_map(|node| node.reg())
         .flatten()
-    {
+        .collect();
+    virtio_devices.sort_by_key(|reg| reg.starting_address);
+
+    for reg in virtio_devices {
         let base = PAddr::from(reg.starting_address as usize);
         let size = reg.size.expect("Virtio device must have a size");
 

+ 1 - 1
src/fs/ext4.rs

@@ -229,7 +229,7 @@ impl MountCreator for Ext4MountCreator {
     fn create_mount(&self, _source: &str, _flags: u64, mp: &Arc<Dentry>) -> KResult<Mount> {
         // TODO: temporarily the second disk, should generate from _source
         let (ext4fs, root_inode) = 
-            Ext4Fs::create(make_device(8, 0))?;
+            Ext4Fs::create(make_device(8, 16))?;
 
         Mount::new(mp, ext4fs, root_inode)
     }

+ 80 - 14
src/kernel/block.rs

@@ -5,7 +5,10 @@ use super::{
     mem::{paging::Page, AsMemoryBlock as _},
     vfs::DevId,
 };
-use crate::kernel::constants::{EEXIST, EINVAL};
+use crate::{
+    io::ByteBuffer,
+    kernel::constants::{EEXIST, EINVAL, EIO}
+};
 use crate::{
     io::{Buffer, FillResult},
     prelude::*,
@@ -48,6 +51,12 @@ enum BlockDeviceType {
     },
 }
 
+#[derive(Debug, Clone)]
+pub enum FileSystemType {
+    Ext4,
+    Fat32,
+}
+
 pub struct BlockDevice {
     /// Unique device identifier, major and minor numbers
     devid: DevId,
@@ -136,24 +145,81 @@ impl BlockDevice {
         }
     }
 
+    fn is_ext4_signature(&self, buffer: &[u8]) -> bool {
+        if buffer.len() >= 1080 + 2 {
+            &buffer[1080..1082] == &[0x53, 0xEF]
+        } else {
+            false
+        }
+    }
+
+    fn is_fat32_signature(&self, buffer: &[u8]) -> bool {
+        if buffer.len() >= 90 {
+            &buffer[82..90] == b"FAT32   "
+        } else {
+            false
+        }
+    }
+
+    fn detect_filesystem(&self) -> KResult<FileSystemType> {
+        let mut buffer = vec![0u8; 4096];
+        let mut byte_buffer = ByteBuffer::new(buffer.as_mut_slice());
+        self.read_some(0, &mut byte_buffer)?.ok_or(EIO)?;
+
+        if self.is_ext4_signature(&buffer) {
+            Ok(FileSystemType::Ext4)
+        } else if self.is_fat32_signature(&buffer) {
+            Ok(FileSystemType::Fat32)
+        } else {
+            Err(0)
+        }
+    }
+
+    fn register_whole_disk_partition(&self) -> KResult<Arc<Self>> {
+        let queue = match &self.dev_type {
+            BlockDeviceType::Disk { queue } => queue.clone(),
+            BlockDeviceType::Partition { .. } => return Err(EINVAL),
+        };
+
+        let device = Arc::new(BlockDevice {
+            devid: make_device(self.devid >> 8, 0u32),
+            sector_count: self.sector_count,
+            dev_type: BlockDeviceType::Partition {
+                disk_dev: self.devid,
+                lba_offset: 0,
+                queue,
+            },
+        });
+
+        match BLOCK_DEVICE_LIST.lock().entry(device.devid()) {
+            Entry::Vacant(entry) => Ok(entry.insert(device).clone()),
+            Entry::Occupied(_) => Err(EEXIST),
+        }
+    }
+
     pub async fn partprobe(&self) -> KResult<()> {
         match self.dev_type {
             BlockDeviceType::Partition { .. } => Err(EINVAL),
             BlockDeviceType::Disk { .. } => {
-                let mbr_table = MBRPartTable::from_disk(self).await?;
-
-                for (
-                    idx,
-                    Partition {
-                        lba_offset,
-                        sector_count,
-                    },
-                ) in mbr_table.partitions().enumerate()
-                {
-                    self.register_partition(idx as u32 + 1, lba_offset, sector_count)?;
+                let base_minor = (self.devid & 0xFF) as u32;
+                if let Ok(mbr_table) = MBRPartTable::from_disk(self).await {
+                    for (idx, partition) in mbr_table.partitions().enumerate() {
+                        self.register_partition(
+                            base_minor + idx as u32 + 1,
+                            partition.lba_offset,
+                            partition.sector_count,
+                        )?;
+                    }
+                    Ok(())
+                } else {
+                    match self.detect_filesystem() {
+                        Ok(_fs_type) => {
+                            self.register_whole_disk_partition();
+                            Ok(())
+                        }
+                        Err(_) => Ok(()),
+                    }
                 }
-
-                Ok(())
             }
         }
     }

+ 2 - 9
src/lib.rs

@@ -148,7 +148,7 @@ async fn init_process(early_kstack: PRange) {
     fs::ext4::init();
 
     let load_info = {
-        // mount ext4 /mnt directory
+        // mount fat32 /mnt directory
         let fs_context = FsContext::global();
         let mnt_dir = Dentry::open(fs_context, Path::new(b"/mnt/").unwrap(), true).unwrap();
 
@@ -158,18 +158,11 @@ async fn init_process(early_kstack: PRange) {
             &mnt_dir,
             "/dev/sda",
             "/mnt",
-            "ext4",
+            "fat32",
             MS_RDONLY | MS_NOATIME | MS_NODEV | MS_NOSUID,
         )
         .unwrap();
 
-        println!("{:?}", mnt_dir.find(b"musl"));
-
-        let musl_dir = Dentry::open(fs_context, Path::new(b"/mnt/musl/").unwrap(), true).unwrap();
-        println!("{:?}", musl_dir.find(b"basic"));
-        let basic_dir = Dentry::open(fs_context, Path::new(b"/mnt/musl/basic/").unwrap(), true).unwrap();
-        println!("{:?}", basic_dir.find(b"run-all.sh"));
-
         let init_names = [
             &b"/sbin/init"[..],
             &b"/init"[..],