This patch enables the cram filesystem to be used as an initrd. Note that you have to set ramdisk_blocksize=4096. diff -rNu ../linux-2.4.0/drivers/block/rd.c ./drivers/block/rd.c --- ../linux-2.4.0/drivers/block/rd.c Mon Dec 18 20:57:17 2000 +++ ./drivers/block/rd.c Tue Jan 9 01:24:36 2001 @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -473,6 +474,7 @@ struct minix_super_block *minixsb; struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; + struct cramfs_super *cramfsb; int nblocks = -1; unsigned char *buf; @@ -483,6 +485,7 @@ minixsb = (struct minix_super_block *) buf; ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; + cramfsb = (struct cramfs_super *) buf; memset(buf, 0xe5, size); /* @@ -512,6 +515,15 @@ "RAMDISK: romfs filesystem found at block %d\n", start_block); nblocks = (ntohl(romfsb->size)+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + + /* so is cramfs */ + if (cramfsb->magic == CRAMFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: cramfs filesystem found at block %d\n", + start_block); + nblocks = (cramfsb->size+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; goto done; } diff -rNu ../linux-2.4.0/fs/cramfs/README ./fs/cramfs/README --- ../linux-2.4.0/fs/cramfs/README Sun Jan 23 18:54:59 2000 +++ ./fs/cramfs/README Tue Jan 9 01:24:36 2001 @@ -14,7 +14,7 @@ -: struct cramfs_super (see cramfs.h). +: struct cramfs_super (see cramfs_fs.h). : For each file: diff -rNu ../linux-2.4.0/fs/cramfs/cramfs.h ./fs/cramfs/cramfs.h --- ../linux-2.4.0/fs/cramfs/cramfs.h Sun Jan 23 18:54:59 2000 +++ ./fs/cramfs/cramfs.h Thu Jan 1 01:00:00 1970 @@ -1,52 +0,0 @@ -#ifndef __CRAMFS_H -#define __CRAMFS_H - -#define CRAMFS_MAGIC 0x28cd3d45 /* some random number */ -#define CRAMFS_SIGNATURE "Compressed ROMFS" - -/* - * Reasonably terse representation of the inode data. - */ -struct cramfs_inode { - u32 mode:16, uid:16; - /* SIZE for device files is i_rdev */ - u32 size:24, gid:8; - /* NAMELEN is the length of the file name, divided by 4 and - rounded up. (cramfs doesn't support hard links.) */ - /* OFFSET: For symlinks and non-empty regular files, this - contains the offset (divided by 4) of the file data in - compressed form (starting with an array of block pointers; - see README). For non-empty directories it is the offset - (divided by 4) of the inode of the first file in that - directory. For anything else, offset is zero. */ - u32 namelen:6, offset:26; -}; - -/* - * Superblock information at the beginning of the FS. - */ -struct cramfs_super { - u32 magic; /* 0x28cd3d45 - random number */ - u32 size; /* Not used. mkcramfs currently - writes a constant 1<<16 here. */ - u32 flags; /* 0 */ - u32 future; /* 0 */ - u8 signature[16]; /* "Compressed ROMFS" */ - u8 fsid[16]; /* random number */ - u8 name[16]; /* user-defined name */ - struct cramfs_inode root; /* Root inode data */ -}; - -/* - * Valid values in super.flags. Currently we refuse to mount - * if (flags & ~CRAMFS_SUPPORTED_FLAGS). Maybe that should be - * changed to test super.future instead. - */ -#define CRAMFS_SUPPORTED_FLAGS (0xff) - -/* Uncompression interfaces to the underlying zlib */ -int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen); -int cramfs_uncompress_init(void); -int cramfs_uncompress_exit(void); - -#endif diff -rNu ../linux-2.4.0/fs/cramfs/inode.c ./fs/cramfs/inode.c --- ../linux-2.4.0/fs/cramfs/inode.c Fri Jan 5 13:56:45 2001 +++ ./fs/cramfs/inode.c Tue Jan 9 01:25:57 2001 @@ -20,7 +20,7 @@ #include -#include "cramfs.h" +#include static struct super_operations cramfs_ops; static struct inode_operations cramfs_dir_inode_operations; @@ -138,7 +138,7 @@ struct buffer_head * bh = bh_array[i]; if (bh) { memcpy(data, bh->b_data, PAGE_CACHE_SIZE); - bforget(bh); + brelse(bh); } else memset(data, 0, PAGE_CACHE_SIZE); data += PAGE_CACHE_SIZE; diff -rNu ../linux-2.4.0/include/linux/cramfs_fs.h ./include/linux/cramfs_fs.h --- ../linux-2.4.0/include/linux/cramfs_fs.h Thu Jan 1 01:00:00 1970 +++ ./include/linux/cramfs_fs.h Tue Jan 9 01:27:15 2001 @@ -0,0 +1,51 @@ +#ifndef __CRAMFS_H +#define __CRAMFS_H + +#define CRAMFS_MAGIC 0x28cd3d45 /* some random number */ +#define CRAMFS_SIGNATURE "Compressed ROMFS" + +/* + * Reasonably terse representation of the inode data. + */ +struct cramfs_inode { + u32 mode:16, uid:16; + /* SIZE for device files is i_rdev */ + u32 size:24, gid:8; + /* NAMELEN is the length of the file name, divided by 4 and + rounded up. (cramfs doesn't support hard links.) */ + /* OFFSET: For symlinks and non-empty regular files, this + contains the offset (divided by 4) of the file data in + compressed form (starting with an array of block pointers; + see README). For non-empty directories it is the offset + (divided by 4) of the inode of the first file in that + directory. For anything else, offset is zero. */ + u32 namelen:6, offset:26; +}; + +/* + * Superblock information at the beginning of the FS. + */ +struct cramfs_super { + u32 magic; /* 0x28cd3d45 - random number */ + u32 size; /* Size of fs in bytes */ + u32 flags; /* 0 */ + u32 future; /* 0 */ + u8 signature[16]; /* "Compressed ROMFS" */ + u8 fsid[16]; /* random number */ + u8 name[16]; /* user-defined name */ + struct cramfs_inode root; /* Root inode data */ +}; + +/* + * Valid values in super.flags. Currently we refuse to mount + * if (flags & ~CRAMFS_SUPPORTED_FLAGS). Maybe that should be + * changed to test super.future instead. + */ +#define CRAMFS_SUPPORTED_FLAGS (0xff) + +/* Uncompression interfaces to the underlying zlib */ +int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen); +int cramfs_uncompress_init(void); +int cramfs_uncompress_exit(void); + +#endif diff -rNu ../linux-2.4.0/scripts/cramfs/mkcramfs.c ./scripts/cramfs/mkcramfs.c --- ../linux-2.4.0/scripts/cramfs/mkcramfs.c Mon Dec 18 20:54:27 2000 +++ ./scripts/cramfs/mkcramfs.c Tue Jan 9 01:24:36 2001 @@ -17,7 +17,7 @@ typedef unsigned short u16; typedef unsigned int u32; -#include "cramfs.h" +#include static const char *progname = "mkcramfs"; @@ -274,16 +274,20 @@ } /* Returns sizeof(struct cramfs_super), which includes the root inode. */ -static unsigned int write_superblock(struct entry *root, char *base) +static unsigned int get_superblock_size(struct entry *root, char *base) +{ + return sizeof(struct cramfs_super); +} + +/* Returns sizeof(struct cramfs_super), which includes the root inode. */ +static unsigned int write_superblock(struct entry *root, char *base, unsigned int size) { struct cramfs_super *super = (struct cramfs_super *) base; unsigned int offset = sizeof(struct cramfs_super); super->magic = CRAMFS_MAGIC; super->flags = 0; - /* Note: 0x10000 is meaningless, which is a bug; but - super->size is never used anyway. */ - super->size = 0x10000; + super->size = size; memcpy(super->signature, CRAMFS_SIGNATURE, sizeof(super->signature)); set_random(super->fsid, sizeof(super->fsid)); strncpy(super->name, "Compressed", sizeof(super->name)); @@ -521,6 +525,7 @@ struct entry *root_entry; char *rom_image; unsigned int offset; + unsigned int sbsize; ssize_t written; int fd; loff_t fslen_ub = 0; /* initial guess (upper-bound) of @@ -575,10 +580,9 @@ perror("ROM image map"); exit(1); } - offset = write_superblock(root_entry, rom_image); - printf("Super block: %d bytes\n", offset); - offset = write_directory_structure(root_entry->child, rom_image, offset); + sbsize = get_superblock_size(root_entry, rom_image); + offset = write_directory_structure(root_entry->child, rom_image, sbsize); printf("Directory data: %d bytes\n", offset); offset = write_data(root_entry, rom_image, offset); @@ -586,6 +590,11 @@ /* We always write a multiple of blksize bytes, so that losetup works. */ offset = ((offset - 1) | (blksize - 1)) + 1; + + /* Finally, write the superblock, with the given size */ + write_superblock(root_entry, rom_image, offset); + printf("Super block: %d bytes\n", sbsize); + printf("Everything: %d kilobytes\n", offset >> 10); written = write(fd, rom_image, offset);