* Minix 3 subpartition/filesystem patch
@ 2010-07-19 4:39 Fam Zheng
2010-07-20 13:20 ` Vladimir 'φ-coder/phcoder' Serbinenko
0 siblings, 1 reply; 2+ messages in thread
From: Fam Zheng @ 2010-07-19 4:39 UTC (permalink / raw)
To: The development of GNU GRUB; +Cc: Erik van der Kouwe
[-- Attachment #1.1: Type: text/plain, Size: 1507 bytes --]
Hi all,
As a project of GSoC of MINIX community, we have almost completed the work
making MINIX 3 Multiboot compliant. I believe it would be very helpful for
us if GRUB can handle MINIX 3's subpartition and filesystem correctly in the
future, so I've made a patch for reading the currently in use MINIX
subpartition, so as to make GRUB Multiboot access the OS kernel image. This
patch has already been used for a while in our development, to load and test
MINIX kernel, and I think now it's ready to be submitted here.
There are two parts of the patch. First part is on fs/minix.c which is
changed to support the latest MINIX FS version 3 (previously only version 2
is supported). The other part is on partmap/msdos.c, the changes are made
for the following reason:
AFAIK there are two kinds of subpartition, one is from BSD, the other is
MINIX. With the latest trunk source, the subpartition is found by GRUB,
partition names like (hd0,msdos1,msdos1) can be recognized, but the problem
is the 'start' of partition: in the partition table for MINIX subpartitions
(the table found at the end of the first sector of (hd0,msdos1) in this
example), the field "start" is treated as an relative value, where for MINIX
it is actually an absolute one.
To solve this inconsistency, I patched partmap/msdos.c to convert the value
stored on harddisk to relative simply by a subtraction, this happens only
when a MINIX type (type field == 0x81) subpartition is encountered.
Thank you.
--
Best Regards!
Fam Zheng
[-- Attachment #1.2: Type: text/html, Size: 1704 bytes --]
[-- Attachment #2: minix_support.patch --]
[-- Type: application/octet-stream, Size: 15012 bytes --]
=== modified file 'fs/minix.c'
--- fs/minix.c 2009-12-25 00:04:51 +0000
+++ fs/minix.c 2010-07-19 04:10:00 +0000
@@ -19,6 +19,7 @@
#include <grub/err.h>
#include <grub/file.h>
+#include <grub/partition.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/disk.h>
@@ -27,6 +28,7 @@
#define GRUB_MINIX_MAGIC 0x137F
#define GRUB_MINIX2_MAGIC 0x2468
+#define GRUB_MINIX3_MAGIC 0x4D5A
#define GRUB_MINIX_MAGIC_30 0x138F
#define GRUB_MINIX2_MAGIC_30 0x2478
#define GRUB_MINIX_BSIZE 1024U
@@ -39,10 +41,15 @@
#define GRUB_MINIX_IFLNK 0120000U
#define GRUB_MINIX_INODE(data,field) (data->version == 1 ? \
- data->inode. field : data->inode2. field)
+ data->inode. field : \
+ (data->version==2 ? \
+ data->inode2. field : \
+ data->inode3. field))
#define GRUB_MINIX_INODE_ENDIAN(data,field,bits1,bits2) (data->version == 1 ? \
grub_le_to_cpu##bits1 (data->inode.field) : \
- grub_le_to_cpu##bits2 (data->inode2.field))
+ (data->version == 2 ? \
+ grub_le_to_cpu##bits2 (data->inode2.field) : \
+ grub_le_to_cpu##bits2 (data->inode3.field)))
#define GRUB_MINIX_INODE_SIZE(data) GRUB_MINIX_INODE_ENDIAN (data,size,16,32)
#define GRUB_MINIX_INODE_MODE(data) GRUB_MINIX_INODE_ENDIAN (data,mode,16,16)
#define GRUB_MINIX_INODE_DIR_ZONES(data,blk) GRUB_MINIX_INODE_ENDIAN \
@@ -51,22 +58,28 @@
GRUB_MINIX_INODE_ENDIAN (data,indir_zone,16,32)
#define GRUB_MINIX_INODE_DINDIR_ZONE(data) \
GRUB_MINIX_INODE_ENDIAN (data,double_indir_zone,16,32)
-#define GRUB_MINIX_INODE_BLKSZ(data) (data->version == 1 ? 2 : 4)
#define GRUB_MINIX_LOG2_ZONESZ (GRUB_MINIX_LOG2_BSIZE \
+ grub_le_to_cpu16 (sblock->log2_zone_size))
-#define GRUB_MINIX_ZONESZ (GRUB_MINIX_BSIZE \
+#define GRUB_MINIX_ZONESZ (blocksize \
<< grub_le_to_cpu16 (sblock->log2_zone_size))
struct grub_minix_sblock
{
- grub_uint16_t inode_cnt;
+ grub_uint32_t inode_cnt;
grub_uint16_t zone_cnt;
grub_uint16_t inode_bmap_size;
grub_uint16_t zone_bmap_size;
grub_uint16_t first_data_zone;
grub_uint16_t log2_zone_size;
+ grub_uint16_t pad;
grub_uint32_t max_file_size;
+ grub_uint32_t zones;
grub_uint16_t magic;
+
+ /* V3 only fields */
+ grub_uint16_t pad2;
+ grub_uint16_t block_size;
+ grub_uint8_t disk_version;
};
struct grub_minix_inode
@@ -99,12 +112,31 @@ struct grub_minix2_inode
};
+struct grub_minix3_inode
+{
+ grub_uint16_t mode;
+ grub_uint16_t nlinks;
+ grub_uint16_t uid;
+ grub_uint8_t gid;
+ grub_uint8_t pad_;
+ grub_uint32_t size;
+ grub_uint32_t atime;
+ grub_uint32_t mtime;
+ grub_uint32_t ctime;
+ grub_uint32_t dir_zones[7];
+ grub_uint32_t indir_zone;
+ grub_uint32_t double_indir_zone;
+ grub_uint32_t unused;
+
+};
+
/* Information about a "mounted" minix filesystem. */
struct grub_minix_data
{
struct grub_minix_sblock sblock;
struct grub_minix_inode inode;
struct grub_minix2_inode inode2;
+ struct grub_minix3_inode inode3;
int ino;
int linknest;
grub_disk_t disk;
@@ -113,7 +145,8 @@ struct grub_minix_data
};
static grub_dl_t my_mod;
-\f
+static unsigned int blocksize;
+
static grub_err_t grub_minix_find_file (struct grub_minix_data *data,
const char *path);
@@ -122,9 +155,23 @@ grub_minix_get_file_block (struct grub_m
{
struct grub_minix_sblock *sblock = &data->sblock;
int indir;
-
+ unsigned int first_dbl_indir;
+ unsigned int indir_capacity;
auto int grub_get_indir (int, int);
-
+
+ if (data->version == 1)
+ {
+ indir_capacity=blocksize/2;
+ }
+ else if (data->version == 2)
+ {
+ indir_capacity=blocksize/4;
+ }
+ else
+ {
+ indir_capacity=blocksize/4;
+ }
+
/* Read the block pointer in ZONE, on the offset NUM. */
int grub_get_indir (int zone, int num)
{
@@ -137,7 +184,7 @@ grub_minix_get_file_block (struct grub_m
sizeof (grub_uint16_t), (char *) &indir16);
return grub_le_to_cpu16 (indir16);
}
- else
+ else if (data->version == 2)
{
grub_uint32_t indir32;
grub_disk_read (data->disk,
@@ -146,29 +193,39 @@ grub_minix_get_file_block (struct grub_m
sizeof (grub_uint32_t), (char *) &indir32);
return grub_le_to_cpu32 (indir32);
}
+ else
+ {
+ grub_uint32_t indir32;
+ grub_disk_read (data->disk,
+ zone * (blocksize / GRUB_DISK_SECTOR_SIZE),
+ sizeof (grub_uint32_t) * num,
+ sizeof (grub_uint32_t), (char *) &indir32);
+ return grub_le_to_cpu32 (indir32);
+ }
}
+
/* Direct block. */
if (blk < 7)
return GRUB_MINIX_INODE_DIR_ZONES (data, blk);
-
/* Indirect block. */
- blk -= 7;
- if (blk < GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data))
+ first_dbl_indir=indir_capacity+7;
+
+ if (blk < first_dbl_indir)
{
+ blk -= 7;
indir = grub_get_indir (GRUB_MINIX_INODE_INDIR_ZONE (data), blk);
return indir;
}
/* Double indirect block. */
- blk -= GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data);
- if (blk < (GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data))
- * (GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data)))
+ blk -= first_dbl_indir;
+ if (blk < indir_capacity * indir_capacity)
{
+
indir = grub_get_indir (GRUB_MINIX_INODE_DINDIR_ZONE (data),
- blk / GRUB_MINIX_ZONESZ);
-
- indir = grub_get_indir (indir, blk % GRUB_MINIX_ZONESZ);
+ blk / indir_capacity);
+ indir = grub_get_indir (indir, blk % indir_capacity);
return indir;
}
@@ -191,18 +248,19 @@ grub_minix_read_file (struct grub_minix_
struct grub_minix_sblock *sblock = &data->sblock;
int i;
int blockcnt;
-
/* Adjust len so it we can't read past the end of the file. */
if (len + pos > GRUB_MINIX_INODE_SIZE (data))
len = GRUB_MINIX_INODE_SIZE (data) - pos;
- blockcnt = (len + pos + GRUB_MINIX_BSIZE - 1) / GRUB_MINIX_BSIZE;
+ /*FIXME: compile error if following two statements combined */
+ blockcnt = (len + pos + blocksize - 1);
+ blockcnt /= blocksize;
- for (i = pos / GRUB_MINIX_BSIZE; i < blockcnt; i++)
+ for (i = pos / blocksize; i < blockcnt; i++)
{
int blknr;
- int blockoff = pos % GRUB_MINIX_BSIZE;
- int blockend = GRUB_MINIX_BSIZE;
+ int blockoff = pos % blocksize;
+ int blockend = blocksize;
int skipfirst = 0;
@@ -213,28 +271,33 @@ grub_minix_read_file (struct grub_minix_
/* Last block. */
if (i == blockcnt - 1)
{
- blockend = (len + pos) % GRUB_MINIX_BSIZE;
+ /*FIXME: compile error if following two statements combined */
+ blockend = (len + pos);
+ blockend %= blocksize;
if (!blockend)
- blockend = GRUB_MINIX_BSIZE;
+ blockend = blocksize;
}
/* First block. */
- if (i == (pos / (int) GRUB_MINIX_BSIZE))
+ if (i == (pos / (int) blocksize))
{
skipfirst = blockoff;
blockend -= skipfirst;
}
-
data->disk->read_hook = read_hook;
- grub_disk_read (data->disk, blknr << GRUB_MINIX_LOG2_ZONESZ,
+ if(data->version<3)
+ grub_disk_read (data->disk, blknr << GRUB_MINIX_LOG2_ZONESZ,
+ skipfirst, blockend, buf);
+ else
+ grub_disk_read (data->disk, blknr * (data->sblock.block_size/GRUB_DISK_SECTOR_SIZE),
skipfirst, blockend, buf);
data->disk->read_hook = 0;
if (grub_errno)
return -1;
- buf += GRUB_MINIX_BSIZE - skipfirst;
+ buf += blocksize - skipfirst;
}
return len;
@@ -250,17 +313,17 @@ grub_minix_read_inode (struct grub_minix
/* Block in which the inode is stored. */
int block;
+ if(ino==0) return GRUB_ERR_BAD_ARGUMENT;
data->ino = ino;
-
/* The first inode in minix is inode 1. */
ino--;
- block = ((2 + grub_le_to_cpu16 (sblock->inode_bmap_size)
- + grub_le_to_cpu16 (sblock->zone_bmap_size))
- << GRUB_MINIX_LOG2_BSIZE);
-
if (data->version == 1)
{
+ block = ((2 + grub_le_to_cpu16 (sblock->inode_bmap_size)
+ + grub_le_to_cpu16 (sblock->zone_bmap_size))
+ << GRUB_MINIX_LOG2_BSIZE);
+
block += ino / (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode));
int offs = (ino % (GRUB_DISK_SECTOR_SIZE
/ sizeof (struct grub_minix_inode))
@@ -269,8 +332,11 @@ grub_minix_read_inode (struct grub_minix
grub_disk_read (data->disk, block, offs,
sizeof (struct grub_minix_inode), &data->inode);
}
- else
+ else if (data->version == 2)
{
+ block = ((2 + grub_le_to_cpu16 (sblock->inode_bmap_size)
+ + grub_le_to_cpu16 (sblock->zone_bmap_size))
+ << GRUB_MINIX_LOG2_BSIZE);
block += ino / (GRUB_DISK_SECTOR_SIZE
/ sizeof (struct grub_minix2_inode));
int offs = (ino
@@ -280,7 +346,20 @@ grub_minix_read_inode (struct grub_minix
grub_disk_read (data->disk, block, offs,
sizeof (struct grub_minix2_inode),&data->inode2);
}
-
+ else
+ {
+ block = ((2 + grub_le_to_cpu16 (sblock->inode_bmap_size)
+ + grub_le_to_cpu16 (sblock->zone_bmap_size))
+ *(sblock->block_size/GRUB_DISK_SECTOR_SIZE));
+ block += ino / (GRUB_DISK_SECTOR_SIZE
+ / sizeof (struct grub_minix3_inode));
+ int offs = (ino
+ % (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix3_inode))
+ * sizeof (struct grub_minix3_inode));
+
+ grub_disk_read (data->disk, block, offs,
+ sizeof (struct grub_minix3_inode),&data->inode3);
+ }
return GRUB_ERR_NONE;
}
@@ -348,16 +427,17 @@ grub_minix_find_file (struct grub_minix_
do
{
- grub_uint16_t ino;
+ grub_uint32_t ino;
+ unsigned int ino_size=data->version<3 ? 2 : 4;
char filename[data->filename_size + 1];
if (grub_strlen (name) == 0)
- return GRUB_ERR_NONE;
+ return GRUB_ERR_NONE;
- if (grub_minix_read_file (data, 0, pos, sizeof (ino),
+ if (grub_minix_read_file (data, 0, pos, ino_size,
(char *) &ino) < 0)
return grub_errno;
- if (grub_minix_read_file (data, 0, pos + sizeof (ino),
+ if (grub_minix_read_file (data, 0, pos + ino_size,
data->filename_size, (char *) filename)< 0)
return grub_errno;
@@ -399,7 +479,7 @@ grub_minix_find_file (struct grub_minix_
continue;
}
- pos += sizeof (ino) + data->filename_size;
+ pos += ino_size + data->filename_size;
} while (pos < GRUB_MINIX_INODE_SIZE (data));
grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
@@ -433,6 +513,11 @@ grub_minix_mount (grub_disk_t disk)
data->version = 2;
data->filename_size = 14;
}
+ else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX3_MAGIC)
+ {
+ data->version = 3;
+ data->filename_size = 60;
+ }
else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC_30)
{
data->version = 1;
@@ -448,7 +533,12 @@ grub_minix_mount (grub_disk_t disk)
data->disk = disk;
data->linknest = 0;
+ /* set global block size var for mounted fs */
+ if(data->version==3)
+ blocksize=data->sblock.block_size;
+ else
+ blocksize=GRUB_MINIX_BSIZE;
return data;
fail:
@@ -488,35 +578,38 @@ grub_minix_dir (grub_device_t device, co
while (pos < GRUB_MINIX_INODE_SIZE (data))
{
- grub_uint16_t ino;
+ grub_uint32_t ino;
+ /* Inode type is different in size between v2 and v3 */
+ unsigned int ino_size=data->version<3 ? 2 : 4;
char filename[data->filename_size + 1];
int dirino = data->ino;
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
- if (grub_minix_read_file (data, 0, pos, sizeof (ino),
+ if (grub_minix_read_file (data, 0, pos, ino_size,
(char *) &ino) < 0)
return grub_errno;
-
- if (grub_minix_read_file (data, 0, pos + sizeof (ino),
+ if (grub_minix_read_file (data, 0, pos + ino_size,
data->filename_size,
(char *) filename) < 0)
return grub_errno;
filename[data->filename_size] = '\0';
-
- /* The filetype is not stored in the dirent. Read the inode to
- find out the filetype. This *REALLY* sucks. */
+ if(ino)
+ {
+ /* It's a valid dirent only when ino > 0, check before calling the hook.
+ The filetype is not stored in the dirent. Read the inode to
+ find out the filetype. This *REALLY* sucks. */
grub_minix_read_inode (data, grub_le_to_cpu16 (ino));
info.dir = ((GRUB_MINIX_INODE_MODE (data)
& GRUB_MINIX_IFDIR) == GRUB_MINIX_IFDIR);
if (hook (filename, &info) ? 1 : 0)
break;
-
+
/* Load the old inode back in. */
grub_minix_read_inode (data, dirino);
-
- pos += sizeof (ino) + data->filename_size;
+ }
+ pos += ino_size + data->filename_size;
}
fail:
@@ -582,14 +675,6 @@ grub_minix_close (grub_file_t file)
return GRUB_ERR_NONE;
}
-
-static grub_err_t
-grub_minix_label (grub_device_t device __attribute ((unused)),
- char **label __attribute ((unused)))
-{
- return GRUB_ERR_NONE;
-}
-
\f
static struct grub_fs grub_minix_fs =
{
@@ -598,7 +683,7 @@ static struct grub_fs grub_minix_fs =
.open = grub_minix_open,
.read = grub_minix_read,
.close = grub_minix_close,
- .label = grub_minix_label,
+ .label = 0,
.next = 0
};
=== modified file 'partmap/msdos.c'
--- partmap/msdos.c 2010-03-26 14:44:13 +0000
+++ partmap/msdos.c 2010-07-19 04:12:17 +0000
@@ -37,7 +37,6 @@ pc_partition_map_iterate (grub_disk_t di
int labeln = 0;
grub_disk_addr_t lastaddr;
grub_disk_addr_t ext_offset;
-
p.offset = 0;
ext_offset = 0;
p.number = -1;
@@ -51,7 +50,6 @@ pc_partition_map_iterate (grub_disk_t di
{
int i;
struct grub_msdos_partition_entry *e;
-
/* Read the MBR. */
if (grub_disk_read (disk, p.offset, 0, sizeof (mbr), &mbr))
goto finish;
@@ -76,14 +74,16 @@ pc_partition_map_iterate (grub_disk_t di
if (mbr.entries[i].flag & 0x7f)
return grub_error (GRUB_ERR_BAD_PART_TABLE, "bad boot flag");
+
/* Analyze DOS partitions. */
for (p.index = 0; p.index < 4; p.index++)
{
e = mbr.entries + p.index;
p.start = p.offset + grub_le_to_cpu32 (e->start);
+ if(disk->partition && e->type == GRUB_PC_PARTITION_TYPE_LINUX_MINIX)
+ p.start -= disk->partition->start;
p.len = grub_le_to_cpu32 (e->length);
-
grub_dprintf ("partition",
"partition %d: flag 0x%x, type 0x%x, start 0x%llx, len 0x%llx\n",
p.index, e->flag, e->type,
@@ -93,13 +93,11 @@ pc_partition_map_iterate (grub_disk_t di
/* If this is a GPT partition, this MBR is just a dummy. */
if (e->type == GRUB_PC_PARTITION_TYPE_GPT_DISK && p.index == 0)
return grub_error (GRUB_ERR_BAD_PART_TABLE, "dummy mbr");
-
/* If this partition is a normal one, call the hook. */
if (! grub_msdos_partition_is_empty (e->type)
&& ! grub_msdos_partition_is_extended (e->type))
{
p.number++;
-
if (hook (disk, &p))
return grub_errno;
}
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: Minix 3 subpartition/filesystem patch
2010-07-19 4:39 Minix 3 subpartition/filesystem patch Fam Zheng
@ 2010-07-20 13:20 ` Vladimir 'φ-coder/phcoder' Serbinenko
0 siblings, 0 replies; 2+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2010-07-20 13:20 UTC (permalink / raw)
To: The development of GNU GRUB; +Cc: Erik van der Kouwe, Fam Zheng
[-- Attachment #1: Type: text/plain, Size: 2976 bytes --]
On 07/19/2010 06:39 AM, Fam Zheng wrote:
> Hi all,
>
> As a project of GSoC of MINIX community, we have almost completed the
> work making MINIX 3 Multiboot compliant. I believe it would be very
> helpful for us if GRUB can handle MINIX 3's subpartition and
> filesystem correctly in the future, so I've made a patch for reading
> the currently in use MINIX subpartition, so as to make GRUB Multiboot
> access the OS kernel image. This patch has already been used for a
> while in our development, to load and test MINIX kernel, and I think
> now it's ready to be submitted here.
>
Why not multiboot2? It supplies a structure which is easier to copy and
move around. If you need any multiboot2 amendment please contact.
> There are two parts of the patch. First part is on fs/minix.c which is
> changed to support the latest MINIX FS version 3 (previously only
> version 2 is supported). The other part is on partmap/msdos.c, the
> changes are made for the following reason:
>
Please don't mix 2 patches. Patch for subpartitions is
copyright-insignificant so can go directly in. Minix3fs on the other
hand would need some papers.
> AFAIK there are two kinds of subpartition, one is from BSD, the other
> is MINIX. With the latest trunk source, the subpartition is found by
> GRUB, partition names like (hd0,msdos1,msdos1) can be recognized, but
> the problem is the 'start' of partition: in the partition table for
> MINIX subpartitions (the table found at the end of the first sector of
> (hd0,msdos1) in this example), the field "start" is treated as an
> relative value, where for MINIX it is actually an absolute one.
Common brain damage. NetBSD has the same.
+ if(disk->partition && e->type ==
GRUB_PC_PARTITION_TYPE_LINUX_MINIX)
+ p.start -= disk->partition->start;
The criteria is probably wrong unless minix subpartition label mixes
relative and absolute offset. Instead of this you have to check that
container is msdos itself and that its type is minix. We'll need a
similar check in bsdlabel too.
We use gnu and not bsd indentation. Please adjust your patches.
Patch for minix3 fs breaks any other version of minixfs. E.g.
- grub_uint16_t inode_cnt;
+ grub_uint32_t inode_cnt;
offsets all other fields.
minix.mod must be split into 3 modules: minix1.mod, minix2.mod and
minix3.mod with mostly shared source code. Look at ufs/ufs2 and
afs/befs/afs_be/befs_be for how to do it.
>
> To solve this inconsistency, I patched partmap/msdos.c to convert the
> value stored on harddisk to relative simply by a subtraction, this
> happens only when a MINIX type (type field == 0x81) subpartition is
> encountered.
>
> Thank you.
>
> --
> Best Regards!
> Fam Zheng
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>
--
Regards
Vladimir 'φ-coder/phcoder' Serbinenko
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 294 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2010-07-20 13:21 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-07-19 4:39 Minix 3 subpartition/filesystem patch Fam Zheng
2010-07-20 13:20 ` Vladimir 'φ-coder/phcoder' Serbinenko
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.