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