FS.FILO.Ext2: Fill Mount() procedure
diff --git a/src/fs-filo-ext2.adb b/src/fs-filo-ext2.adb
index a00e0a4..d0054da 100644
--- a/src/fs-filo-ext2.adb
+++ b/src/fs-filo-ext2.adb
@@ -1,3 +1,12 @@
+-- Derived from GRUB -- GRand Unified Bootloader
+-- Copyright (C) 1999, 2001, 2003 Free Software Foundation, Inc.
+-- Copyright (C) 2023 secunet Security Networks AG
+--
+-- This program is free software; you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation; either version 2 of the License, or
+-- (at your option) any later version.
+
with System;
with Interfaces;
with Interfaces.C;
@@ -13,13 +22,109 @@
function Is_Mounted (State : T) return Boolean is (State.S >= Mounted);
function Is_Open (State : T) return Boolean is (State.S = File_Opened);
+ --------------------------------------------------------------------------
+
+ SUPERBLOCK_SIZE : constant := 1024;
+ SUPERBLOCK_BLOCKS : constant := SUPERBLOCK_SIZE / BLOCK_SIZE;
+
+ SUPERBLOCK_MAGIC : constant := 16#ef53#;
+ OLD_REV : constant := 0;
+ DYNAMIC_REV : constant := 1;
+ FEATURE_INCOMPAT_EXTENTS : constant := 16#0040#;
+ FEATURE_INCOMPAT_64BIT : constant := 16#0080#;
+
procedure Mount
(State : in out T;
Part_Len : in Partition_Length;
Success : out Boolean)
is
+ Super_Block : Buffer_Type (0 .. SUPERBLOCK_SIZE - 1) := (others => 0);
begin
- Success := False;
+ if Part_Len < 2 * SUPERBLOCK_SIZE then
+ Success := False;
+ return;
+ end if;
+
+ Dev.Read (Super_Block, 1 * SUPERBLOCK_SIZE, Success);
+ if not Success then
+ return;
+ end if;
+
+ if Read_LE16 (Super_Block, 14 * 4) /= 16#ef53# then
+ Success := False;
+ return;
+ end if;
+
+ State.Part_Len := Part_Len;
+ State.First_Data_Block := Block_Offset (Read_LE32 (Super_Block, 5 * 4));
+
+ declare
+ S_Log_Block_Size : constant Unsigned_32 := Read_LE32 (Super_Block, 6 * 4);
+ begin
+ if S_Log_Block_Size <= Unsigned_32 (Log_Block_Size'Last - 10) then
+ State.Block_Size_Bits := Log_Block_Size (S_Log_Block_Size + 10);
+ else
+ Success := False;
+ return;
+ end if;
+ end;
+
+ declare
+ S_Inodes_Per_Group : constant Unsigned_32 := Read_LE32 (Super_Block, 10 * 4);
+ begin
+ if S_Inodes_Per_Group in 1 .. Unsigned_32 (Positive'Last) then
+ State.Inodes_Per_Group := Positive (S_Inodes_Per_Group);
+ else
+ Success := False;
+ return;
+ end if;
+ end;
+
+ declare
+ S_Rev_Level : constant Unsigned_32 := Read_LE32 (Super_Block, 19 * 4);
+ begin
+ if S_Rev_Level >= DYNAMIC_REV then
+ declare
+ S_Inode_Size : constant Unsigned_16 := Read_LE16 (Super_Block, 22 * 4);
+ begin
+ if S_Inode_Size in
+ Unsigned_16 (Inode_Size'First) .. Unsigned_16 (Inode_Size'Last)
+ then
+ State.Inode_Size := Inode_Size (S_Inode_Size);
+ else
+ Success := False;
+ return;
+ end if;
+ end;
+ else
+ State.Inode_Size := Inode_Size'First;
+ end if;
+ end;
+
+ declare
+ S_Feature_Incompat : constant Unsigned_32 := Read_LE32 (Super_Block, 24 * 4);
+ begin
+ State.Feature_Extents := (S_Feature_Incompat and FEATURE_INCOMPAT_EXTENTS) /= 0;
+ State.Feature_64Bit := (S_Feature_Incompat and FEATURE_INCOMPAT_64BIT) /= 0;
+ if State.Feature_64Bit then
+ declare
+ S_Desc_Size : constant Unsigned_16 := Read_LE16 (Super_Block, 63 * 4 + 2);
+ begin
+ if S_Desc_Size in
+ Unsigned_16 (Desc_Size'First) .. Unsigned_16 (Desc_Size'Last)
+ then
+ State.Desc_Size := Desc_Size (S_Desc_Size);
+ else
+ Success := False;
+ return;
+ end if;
+ end;
+ else
+ State.Desc_Size := Desc_Size'First;
+ end if;
+ end;
+
+ State.S := Mounted;
end Mount;
procedure Open
@@ -50,7 +155,9 @@
Len := 0;
end Read;
- package C is new VFS (T => T, Initial => (S => Unmounted));
+ --------------------------------------------------------------------------
+
+ package C is new VFS (T => T, Initial => (S => Unmounted, others => <>));
function C_Mount return int
with
diff --git a/src/fs-filo-ext2.ads b/src/fs-filo-ext2.ads
index d8cc7e9..32e31fe 100644
--- a/src/fs-filo-ext2.ads
+++ b/src/fs-filo-ext2.ads
@@ -42,8 +42,22 @@
private
type State is (Unmounted, Mounted, File_Opened);
+ -- maximum block size is 64KiB (2^16):
+ subtype Log_Block_Size is Positive range 10 .. 16;
+
+ subtype Inode_Size is Positive range 128 .. Positive (Unsigned_16'Last);
+ subtype Desc_Size is Positive range 32 .. Positive (Unsigned_16'Last);
+
type T is record
S : State;
+ Part_Len : Partition_Length := 0;
+ First_Data_Block : Block_Offset := 0;
+ Block_Size_Bits : Log_Block_Size := 10;
+ Inodes_Per_Group : Positive := 1;
+ Inode_Size : Ext2.Inode_Size := Ext2.Inode_Size'First;
+ Desc_Size : Ext2.Desc_Size := Ext2.Desc_Size'First;
+ Feature_Extents : Boolean := False;
+ Feature_64Bit : Boolean := False;
end record;
end FS.FILO.Ext2;
diff --git a/src/fs-filo.ads b/src/fs-filo.ads
index a3d8f31..dfd0403 100644
--- a/src/fs-filo.ads
+++ b/src/fs-filo.ads
@@ -8,6 +8,9 @@
type Partition_Length is range 0 .. Interfaces.Unsigned_64'Last;
subtype Partition_Offset is Partition_Length range 0 .. Partition_Length'Last - 1;
+ BLOCK_SIZE : constant := 512;
+ type Block_Offset is range 0 .. Partition_Offset'Last / BLOCK_SIZE;
+
type File_Length is range 0 .. int'Last; -- Should be higher, fix FILO first
subtype File_Offset is File_Length;