* Makefile.util.def (libgrubmods.a): Add minix3.

* grub-core/Makefile.core.def (minix3): New module.
	* grub-core/fs/minix.c (GRUB_MINIX_MAGIC) [MODE_MINIX3]: New value.
	(GRUB_MINIX_BSIZE): Removed.
	(GRUB_MINIX_INODE_DIR_BLOCKS): New definition. All users updated.
	(grub_minix_ino_t): New type.
	(grub_minix_le_to_cpu_ino): New macro.
	(GRUB_MINIX_ZONE2SECT): New definition. All users updated.
	(grub_minix_sblock) [MODE_MINIX3]: Change for minix3.
	(grub_minix_data): New field block_size.
	(grub_minix_read_file): Handle 64-bit correctly.
	* grub-core/fs/minix3.c: New file.

	Also-By: Vladimir Serbinenko <phcoder@gmail.com>
This commit is contained in:
Feiran Zheng 2011-05-15 11:53:16 +02:00 committed by Vladimir 'phcoder' Serbinenko
commit bcb18e748f
5 changed files with 142 additions and 59 deletions

View file

@ -1,3 +1,19 @@
2011-05-15 Vladimir Serbinenko <phcoder@gmail.com>
2011-05-15 Feiran Zheng <famcool@gmail.com>
* Makefile.util.def (libgrubmods.a): Add minix3.
* grub-core/Makefile.core.def (minix3): New module.
* grub-core/fs/minix.c (GRUB_MINIX_MAGIC) [MODE_MINIX3]: New value.
(GRUB_MINIX_BSIZE): Removed.
(GRUB_MINIX_INODE_DIR_BLOCKS): New definition. All users updated.
(grub_minix_ino_t): New type.
(grub_minix_le_to_cpu_ino): New macro.
(GRUB_MINIX_ZONE2SECT): New definition. All users updated.
(grub_minix_sblock) [MODE_MINIX3]: Change for minix3.
(grub_minix_data): New field block_size.
(grub_minix_read_file): Handle 64-bit correctly.
* grub-core/fs/minix3.c: New file.
2011-05-15 Tristan Gingold <gingold@free.fr> 2011-05-15 Tristan Gingold <gingold@free.fr>
2011-05-15 Robert Millan <rmh.grub@aybabtu.com> 2011-05-15 Robert Millan <rmh.grub@aybabtu.com>
2011-05-15 Vladimir Serbinenko <phcoder@gmail.com> 2011-05-15 Vladimir Serbinenko <phcoder@gmail.com>

View file

