From 3dd3dd335fe8efb23d54bfbc322701d54c28a65d Mon Sep 17 00:00:00 2001 From: Feiran Zheng Date: Mon, 11 Apr 2011 08:16:13 +0200 Subject: [PATCH 1/4] minix3fs support --- grub-core/Makefile.core.def | 5 ++ grub-core/fs/minix.c | 164 +++++++++++++++++++++++++++--------- grub-core/fs/minix3.c | 2 + 3 files changed, 132 insertions(+), 39 deletions(-) create mode 100644 grub-core/fs/minix3.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 7c26b37e9..9f418a0b7 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -958,6 +958,11 @@ module = { common = fs/minix2.c; }; +module = { + name = minix3; + common = fs/minix3.c; +}; + module = { name = nilfs2; common = fs/nilfs2.c; diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c index 679e1ec51..c93dfe085 100644 --- a/grub-core/fs/minix.c +++ b/grub-core/fs/minix.c @@ -25,14 +25,17 @@ #include #include -#ifdef MODE_MINIX2 +#ifdef MODE_MINIX3 +#define GRUB_MINIX_MAGIC 0x4D5A +#elif defined(MODE_MINIX2) #define GRUB_MINIX_MAGIC 0x2468 #define GRUB_MINIX_MAGIC_30 0x2478 #else #define GRUB_MINIX_MAGIC 0x137F #define GRUB_MINIX_MAGIC_30 0x138F #endif -#define GRUB_MINIX_BSIZE 1024U + +#define GRUB_MINIX_INODE_DIR_BLOCKS 7 #define GRUB_MINIX_LOG2_BSIZE 1 #define GRUB_MINIX_ROOT_INODE 1 #define GRUB_MINIX_MAX_SYMLNK_CNT 8 @@ -41,7 +44,7 @@ #define GRUB_MINIX_IFDIR 0040000U #define GRUB_MINIX_IFLNK 0120000U -#ifdef MODE_MINIX2 +#if defined(MODE_MINIX2) || defined(MODE_MINIX3) typedef grub_uint32_t grub_minix_uintn_t; #define grub_minix_le_to_cpu_n grub_le_to_cpu32 #else @@ -50,6 +53,13 @@ typedef grub_uint16_t grub_minix_uintn_t; #endif #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_MODE(data) (grub_le_to_cpu16 (data->inode.mode)) @@ -62,9 +72,28 @@ typedef grub_uint16_t grub_minix_uintn_t; #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 (data->block_size \ << grub_le_to_cpu16 (sblock->log2_zone_size)) +#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 { grub_uint16_t inode_cnt; @@ -76,8 +105,28 @@ struct grub_minix_sblock grub_uint32_t max_file_size; grub_uint16_t magic; }; +#endif -#ifndef MODE_MINIX2 +#if defined(MODE_MINIX3) + +struct grub_minix_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; +}; + +#elif defined(MODE_MINIX2) struct grub_minix_inode { grub_uint16_t mode; @@ -121,6 +170,7 @@ struct grub_minix_data int linknest; grub_disk_t disk; int filename_size; + grub_size_t block_size; }; static grub_dl_t my_mod; @@ -141,18 +191,22 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk) { grub_minix_uintn_t indirn; grub_disk_read (data->disk, +#ifdef MODE_MINIX3 + zone * (data->block_size / GRUB_DISK_SECTOR_SIZE), +#else zone << GRUB_MINIX_LOG2_ZONESZ, +#endif sizeof (grub_minix_uintn_t) * num, sizeof (grub_minix_uintn_t), (char *) &indirn); return grub_minix_le_to_cpu_n (indirn); } /* Direct block. */ - if (blk < 7) + if (blk < GRUB_MINIX_INODE_DIR_BLOCKS) return GRUB_MINIX_INODE_DIR_ZONES (data, blk); /* Indirect block. */ - blk -= 7; + blk -= GRUB_MINIX_INODE_DIR_BLOCKS; if (blk < GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data)) { indir = grub_get_indir (GRUB_MINIX_INODE_INDIR_ZONE (data), blk); @@ -185,25 +239,27 @@ static grub_ssize_t grub_minix_read_file (struct grub_minix_data *data, void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, 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; - int i; - int blockcnt; + grub_disk_addr_t i; + grub_disk_addr_t blockcnt; + grub_uint64_t posblock; + grub_uint32_t blockoff; /* 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; + 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; - int blockoff = pos % GRUB_MINIX_BSIZE; - int blockend = GRUB_MINIX_BSIZE; - - int skipfirst = 0; + grub_disk_addr_t blknr; + grub_uint32_t blockend = data->block_size; + grub_off_t skipfirst = 0; blknr = grub_minix_get_file_block (data, i); if (grub_errno) @@ -212,28 +268,32 @@ grub_minix_read_file (struct grub_minix_data *data, /* Last block. */ if (i == blockcnt - 1) { - blockend = (len + pos) % GRUB_MINIX_BSIZE; + grub_divmod64 (len + pos, data->block_size, &blockend); if (!blockend) - blockend = GRUB_MINIX_BSIZE; + blockend = data->block_size; } /* First block. */ - if (i == (pos / (int) GRUB_MINIX_BSIZE)) + if (i == posblock) { skipfirst = blockoff; blockend -= skipfirst; } data->disk->read_hook = read_hook; - grub_disk_read (data->disk, blknr << GRUB_MINIX_LOG2_ZONESZ, + grub_disk_read (data->disk, +#ifdef MODE_MINIX3 + blknr * (sblock->block_size / GRUB_DISK_SECTOR_SIZE), +#else + blknr << GRUB_MINIX_LOG2_ZONESZ, +#endif skipfirst, blockend, buf); - data->disk->read_hook = 0; if (grub_errno) return -1; - buf += GRUB_MINIX_BSIZE - skipfirst; + buf += data->block_size - skipfirst; } return len; @@ -248,16 +308,18 @@ grub_minix_read_inode (struct grub_minix_data *data, int ino) struct grub_minix_sblock *sblock = &data->sblock; /* Block in which the inode is stored. */ - int block; + grub_disk_addr_t block; 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); - + block = (2 + grub_le_to_cpu16 (sblock->inode_bmap_size) + + grub_le_to_cpu16 (sblock->zone_bmap_size)); +#ifndef MODE_MINIX3 + block <<= GRUB_MINIX_LOG2_BSIZE; +#else + block *= sblock->block_size / GRUB_DISK_SECTOR_SIZE; +#endif block += ino / (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode)); int offs = (ino % (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode)) @@ -333,7 +395,7 @@ grub_minix_find_file (struct grub_minix_data *data, const char *path) do { - grub_uint16_t ino; + grub_minix_ino_t ino; char filename[data->filename_size + 1]; if (grub_strlen (name) == 0) @@ -353,7 +415,7 @@ grub_minix_find_file (struct grub_minix_data *data, const char *path) if (!grub_strcmp (name, filename)) { 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. */ if ((GRUB_MINIX_INODE_MODE (data) @@ -409,20 +471,35 @@ grub_minix_mount (grub_disk_t disk) goto fail; if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC) + { +#if !defined(MODE_MINIX3) 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) data->filename_size = 30; +#endif else goto fail; data->disk = disk; 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; fail: 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"); #else grub_error (GRUB_ERR_BAD_FS, "not a minix filesystem"); @@ -458,7 +535,7 @@ grub_minix_dir (grub_device_t device, const char *path, while (pos < GRUB_MINIX_INODE_SIZE (data)) { - grub_uint16_t ino; + grub_minix_ino_t ino; char filename[data->filename_size + 1]; int dirino = data->ino; struct grub_dirhook_info info; @@ -474,10 +551,13 @@ grub_minix_dir (grub_device_t device, const char *path, (char *) filename) < 0) return grub_errno; 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 - find out the filetype. This *REALLY* sucks. */ - grub_minix_read_inode (data, grub_le_to_cpu16 (ino)); + grub_minix_read_inode (data, grub_minix_le_to_cpu_ino (ino)); info.dir = ((GRUB_MINIX_INODE_MODE (data) & GRUB_MINIX_IFDIR) == GRUB_MINIX_IFDIR); if (hook (filename, &info) ? 1 : 0) @@ -556,7 +636,9 @@ grub_minix_close (grub_file_t file) static struct grub_fs grub_minix_fs = { -#ifdef MODE_MINIX2 +#if defined(MODE_MINIX3) + .name = "minix3", +#elif defined(MODE_MINIX2) .name = "minix2", #else .name = "minix", @@ -568,7 +650,9 @@ static struct grub_fs grub_minix_fs = .next = 0 }; -#ifdef MODE_MINIX2 +#if defined(MODE_MINIX3) +GRUB_MOD_INIT(minix3) +#elif defined(MODE_MINIX2) GRUB_MOD_INIT(minix2) #else GRUB_MOD_INIT(minix) @@ -578,7 +662,9 @@ GRUB_MOD_INIT(minix) my_mod = mod; } -#ifdef MODE_MINIX2 +#if defined(MODE_MINIX3) +GRUB_MOD_FINI(minix3) +#elif defined(MODE_MINIX2) GRUB_MOD_FINI(minix2) #else GRUB_MOD_FINI(minix) diff --git a/grub-core/fs/minix3.c b/grub-core/fs/minix3.c new file mode 100644 index 000000000..58a21d2b5 --- /dev/null +++ b/grub-core/fs/minix3.c @@ -0,0 +1,2 @@ +#define MODE_MINIX3 1 +#include "minix.c" From 58ee1408a8be7d386027882cb07e14f76a2b6cfb Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 11 Apr 2011 08:53:28 +0200 Subject: [PATCH 2/4] Fix an error in minix inode declaration --- grub-core/fs/minix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c index c93dfe085..877f71921 100644 --- a/grub-core/fs/minix.c +++ b/grub-core/fs/minix.c @@ -126,7 +126,7 @@ struct grub_minix_inode grub_uint32_t unused; }; -#elif defined(MODE_MINIX2) +#elif !defined(MODE_MINIX2) struct grub_minix_inode { grub_uint16_t mode; From 65f01628e19d04be6cad0242d3056dbb656a54b2 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 11 Apr 2011 08:56:42 +0200 Subject: [PATCH 3/4] unify minix3 and minix2 inode declarations --- grub-core/fs/minix.c | 49 +++++++++++++------------------------------- 1 file changed, 14 insertions(+), 35 deletions(-) diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c index 877f71921..a01ee77ca 100644 --- a/grub-core/fs/minix.c +++ b/grub-core/fs/minix.c @@ -107,41 +107,7 @@ struct grub_minix_sblock }; #endif -#if defined(MODE_MINIX3) - -struct grub_minix_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; -}; - -#elif !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 - +#if defined(MODE_MINIX3) || defined(MODE_MINIX2) struct grub_minix_inode { grub_uint16_t mode; @@ -158,6 +124,19 @@ struct grub_minix_inode 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 From 8fc88523dd88ed4e7852bbab28faa8225cde7f21 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 11 Apr 2011 14:09:02 +0200 Subject: [PATCH 4/4] Add minix3 to util filesystems --- Makefile.util.def | 1 + grub-core/fs/minix.c | 36 +++++++++++++++--------------------- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/Makefile.util.def b/Makefile.util.def index 303baea3f..678e581e6 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -60,6 +60,7 @@ library = { common = grub-core/fs/jfs.c; common = grub-core/fs/minix.c; common = grub-core/fs/minix2.c; + common = grub-core/fs/minix3.c; common = grub-core/fs/nilfs2.c; common = grub-core/fs/ntfs.c; common = grub-core/fs/ntfscomp.c; diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c index a01ee77ca..298eef394 100644 --- a/grub-core/fs/minix.c +++ b/grub-core/fs/minix.c @@ -70,10 +70,19 @@ typedef grub_uint16_t grub_minix_ino_t; #define GRUB_MINIX_INODE_DINDIR_ZONE(data) (grub_minix_le_to_cpu_n \ (data->inode.double_indir_zone)) +#ifndef MODE_MINIX3 #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)) +#endif #define GRUB_MINIX_ZONESZ (data->block_size \ - << grub_le_to_cpu16 (sblock->log2_zone_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 @@ -160,7 +169,6 @@ static grub_err_t grub_minix_find_file (struct grub_minix_data *data, static int grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk) { - struct grub_minix_sblock *sblock = &data->sblock; int indir; auto int grub_get_indir (int, int); @@ -170,11 +178,7 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk) { grub_minix_uintn_t indirn; grub_disk_read (data->disk, -#ifdef MODE_MINIX3 - zone * (data->block_size / GRUB_DISK_SECTOR_SIZE), -#else - zone << GRUB_MINIX_LOG2_ZONESZ, -#endif + GRUB_MINIX_ZONE2SECT(zone), sizeof (grub_minix_uintn_t) * num, sizeof (grub_minix_uintn_t), (char *) &indirn); return grub_minix_le_to_cpu_n (indirn); @@ -220,7 +224,6 @@ grub_minix_read_file (struct grub_minix_data *data, unsigned offset, unsigned length), grub_off_t pos, grub_disk_addr_t len, char *buf) { - struct grub_minix_sblock *sblock = &data->sblock; grub_disk_addr_t i; grub_disk_addr_t blockcnt; grub_uint64_t posblock; @@ -262,11 +265,7 @@ grub_minix_read_file (struct grub_minix_data *data, data->disk->read_hook = read_hook; grub_disk_read (data->disk, -#ifdef MODE_MINIX3 - blknr * (sblock->block_size / GRUB_DISK_SECTOR_SIZE), -#else - blknr << GRUB_MINIX_LOG2_ZONESZ, -#endif + GRUB_MINIX_ZONE2SECT(blknr), skipfirst, blockend, buf); data->disk->read_hook = 0; if (grub_errno) @@ -292,13 +291,8 @@ grub_minix_read_inode (struct grub_minix_data *data, int 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)); -#ifndef MODE_MINIX3 - block <<= GRUB_MINIX_LOG2_BSIZE; -#else - block *= sblock->block_size / GRUB_DISK_SECTOR_SIZE; -#endif + block = GRUB_MINIX_ZONE2SECT (2 + grub_le_to_cpu16 (sblock->inode_bmap_size) + + grub_le_to_cpu16 (sblock->zone_bmap_size)); block += ino / (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode)); int offs = (ino % (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode))