diff --git a/repos/os/src/server/part_blk/fsprobe.h b/repos/os/src/server/part_blk/fsprobe.h new file mode 100644 index 0000000000..11de3af6f8 --- /dev/null +++ b/repos/os/src/server/part_blk/fsprobe.h @@ -0,0 +1,104 @@ +/* + * \brief Poor man's partition probe for known file system + * \author Josef Soentgen + * \date 2018-05-03 + */ + +/* + * Copyright (C) 2018 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _PART_BLK__FSPROBE_H_ +#define _PART_BLK__FSPROBE_H_ + +/* Genode includes */ +#include +#include + +namespace Fs { + + using namespace Genode; + + using Type = Genode::String<32>; + + Type probe(uint8_t *buffer, size_t len); + + /** + * Probe for Ext2/3/4 + */ + Type _probe_extfs(uint8_t *p, size_t len) + { + if (len < 4096) { return Type(); } + + /* super block starts a byte offset 1024 */ + p += 0x400; + + bool const found_ext_sig = p[0x38] == 0x53 && p[0x39] == 0xEF; + + enum { + COMPAT_HAS_JOURNAL = 0x004u, + INCOMPAT_EXTENTS = 0x040u, + RO_COMPAT_METADATA_CSUM = 0x400u, + }; + + uint32_t const compat = *(uint32_t*)(p + 0x5C); + uint32_t const incompat = *(uint32_t*)(p + 0x60); + uint32_t const ro_compat = *(uint32_t*)(p + 0x64); + + /* the feature flags should denote a given Ext version */ + + bool const ext3 = compat & COMPAT_HAS_JOURNAL; + bool const ext4 = ext3 && ((incompat & INCOMPAT_EXTENTS) + && (ro_compat & RO_COMPAT_METADATA_CSUM)); + + if (found_ext_sig && ext4) { return Type("Ext4"); } + else if (found_ext_sig && ext3) { return Type("Ext3"); } + else if (found_ext_sig) { return Type("Ext2"); } + + return Type(); + } + + /** + * Probe for FAT16/32 + */ + Type _probe_fatfs(uint8_t *p, size_t len) + { + if (len < 512) { return Type(); } + + /* at least the checks ring true when mkfs.vfat is used... */ + + bool const found_boot_sig = p[510] == 0x55 && p[511] == 0xAA; + + bool const fat16 = p[38] == 0x28 || p[38] == 0x29; + bool const fat32 = (p[66] == 0x28 || p[66] == 0x29) + && (p[82] == 'F' && p[83] == 'A'); + + if (found_boot_sig && fat32) { return Type("FAT32"); } + if (found_boot_sig && fat16) { return Type("FAT16"); } + + return Type(); + } +} + + +Fs::Type Fs::probe(uint8_t *p, size_t len) +{ + /* Ext2/3/4 */ + { + Type t = _probe_extfs(p, len); + if (t.valid()) { return t; } + } + + /* FAT16/32 */ + { + Type t = _probe_fatfs(p, len); + if (t.valid()) { return t; } + } + + return Type(); +} + +#endif /* _PART_BLK__FSPROBE_H_ */ diff --git a/repos/os/src/server/part_blk/gpt.h b/repos/os/src/server/part_blk/gpt.h index 63c5a8044f..38b0f576a5 100644 --- a/repos/os/src/server/part_blk/gpt.h +++ b/repos/os/src/server/part_blk/gpt.h @@ -20,6 +20,7 @@ #include "driver.h" #include "partition_table.h" +#include "fsprobe.h" namespace { @@ -265,6 +266,10 @@ class Gpt : public Block::Partition_table continue; } + enum { BYTES = 4096, }; + Sector fs(driver, e->_lba_start, BYTES / driver.blk_size()); + Fs::Type fs_type = Fs::probe(fs.addr(), BYTES); + xml.node("partition", [&] () { xml.attribute("number", i + 1); xml.attribute("name", e->name()); @@ -272,6 +277,9 @@ class Gpt : public Block::Partition_table xml.attribute("guid", e->_guid.to_string()); xml.attribute("start", e->_lba_start); xml.attribute("length", e->_lba_end - e->_lba_start + 1); + if (fs_type.valid()) { + xml.attribute("file_system", fs_type); + } }); } }); diff --git a/repos/os/src/server/part_blk/mbr.h b/repos/os/src/server/part_blk/mbr.h index 1cf8cb7968..a867057708 100644 --- a/repos/os/src/server/part_blk/mbr.h +++ b/repos/os/src/server/part_blk/mbr.h @@ -21,6 +21,7 @@ #include #include "partition_table.h" +#include "fsprobe.h" struct Mbr_partition_table : public Block::Partition_table @@ -165,11 +166,20 @@ struct Mbr_partition_table : public Block::Partition_table xml.attribute("type", "mbr"); _parse_mbr(mbr, [&] (int i, Partition_record *r, unsigned offset) { + + enum { BYTES = 4096, }; + Sector fs(driver, r->_lba + offset, BYTES / driver.blk_size()); + Fs::Type fs_type = Fs::probe(fs.addr(), BYTES); + xml.node("partition", [&] { xml.attribute("number", i); xml.attribute("type", r->_type); xml.attribute("start", r->_lba + offset); xml.attribute("length", r->_sectors); + + if (fs_type.valid()) { + xml.attribute("file_system", fs_type); + } }); }); });