Hi. I've been implementing romfs support into grub, and need
help with regard to automake/autoconf and friends.
First, about romfs. It's a simple, read-only filesystem,
included in Linux 2.4. There's a file documenting the on-disk
layout in the kernel source, you can browse it at
http://lxr.linux.no/source/Documentation/filesystems/romfs.txt?v=2.4.17
and the actual implementation is at
http://lxr.linux.no/source/fs/romfs/?v=2.4.17
Now, I have a patch that implements the first steps towards
romfs support in grub. The code is still very raw, and I have
only tested it with the grub shell tool, not booted from it.
However, I can't progress any further without some help from
you.
It seems that I can't create Makefile.in etc from Makefile.am
succesfully. Rather than drag you down into debugging auto* for
me, could you apply the patch (fix the Makefile.am part if I
misunderstood something), regenerate the generated files, and
send them to me? Thank you.
Any input as to the functioning of fsys_romfs.c is
appreciated, the interface is very sketchy and I had to guess
what global variables to manipulate. I will format the code to
fit the existing coding style before proper submission.
diff -Naur grub-0.91.orig/stage2/Makefile.am grub-0.91/stage2/Makefile.am
--- grub-0.91.orig/stage2/Makefile.am Sat Oct 27 19:04:24 2001
+++ grub-0.91/stage2/Makefile.am Thu Feb 28 14:05:55 2002
@@ -17,11 +17,11 @@
libgrub_a_SOURCES = boot.c builtins.c common.c char_io.c cmdline.c \
disk_io.c gunzip.c fsys_ffs.c fsys_ext2fs.c fsys_fat.c \
fsys_jfs.c fsys_minix.c fsys_reiserfs.c fsys_vstafs.c \
- fsys_xfs.c stage2.c md5.c
+ fsys_xfs.c fsys_romfs.c stage2.c md5.c
libgrub_a_CFLAGS = $(GRUB_CFLAGS) -I$(top_srcdir)/lib \
-DGRUB_UTIL=1 -DFSYS_EXT2FS=1 -DFSYS_FAT=1 -DFSYS_FFS=1 \
- -DFSYS_JFS=1 -DFSYS_MINIX=1 -DFSYS_REISERFS=1 -DFSYS_VSTAFS=1
- -DFSYS_XFS=1 -DUSE_MD5_PASSWORDS=1 \
+ -DFSYS_JFS=1 -DFSYS_MINIX=1 -DFSYS_REISERFS=1 -DFSYS_VSTAFS=1 \
+ -DFSYS_XFS=1 -DFSYS_ROMFS=1 -DUSE_MD5_PASSWORDS=1 \
-DSUPPORT_SERIAL=1 -DSUPPORT_HERCULES=1 -fwritable-strings
# Stage 2 and Stage 1.5's.
@@ -32,7 +32,7 @@
if DISKLESS_SUPPORT
pkgdata_DATA = stage2 e2fs_stage1_5 fat_stage1_5 ffs_stage1_5 \
jfs_stage1_5 minix_stage1_5 reiserfs_stage1_5 vstafs_stage1_5 \
- xfs_stage1_5 nbgrub pxegrub
+ xfs_stage1_5 nbgrub pxegrub romfs_stage1_5
noinst_DATA = pre_stage2 start nbloader pxeloader diskless
noinst_PROGRAMS = pre_stage2.exec start.exec e2fs_stage1_5.exec \
fat_stage1_5.exec ffs_stage1_5.exec jfs_stage1_5.exec \
@@ -42,12 +42,12 @@
else
pkgdata_DATA = stage2 e2fs_stage1_5 fat_stage1_5 ffs_stage1_5 \
jfs_stage1_5 minix_stage1_5 reiserfs_stage1_5 vstafs_stage1_5 \
- xfs_stage1_5
+ xfs_stage1_5 romfs_stage1_5
noinst_DATA = pre_stage2 start
noinst_PROGRAMS = pre_stage2.exec start.exec e2fs_stage1_5.exec \
fat_stage1_5.exec ffs_stage1_5.exec jfs_stage1_5.exec \
minix_stage1_5.exec reiserfs_stage1_5.exec \
- vstafs_stage1_5.exec xfs_stage1_5.exec
+ vstafs_stage1_5.exec xfs_stage1_5.exec romfs_stage1_5.exec
endif
MOSTLYCLEANFILES = $(noinst_PROGRAMS)
@@ -85,7 +85,7 @@
char_io.c cmdline.c disk_io.c gunzip.c fsys_ext2fs.c \
fsys_fat.c fsys_ffs.c fsys_jfs.c fsys_minix.c fsys_reiserfs.c \
fsys_vstafs.c fsys_xfs.c hercules.c serial.c smp-imps.c \
- stage2.c md5.c
+ stage2.c md5.c fsys_romfs.c
pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
pre_stage2_exec_ASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK)
@@ -192,6 +192,15 @@
xfs_stage1_5_exec_ASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_XFS=1 \
-DNO_BLOCK_FILES=1
xfs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
+
+# For romfs_stage1_5 target.
+romfs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c disk_io.c \
+ stage1_5.c fsys_romfs.c bios.c
+romfs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_ROMFS=1 \
+ -DNO_BLOCK_FILES=1
+romfs_stage1_5_exec_ASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_ROMFS=1 \
+ -DNO_BLOCK_FILES=1
+romfs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
# For diskless target.
diskless_exec_SOURCES = $(pre_stage2_exec_SOURCES)
diff -Naur grub-0.91.orig/stage2/disk_io.c grub-0.91/stage2/disk_io.c
--- grub-0.91.orig/stage2/disk_io.c Wed Nov 28 20:43:56 2001
+++ grub-0.91/stage2/disk_io.c Thu Feb 28 14:05:55 2002
@@ -68,6 +68,9 @@
# ifdef FSYS_XFS
{"xfs", xfs_mount, xfs_read, xfs_dir, 0, 0},
# endif
+# ifdef FSYS_ROMFS
+ {"romfs", romfs_mount, romfs_read, romfs_dir, 0, 0},
+# endif
/* XX FFS should come last as it's superblock is commonly crossing tracks
on floppies from track 1 to 2, while others only use 1. */
# ifdef FSYS_FFS
diff -Naur grub-0.91.orig/stage2/filesys.h grub-0.91/stage2/filesys.h
--- grub-0.91.orig/stage2/filesys.h Mon Nov 12 08:57:29 2001
+++ grub-0.91/stage2/filesys.h Thu Feb 28 14:05:55 2002
@@ -105,11 +105,20 @@
#define FSYS_TFTP_NUM 0
#endif
+#ifdef FSYS_ROMFS
+#define FSYS_ROMFS_NUM 1
+int romfs_mount (void);
+int romfs_read (char *buf, int len);
+int romfs_dir (char *dirname);
+#else
+#define FSYS_ROMFS_NUM 0
+#endif
+
#ifndef NUM_FSYS
#define NUM_FSYS \
(FSYS_FFS_NUM + FSYS_FAT_NUM + FSYS_EXT2FS_NUM + FSYS_MINIX_NUM \
+ FSYS_REISERFS_NUM + FSYS_VSTAFS_NUM + FSYS_JFS_NUM + FSYS_XFS_NUM \
- + FSYS_TFTP_NUM)
+ + FSYS_TFTP_NUM + FSYS_ROMFS_NUM)
#endif
/* defines for the block filesystem info area */
diff -Naur grub-0.91.orig/stage2/fsys_romfs.c grub-0.91/stage2/fsys_romfs.c
--- grub-0.91.orig/stage2/fsys_romfs.c Thu Jan 1 02:00:00 1970
+++ grub-0.91/stage2/fsys_romfs.c Thu Feb 28 14:11:22 2002
@@ -0,0 +1,235 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999, 2001 Free Software Foundation, Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef FSYS_ROMFS
+
+#include "shared.h"
+#include "filesys.h"
+
+#include "romfs_fs.h"
+
+/* "local" defs, not stolen from a header file */
+#define MAX_LINK_COUNT 5
+
+/* made up, these are pointers into FSYS_BUF */
+/* read once, always stays there: */
+#define SUPERBLOCK \
+ ((struct romfs_super_block *)(FSYS_BUF))
+#define INODE \
+ ((struct romfs_inode *)((int)SUPERBLOCK + sizeof(struct romfs_super_block)))
+
+int rootdir_offset;
+
+static int find_string_len(unsigned char *buf, int offset) {
+ int i=0;
+ /* all strings are nul-padded to even 16 bytes */
+
+ do {
+ devread ( (offset+i*16) / SECTOR_SIZE,
+ (offset+i*16) % SECTOR_SIZE,
+ 16, buf+(i*16));
+ i++;
+ } while (buf[i*16-1] != '\0');
+ return i*16;
+}
+
+/* return disk offset of file data. */
+static int load_inode(int offset) {
+ disk_read_func = disk_read_hook;
+
+ devread (offset / SECTOR_SIZE,
+ offset % SECTOR_SIZE,
+ sizeof(*INODE)+16, (unsigned char*)INODE);
+
+ INODE->next=ntohl(INODE->next);
+ INODE->spec=ntohl(INODE->spec);
+ INODE->size=ntohl(INODE->size);
+ INODE->checksum=ntohl(INODE->checksum);
+
+ disk_read_func = NULL;
+ {
+ int namelen;
+ namelen = find_string_len(((unsigned char*)INODE)+sizeof(*INODE),
+ offset+16);
+ return offset+16+namelen;
+ }
+}
+
+/* check filesystem types and read superblock into memory buffer */
+int
+romfs_mount (void)
+{
+ int retval = 1;
+
+ errnum=0;
+ if ((((current_drive & 0x80) || (current_slice != 0))
+ && (current_slice != PC_SLICE_TYPE_EXT2FS)
+ && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_EXT2FS))
+ && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_OTHER)))) {
+ retval = 0;
+ } else if (!devread (0, 0, sizeof (struct romfs_super_block),
+ (char *) SUPERBLOCK)) {
+ retval = 0;
+ } else if (SUPERBLOCK->word0 != ROMSB_WORD0
+ || SUPERBLOCK->word1 != ROMSB_WORD1) {
+ retval = 0;
+ }
+ /* TODO verify checksum */
+
+ rootdir_offset = 16+find_string_len(&SUPERBLOCK->name, 16);
+
+ return retval;
+}
+
+static int disk_offset;
+static int is_eof;
+
+int
+romfs_read (char *buf, int len)
+{
+ int ret = 0;
+
+ if (is_eof)
+ return 0;
+
+ disk_read_func = disk_read_hook;
+
+ devread (disk_offset / SECTOR_SIZE,
+ disk_offset % SECTOR_SIZE,
+ len, buf);
+
+ disk_read_func = NULL;
+
+ disk_offset += len;
+ filepos += len;
+ ret = len;
+
+ if (errnum)
+ ret = 0;
+
+ if (filepos==filemax)
+ is_eof=1;
+ return ret;
+}
+
+int
+romfs_dir (char *dirname)
+{
+ int link_count = 0;
+ char *rest;
+ char ch; /* temp char holder */
+ int str_chk; /* used to hold the results of a string compare */
+
+ disk_offset = rootdir_offset;
+
+ /* loop invariants:
+ current_ino = inode to lookup
+ dirname = pointer to filename component we are cur looking up within
+ the directory known pointed to by current_ino (if any)
+ */
+
+ while (1) {
+ int type;
+
+ /* look up an inode */
+
+ load_inode(disk_offset);
+
+ type = INODE->next&ROMFH_TYPE;
+
+ if (type==ROMFH_HRD) {
+ disk_offset = INODE->spec;
+ continue;
+ } else if (type==ROMFH_SYM) {
+ errnum = ERR_SYMLINK_LOOP;
+ return 0;
+ } else {
+ /* if end of filename, INODE points to the file's inode */
+ if (!*dirname || isspace (*dirname)) {
+ if (type!=ROMFH_REG) {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+
+ filemax = INODE->size;
+ return 1;
+ } else {
+ /* else we have to traverse a directory */
+
+ /* skip over slashes */
+ while (*dirname == '/')
+ dirname++;
+
+ /* if this isn't a directory of sufficient size to hold our file, abort */
+ if (type!=ROMFH_DIR) {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+
+ /* skip to next slash or end of filename (space) */
+ for (rest = dirname;
+ (ch = *rest) && !isspace (ch) && ch != '/';
+ rest++)
+ ;
+
+ /* look through this directory and find the next filename
+ component */
+ /* invariant: rest points to slash after the next filename
+ component */
+ *rest = 0;
+
+ {
+ int dir_offset=INODE->spec; /* disk offset for this dir search */
+
+ do {
+ if (!dir_offset) {
+ /* not found */
+ if (print_possibilities >= 0) {
+ errnum = ERR_FILE_NOT_FOUND;
+ *rest = ch;
+ }
+ return (print_possibilities < 0);
+ }
+
+ load_inode(dir_offset);
+ str_chk = strcmp(dirname, INODE->name);
+
+#ifndef STAGE1_5
+ if (print_possibilities && ch != '/'
+ && (!*dirname || str_chk <= 0)) {
+ if (print_possibilities > 0)
+ print_possibilities = -print_possibilities;
+ print_a_completion (INODE->name);
+ }
+#endif
+
+ if (str_chk)
+ dir_offset=INODE->next & ROMFH_SIZE_MASK;
+ } while (str_chk || (print_possibilities && ch != '/'));
+
+ disk_offset = dir_offset;
+ *(dirname = rest) = ch;
+ }
+ }
+ }
+ }
+ /* never get here */
+}
+
+#endif /* FSYS_ROMFS */
diff -Naur grub-0.91.orig/stage2/romfs_fs.h grub-0.91/stage2/romfs_fs.h
--- grub-0.91.orig/stage2/romfs_fs.h Thu Jan 1 02:00:00 1970
+++ grub-0.91/stage2/romfs_fs.h Thu Feb 28 14:08:00 2002
@@ -0,0 +1,46 @@
+#ifndef __LINUX_ROMFS_FS_H
+#define __LINUX_ROMFS_FS_H
+
+#include <netinet/in.h>
+
+/* The basic structures of the romfs filesystem */
+
+#define __mkw(h,l) (((h)&0x00ff)<< 8|((l)&0x00ff))
+#define __mkl(h,l) (((h)&0xffff)<<16|((l)&0xffff))
+#define __mk4(a,b,c,d) htonl(__mkl(__mkw(a,b),__mkw(c,d)))
+#define ROMSB_WORD0 __mk4('-','r','o','m')
+#define ROMSB_WORD1 __mk4('1','f','s','-')
+
+/* On-disk "super block" */
+
+struct romfs_super_block {
+ __u32 word0;
+ __u32 word1;
+ __u32 size;
+ __u32 checksum;
+ char name[0]; /* volume name */
+};
+
+/* On disk inode */
+
+struct romfs_inode {
+ __u32 next; /* low 4 bits see ROMFH_ */
+ __u32 spec;
+ __u32 size;
+ __u32 checksum;
+ char name[0];
+};
+
+#define ROMFH_SIZE_MASK (~15)
+#define ROMFH_TYPE 7
+#define ROMFH_HRD 0
+#define ROMFH_DIR 1
+#define ROMFH_REG 2
+#define ROMFH_SYM 3
+#define ROMFH_BLK 4
+#define ROMFH_CHR 5
+#define ROMFH_SCK 6
+#define ROMFH_FIF 7
+#define ROMFH_EXEC 8
+
+#endif
--
tv@{{hq.yok.utu,havoc,gaeshido}.fi,{debian,wanderer}.org,stonesoft.com}
double a,b=4,c;main(){for(;++a<2e6;c-=(b=-b)/a++);printf("%f\n",c);}