@ -60,6 +60,7 @@ library = {
common = grub-core/fs/jfs.c; common = grub-core/fs/jfs.c;
common = grub-core/fs/minix.c; common = grub-core/fs/minix.c;
common = grub-core/fs/minix2.c; common = grub-core/fs/minix2.c;
common = grub-core/fs/minix3.c;
common = grub-core/fs/nilfs2.c; common = grub-core/fs/nilfs2.c;
common = grub-core/fs/ntfs.c; common = grub-core/fs/ntfs.c;
common = grub-core/fs/ntfscomp.c; common = grub-core/fs/ntfscomp.c;

View file

@ -984,6 +984,11 @@ module = {
common = fs/minix2.c; common = fs/minix2.c;
}; };
module = {
name = minix3;
common = fs/minix3.c;
};
module = { module = {
name = nilfs2; name = nilfs2;
common = fs/nilfs2.c; common = fs/nilfs2.c;

View file

@ -27,14 +27,17 @@
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
#ifdef MODE_MINIX2 #ifdef MODE_MINIX3
#define GRUB_MINIX_MAGIC 0x4D5A
#elif defined(MODE_MINIX2)
#define GRUB_MINIX_MAGIC 0x2468 #define GRUB_MINIX_MAGIC 0x2468
#define GRUB_MINIX_MAGIC_30 0x2478 #define GRUB_MINIX_MAGIC_30 0x2478
#else #else
#define GRUB_MINIX_MAGIC 0x137F #define GRUB_MINIX_MAGIC 0x137F
#define GRUB_MINIX_MAGIC_30 0x138F #define GRUB_MINIX_MAGIC_30 0x138F
#endif #endif
#define GRUB_MINIX_BSIZE 1024U
#define GRUB_MINIX_INODE_DIR_BLOCKS 7
#define GRUB_MINIX_LOG2_BSIZE 1 #define GRUB_MINIX_LOG2_BSIZE 1
#define GRUB_MINIX_ROOT_INODE 1 #define GRUB_MINIX_ROOT_INODE 1
#define GRUB_MINIX_MAX_SYMLNK_CNT 8 #define GRUB_MINIX_MAX_SYMLNK_CNT 8
@ -43,7 +46,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
#define GRUB_MINIX_IFDIR 0040000U #define GRUB_MINIX_IFDIR 0040000U
#define GRUB_MINIX_IFLNK 0120000U #define GRUB_MINIX_IFLNK 0120000U
#ifdef MODE_MINIX2 #if defined(MODE_MINIX2) || defined(MODE_MINIX3)
typedef grub_uint32_t grub_minix_uintn_t; typedef grub_uint32_t grub_minix_uintn_t;
#define grub_minix_le_to_cpu_n grub_le_to_cpu32 #define grub_minix_le_to_cpu_n grub_le_to_cpu32
#else #else
@ -52,6 +55,13 @@ typedef grub_uint16_t grub_minix_uintn_t;
#endif #endif
#define GRUB_MINIX_INODE_BLKSZ(data) sizeof (grub_minix_uintn_t) #define GRUB_MINIX_INODE_BLKSZ(data) sizeof (grub_minix_uintn_t)
#ifdef MODE_MINIX3
typedef grub_uint32_t grub_minix_ino_t;
#define grub_minix_le_to_cpu_ino grub_le_to_cpu32
#else
typedef grub_uint16_t grub_minix_ino_t;
#define grub_minix_le_to_cpu_ino grub_le_to_cpu16
#endif
#define GRUB_MINIX_INODE_SIZE(data) (grub_minix_le_to_cpu_n (data->inode.size)) #define GRUB_MINIX_INODE_SIZE(data) (grub_minix_le_to_cpu_n (data->inode.size))
#define GRUB_MINIX_INODE_MODE(data) (grub_le_to_cpu16 (data->inode.mode)) #define GRUB_MINIX_INODE_MODE(data) (grub_le_to_cpu16 (data->inode.mode))
@ -62,11 +72,39 @@ typedef grub_uint16_t grub_minix_uintn_t;
#define GRUB_MINIX_INODE_DINDIR_ZONE(data) (grub_minix_le_to_cpu_n \ #define GRUB_MINIX_INODE_DINDIR_ZONE(data) (grub_minix_le_to_cpu_n \
(data->inode.double_indir_zone)) (data->inode.double_indir_zone))
#ifndef MODE_MINIX3
#define GRUB_MINIX_LOG2_ZONESZ (GRUB_MINIX_LOG2_BSIZE \ #define GRUB_MINIX_LOG2_ZONESZ (GRUB_MINIX_LOG2_BSIZE \
+ grub_le_to_cpu16 (sblock->log2_zone_size)) + grub_le_to_cpu16 (data->sblock.log2_zone_size))
#define GRUB_MINIX_ZONESZ (GRUB_MINIX_BSIZE \ #endif
<< grub_le_to_cpu16 (sblock->log2_zone_size)) #define GRUB_MINIX_ZONESZ (data->block_size \
<< grub_le_to_cpu16 (data->sblock.log2_zone_size))
#ifdef MODE_MINIX3
#define GRUB_MINIX_ZONE2SECT(zone) ((zone) * (data->block_size / GRUB_DISK_SECTOR_SIZE))
#else
#define GRUB_MINIX_ZONE2SECT(zone) ((zone) << GRUB_MINIX_LOG2_ZONESZ)
#endif
#ifdef MODE_MINIX3
struct grub_minix_sblock
{
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;
grub_uint16_t pad2;
grub_uint16_t block_size;
grub_uint8_t disk_version;
};
#else
struct grub_minix_sblock struct grub_minix_sblock
{ {
grub_uint16_t inode_cnt; grub_uint16_t inode_cnt;
@ -78,23 +116,9 @@ struct grub_minix_sblock
grub_uint32_t max_file_size; grub_uint32_t max_file_size;
grub_uint16_t magic; grub_uint16_t magic;
}; };
#endif
#ifndef MODE_MINIX2 #if defined(MODE_MINIX3) || defined(MODE_MINIX2)
struct grub_minix_inode
{
grub_uint16_t mode;
grub_uint16_t uid;
grub_uint16_t size;
grub_uint32_t ctime;
grub_uint8_t gid;
grub_uint8_t nlinks;
grub_uint16_t dir_zones[7];
grub_uint16_t indir_zone;
grub_uint16_t double_indir_zone;
};
#else
struct grub_minix_inode struct grub_minix_inode
{ {
grub_uint16_t mode; grub_uint16_t mode;
@ -111,6 +135,19 @@ struct grub_minix_inode
grub_uint32_t unused; grub_uint32_t unused;
}; };
#else
struct grub_minix_inode
{
grub_uint16_t mode;
grub_uint16_t uid;
grub_uint16_t size;
grub_uint32_t ctime;
grub_uint8_t gid;
grub_uint8_t nlinks;
grub_uint16_t dir_zones[7];
grub_uint16_t indir_zone;
grub_uint16_t double_indir_zone;
};
#endif #endif
@ -123,6 +160,7 @@ struct grub_minix_data
int linknest; int linknest;
grub_disk_t disk; grub_disk_t disk;
int filename_size; int filename_size;
grub_size_t block_size;
}; };
static grub_dl_t my_mod; static grub_dl_t my_mod;
@ -133,7 +171,6 @@ static grub_err_t grub_minix_find_file (struct grub_minix_data *data,
static int static int
grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk) grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk)
{ {
struct grub_minix_sblock *sblock = &data->sblock;
int indir; int indir;
auto int grub_get_indir (int, int); auto int grub_get_indir (int, int);
@ -143,18 +180,18 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk)
{ {
grub_minix_uintn_t indirn; grub_minix_uintn_t indirn;
grub_disk_read (data->disk, grub_disk_read (data->disk,
zone << GRUB_MINIX_LOG2_ZONESZ, GRUB_MINIX_ZONE2SECT(zone),
sizeof (grub_minix_uintn_t) * num, sizeof (grub_minix_uintn_t) * num,
sizeof (grub_minix_uintn_t), (char *) &indirn); sizeof (grub_minix_uintn_t), (char *) &indirn);
return grub_minix_le_to_cpu_n (indirn); return grub_minix_le_to_cpu_n (indirn);
} }
/* Direct block. */ /* Direct block. */
if (blk < 7) if (blk < GRUB_MINIX_INODE_DIR_BLOCKS)
return GRUB_MINIX_INODE_DIR_ZONES (data, blk); return GRUB_MINIX_INODE_DIR_ZONES (data, blk);
/* Indirect block. */ /* Indirect block. */
blk -= 7; blk -= GRUB_MINIX_INODE_DIR_BLOCKS;
if (blk < GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data)) if (blk < GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data))
{ {
indir = grub_get_indir (GRUB_MINIX_INODE_INDIR_ZONE (data), blk); indir = grub_get_indir (GRUB_MINIX_INODE_INDIR_ZONE (data), blk);
@ -187,25 +224,26 @@ static grub_ssize_t
grub_minix_read_file (struct grub_minix_data *data, grub_minix_read_file (struct grub_minix_data *data,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length), unsigned offset, unsigned length),
int pos, grub_disk_addr_t len, char *buf) grub_off_t pos, grub_disk_addr_t len, char *buf)
{ {
struct grub_minix_sblock *sblock = &data->sblock; grub_disk_addr_t i;
int i; grub_disk_addr_t blockcnt;
int blockcnt; grub_uint64_t posblock;
grub_uint32_t blockoff;
/* Adjust len so it we can't read past the end of the file. */ /* Adjust len so it we can't read past the end of the file. */
if (len + pos > GRUB_MINIX_INODE_SIZE (data)) if (len + pos > GRUB_MINIX_INODE_SIZE (data))
len = GRUB_MINIX_INODE_SIZE (data) - pos; len = GRUB_MINIX_INODE_SIZE (data) - pos;
blockcnt = (len + pos + GRUB_MINIX_BSIZE - 1) / GRUB_MINIX_BSIZE; blockcnt = grub_divmod64 ((len + pos + data->block_size - 1),
data->block_size, 0);
posblock = grub_divmod64 (pos, data->block_size, &blockoff);
for (i = pos / GRUB_MINIX_BSIZE; i < blockcnt; i++) for (i = posblock; i < blockcnt; i++)
{ {
int blknr; grub_disk_addr_t blknr;
int blockoff = pos % GRUB_MINIX_BSIZE; grub_uint32_t blockend = data->block_size;
int blockend = GRUB_MINIX_BSIZE; grub_off_t skipfirst = 0;
int skipfirst = 0;
blknr = grub_minix_get_file_block (data, i); blknr = grub_minix_get_file_block (data, i);
if (grub_errno) if (grub_errno)
@ -214,28 +252,28 @@ grub_minix_read_file (struct grub_minix_data *data,
/* Last block. */ /* Last block. */
if (i == blockcnt - 1) if (i == blockcnt - 1)
{ {
blockend = (len + pos) % GRUB_MINIX_BSIZE; grub_divmod64 (len + pos, data->block_size, &blockend);
if (!blockend) if (!blockend)
blockend = GRUB_MINIX_BSIZE; blockend = data->block_size;
} }
/* First block. */ /* First block. */
if (i == (pos / (int) GRUB_MINIX_BSIZE)) if (i == posblock)
{ {
skipfirst = blockoff; skipfirst = blockoff;
blockend -= skipfirst; blockend -= skipfirst;
} }
data->disk->read_hook = read_hook; data->disk->read_hook = read_hook;
grub_disk_read (data->disk, blknr << GRUB_MINIX_LOG2_ZONESZ, grub_disk_read (data->disk,
GRUB_MINIX_ZONE2SECT(blknr),
skipfirst, blockend, buf); skipfirst, blockend, buf);
data->disk->read_hook = 0; data->disk->read_hook = 0;
if (grub_errno) if (grub_errno)
return -1; return -1;
buf += GRUB_MINIX_BSIZE - skipfirst; buf += data->block_size - skipfirst;
} }
return len; return len;
@ -250,16 +288,13 @@ grub_minix_read_inode (struct grub_minix_data *data, int ino)
struct grub_minix_sblock *sblock = &data->sblock; struct grub_minix_sblock *sblock = &data->sblock;
/* Block in which the inode is stored. */ /* Block in which the inode is stored. */
int block; grub_disk_addr_t block;
data->ino = ino; data->ino = ino;
/* The first inode in minix is inode 1. */ /* The first inode in minix is inode 1. */
ino--; ino--;
block = GRUB_MINIX_ZONE2SECT (2 + grub_le_to_cpu16 (sblock->inode_bmap_size)
block = ((2 + grub_le_to_cpu16 (sblock->inode_bmap_size) + grub_le_to_cpu16 (sblock->zone_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)); block += ino / (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode));
int offs = (ino % (GRUB_DISK_SECTOR_SIZE int offs = (ino % (GRUB_DISK_SECTOR_SIZE
/ sizeof (struct grub_minix_inode)) / sizeof (struct grub_minix_inode))
@ -335,7 +370,7 @@ grub_minix_find_file (struct grub_minix_data *data, const char *path)
do do
{ {
grub_uint16_t ino; grub_minix_ino_t ino;
char filename[data->filename_size + 1]; char filename[data->filename_size + 1];
if (grub_strlen (name) == 0) if (grub_strlen (name) == 0)
@ -355,7 +390,7 @@ grub_minix_find_file (struct grub_minix_data *data, const char *path)
if (!grub_strcmp (name, filename)) if (!grub_strcmp (name, filename))
{ {
dirino = data->ino; dirino = data->ino;
grub_minix_read_inode (data, grub_le_to_cpu16 (ino)); grub_minix_read_inode (data, grub_minix_le_to_cpu_ino (ino));
/* Follow the symlink. */ /* Follow the symlink. */
if ((GRUB_MINIX_INODE_MODE (data) if ((GRUB_MINIX_INODE_MODE (data)
@ -411,20 +446,35 @@ grub_minix_mount (grub_disk_t disk)
goto fail; goto fail;
if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC) if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC)
{
#if !defined(MODE_MINIX3)
data->filename_size = 14; data->filename_size = 14;
#else
data->filename_size = 60;
#endif
}
#if !defined(MODE_MINIX3)
else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC_30) else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC_30)
data->filename_size = 30; data->filename_size = 30;
#endif
else else
goto fail; goto fail;
data->disk = disk; data->disk = disk;
data->linknest = 0; data->linknest = 0;
#ifdef MODE_MINIX3
data->block_size = grub_le_to_cpu16 (data->sblock.block_size);
#else
data->block_size = 1024U;
#endif
return data; return data;
fail: fail:
grub_free (data); grub_free (data);
#ifdef MODE_MINIX2 #if defined(MODE_MINIX3)
grub_error (GRUB_ERR_BAD_FS, "not a minix3 filesystem");
#elif defined(MODE_MINIX2)
grub_error (GRUB_ERR_BAD_FS, "not a minix2 filesystem"); grub_error (GRUB_ERR_BAD_FS, "not a minix2 filesystem");
#else #else
grub_error (GRUB_ERR_BAD_FS, "not a minix filesystem"); grub_error (GRUB_ERR_BAD_FS, "not a minix filesystem");
@ -460,7 +510,7 @@ grub_minix_dir (grub_device_t device, const char *path,
while (pos < GRUB_MINIX_INODE_SIZE (data)) while (pos < GRUB_MINIX_INODE_SIZE (data))
{ {
grub_uint16_t ino; grub_minix_ino_t ino;
char filename[data->filename_size + 1]; char filename[data->filename_size + 1];
int dirino = data->ino; int dirino = data->ino;
struct grub_dirhook_info info; struct grub_dirhook_info info;
@ -476,10 +526,13 @@ grub_minix_dir (grub_device_t device, const char *path,
(char *) filename) < 0) (char *) filename) < 0)
return grub_errno; return grub_errno;
filename[data->filename_size] = '\0'; filename[data->filename_size] = '\0';
if (!ino)
{
pos += sizeof (ino) + data->filename_size;
continue;
}
/* The filetype is not stored in the dirent. Read the inode to grub_minix_read_inode (data, grub_minix_le_to_cpu_ino (ino));
find out the filetype. This *REALLY* sucks. */
grub_minix_read_inode (data, grub_le_to_cpu16 (ino));
info.dir = ((GRUB_MINIX_INODE_MODE (data) info.dir = ((GRUB_MINIX_INODE_MODE (data)
& GRUB_MINIX_IFDIR) == GRUB_MINIX_IFDIR); & GRUB_MINIX_IFDIR) == GRUB_MINIX_IFDIR);
if (hook (filename, &info) ? 1 : 0) if (hook (filename, &info) ? 1 : 0)
@ -558,7 +611,9 @@ grub_minix_close (grub_file_t file)
static struct grub_fs grub_minix_fs = static struct grub_fs grub_minix_fs =
{ {
#ifdef MODE_MINIX2 #if defined(MODE_MINIX3)
.name = "minix3",
#elif defined(MODE_MINIX2)
.name = "minix2", .name = "minix2",
#else #else
.name = "minix", .name = "minix",
@ -570,7 +625,9 @@ static struct grub_fs grub_minix_fs =
.next = 0 .next = 0
}; };
#ifdef MODE_MINIX2 #if defined(MODE_MINIX3)
GRUB_MOD_INIT(minix3)
#elif defined(MODE_MINIX2)
GRUB_MOD_INIT(minix2) GRUB_MOD_INIT(minix2)
#else #else
GRUB_MOD_INIT(minix) GRUB_MOD_INIT(minix)
@ -580,7 +637,9 @@ GRUB_MOD_INIT(minix)
my_mod = mod; my_mod = mod;
} }
#ifdef MODE_MINIX2 #if defined(MODE_MINIX3)
GRUB_MOD_FINI(minix3)
#elif defined(MODE_MINIX2)
GRUB_MOD_FINI(minix2) GRUB_MOD_FINI(minix2)
#else #else
GRUB_MOD_FINI(minix) GRUB_MOD_FINI(minix)

2
grub-core/fs/minix3.c Normal file
View file

@ -0,0 +1,2 @@
#define MODE_MINIX3 1
#include "minix.c"