tools/version.h: $(CONFIGURE) Makefile
@./makever.sh
- @echo \#define UTS_RELEASE \"0.99.pl5-`cat .version`\" > tools/version.h
+ @echo \#define UTS_RELEASE \"0.99.pl6-`cat .version`\" > tools/version.h
@echo \#define UTS_VERSION \"`date +%D`\" >> tools/version.h
@echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> tools/version.h
@echo \#define LINUX_COMPILE_BY \"`whoami`\" >> tools/version.h
@echo \#define LINUX_COMPILE_HOST \"`hostname`\" >> tools/version.h
Image: $(CONFIGURE) boot/bootsect boot/setup tools/system tools/build
- cp tools/system system.tmp
- $(STRIP) system.tmp
- tools/build boot/bootsect boot/setup system.tmp $(ROOT_DEV) > Image
- rm system.tmp
+ tools/build boot/bootsect boot/setup tools/system $(ROOT_DEV) > Image
sync
disk: Image
$(AS86) -o boot/bootsect.o boot/bootsect.s
$(LD86) -s -o boot/bootsect boot/bootsect.o
+zBoot/zSystem: zBoot/*.c zBoot/*.S tools/zSystem
+ cd zBoot;$(MAKE)
+
+zImage: $(CONFIGURE) boot/bootsect boot/setup zBoot/zSystem tools/build
+ cp zBoot/zSystem system.tmp
+ $(STRIP) system.tmp
+ tools/build boot/bootsect boot/setup system.tmp $(ROOT_DEV) > zImage
+ rm system.tmp
+ sync
+
+zdisk: zImage
+ dd bs=8192 if=zImage of=/dev/fd0
+
+zlilo: $(CONFIGURE) zImage
+ cat zImage > /vmlinuz
+ /etc/lilo/install
+
+
+tools/zSystem: boot/head.o init/main.o tools/version.o linuxsubdirs
+ $(LD) $(LDFLAGS) -T 100000 -M boot/head.o init/main.o tools/version.o \
+ $(ARCHIVES) \
+ $(FILESYSTEMS) \
+ $(DRIVERS) \
+ $(MATH) \
+ $(LIBS) \
+ -o tools/zSystem > zSystem.map
+
fs: dummy
$(MAKE) linuxsubdirs SUBDIRS=fs
$(MAKE) linuxsubdirs SUBDIRS=kernel
clean:
+ rm -f zImage zSystem.map tools/zSystem
rm -f Image System.map core boot/bootsect boot/setup \
boot/bootsect.s boot/setup.s boot/head.s init/main.s
rm -f init/*.o tools/system tools/build boot/*.o tools/*.o
- for i in $(SUBDIRS); do (cd $$i && $(MAKE) clean); done
+ for i in zBoot $(SUBDIRS); do (cd $$i && $(MAKE) clean); done
backup: clean
cd .. && tar cf - linux | compress - > backup.Z
! now we want to move to protected mode ...
cli ! no interrupts allowed !
+ mov al,#0x80 ! disable NMI for the bootup sequence
+ out #0x70,al
! first we move the system to it's rightful place
.s.o:
$(AS) -o $*.o $<
-OBJS= open.o read_write.o inode.o file_table.o buffer.o super.o \
+OBJS= open.o read_write.o inode.o devices.o file_table.o buffer.o super.o \
block_dev.o stat.o exec.o pipe.o namei.o fcntl.o ioctl.o \
select.o fifo.o locks.o filesystems.o
--- /dev/null
+/*
+ * linux/fs/devices.c
+ *
+ * (C) 1993 Matthias Urlichs -- collected common code and tables.
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/ext_fs.h>
+#include <linux/tty.h>
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+#include <linux/errno.h>
+
+struct file_operations * chrdev_fops[MAX_CHRDEV] = {
+ NULL,
+};
+
+struct file_operations * blkdev_fops[MAX_BLKDEV] = {
+ NULL,
+};
+
+int register_chrdev(unsigned int major, const char * name, struct file_operations *fops)
+{
+ if (major >= MAX_CHRDEV)
+ return -EINVAL;
+ if (chrdev_fops[major])
+ return -EBUSY;
+ chrdev_fops[major] = fops;
+ return 0;
+}
+
+int register_blkdev(unsigned int major, const char * name, struct file_operations *fops)
+{
+ if (major >= MAX_BLKDEV)
+ return -EINVAL;
+ if (blkdev_fops[major])
+ return -EBUSY;
+ blkdev_fops[major] = fops;
+ return 0;
+}
+
+/*
+ * Called every time a block special file is opened
+ */
+int blkdev_open(struct inode * inode, struct file * filp)
+{
+ int i;
+
+ i = MAJOR(inode->i_rdev);
+ if (i >= MAX_BLKDEV || !blkdev_fops[i])
+ return -ENODEV;
+ filp->f_op = blkdev_fops[i];
+ if (filp->f_op->open)
+ return filp->f_op->open(inode,filp);
+ return 0;
+}
+
+/*
+ * Dummy default file-operations: the only thing this does
+ * is contain the open that then fills in the correct operations
+ * depending on the special file...
+ */
+struct file_operations def_blk_fops = {
+ NULL, /* lseek */
+ NULL, /* read */
+ NULL, /* write */
+ NULL, /* readdir */
+ NULL, /* select */
+ NULL, /* ioctl */
+ NULL, /* mmap */
+ blkdev_open, /* open */
+ NULL, /* release */
+};
+
+struct inode_operations blkdev_inode_operations = {
+ &def_blk_fops, /* default file operations */
+ NULL, /* create */
+ NULL, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ NULL, /* readlink */
+ NULL, /* follow_link */
+ NULL, /* bmap */
+ NULL, /* truncate */
+ NULL /* permission */
+};
+
+/*
+ * Called every time a character special file is opened
+ */
+int chrdev_open(struct inode * inode, struct file * filp)
+{
+ int i;
+
+ i = MAJOR(inode->i_rdev);
+ if (i >= MAX_CHRDEV || !chrdev_fops[i])
+ return -ENODEV;
+ filp->f_op = chrdev_fops[i];
+ if (filp->f_op->open)
+ return filp->f_op->open(inode,filp);
+ return 0;
+}
+
+/*
+ * Dummy default file-operations: the only thing this does
+ * is contain the open that then fills in the correct operations
+ * depending on the special file...
+ */
+struct file_operations def_chr_fops = {
+ NULL, /* lseek */
+ NULL, /* read */
+ NULL, /* write */
+ NULL, /* readdir */
+ NULL, /* select */
+ NULL, /* ioctl */
+ NULL, /* mmap */
+ chrdev_open, /* open */
+ NULL, /* release */
+};
+
+struct inode_operations chrdev_inode_operations = {
+ &def_chr_fops, /* default file operations */
+ NULL, /* create */
+ NULL, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ NULL, /* readlink */
+ NULL, /* follow_link */
+ NULL, /* bmap */
+ NULL, /* truncate */
+ NULL /* permission */
+};
$(AS) -o $*.o $<
OBJS= freelists.o truncate.o namei.o inode.o \
- file.o dir.o symlink.o blkdev.o chrdev.o fifo.o
+ file.o dir.o symlink.o
ext.o: $(OBJS)
$(LD) -r -o ext.o $(OBJS)
+++ /dev/null
-/*
- * linux/fs/ext/blkdev.c
- *
- * Copyright (C) 1992 Remy Card (card@masi.ibp.fr)
- *
- * from
- *
- * linux/fs/minix/blkdev.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- */
-
-#include <linux/sched.h>
-#include <linux/ext_fs.h>
-#include <linux/tty.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <linux/errno.h>
-
-/*
- * Called every time an ext block special file is opened
- */
-static int blkdev_open(struct inode * inode, struct file * filp)
-{
- int i;
-
- i = MAJOR(inode->i_rdev);
- if (i >= MAX_BLKDEV || !blkdev_fops[i])
- return -ENODEV;
- filp->f_op = blkdev_fops[i];
- if (filp->f_op->open)
- return filp->f_op->open(inode,filp);
- return 0;
-}
-
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the special file...
- */
-static struct file_operations def_blk_fops = {
- NULL, /* lseek */
- NULL, /* read */
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* select */
- NULL, /* ioctl */
- NULL, /* mmap */
- blkdev_open, /* open */
- NULL, /* release */
-};
-
-struct inode_operations ext_blkdev_inode_operations = {
- &def_blk_fops, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* bmap */
- NULL, /* truncate */
- NULL /* permission */
-};
+++ /dev/null
-/*
- * linux/fs/ext/chrdev.c
- *
- * Copyright (C) 1992 Remy Card (card@masi.ibp.fr)
- *
- * from
- *
- * linux/fs/minix/chrdev.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- */
-
-#include <linux/sched.h>
-#include <linux/ext_fs.h>
-#include <linux/tty.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <linux/errno.h>
-
-/*
- * Called every time an ext character special file is opened
- */
-static int chrdev_open(struct inode * inode, struct file * filp)
-{
- int i;
-
- i = MAJOR(inode->i_rdev);
- if (i >= MAX_CHRDEV || !chrdev_fops[i])
- return -ENODEV;
- filp->f_op = chrdev_fops[i];
- if (filp->f_op->open)
- return filp->f_op->open(inode,filp);
- return 0;
-}
-
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the special file...
- */
-static struct file_operations def_chr_fops = {
- NULL, /* lseek */
- NULL, /* read */
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* select */
- NULL, /* ioctl */
- NULL, /* mmap */
- chrdev_open, /* open */
- NULL, /* release */
-};
-
-struct inode_operations ext_chrdev_inode_operations = {
- &def_chr_fops, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* bmap */
- NULL, /* truncate */
- NULL /* permission */
-};
-
NULL, /* ioctl - default */
NULL, /* mmap */
NULL, /* no special open code */
- NULL /* no special release code */
+ NULL, /* no special release code */
+ NULL /* fsync */
};
/*
+++ /dev/null
-/*
- * linux/fs/fifo.c
- *
- * written by Paul H. Hargrove.
- */
-
-#include <linux/sched.h>
-#include <linux/ext_fs.h>
-
-extern struct file_operations def_fifo_fops;
-
-struct inode_operations ext_fifo_inode_operations = {
- &def_fifo_fops, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* bmap */
- NULL, /* truncate */
- NULL /* permission */
-};
NULL, /* ioctl - default */
NULL, /* mmap */
NULL, /* no special open is needed */
- NULL /* release */
+ NULL, /* release */
+ NULL /* fsync */
};
struct inode_operations ext_file_inode_operations = {
else if (S_ISLNK(inode->i_mode))
inode->i_op = &ext_symlink_inode_operations;
else if (S_ISCHR(inode->i_mode))
- inode->i_op = &ext_chrdev_inode_operations;
+ inode->i_op = &chrdev_inode_operations;
else if (S_ISBLK(inode->i_mode))
- inode->i_op = &ext_blkdev_inode_operations;
+ inode->i_op = &blkdev_inode_operations;
else if (S_ISFIFO(inode->i_mode)) {
- inode->i_op = &ext_fifo_inode_operations;
+ inode->i_op = &fifo_inode_operations;
inode->i_pipe = 1;
PIPE_BASE(*inode) = NULL;
PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
else if (S_ISLNK(inode->i_mode))
inode->i_op = &ext_symlink_inode_operations;
else if (S_ISCHR(inode->i_mode))
- inode->i_op = &ext_chrdev_inode_operations;
+ inode->i_op = &chrdev_inode_operations;
else if (S_ISBLK(inode->i_mode))
- inode->i_op = &ext_blkdev_inode_operations;
+ inode->i_op = &blkdev_inode_operations;
else if (S_ISFIFO(inode->i_mode)) {
- inode->i_op = &ext_fifo_inode_operations;
+ inode->i_op = &fifo_inode_operations;
inode->i_pipe = 1;
PIPE_BASE(*inode) = NULL;
PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
NULL,
NULL,
fifo_open, /* will set read or write pipe_fops */
+ NULL,
NULL
};
+
+struct inode_operations fifo_inode_operations = {
+ &def_fifo_fops, /* default file operations */
+ NULL, /* create */
+ NULL, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ NULL, /* readlink */
+ NULL, /* follow_link */
+ NULL, /* bmap */
+ NULL, /* truncate */
+ NULL /* permission */
+};
struct inode * inode;
for(inode = 0+inode_table ; inode < NR_INODE+inode_table ; inode++) {
+ if (dev && inode->i_dev != dev)
+ continue;
wait_on_inode(inode);
if (inode->i_dirt)
write_inode(inode);
.s.o:
$(AS) -o $*.o $<
-OBJS= namei.o inode.o file.o dir.o util.o rock.o symlink.o \
- fifo.o blkdev.o chrdev.o
+OBJS= namei.o inode.o file.o dir.o util.o rock.o symlink.o
isofs.o: $(OBJS)
$(LD) -r -o isofs.o $(OBJS)
+++ /dev/null
-/*
- * linux/fs/isofs/blkdev.c
- *
- * (C) 1992 Eric Youngdale Modified for ISO9660 filesystem.
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * isofs blkdev handling code. This is only used with the Rock Ridge
- * extensions to iso9660
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/iso_fs.h>
-#include <linux/tty.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-
-/*
- * Called every time a isofs block special file is opened
- */
-static int blkdev_open(struct inode * inode, struct file * filp)
-{
- int i;
-
- i = MAJOR(inode->i_rdev);
- if (i >= MAX_BLKDEV || !blkdev_fops[i])
- return -ENODEV;
- filp->f_op = blkdev_fops[i];
- if (filp->f_op->open)
- return filp->f_op->open(inode,filp);
- return 0;
-}
-
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the special file...
- */
-static struct file_operations def_blk_fops = {
- NULL, /* lseek */
- NULL, /* read */
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* select */
- NULL, /* ioctl */
- NULL, /* mmap */
- blkdev_open, /* open */
- NULL, /* release */
-};
-
-struct inode_operations isofs_blkdev_inode_operations = {
- &def_blk_fops, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- isofs_bmap, /* bmap */
- NULL, /* truncate */
- NULL /* permission */
-};
+++ /dev/null
-/*
- * linux/fs/isofs/chrdev.c
- *
- * (C) 1992 Eric Youngdale Modified for ISO9660 filesystem.
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * isofs chrdev handling code. This is only used with the Rock Ridge
- * extensions to iso9660
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/iso_fs.h>
-#include <linux/tty.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-
-/*
- * Called every time a isofs character special file is opened
- */
-static int chrdev_open(struct inode * inode, struct file * filp)
-{
- int i;
-
- i = MAJOR(inode->i_rdev);
- if (i >= MAX_CHRDEV || !chrdev_fops[i])
- return -ENODEV;
- filp->f_op = chrdev_fops[i];
- if (filp->f_op->open)
- return filp->f_op->open(inode,filp);
- return 0;
-}
-
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the special file...
- */
-static struct file_operations def_chr_fops = {
- NULL, /* lseek */
- NULL, /* read */
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* select */
- NULL, /* ioctl */
- NULL, /* mmap */
- chrdev_open, /* open */
- NULL, /* release */
-};
-
-struct inode_operations isofs_chrdev_inode_operations = {
- &def_chr_fops, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- isofs_bmap, /* bmap */
- NULL, /* truncate */
- NULL /* permission */
-};
-
NULL, /* select - default */
NULL, /* ioctl - default */
NULL, /* no special open code */
- NULL /* no special release code */
+ NULL, /* no special release code */
+ NULL /* fsync */
};
/*
+++ /dev/null
-/*
- * linux/fs/fifo.c
- *
- * written by Paul H. Hargrove
- */
-
-#include <linux/sched.h>
-#include <linux/iso_fs.h>
-
-extern struct file_operations def_fifo_fops;
-
-struct inode_operations isofs_fifo_inode_operations = {
- &def_fifo_fops, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* bmap */
- NULL, /* truncate */
- NULL /* permission */
-};
NULL, /* select - default */
NULL, /* ioctl - default */
NULL, /* no special open is needed */
- NULL /* release */
+ NULL, /* release */
+ NULL /* fsync */
};
struct inode_operations isofs_file_inode_operations = {
else if (S_ISLNK(inode->i_mode))
inode->i_op = &isofs_symlink_inode_operations;
else if (S_ISCHR(inode->i_mode))
- inode->i_op = &isofs_chrdev_inode_operations;
+ inode->i_op = &chrdev_inode_operations;
else if (S_ISBLK(inode->i_mode))
- inode->i_op = &isofs_blkdev_inode_operations;
+ inode->i_op = &blkdev_inode_operations;
else if (S_ISFIFO(inode->i_mode)) {
- inode->i_op = &isofs_fifo_inode_operations;
+ inode->i_op = &fifo_inode_operations;
inode->i_pipe = 1;
PIPE_BASE(*inode) = NULL;
PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
$(AS) -o $*.o $<
OBJS= bitmap.o truncate.o namei.o inode.o \
- file.o dir.o symlink.o blkdev.o chrdev.o fifo.o
+ file.o dir.o symlink.o
minix.o: $(OBJS)
$(LD) -r -o minix.o $(OBJS)
+++ /dev/null
-/*
- * linux/fs/minix/blkdev.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/minix_fs.h>
-#include <linux/tty.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-
-/*
- * Called every time a minix block special file is opened
- */
-static int blkdev_open(struct inode * inode, struct file * filp)
-{
- int i;
-
- i = MAJOR(inode->i_rdev);
- if (i >= MAX_BLKDEV || !blkdev_fops[i])
- return -ENODEV;
- filp->f_op = blkdev_fops[i];
- if (filp->f_op->open)
- return filp->f_op->open(inode,filp);
- return 0;
-}
-
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the special file...
- */
-static struct file_operations def_blk_fops = {
- NULL, /* lseek */
- NULL, /* read */
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* select */
- NULL, /* ioctl */
- NULL, /* mmap */
- blkdev_open, /* open */
- NULL, /* release */
-};
-
-struct inode_operations minix_blkdev_inode_operations = {
- &def_blk_fops, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* bmap */
- NULL, /* truncate */
- NULL /* permission */
-};
+++ /dev/null
-/*
- * linux/fs/minix/chrdev.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/minix_fs.h>
-#include <linux/tty.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-
-/*
- * Called every time a minix character special file is opened
- */
-static int chrdev_open(struct inode * inode, struct file * filp)
-{
- int i;
-
- i = MAJOR(inode->i_rdev);
- if (i >= MAX_CHRDEV || !chrdev_fops[i])
- return -ENODEV;
- filp->f_op = chrdev_fops[i];
- if (filp->f_op->open)
- return filp->f_op->open(inode,filp);
- return 0;
-}
-
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the special file...
- */
-static struct file_operations def_chr_fops = {
- NULL, /* lseek */
- NULL, /* read */
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* select */
- NULL, /* ioctl */
- NULL, /* mmap */
- chrdev_open, /* open */
- NULL, /* release */
-};
-
-struct inode_operations minix_chrdev_inode_operations = {
- &def_chr_fops, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* bmap */
- NULL, /* truncate */
- NULL /* permission */
-};
-
NULL, /* ioctl - default */
NULL, /* mmap */
NULL, /* no special open code */
- NULL /* no special release code */
+ NULL, /* no special release code */
+ NULL /* default fsync */
};
/*
+++ /dev/null
-/*
- * linux/fs/fifo.c
- *
- * written by Paul H. Hargrove
- */
-
-#include <linux/sched.h>
-#include <linux/minix_fs.h>
-
-extern struct file_operations def_fifo_fops;
-
-struct inode_operations minix_fifo_inode_operations = {
- &def_fifo_fops, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* bmap */
- NULL, /* truncate */
- NULL /* permission */
-};
NULL, /* ioctl - default */
NULL, /* mmap */
NULL, /* no special open is needed */
- NULL /* release */
+ NULL, /* release */
+ NULL /* fsync */
};
struct inode_operations minix_file_inode_operations = {
else if (S_ISLNK(inode->i_mode))
inode->i_op = &minix_symlink_inode_operations;
else if (S_ISCHR(inode->i_mode))
- inode->i_op = &minix_chrdev_inode_operations;
+ inode->i_op = &chrdev_inode_operations;
else if (S_ISBLK(inode->i_mode))
- inode->i_op = &minix_blkdev_inode_operations;
+ inode->i_op = &blkdev_inode_operations;
else if (S_ISFIFO(inode->i_mode)) {
- inode->i_op = &minix_fifo_inode_operations;
+ inode->i_op = &fifo_inode_operations;
inode->i_pipe = 1;
PIPE_BASE(*inode) = NULL;
PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
}
block = 2 + inode->i_sb->u.minix_sb.s_imap_blocks + inode->i_sb->u.minix_sb.s_zmap_blocks +
(ino-1)/MINIX_INODES_PER_BLOCK;
- if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE)))
- panic("unable to read i-node block");
+ if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE))) {
+ printk("unable to read i-node block\n");
+ inode->i_dirt = 0;
+ return;
+ }
raw_inode = ((struct minix_inode *)bh->b_data) +
(ino-1)%MINIX_INODES_PER_BLOCK;
raw_inode->i_mode = inode->i_mode;
else if (S_ISLNK(inode->i_mode))
inode->i_op = &minix_symlink_inode_operations;
else if (S_ISCHR(inode->i_mode))
- inode->i_op = &minix_chrdev_inode_operations;
+ inode->i_op = &chrdev_inode_operations;
else if (S_ISBLK(inode->i_mode))
- inode->i_op = &minix_blkdev_inode_operations;
+ inode->i_op = &blkdev_inode_operations;
else if (S_ISFIFO(inode->i_mode)) {
- inode->i_op = &minix_fifo_inode_operations;
+ inode->i_op = &fifo_inode_operations;
inode->i_pipe = 1;
PIPE_BASE(*inode) = NULL;
PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
NULL, /* ioctl - default */
NULL, /* mmap */
NULL, /* no special open code */
- NULL /* no special release code */
+ NULL, /* no special release code */
+ NULL /* fsync */
};
struct inode_operations msdos_dir_inode_operations = {
NULL, /* ioctl - default */
NULL, /* mmap */
NULL, /* no special open is needed */
- NULL /* release */
+ NULL, /* release */
+ NULL /* fsync */
};
struct inode_operations msdos_file_inode_operations = {
$(AS) -o $*.o $<
OBJS= proc.o sock.o inode.o file.o dir.o \
- symlink.o blkdev.o chrdev.o fifo.o
+ symlink.o
nfs.o: $(OBJS)
$(LD) -r -o nfs.o $(OBJS)
+++ /dev/null
-/*
- * linux/fs/nfs/blkdev.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/nfs_fs.h>
-#include <linux/tty.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-
-/*
- * Called every time a nfs block special file is opened
- */
-static int blkdev_open(struct inode * inode, struct file * filp)
-{
- int i;
-
- i = MAJOR(inode->i_rdev);
- if (i >= MAX_BLKDEV || !blkdev_fops[i])
- return -ENODEV;
- filp->f_op = blkdev_fops[i];
- if (filp->f_op->open)
- return filp->f_op->open(inode,filp);
- return 0;
-}
-
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the special file...
- */
-static struct file_operations def_blk_fops = {
- NULL, /* lseek */
- NULL, /* read */
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* select */
- NULL, /* ioctl */
- NULL, /* mmap */
- blkdev_open, /* open */
- NULL, /* release */
-};
-
-struct inode_operations nfs_blkdev_inode_operations = {
- &def_blk_fops, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* bmap */
- NULL, /* truncate */
- NULL /* permission */
-};
+++ /dev/null
-/*
- * linux/fs/nfs/chrdev.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/nfs_fs.h>
-#include <linux/tty.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-
-/*
- * Called every time a nfs character special file is opened
- */
-static int chrdev_open(struct inode * inode, struct file * filp)
-{
- int i;
-
- i = MAJOR(inode->i_rdev);
- if (i >= MAX_CHRDEV || !chrdev_fops[i])
- return -ENODEV;
- filp->f_op = chrdev_fops[i];
- if (filp->f_op->open)
- return filp->f_op->open(inode,filp);
- return 0;
-}
-
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the special file...
- */
-static struct file_operations def_chr_fops = {
- NULL, /* lseek */
- NULL, /* read */
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* select */
- NULL, /* ioctl */
- NULL, /* mmap */
- chrdev_open, /* open */
- NULL, /* release */
-};
-
-struct inode_operations nfs_chrdev_inode_operations = {
- &def_chr_fops, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* bmap */
- NULL, /* truncate */
- NULL /* permission */
-};
-
NULL, /* ioctl - default */
NULL, /* mmap */
NULL, /* no special open code */
- NULL /* no special release code */
+ NULL, /* no special release code */
+ NULL /* fsync */
};
struct inode_operations nfs_dir_inode_operations = {
else if (S_ISLNK(inode->i_mode))
inode->i_op = &nfs_symlink_inode_operations;
else if (S_ISCHR(inode->i_mode))
- inode->i_op = &nfs_chrdev_inode_operations;
+ inode->i_op = &chrdev_inode_operations;
else if (S_ISBLK(inode->i_mode))
- inode->i_op = &nfs_blkdev_inode_operations;
+ inode->i_op = &blkdev_inode_operations;
else if (S_ISFIFO(inode->i_mode)) {
- inode->i_op = &nfs_fifo_inode_operations;
+ inode->i_op = &fifo_inode_operations;
inode->i_pipe = 1;
PIPE_BASE(*inode) = NULL;
PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
+++ /dev/null
-/*
- * linux/fs/fifo.c
- *
- * written by Paul H. Hargrove
- */
-
-#include <linux/sched.h>
-#include <linux/nfs_fs.h>
-
-extern struct file_operations def_fifo_fops;
-
-struct inode_operations nfs_fifo_inode_operations = {
- &def_fifo_fops, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* bmap */
- NULL, /* truncate */
- NULL /* permission */
-};
NULL, /* ioctl - default */
NULL, /* mmap */
NULL, /* no special open is needed */
- NULL /* release */
+ NULL, /* release */
+ NULL /* fsync */
};
struct inode_operations nfs_file_inode_operations = {
extern void fcntl_remove_locks(struct task_struct *, struct file *);
-struct file_operations * chrdev_fops[MAX_CHRDEV] = {
- NULL,
-};
-
-struct file_operations * blkdev_fops[MAX_BLKDEV] = {
- NULL,
-};
-
int sys_ustat(int dev, struct ustat * ubuf)
{
return -ENOSYS;
}
/*
- * This routine is used by vhangup. It send's sigkill to everything
- * waiting on a particular wait_queue. It assumes root privledges.
- * We don't want to destroy the wait queue here, because the caller
- * should call wake_up immediately after calling kill_wait.
- */
-static void kill_wait(struct wait_queue **q, int sig)
-{
- struct wait_queue *next;
- struct wait_queue *tmp;
- struct task_struct *p;
-
- if (!q || !(next = *q))
- return;
- do {
- tmp = next;
- next = tmp->next;
- if ((p = tmp->task) != NULL)
- send_sig (sig, p , 1);
- } while (next && next != *q);
-}
-
-/*
- * This routine looks through all the process's and closes any
- * references to the current processes tty. To avoid problems with
- * process sleeping on an inode which has already been iput, anyprocess
- * which is sleeping on the tty is sent a sigkill (It's probably a rogue
- * process.) Also no process should ever have /dev/console as it's
- * controlling tty, or have it open for reading. So we don't have to
- * worry about messing with all the daemons abilities to write messages
- * to the console. (Besides they should be using syslog.)
+ * This routine simulates a hangup on the tty, to arrange that users
+ * are given clean terminals at login time.
*/
int sys_vhangup(void)
{
- int j;
- struct task_struct ** process;
- struct file *filep;
- struct inode *inode;
struct tty_struct *tty;
- extern int kill_pg (int pgrp, int sig, int priv);
if (!suser())
return -EPERM;
/* See if there is a controlling tty. */
if (current->tty < 0)
return 0;
- /* send the SIGHUP signal. */
- tty = TTY_TABLE(current->tty);
- if (tty && tty->pgrp > 0)
- kill_pg(tty->pgrp, SIGHUP, 0);
-
- for (process = task + 0; process < task + NR_TASKS; process++) {
- for (j = 0; j < NR_OPEN; j++) {
- if (!*process)
- break;
- if (!(filep = (*process)->filp[j]))
- continue;
- if (!(inode = filep->f_inode))
- continue;
- if (!S_ISCHR(inode->i_mode))
- continue;
- if ((MAJOR(inode->i_rdev) == 5 ||
- MAJOR(inode->i_rdev) == 4 ) &&
- (MAJOR(filep->f_rdev) == 4 &&
- MINOR(filep->f_rdev) == MINOR (current->tty))) {
- /* so now we have found something to close. We
- need to kill every process waiting on the
- inode. */
- (*process)->filp[j] = NULL;
- kill_wait (&inode->i_wait, SIGKILL);
-
- /* now make sure they are awake before we close the
- file. */
-
- wake_up (&inode->i_wait);
-
- /* finally close the file. */
-
- FD_CLR(j, &(*process)->close_on_exec);
- close_fp (filep);
- }
- }
- /* can't let them keep a reference to it around.
- But we can't touch current->tty until after the
- loop is complete. */
-
- if (*process && (*process)->tty == current->tty && *process != current) {
- (*process)->tty = -1;
- }
- }
- /* need to do tty->session = 0 */
tty = TTY_TABLE(MINOR(current->tty));
- if (tty) {
- tty->session = 0;
- tty->pgrp = -1;
- current->tty = -1;
- }
+ tty_hangup(tty);
return 0;
}
-
pipe_ioctl,
NULL, /* no mmap on pipes.. surprise */
NULL, /* no special open code */
- pipe_read_release
+ pipe_read_release,
+ NULL
};
struct file_operations write_pipe_fops = {
pipe_ioctl,
NULL, /* mmap */
NULL, /* no special open code */
- pipe_write_release
+ pipe_write_release,
+ NULL
};
struct file_operations rdwr_pipe_fops = {
pipe_ioctl,
NULL, /* mmap */
NULL, /* no special open code */
- pipe_rdwr_release
+ pipe_rdwr_release,
+ NULL
};
int sys_pipe(unsigned long * fildes)
{
struct task_struct ** p = get_task(pid);
unsigned long sigignore=0, sigcatch=0, bit=1, wchan;
- int i;
+ int i,tty_pgrp;
char state;
if (!p || !*p)
default: sigcatch |= bit;
} bit <<= 1;
}
+ tty_pgrp = (*p)->tty;
+ if (tty_pgrp > 0 && tty_table[tty_pgrp])
+ tty_pgrp = tty_table[tty_pgrp]->pgrp;
+ else
+ tty_pgrp = -1;
return sprintf(buffer,"%d (%s) %c %d %d %d %d %d %u %u \
%u %u %u %d %d %d %d %d %d %u %u %d %u %u %u %u %u %u %u %u %d \
%d %d %d %u\n",
(*p)->pgrp,
(*p)->session,
(*p)->tty,
- ((*p)->tty == -1) ? -1 :
- tty_table[(*p)->tty]->pgrp,
+ tty_pgrp,
(*p)->flags,
(*p)->min_flt,
(*p)->cmin_flt,
NULL, /* array_ioctl */
NULL, /* mmap */
NULL, /* no special open code */
- NULL /* no special release code */
+ NULL, /* no special release code */
+ NULL /* can't fsync */
};
struct inode_operations proc_array_inode_operations = {
NULL, /* ioctl - default */
NULL, /* mmap */
NULL, /* no special open code */
- NULL /* no special release code */
+ NULL, /* no special release code */
+ NULL /* can't fsync */
};
/*
NULL, /* ioctl - default */
NULL, /* mmap */
NULL, /* no special open code */
- NULL /* no special release code */
+ NULL, /* no special release code */
+ NULL /* can't fsync */
};
/*
NULL, /* kmsg_ioctl */
NULL, /* mmap */
kmsg_open,
- kmsg_release
+ kmsg_release,
+ NULL /* can't fsync */
};
struct inode_operations proc_kmsg_inode_operations = {
NULL, /* mem_ioctl */
NULL, /* mmap */
NULL, /* no special open code */
- NULL /* no special release code */
+ NULL, /* no special release code */
+ NULL /* can't fsync */
};
struct inode_operations proc_mem_inode_operations = {
NULL, /* ioctl - default */
NULL, /* mmap */
NULL, /* no special open code */
- NULL /* no special release code */
+ NULL, /* no special release code */
+ NULL /* no fsync */
};
/*
*/
extern struct file_system_type file_systems[];
+extern struct file_operations * blkdev_fops[];
extern void wait_for_keypress(void);
extern void fcntl_init_locks(void);
for (sb = super_block + 0 ; sb < super_block + NR_SUPER ; sb++) {
if (!sb->s_dev)
continue;
+ if (dev && sb->s_dev != dev)
+ continue;
wait_on_super(sb);
if (!sb->s_dev || !sb->s_dirt)
continue;
#ifndef _LINUX_DIRENT_H
#define _LINUX_DIRENT_H
+#include <linux/limits.h>
+
struct dirent {
long d_ino;
off_t d_off;
#define FDFMTTRK 7 /* format the specified track */
#define FDFMTEND 8 /* end formatting a disk */
#define FDSETEMSGTRESH 10 /* set fdc error reporting treshold */
+#define FDFLUSH 11 /* flush buffers for media; either for verifying media, or for
+ handling a media change without closing the file
+ descriptor */
#define FD_FILL_BYTE 0xF6 /* format fill byte */
*
* Exception: MS_RDONLY is always applied to the entire file system.
*/
-#define IS_RDONLY(inode) ((inode)->i_sb->s_flags & MS_RDONLY)
+#define IS_RDONLY(inode) (((inode)->i_sb) && ((inode)->i_sb->s_flags & MS_RDONLY))
#define IS_NOSUID(inode) ((inode)->i_flags & MS_NOSUID)
#define IS_NODEV(inode) ((inode)->i_flags & MS_NODEV)
#define IS_NOEXEC(inode) ((inode)->i_flags & MS_NOEXEC)
int (*mmap) (void);
int (*open) (struct inode *, struct file *);
void (*release) (struct inode *, struct file *);
+ int (*fsync) (struct inode *, struct file *);
};
struct inode_operations {
int requires_dev;
};
-extern struct file_operations * chrdev_fops[MAX_CHRDEV];
-extern struct file_operations * blkdev_fops[MAX_BLKDEV];
+extern int register_blkdev(unsigned int, const char *, struct file_operations *);
+extern int blkdev_open(struct inode * inode, struct file * filp);
+extern struct file_operations def_blk_fops;
+extern struct inode_operations blkdev_inode_operations;
+
+extern int register_chrdev(unsigned int, const char *, struct file_operations *);
+extern int chrdev_open(struct inode * inode, struct file * filp);
+extern struct file_operations def_chr_fops;
+extern struct inode_operations chrdev_inode_operations;
+
+extern struct inode_operations fifo_inode_operations;
extern struct file_system_type *get_fs_type(char *name);
/*
* INIT_TASK is used to set up the first task table, touch at
- * your own risk!. Base=0, limit=0x9ffff (=640kB)
+ * your own risk!. Base=0, limit=0x1fffff (=2MB)
*/
#define INIT_TASK \
/* state etc */ { 0,15,15, \
/* cloe */ {{ 0, }}, \
{ \
{0,0}, \
-/* ldt */ {0x9f,0xc0c0fa00}, \
- {0x9f,0xc0c0f200}, \
+/* ldt */ {0x1ff,0xc0c0fa00}, \
+ {0x1ff,0xc0c0f200}, \
}, \
/*tss*/ {0,sizeof(init_kernel_stack) + (long) &init_kernel_stack, \
0x10,0,0,0,0,(long) &swapper_pg_dir,\
#define START_CHAR(tty) ((tty)->termios->c_cc[VSTART])
#define STOP_CHAR(tty) ((tty)->termios->c_cc[VSTOP])
#define SUSPEND_CHAR(tty) ((tty)->termios->c_cc[VSUSP])
+#define LNEXT_CHAR(tty) ((tty)->termios->c_cc[VLNEXT])
#define _L_FLAG(tty,f) ((tty)->termios->c_lflag & f)
#define _I_FLAG(tty,f) ((tty)->termios->c_iflag & f)
struct termios *termios;
int pgrp;
int session;
- unsigned char stopped:1, status_changed:1, packet:1;
+ unsigned char stopped:1, status_changed:1, packet:1, lnext:1;
unsigned char ctrl_status;
short line;
int disc;
if (memory_end > 16*1024*1024)
memory_end = 16*1024*1024;
#endif
- memory_start = 1024*1024;
- low_memory_start = (unsigned long) &end;
+ if ((unsigned long)&end >= (1024*1024)) {
+ memory_start = (unsigned long) &end;
+ low_memory_start = 4096;
+ } else {
+ memory_start = 1024*1024;
+ low_memory_start = (unsigned long) &end;
+ }
low_memory_start += 0xfff;
low_memory_start &= 0xfffff000;
memory_start = paging_init(memory_start,memory_end);
*/
if (hard_math) {
unsigned short control_word;
+
+ printk("Checking for 387 error mechanism ...");
__asm__("fninit ; fnstcw %0 ; fwait":"=m" (*&control_word));
control_word &= 0xffc0;
__asm__("fldcw %0 ; fwait"::"m" (*&control_word));
outb_p(inb_p(0x21) | (1 << 2), 0x21);
__asm__("fldz ; fld1 ; fdiv %st,%st(1) ; fwait");
+ printk(" ok, using %s.\n",ignore_irq13?"exception 16":"irq13");
}
move_to_user_mode();
if (!fork()) /* we count on this going ok */
sync
clean:
- rm -f core *.o *.a *.s *~
+ rm -f core *.o *.a *.s
dep:
$(CPP) -M *.c *.S > .depend
/* Convert to a QNaN */
FPU_st0_ptr->sigh |= 0x40000000;
}
+ break; /* return with a NaN in st(0) */
case TW_Empty:
- stack_underflow();
+ stack_underflow(); /* Puts a QNaN in st(0) */
+ break;
#ifdef PARANOID
default:
EXCEPTION(EX_INTERNAL|0x0112);
#include "exception.h"
#include "reg_constant.h"
#include "fpu_emu.h"
-
+#include "control_w.h"
+#include "fpu_system.h"
void reg_add(FPU_REG *a, FPU_REG *b, FPU_REG *dest)
{
diff = a->sigh - b->sigh; /* Works only if ms bits are identical */
if (!diff)
- diff = a->sigl > b->sigl;
+ {
+ diff = a->sigl > b->sigl;
+ if (!diff)
+ diff = -(a->sigl < b->sigl);
+ }
}
if (diff > 0)
{
reg_u_sub(a, b, dest);
dest->sign = a->sign;
- return;
+ }
+ else if ( diff == 0 )
+ {
+ reg_move(&CONST_Z, dest);
+ /* sign depends upon rounding mode */
+ dest->sign = ((control_word & CW_RC) != RC_DOWN)
+ ? SIGN_POS : SIGN_NEG;
}
else
{
reg_u_sub(b, a, dest);
dest->sign = b->sign;
- return;
}
+ return;
}
else
{
if ( (a->tag == TW_NaN) || (b->tag == TW_NaN) )
{ real_2op_NaN(a, b, dest); return; }
else if (a->tag == TW_Zero)
- { reg_move(b, dest); return; }
+ {
+ if (b->tag == TW_Zero)
+ {
+ char different_signs = a->sign ^ b->sign;
+ /* Both are zero, result will be zero. */
+ reg_move(a, dest);
+ if (different_signs)
+ {
+ /* Signs are different. */
+ /* Sign of answer depends upon rounding mode. */
+ dest->sign = ((control_word & CW_RC) != RC_DOWN)
+ ? SIGN_POS : SIGN_NEG;
+ }
+ }
+ else
+ reg_move(b, dest);
+ return;
+ }
else if (b->tag == TW_Zero)
{ reg_move(a, dest); return; }
else if (a->tag == TW_Infinity)
{
diff = a->sigh - b->sigh; /* Works only if ms bits are identical */
if (!diff)
- diff = a->sigl > b->sigl;
+ {
+ diff = a->sigl > b->sigl;
+ if (!diff)
+ diff = -(a->sigl < b->sigl);
+ }
}
switch (a->sign*2 + b->sign)
reg_u_sub(a, b, dest);
dest->sign = a->sign;
}
+ else if ( diff == 0 )
+ {
+ reg_move(&CONST_Z, dest);
+ /* sign depends upon rounding mode */
+ dest->sign = ((control_word & CW_RC) != RC_DOWN)
+ ? SIGN_POS : SIGN_NEG;
+ }
else
{
reg_u_sub(b, a, dest);
if ( (a->tag == TW_NaN) || (b->tag == TW_NaN) )
{ real_2op_NaN(a, b, dest); return; }
else if (b->tag == TW_Zero)
- { reg_move(a, dest); return; }
+ {
+ if (a->tag == TW_Zero)
+ {
+ char same_signs = !(a->sign ^ b->sign);
+ /* Both are zero, result will be zero. */
+ reg_move(a, dest); /* Answer for different signs. */
+ if (same_signs)
+ {
+ /* Sign depends upon rounding mode */
+ dest->sign = ((control_word & CW_RC) != RC_DOWN)
+ ? SIGN_POS : SIGN_NEG;
+ }
+ }
+ else
+ reg_move(a, dest);
+ return;
+ }
else if (a->tag == TW_Zero)
{
reg_move(b, dest);
| |
+---------------------------------------------------------------------------*/
-#define FPU_VERSION "wm-FPU-emu version BETA 1.0"
+#define FPU_VERSION "wm-FPU-emu version BETA 1.1"
#ifndef _BLK_H
#define _BLK_H
-#define NR_BLK_DEV 12
+#include <linux/fs.h>
+
/*
* NR_REQUEST is the number of entries in the request-queue.
* NOTE that writes may use only the low 2/3 of these: reads
#define SECTOR_MASK ((1 << (BLOCK_SIZE_BITS - 9)) -1)
#define SUBSECTOR(block) ((block) & SECTOR_MASK)
-extern struct sec_size * blk_sec[NR_BLK_DEV];
-extern struct blk_dev_struct blk_dev[NR_BLK_DEV];
+extern struct sec_size * blk_sec[MAX_BLKDEV];
+extern struct blk_dev_struct blk_dev[MAX_BLKDEV];
extern struct request request[NR_REQUEST];
extern struct wait_queue * wait_for_request;
-extern int * blk_size[NR_BLK_DEV];
+extern int * blk_size[MAX_BLKDEV];
extern unsigned long hd_init(unsigned long mem_start, unsigned long mem_end);
extern int is_read_only(int dev);
format_status = FORMAT_NONE;
wake_up(&format_done);
return okay ? 0 : -EIO;
+ case FDFLUSH:
+ if (!permission(inode, 2))
+ return -EPERM;
+ cli();
+ fake_change |= 1 << (drive & 3);
+ sti();
+ check_disk_change(inode->i_rdev);
+ return 0;
}
if (!suser())
return -EPERM;
}
#define CMOS_READ(addr) ({ \
-outb_p(0x80|addr,0x70); \
+outb_p(addr,0x70); \
inb_p(0x71); \
})
void floppy_init(void)
{
outb(current_DOR,FD_DOR);
+ if (register_blkdev(MAJOR_NR,"fd",&floppy_fops)) {
+ printk("Unable to get major %d for floppy\n",MAJOR_NR);
+ return;
+ }
blk_size[MAJOR_NR] = floppy_sizes;
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
- blkdev_fops[MAJOR_NR] = &floppy_fops;
timer_table[FLOPPY_TIMER].fn = floppy_shutdown;
timer_active &= ~(1 << FLOPPY_TIMER);
config_types();
static inline unsigned char CMOS_READ(unsigned char addr)
{
- outb_p(0x80|addr,0x70);
+ outb_p(addr,0x70);
return inb_p(0x71);
}
unsigned long hd_init(unsigned long mem_start, unsigned long mem_end)
{
+ if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
+ printk("Unable to get major %d for harddisk\n",MAJOR_NR);
+ return mem_start;
+ }
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
- blkdev_fops[MAJOR_NR] = &hd_fops;
read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read-ahead */
hd_gendisk.next = gendisk_head;
gendisk_head = &hd_gendisk;
/* This specifies how many sectors to read ahead on the disk. */
-int read_ahead[NR_BLK_DEV] = {0, };
+int read_ahead[MAX_BLKDEV] = {0, };
/* blk_dev_struct is:
* do_request-address
* next-request
*/
-struct blk_dev_struct blk_dev[NR_BLK_DEV] = {
+struct blk_dev_struct blk_dev[MAX_BLKDEV] = {
{ NULL, NULL }, /* no_dev */
{ NULL, NULL }, /* dev mem */
{ NULL, NULL }, /* dev fd */
*
* if (!blk_size[MAJOR]) then no minor size checking is done.
*/
-int * blk_size[NR_BLK_DEV] = { NULL, NULL, };
+int * blk_size[MAX_BLKDEV] = { NULL, NULL, };
/* RO fail safe mechanism */
-static long ro_bits[NR_BLK_DEV][8];
+static long ro_bits[MAX_BLKDEV][8];
int is_read_only(int dev)
{
major = MAJOR(dev);
minor = MINOR(dev);
- if (major < 0 || major >= NR_BLK_DEV) return 0;
+ if (major < 0 || major >= MAX_BLKDEV) return 0;
return ro_bits[major][minor >> 5] & (1 << (minor & 31));
}
major = MAJOR(dev);
minor = MINOR(dev);
- if (major < 0 || major >= NR_BLK_DEV) return;
+ if (major < 0 || major >= MAX_BLKDEV) return;
if (flag) ro_bits[major][minor >> 5] |= 1 << (minor & 31);
else ro_bits[major][minor >> 5] &= ~(1 << (minor & 31));
}
struct request * req;
unsigned int major = MAJOR(dev);
- if (major >= NR_BLK_DEV || !(blk_dev[major].request_fn)) {
+ if (major >= MAX_BLKDEV || !(blk_dev[major].request_fn)) {
printk("Trying to read nonexistent block-device %04x (%d)\n",dev,page*8);
return;
}
}
};
- if ((major=MAJOR(bh[0]->b_dev)) >= NR_BLK_DEV ||
+ if ((major=MAJOR(bh[0]->b_dev)) >= MAX_BLKDEV ||
!(blk_dev[major].request_fn)) {
printk("ll_rw_block: Trying to read nonexistent block-device %04x (%d)\n",bh[0]->b_dev,bh[0]->b_blocknr);
for (i=0;i<nr; i++)
struct request * req;
unsigned int major = MAJOR(dev);
- if (major >= NR_BLK_DEV || !(blk_dev[major].request_fn)) {
+ if (major >= MAX_BLKDEV || !(blk_dev[major].request_fn)) {
printk("ll_rw_swap_file: trying to swap nonexistent block-device\n\r");
return;
}
int i;
char *cp;
+ if (register_blkdev(MAJOR_NR,"rd",&rd_fops)) {
+ printk("Unable to get major %d for ramdisk\n",MAJOR_NR);
+ return 0;
+ }
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
- blkdev_fops[MAJOR_NR] = &rd_fops;
rd_start = (char *) mem_start;
rd_length = length;
cp = rd_start;
/* fdomain.c -- Future Domain TMC-1660/TMC-1680 driver
* Created: Sun May 3 18:53:19 1992 by faith
- * Revised: Sun Jan 10 01:23:29 1993 by root
+ * Revised: Thu Feb 18 21:02:12 1993 by faith@cs.unc.edu
* Author: Rickard E. Faith, faith@cs.unc.edu
* Copyright 1992, 1993 Rickard E. Faith
*
#include <asm/system.h>
#include <linux/errno.h>
-#define VERSION "3.3" /* Change with each revision */
+#define VERSION "3.5" /* Change with each revision */
/* START OF USER DEFINABLE OPTIONS */
static int can_queue = QUEUE;
static volatile int in_command = 0;
-static volatile int in_interrupt_code = 0;
static Scsi_Cmnd *current_SC = NULL;
enum { non_queueing = 0x01,
{
if (in_command) {
in_command = 0;
- in_interrupt_code = 0;
outb( 0x00, Interrupt_Cntl_port );
fdomain_make_bus_idle();
current_SC->result = error;
unsigned data_count;
sti();
-
- if (in_interrupt_code)
- panic( "SCSI (Future Domain): fdomain_16x0_intr() NOT REENTRANT!\n" );
- else
- ++in_interrupt_code;
outb( 0x00, Interrupt_Cntl_port );
+ /* We usually have one spurious interrupt after each command. Ignore it. */
+ if (!in_command || !current_SC) { /* Spurious interrupt */
+ return;
+ }
+
if (current_SC->SCp.phase & aborted) {
#if EVERY_ACCESS
if (current_SC->SCp.phase & (in_other || disconnect))
return;
}
- /* We usually have one spurious interrupt after each command. Ignore it. */
- if (!in_command) { /* Spurious interrupt */
- in_interrupt_code = 0;
- return;
- }
-
#if RESELECTION
if (current_SC->SCp.phase & disconnect) {
printk( " RECON %x ", inb( SCSI_Data_NoACK_port ) );
/* Stop arbitration (also set FIFO for output and enable parity) */
outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
- in_interrupt_code = 0;
return;
} else if (current_SC->SCp.phase & in_selection) {
status = inb( SCSI_Status_port );
}
}
current_SC->SCp.phase = in_other;
- in_interrupt_code = 0;
outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
#if RESELECTION
outb( 0x88, SCSI_Cntl_port );
#endif
} else {
- in_interrupt_code = 0;
if (current_SC->SCp.phase & disconnect) {
outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port );
outb( 0x00, SCSI_Cntl_port );
#endif
#if DEBUG_ABORT
- printk( "Phase = %d, flag = %d, target = %d cmnd = 0x%02x pieces = %d size = %u\n",
+ printk( "Phase = %d, target = %d cmnd = 0x%02x pieces = %d size = %u\n",
current_SC->SCp.phase,
- in_interrupt_code,
current_SC->target,
*(unsigned char *)current_SC->cmnd,
current_SC->use_sg,
{
int i;
- blkdev_fops[MAJOR_NR] = &sd_fops; /* to get sd_open in table */
+ if (register_blkdev(MAJOR_NR,"sd",&sd_fops)) {
+ printk("Unable to get major %d for SCSI disk\n",MAJOR_NR);
+ return memory_start;
+ }
if (MAX_SD == 0) return memory_start;
sd_sizes = (int *) memory_start;
{
int i;
- blkdev_fops[MAJOR_NR] = &sr_fops;
+ if (register_blkdev(MAJOR_NR,"sr",&sr_fops)) {
+ printk("Unable to get major %d for SCSI-CD\n",MAJOR_NR);
+ return memory_start;
+ }
if(MAX_SR == 0) return memory_start;
sr_sizes = (int *) memory_start;
{
int i;
- chrdev_fops[MAJOR_NR] = &st_fops;
+ if (register_chrdev(MAJOR_NR,"st",&st_fops)) {
+ printk("Unable to get major %d for SCSI tapes\n",MAJOR_NR);
+ return mem_start;
+ }
if (NR_ST == 0) return mem_start;
#ifdef DEBUG
}
-static const char *wd_bases[] = {
- (char *)0xde000,
- (char *)0xdc000,
- (char *)0xda000,
- (char *)0xd8000,
- (char *)0xd6000,
- (char *)0xd4000,
- (char *)0xd2000,
- (char *)0xd0000,
- (char *)0xce000,
- (char *)0xcc000,
- (char *)0xca000,
- (char *)0xc8000,
- (char *)0xc6000,
- (char *)0xc4000,
- (char *)0xc2000,
- (char *)0xc0000
- };
+static const char *wd_bases[] = {(char *)0xce000};
typedef struct {
char * signature;
unsigned offset;
"\376\245\376\376\376\376\231\376\376\376\376\376\232\376\376\341"
"\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
"\376\244\225\242\223\376\224\366\376\227\243\226\201\376\376\230",
-/* IBM grapgics: minimal translations (CR, LF, LL and ESC) */
- "\000\001\002\003\004\005\006\007\010\011\000\013\000\000\016\017"
+/* IBM grapgics: minimal translations (CR, LF, LL, SO, SI and ESC) */
+ "\000\001\002\003\004\005\006\007\010\011\000\013\000\000\000\000"
"\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
"\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
"\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
struct tty_queue *qp;
unsigned long new_head;
- wake_up_interruptible(&keypress_wait);
+ wake_up(&keypress_wait);
if (!tty)
return;
qp = &tty->read_q;
unsigned int testvalue = 0;
int count = 0;
- chrdev_fops[6] = &lp_fops;
+ if (register_chrdev(6,"lp",&lp_fops))
+ printk("unable to get major 6 for line printer\n");
/* take on all known port values */
for (offset = 0; offset < LP_NO; offset++) {
/* write to port & read back to check */
long chr_dev_init(long mem_start, long mem_end)
{
- chrdev_fops[1] = &memory_fops;
+ if (register_chrdev(1,"mem",&memory_fops))
+ printk("unable to get major 1 for memory devs\n");
mem_start = tty_init(mem_start);
mem_start = lp_init(mem_start);
mem_start = mouse_init(mem_start);
#include <linux/errno.h>
#include <linux/mouse.h>
#include <linux/config.h>
+#include <linux/kernel.h>
/*
* note that you can remove any or all of the drivers by undefining
#ifdef CONFIG_ATIXL_BUSMOUSE
kmem_start = atixl_busmouse_init(kmem_start);
#endif
- chrdev_fops[10] = &mouse_fops;
+ if (register_chrdev(10,"mouse",&mouse_fops))
+ printk("unable to get major 10 for mouse devices\n");
return kmem_start;
}
if (info->blocked_open) {
shutdown(info);
startup(info);
- wake_up_interruptible(&info->open_wait);
return;
}
if (info->flags & ASYNC_INITIALIZED) {
}
info->baud_base = new.baud_base;
- info->flags = new.flags & ASYNC_FLAGS;
+ info->flags = ((info->flags & ~ASYNC_FLAGS) |
+ (new.flags & ASYNC_FLAGS));
info->custom_divisor = new.custom_divisor;
info->type = new.type;
init(info);
if (info->type == PORT_UNKNOWN)
continue;
- printk("ttyS%d%s at 0x%04x (irq = %d)", info->line,
+ printk("tty%02d%s at 0x%04x (irq = %d)", info->line,
(info->flags & ASYNC_FOURPORT) ? " FourPort" : "",
info->port, info->irq);
switch (info->type) {
void tty_hangup(struct tty_struct * tty)
{
struct file * filp;
+ struct task_struct **p;
int dev;
if (!tty)
wake_up_interruptible(&tty->write_q.proc_list);
if (tty->session > 0)
kill_sl(tty->session,SIGHUP,1);
+ tty->session = 0;
+ tty->pgrp = -1;
+ for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
+ if ((*p) && (*p)->tty == tty->line)
+ (*p)->tty = -1;
+ }
}
void tty_unhangup(struct file *filp)
c=13;
if (I_UCLC(tty))
c=tolower(c);
- if (L_CANON(tty)) {
- if ((KILL_CHAR(tty) != __DISABLED_CHAR) &&
- (c==KILL_CHAR(tty))) {
+ if (c == __DISABLED_CHAR)
+ tty->lnext = 1;
+ if (L_CANON(tty) && !tty->lnext) {
+ if (c == KILL_CHAR(tty)) {
/* deal with killing the input line */
while(!(EMPTY(&tty->secondary) ||
(c=LAST(&tty->secondary))==10 ||
}
continue;
}
- if ((ERASE_CHAR(tty) != __DISABLED_CHAR) &&
- (c==ERASE_CHAR(tty))) {
+ if (c == ERASE_CHAR(tty)) {
if (EMPTY(&tty->secondary) ||
(c=LAST(&tty->secondary))==10 ||
((EOF_CHAR(tty) != __DISABLED_CHAR) &&
DEC(tty->secondary.head);
continue;
}
+ if (c == LNEXT_CHAR(tty)) {
+ tty->lnext = 1;
+ if (L_ECHO(tty)) {
+ put_tty_queue('^',&tty->write_q);
+ put_tty_queue(8,&tty->write_q);
+ }
+ continue;
+ }
}
- if (I_IXON(tty)) {
- if ((STOP_CHAR(tty) != __DISABLED_CHAR) &&
- (c==STOP_CHAR(tty))) {
+ if (I_IXON(tty) && !tty->lnext) {
+ if (c == STOP_CHAR(tty)) {
tty->status_changed = 1;
tty->ctrl_status |= TIOCPKT_STOP;
tty->stopped=1;
continue;
}
if (((I_IXANY(tty)) && tty->stopped) ||
- ((START_CHAR(tty) != __DISABLED_CHAR) &&
- (c==START_CHAR(tty)))) {
+ (c == START_CHAR(tty))) {
tty->status_changed = 1;
tty->ctrl_status |= TIOCPKT_START;
tty->stopped=0;
continue;
}
}
- if (L_ISIG(tty)) {
- if ((INTR_CHAR(tty) != __DISABLED_CHAR) &&
- (c==INTR_CHAR(tty))) {
+ if (L_ISIG(tty) && !tty->lnext) {
+ if (c == INTR_CHAR(tty)) {
kill_pg(tty->pgrp, SIGINT, 1);
flush_input(tty);
continue;
}
- if ((QUIT_CHAR(tty) != __DISABLED_CHAR) &&
- (c==QUIT_CHAR(tty))) {
+ if (c == QUIT_CHAR(tty)) {
kill_pg(tty->pgrp, SIGQUIT, 1);
flush_input(tty);
continue;
}
- if ((SUSPEND_CHAR(tty) != __DISABLED_CHAR) &&
- (c==SUSPEND_CHAR(tty))) {
+ if (c == SUSPEND_CHAR(tty)) {
if (!is_orphaned_pgrp(tty->pgrp))
kill_pg(tty->pgrp, SIGTSTP, 1);
continue;
if (c<32 && L_ECHOCTL(tty)) {
put_tty_queue('^',&tty->write_q);
put_tty_queue(c+64, &tty->write_q);
+ if (EOF_CHAR(tty) != __DISABLED_CHAR &&
+ c==EOF_CHAR(tty) && !tty->lnext) {
+ put_tty_queue(8,&tty->write_q);
+ put_tty_queue(8,&tty->write_q);
+ }
} else
put_tty_queue(c, &tty->write_q);
}
+ tty->lnext = 0;
put_tty_queue(c, &tty->secondary);
}
TTY_WRITE_FLUSH(tty);
}
add_wait_queue(&tty->secondary.proc_list, &wait);
while (nr>0) {
+ if (hung_up(file)) {
+ file->f_flags &= ~O_NONBLOCK;
+ break; /* force read() to return 0 */
+ }
TTY_READ_FLUSH(tty);
if (tty->link)
TTY_WRITE_FLUSH(tty->link);
TTY_WRITE_FLUSH(tty->link);
if (!EMPTY(&tty->secondary))
continue;
- if (hung_up(file))
- break;
current->state = TASK_INTERRUPTIBLE;
if (EMPTY(&tty->secondary))
schedule();
tty = TTY_TABLE(dev);
if (!tty || (tty->flags & (1 << TTY_IO_ERROR)))
return -EIO;
- if (MINOR(inode->i_rdev) && (tty->pgrp > 0) &&
+ if ((inode->i_rdev != 0x0400) && /* don't stop on /dev/console */
+ (tty->pgrp > 0) &&
(current->tty == dev) &&
(tty->pgrp != current->pgrp))
if (is_ignored(SIGTTIN) || is_orphaned_pgrp(current->pgrp))
if (sizeof(struct tty_struct) > 4096)
panic("size of tty structure > 4096!");
-
- chrdev_fops[4] = &tty_fops;
- chrdev_fops[5] = &tty_fops;
+ if (register_chrdev(4,"tty",&tty_fops))
+ panic("unable to get major 4 for tty device");
+ if (register_chrdev(5,"tty",&tty_fops))
+ panic("unable to get major 5 for tty device");
for (i=0 ; i< MAX_TTYS ; i++) {
tty_table[i] = 0;
tty_termios[i] = 0;
int datapages = 0;
unsigned long tmp;
unsigned short * p;
+ extern int etext;
cli();
end_mem &= 0xfffff000;
nr_free_pages = 0;
for (tmp = 0 ; tmp < end_mem ; tmp += 4096) {
if (mem_map[MAP_NR(tmp)]) {
- if (tmp < 0xA0000)
- codepages++;
- else if (tmp < 0x100000)
+ if (tmp >= 0xA0000 && tmp < 0x100000)
reservedpages++;
+ else if (tmp < (unsigned long) &etext)
+ codepages++;
else
datapages++;
continue;
nr_free_pages++;
}
tmp = nr_free_pages << PAGE_SHIFT;
- printk("Memory: %dk/%dk available (%dk kernel, %dk reserved, %dk data)\n",
+ printk("Memory: %dk/%dk available (%dk kernel code, %dk reserved, %dk data)\n",
tmp >> 10,
end_mem >> 10,
codepages << 2,
sti();
/* this will send it through the process again. */
dev->queue_xmit (skb, dev, -i-1);
+ if (dev->tbusy)
+ return;
}
}
}
PRINTK(("\nIP: *** datagram routing not yet implemented ***\n"));
PRINTK((" SRC = %s ", in_ntoa(iph->saddr)));
PRINTK((" DST = %s (ignored)\n", in_ntoa(iph->daddr)));
- icmp_reply (skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, dev);
+/* icmp_reply (skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, dev); */
skb->sk = NULL;
kfree_skb(skb, 0);
#include <unistd.h> /* contains read/write */
#include <fcntl.h>
#include <linux/config.h>
+#include <linux/a.out.h>
#define MINIX_HEADER 32
#define GCC_HEADER 1024
int main(int argc, char ** argv)
{
- int i,c,id;
+ int i,c,id, sz;
char buf[1024];
+ struct exec *ex = (struct exec *)buf;
char major_root, minor_root;
struct stat sb;
die("Non-Minix header of 'boot'");
if (((long *) buf)[1]!=intel_long(MINIX_HEADER))
die("Non-Minix header of 'boot'");
- if (((long *) buf)[3]!=0)
+ if (((long *) buf)[3] != 0)
die("Illegal data segment in 'boot'");
- if (((long *) buf)[4]!=0)
+ if (((long *) buf)[4] != 0)
die("Illegal bss in 'boot'");
if (((long *) buf)[5] != 0)
die("Non-Minix header of 'boot'");
die("Non-Minix header of 'setup'");
if (((long *) buf)[1]!=intel_long(MINIX_HEADER))
die("Non-Minix header of 'setup'");
- if (((long *) buf)[3]!=0)
+ if (((long *) buf)[3] != 0)
die("Illegal data segment in 'setup'");
- if (((long *) buf)[4]!=0)
+ if (((long *) buf)[4] != 0)
die("Illegal bss in 'setup'");
if (((long *) buf)[5] != 0)
die("Non-Minix header of 'setup'");
for (i=0 ; (c=read(id,buf,sizeof buf))>0 ; i+=c )
if (write(1,buf,c)!=c)
die("Write call failed");
+ if (c != 0)
+ die("read-error on 'setup'");
close (id);
if (i > SETUP_SECTS*512)
die("Setup exceeds " STRINGIFY(SETUP_SECTS)
die("Unable to open 'system'");
if (read(id,buf,GCC_HEADER) != GCC_HEADER)
die("Unable to read header of 'system'");
- if (((long *) buf)[5] != 0)
+ if (N_MAGIC(*ex) != ZMAGIC)
die("Non-GCC header of 'system'");
- for (i=0 ; (c=read(id,buf,sizeof buf))>0 ; i+=c )
- if (write(1,buf,c)!=c)
- die("Write call failed");
- close(id);
- fprintf(stderr,"System is %d bytes.\n",i);
- if (i > SYS_SIZE*16)
+ sz = N_SYMOFF(*ex) - GCC_HEADER + 4;
+ fprintf(stderr,"System is %d bytes.\n", sz);
+ if (sz > SYS_SIZE*16)
die("System is too big");
+ while (sz > 0) {
+ int l, n;
+
+ l = sz;
+ if (l > sizeof(buf))
+ l = sizeof(buf);
+ if ((n=read(id, buf, l)) != l) {
+ if (n == -1)
+ perror(argv[1]);
+ else
+ fprintf(stderr, "Unexpected EOF\n");
+ die("Can't read 'system'");
+ }
+ write(1, buf, l);
+ sz -= l;
+ }
+ close(id);
return(0);
}
--- /dev/null
+
+HEAD = head.o
+SYSTEM = ../tools/zSystem
+#LD = gcc
+#TEST = -DTEST_DRIVER
+
+zOBJECTS = $(HEAD) inflate.o unzip.o misc.o
+
+CFLAGS = -O6 -DSTDC_HEADERS $(TEST)
+
+.c.s:
+ $(CC) $(CFLAGS) -S -o $*.s $<
+.s.o:
+ $(AS) -c -o $*.o $<
+.c.o:
+ $(CC) $(CFLAGS) -c -o $*.o $<
+
+
+all: zSystem
+
+zSystem: piggy.o $(zOBJECTS)
+ $(LD) $(LDFLAGS) -o zSystem $(zOBJECTS) piggy.o
+
+head.o: head.s
+
+head.s: head.S ../include/linux/tasks.h
+ $(CPP) -traditional head.S -o head.s
+
+piggy.s: $(SYSTEM) xtract piggyback
+ ./xtract $(SYSTEM) | gzip -9 | ./piggyback > piggy.s
+
+$(SYSTEM):
+ cd ..;make tools/zSystem
+
+clean:
+ -rm -f *.o *.s zSystem core piggy.* xtract piggyback
--- /dev/null
+/* crypt.h (dummy version) -- do not perform encrytion
+ * Hardly worth copyrighting :-)
+ */
+
+#ifdef CRYPT
+# undef CRYPT /* dummy version */
+#endif
+
+#define RAND_HEAD_LEN 12 /* length of encryption random header */
+
+#define zencode
+#define zdecode
--- /dev/null
+/* gzip.h -- common declarations for all gzip modules
+ * Copyright (C) 1992-1993 Jean-loup Gailly.
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+#if defined(__STDC__) || defined(PROTO)
+# define OF(args) args
+#else
+# define OF(args) ()
+#endif
+
+#ifdef __STDC__
+ typedef void *voidp;
+#else
+ typedef char *voidp;
+#endif
+
+/* I don't like nested includes, but the string functions are used too often */
+#if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
+# include <string.h>
+# define memzero(s, n) memset ((s), 0, (n))
+#else
+# include <strings.h>
+# define strchr index
+# define strrchr rindex
+# define memcpy(d, s, n) bcopy((s), (d), (n))
+# define memcmp(s1, s2, n) bcmp((s1), (s2), (n))
+# define memzero(s, n) bzero((s), (n))
+#endif
+
+#if !defined(STDC_HEADERS) && defined(HAVE_MEMORY_H)
+# include <memory.h>
+#endif
+
+#ifndef RETSIGTYPE
+# define RETSIGTYPE void
+#endif
+
+#define local static
+
+typedef unsigned char uch;
+typedef unsigned short ush;
+typedef unsigned long ulg;
+
+/* Return codes from gzip */
+#define OK 0
+#define ERROR 1
+#define WARNING 2
+
+/* Compression methods (see algorithm.doc) */
+#define STORED 0
+#define COMPRESSED 1
+#define PACKED 2
+/* methods 3 to 7 reserved */
+#define DEFLATED 8
+extern int method; /* compression method */
+
+/* To save memory for 16 bit systems, some arrays are overlayed between
+ * the various modules:
+ * deflate: prev+head window d_buf l_buf outbuf
+ * unlzw: tab_prefix tab_suffix stack inbuf outbuf
+ * inflate: window inbuf
+ * unpack: window inbuf
+ * For compression, input is done in window[]. For decompression, output
+ * is done in window except for unlzw.
+ */
+
+#ifndef INBUFSIZ
+# define INBUFSIZ 0x8000 /* input buffer size */
+#endif
+#define INBUF_EXTRA 64 /* required by unlzw() */
+
+#ifndef OUTBUFSIZ
+# define OUTBUFSIZ 16384 /* output buffer size */
+#endif
+#define OUTBUF_EXTRA 2048 /* required by unlzw() */
+
+#define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */
+
+#ifdef DYN_ALLOC
+# define EXTERN(type, array) extern type * near array
+# define DECLARE(type, array, size) type * near array
+# define ALLOC(type, array, size) { \
+ array = (type*)fcalloc((unsigned)(((size)+1L)/2), 2*sizeof(type)); \
+ if (array == NULL) error("insufficient memory"); \
+ }
+# define FREE(array) {if (array != NULL) fcfree(array), array=NULL;}
+#else
+# define EXTERN(type, array) extern type array[]
+# define DECLARE(type, array, size) type array[size]
+# define ALLOC(type, array, size)
+# define FREE(array)
+#endif
+
+EXTERN(uch, inbuf); /* input buffer */
+EXTERN(uch, outbuf); /* output buffer */
+EXTERN(ush, d_buf); /* buffer for distances, see trees.c */
+EXTERN(uch, window); /* Sliding window and suffix table (unlzw) */
+#define tab_suffix window
+#ifndef MAXSEG_64K
+# define tab_prefix prev /* hash link (see deflate.c) */
+# define head (prev+WSIZE) /* hash head (see deflate.c) */
+ EXTERN(ush, tab_prefix); /* prefix code (see unlzw.c) */
+#else
+# define tab_prefix0 prev
+# define head tab_prefix1
+ EXTERN(ush, tab_prefix0); /* prefix for even codes */
+ EXTERN(ush, tab_prefix1); /* prefix for odd codes */
+#endif
+
+extern unsigned insize; /* valid bytes in inbuf */
+extern unsigned inptr; /* index of next byte to be processed in inbuf */
+extern unsigned outcnt; /* bytes in output buffer */
+
+extern long bytes_in; /* number of input bytes */
+extern long bytes_out; /* number of output bytes */
+extern long overhead; /* number of bytes in gzip header */
+
+#define isize bytes_in
+/* for compatibility with old zip sources (to be cleaned) */
+
+extern int ifd; /* input file descriptor */
+extern int ofd; /* output file descriptor */
+extern char ifname[]; /* input filename or "stdin" */
+extern char ofname[]; /* output filename or "stdout" */
+
+extern ulg time_stamp; /* original time stamp (modification time) */
+extern long ifile_size; /* input file size, -1 for devices (debug only) */
+
+extern int exit_code; /* program exit code */
+
+typedef int file_t; /* Do not use stdio */
+#define NO_FILE (-1) /* in memory compression */
+
+
+#define GZIP_MAGIC "\037\213" /* Magic header for gzip files, 1F 8B */
+#define OLD_GZIP_MAGIC "\037\236" /* Magic header for gzip 0.5 = freeze 1.x */
+#define PKZIP_MAGIC "PK\003\004" /* Magic header for pkzip files */
+#define PACK_MAGIC "\037\036" /* Magic header for packed files */
+
+/* gzip flag byte */
+#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
+#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
+#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
+#define COMMENT 0x10 /* bit 4 set: file comment present */
+#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
+#define RESERVED 0xC0 /* bit 6,7: reserved */
+
+/* internal file attribute */
+#define UNKNOWN (-1)
+#define BINARY 0
+#define ASCII 1
+
+#ifndef WSIZE
+# define WSIZE 0x8000 /* window size--must be a power of two, and */
+#endif /* at least 32K for zip's deflate method */
+
+#define MIN_MATCH 3
+#define MAX_MATCH 258
+/* The minimum and maximum match lengths */
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST (WSIZE-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+extern int decrypt; /* flag to turn on decryption */
+extern int save_orig_name; /* set if original name must be saved */
+extern int verbose; /* be verbose (-v) */
+extern int level; /* compression level */
+extern int test; /* check .z file integrity */
+extern int to_stdout; /* output to stdout (-c) */
+
+#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
+
+/* put_byte is used for the compressed output, put_char for the
+ * uncompressed output. However unlzw() uses window for its
+ * suffix table instead of its output buffer, so it does not use put_char.
+ * (to be cleaned up).
+ */
+#define put_byte(c) {outbuf[outcnt++]=(uch)(c); if (outcnt==OUTBUFSIZ)\
+ flush_outbuf();}
+#define put_char(c) {window[outcnt++]=(uch)(c); if (outcnt==WSIZE)\
+ flush_window();}
+
+/* Output a 16 bit value, lsb first */
+#define put_short(w) \
+{ if (outcnt < OUTBUFSIZ-2) { \
+ outbuf[outcnt++] = (uch) ((w) & 0xff); \
+ outbuf[outcnt++] = (uch) ((ush)(w) >> 8); \
+ } else { \
+ put_byte((uch)((w) & 0xff)); \
+ put_byte((uch)((ush)(w) >> 8)); \
+ } \
+}
+
+/* Output a 32 bit value to the bit stream, lsb first */
+#define put_long(n) { \
+ put_short((n) & 0xffff); \
+ put_short(((ulg)(n)) >> 16); \
+}
+
+#define seekable() 0 /* force sequential output */
+#define translate_eol 0 /* no option -a yet */
+
+#define tolow(c) (isupper(c) ? (c)-'A'+'a' : (c)) /* force to lower case */
+
+/* Macros for getting two-byte and four-byte header values */
+#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8))
+#define LG(p) ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16))
+
+/* Diagnostic functions */
+#ifdef DEBUG
+# define Assert(cond,msg) {if(!(cond)) error(msg);}
+# define Trace(x) fprintf x
+# define Tracev(x) {if (verbose) fprintf x ;}
+# define Tracevv(x) {if (verbose>1) fprintf x ;}
+# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+#else
+# define Assert(cond,msg)
+# define Trace(x)
+# define Tracev(x)
+# define Tracevv(x)
+# define Tracec(c,x)
+# define Tracecv(c,x)
+#endif
+
+ /* in zip.c: */
+extern void zip OF((int in, int out));
+extern int file_read OF((char *buf, unsigned size));
+
+ /* in unzip.c */
+extern void unzip OF((int in, int out));
+extern int check_zipfile OF((int in));
+
+ /* in unpack.c */
+extern void unpack OF((int in, int out));
+
+ /* in gzip.c */
+RETSIGTYPE abort_gzip OF((void));
+
+ /* in deflate.c */
+void lm_init OF((int pack_level, ush *flags));
+ulg deflate OF((void));
+
+ /* in trees.c */
+void ct_init OF((ush *attr, int *method));
+int ct_tally OF((int dist, int lc));
+ulg flush_block OF((char *buf, ulg stored_len, int eof));
+
+ /* in bits.c */
+void bi_init OF((file_t zipfile));
+void send_bits OF((int value, int length));
+unsigned bi_reverse OF((unsigned value, int length));
+void bi_windup OF((void));
+void copy_block OF((char *buf, unsigned len, int header));
+extern int (*read_buf) OF((char *buf, unsigned size));
+
+ /* in util.c: */
+extern ulg updcrc OF((uch *s, unsigned n));
+extern void clear_bufs OF((void));
+extern int fill_inbuf OF((void));
+extern void flush_outbuf OF((void));
+extern void flush_window OF((void));
+extern char *strlwr OF((char *s));
+extern char *basename OF((char *fname));
+extern char *add_envopt OF((int *argcp, char ***argvp, char *env));
+extern void error OF((char *m));
+extern void warn OF((char *a, char *b));
+extern void read_error OF((void));
+extern void write_error OF((void));
+extern void display_ratio OF((long num, long den));
+extern voidp xmalloc OF((unsigned int size));
+
+ /* in inflate.c */
+extern int inflate OF((void));
--- /dev/null
+/*
+ * linux/boot/head.s
+ *
+ * Copyright (C) 1991, 1992, 1993 Linus Torvalds
+ */
+
+/*
+ * head.s contains the 32-bit startup code.
+ *
+ * NOTE!!! Startup happens at absolute address 0x00000000, which is also where
+ * the page directory will exist. The startup code will be overwritten by
+ * the page directory.
+ */
+.text
+
+startup_32:
+ cld
+ cli
+ movl $0x10,%eax
+ mov %ax,%ds
+ mov %ax,%es
+ mov %ax,%fs
+ mov %ax,%gs
+ lss _stack_start,%esp
+ xorl %eax,%eax
+1: incl %eax # check that A20 really IS enabled
+ movl %eax,0x000000 # loop forever if it isn't
+ cmpl %eax,0x100000
+ je 1b
+/*
+ * Initialize eflags. Some BIOS's leave bits like NT set. This would
+ * confuse the debugger if this code is traced.
+ * XXX - best to initialize before switching to protected mode.
+ */
+ pushl $0
+ popfl
+ call _decompress_kernel
+ ljmp $0x08, $0x100000
--- /dev/null
+#define DEBG(x)
+#define DEBG1(x)
+/* inflate.c -- Not copyrighted 1992 by Mark Adler
+ version c10p1, 10 January 1993 */
+
+/* You can do whatever you like with this source file, though I would
+ prefer that if you modify it and redistribute it that you include
+ comments to that effect with your name and the date. Thank you.
+ [The history has been moved to the file ChangeLog.]
+ */
+
+/*
+ Inflate deflated (PKZIP's method 8 compressed) data. The compression
+ method searches for as much of the current string of bytes (up to a
+ length of 258) in the previous 32K bytes. If it doesn't find any
+ matches (of at least length 3), it codes the next byte. Otherwise, it
+ codes the length of the matched string and its distance backwards from
+ the current position. There is a single Huffman code that codes both
+ single bytes (called "literals") and match lengths. A second Huffman
+ code codes the distance information, which follows a length code. Each
+ length or distance code actually represents a base value and a number
+ of "extra" (sometimes zero) bits to get to add to the base value. At
+ the end of each deflated block is a special end-of-block (EOB) literal/
+ length code. The decoding process is basically: get a literal/length
+ code; if EOB then done; if a literal, emit the decoded byte; if a
+ length then get the distance and emit the referred-to bytes from the
+ sliding window of previously emitted data.
+
+ There are (currently) three kinds of inflate blocks: stored, fixed, and
+ dynamic. The compressor deals with some chunk of data at a time, and
+ decides which method to use on a chunk-by-chunk basis. A chunk might
+ typically be 32K or 64K. If the chunk is uncompressible, then the
+ "stored" method is used. In this case, the bytes are simply stored as
+ is, eight bits per byte, with none of the above coding. The bytes are
+ preceded by a count, since there is no longer an EOB code.
+
+ If the data is compressible, then either the fixed or dynamic methods
+ are used. In the dynamic method, the compressed data is preceded by
+ an encoding of the literal/length and distance Huffman codes that are
+ to be used to decode this block. The representation is itself Huffman
+ coded, and so is preceded by a description of that code. These code
+ descriptions take up a little space, and so for small blocks, there is
+ a predefined set of codes, called the fixed codes. The fixed method is
+ used if the block codes up smaller that way (usually for quite small
+ chunks), otherwise the dynamic method is used. In the latter case, the
+ codes are customized to the probabilities in the current block, and so
+ can code it much better than the pre-determined fixed codes.
+
+ The Huffman codes themselves are decoded using a mutli-level table
+ lookup, in order to maximize the speed of decoding plus the speed of
+ building the decoding tables. See the comments below that precede the
+ lbits and dbits tuning parameters.
+ */
+
+
+/*
+ Notes beyond the 1.93a appnote.txt:
+
+ 1. Distance pointers never point before the beginning of the output
+ stream.
+ 2. Distance pointers can point back across blocks, up to 32k away.
+ 3. There is an implied maximum of 7 bits for the bit length table and
+ 15 bits for the actual data.
+ 4. If only one code exists, then it is encoded using one bit. (Zero
+ would be more efficient, but perhaps a little confusing.) If two
+ codes exist, they are coded using one bit each (0 and 1).
+ 5. There is no way of sending zero distance codes--a dummy must be
+ sent if there are none. (History: a pre 2.0 version of PKZIP would
+ store blocks with no distance codes, but this was discovered to be
+ too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
+ zero distance codes, which is sent as one code of zero bits in
+ length.
+ 6. There are up to 286 literal/length codes. Code 256 represents the
+ end-of-block. Note however that the static length tree defines
+ 288 codes just to fill out the Huffman codes. Codes 286 and 287
+ cannot be used though, since there is no length base or extra bits
+ defined for them. Similarily, there are up to 30 distance codes.
+ However, static trees define 32 codes (all 5 bits) to fill out the
+ Huffman codes, but the last two had better not show up in the data.
+ 7. Unzip can check dynamic Huffman blocks for complete code sets.
+ The exception is that a single code would not be complete (see #4).
+ 8. The five bits following the block type is really the number of
+ literal codes sent minus 257.
+ 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+ (1+6+6). Therefore, to output three times the length, you output
+ three codes (1+1+1), whereas to output four times the same length,
+ you only need two codes (1+3). Hmm.
+ 10. In the tree reconstruction algorithm, Code = Code + Increment
+ only if BitLength(i) is not zero. (Pretty obvious.)
+ 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
+ 12. Note: length code 284 can represent 227-258, but length code 285
+ really is 258. The last length deserves its own, short code
+ since it gets used a lot in very redundant files. The length
+ 258 is special since 258 - 3 (the min match length) is 255.
+ 13. The literal/length and distance code bit lengths are read as a
+ single stream of lengths. It is possible (and advantageous) for
+ a repeat code (16, 17, or 18) to go across the boundary between
+ the two sets of lengths.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: inflate.c,v 0.10 1993/02/04 13:21:06 jloup Exp $";
+#endif
+
+/* #include "tailor.h" */
+#include "gzip.h"
+#define slide window
+
+#if defined(STDC_HEADERS) || defined(HAVE_STDLIB_H)
+# include <sys/types.h>
+# include <stdlib.h>
+#endif
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+ that have 16-bit pointers (e.g. PC's in the small or medium model).
+ Valid extra bits are 0..13. e == 15 is EOB (end of block), e == 16
+ means that v is a literal, 16 < e < 32 means that v is a pointer to
+ the next table, which codes e - 16 bits, and lastly e == 99 indicates
+ an unused code. If a code with e == 99 is looked up, this implies an
+ error in the data. */
+struct huft {
+ uch e; /* number of extra bits or operation */
+ uch b; /* number of bits in this code or subcode */
+ union {
+ ush n; /* literal, length base, or distance base */
+ struct huft *t; /* pointer to next level of table */
+ } v;
+};
+
+
+/* Function prototypes */
+int huft_build OF((unsigned *, unsigned, unsigned, ush *, ush *,
+ struct huft **, int *));
+int huft_free OF((struct huft *));
+int inflate_codes OF((struct huft *, struct huft *, int, int));
+int inflate_stored OF((void));
+int inflate_fixed OF((void));
+int inflate_dynamic OF((void));
+int inflate_block OF((int *));
+int inflate OF((void));
+
+
+/* The inflate algorithm uses a sliding 32K byte window on the uncompressed
+ stream to find repeated byte strings. This is implemented here as a
+ circular buffer. The index is updated simply by incrementing and then
+ and'ing with 0x7fff (32K-1). */
+/* It is left to other modules to supply the 32K area. It is assumed
+ to be usable as if it were declared "uch slide[32768];" or as just
+ "uch *slide;" and then malloc'ed in the latter case. The definition
+ must be in unzip.h, included above. */
+/* unsigned wp; current position in slide */
+#define wp outcnt
+#define flush_output(w) (wp=(w),flush_window())
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+static unsigned border[] = { /* Order of the bit length code lengths */
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+static ush cplens[] = { /* Copy lengths for literal codes 257..285 */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+ /* note: see note #13 above about the 258 in this list. */
+static ush cplext[] = { /* Extra bits for literal codes 257..285 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */
+static ush cpdist[] = { /* Copy offsets for distance codes 0..29 */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577};
+static ush cpdext[] = { /* Extra bits for distance codes */
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+
+
+/* Macros for inflate() bit peeking and grabbing.
+ The usage is:
+
+ NEEDBITS(j)
+ x = b & mask_bits[j];
+ DUMPBITS(j)
+
+ where NEEDBITS makes sure that b has at least j bits in it, and
+ DUMPBITS removes the bits from b. The macros use the variable k
+ for the number of bits in b. Normally, b and k are register
+ variables for speed, and are initialized at the begining of a
+ routine that uses these macros from a global bit buffer and count.
+
+ If we assume that EOB will be the longest code, then we will never
+ ask for bits with NEEDBITS that are beyond the end of the stream.
+ So, NEEDBITS should not read any more bytes than are needed to
+ meet the request. Then no bytes need to be "returned" to the buffer
+ at the end of the last block.
+
+ However, this assumption is not true for fixed blocks--the EOB code
+ is 7 bits, but the other literal/length codes can be 8 or 9 bits.
+ (The EOB code is shorter than other codes becuase fixed blocks are
+ generally short. So, while a block always has an EOB, many other
+ literal/length codes have a significantly lower probability of
+ showing up at all.) However, by making the first table have a
+ lookup of seven bits, the EOB code will be found in that first
+ lookup, and so will not require that too many bits be pulled from
+ the stream.
+ */
+
+ulg bb; /* bit buffer */
+unsigned bk; /* bits in bit buffer */
+
+ush mask_bits[] = {
+ 0x0000,
+ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+#ifdef CRYPT
+ uch cc;
+# define NEXTBYTE() \
+ (decrypt ? (cc = get_byte(), zdecode(cc), cc) : get_byte())
+#else
+# define NEXTBYTE() (uch)get_byte()
+#endif
+#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<<k;k+=8;}}
+#define DUMPBITS(n) {b>>=(n);k-=(n);}
+
+
+/*
+ Huffman code decoding is performed using a multi-level table lookup.
+ The fastest way to decode is to simply build a lookup table whose
+ size is determined by the longest code. However, the time it takes
+ to build this table can also be a factor if the data being decoded
+ is not very long. The most common codes are necessarily the
+ shortest codes, so those codes dominate the decoding time, and hence
+ the speed. The idea is you can have a shorter table that decodes the
+ shorter, more probable codes, and then point to subsidiary tables for
+ the longer codes. The time it costs to decode the longer codes is
+ then traded against the time it takes to make longer tables.
+
+ This results of this trade are in the variables lbits and dbits
+ below. lbits is the number of bits the first level table for literal/
+ length codes can decode in one step, and dbits is the same thing for
+ the distance codes. Subsequent tables are also less than or equal to
+ those sizes. These values may be adjusted either when all of the
+ codes are shorter than that, in which case the longest code length in
+ bits is used, or when the shortest code is *longer* than the requested
+ table size, in which case the length of the shortest code in bits is
+ used.
+
+ There are two different values for the two tables, since they code a
+ different number of possibilities each. The literal/length table
+ codes 286 possible values, or in a flat code, a little over eight
+ bits. The distance table codes 30 possible values, or a little less
+ than five bits, flat. The optimum values for speed end up being
+ about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+ The optimum values may differ though from machine to machine, and
+ possibly even between compilers. Your mileage may vary.
+ */
+
+
+int lbits = 9; /* bits in base literal/length lookup table */
+int dbits = 6; /* bits in base distance lookup table */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
+#define BMAX 16 /* maximum bit length of any code (16 for explode) */
+#define N_MAX 288 /* maximum number of codes in any set */
+
+
+unsigned hufts; /* track memory usage */
+
+
+int huft_build(b, n, s, d, e, t, m)
+unsigned *b; /* code lengths in bits (all assumed <= BMAX) */
+unsigned n; /* number of codes (assumed <= N_MAX) */
+unsigned s; /* number of simple-valued codes (0..s-1) */
+ush *d; /* list of base values for non-simple codes */
+ush *e; /* list of extra bits for non-simple codes */
+struct huft **t; /* result: starting table */
+int *m; /* maximum lookup bits, returns actual */
+/* Given a list of code lengths and a maximum table size, make a set of
+ tables to decode that set of codes. Return zero on success, one if
+ the given code set is incomplete (the tables are still built in this
+ case), two if the input is invalid (all zero length codes or an
+ oversubscribed set of lengths), and three if not enough memory. */
+{
+ unsigned a; /* counter for codes of length k */
+ unsigned c[BMAX+1]; /* bit length count table */
+ unsigned f; /* i repeats in table every f entries */
+ int g; /* maximum code length */
+ int h; /* table level */
+ register unsigned i; /* counter, current code */
+ register unsigned j; /* counter */
+ register int k; /* number of bits in current code */
+ int l; /* bits per table (returned in m) */
+ register unsigned *p; /* pointer into c[], b[], or v[] */
+ register struct huft *q; /* points to current table */
+ struct huft r; /* table entry for structure assignment */
+ struct huft *u[BMAX]; /* table stack */
+ unsigned v[N_MAX]; /* values in order of bit length */
+ register int w; /* bits before this table == (l * h) */
+ unsigned x[BMAX+1]; /* bit offsets, then code stack */
+ unsigned *xp; /* pointer into x */
+ int y; /* number of dummy codes added */
+ unsigned z; /* number of entries in current table */
+
+DEBG("huft1 ");
+
+ /* Generate counts for each bit length */
+ memzero(c, sizeof(c));
+ p = b; i = n;
+ do {
+ Tracecv(*p, (stderr, (n-i >= ' ' && n-i <= '~' ? "%c %d\n" : "0x%x %d\n"),
+ n-i, *p));
+ c[*p++]++; /* assume all entries <= BMAX */
+ } while (--i);
+ if (c[0] == n) /* null input--all zero length codes */
+ {
+ *t = (struct huft *)NULL;
+ *m = 0;
+ return 0;
+ }
+
+DEBG("huft2 ");
+
+ /* Find minimum and maximum length, bound *m by those */
+ l = *m;
+ for (j = 1; j <= BMAX; j++)
+ if (c[j])
+ break;
+ k = j; /* minimum code length */
+ if ((unsigned)l < j)
+ l = j;
+ for (i = BMAX; i; i--)
+ if (c[i])
+ break;
+ g = i; /* maximum code length */
+ if ((unsigned)l > i)
+ l = i;
+ *m = l;
+
+DEBG("huft3 ");
+
+ /* Adjust last length count to fill out codes, if needed */
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ if ((y -= c[j]) < 0)
+ return 2; /* bad input: more codes than bits */
+ if ((y -= c[i]) < 0)
+ return 2;
+ c[i] += y;
+
+DEBG("huft4 ");
+
+ /* Generate starting offsets into the value table for each length */
+ x[1] = j = 0;
+ p = c + 1; xp = x + 2;
+ while (--i) { /* note that i == g from above */
+ *xp++ = (j += *p++);
+ }
+
+DEBG("huft5 ");
+
+ /* Make a table of values in order of bit lengths */
+ p = b; i = 0;
+ do {
+ if ((j = *p++) != 0)
+ v[x[j]++] = i;
+ } while (++i < n);
+
+DEBG("h6 ");
+
+ /* Generate the Huffman codes and for each, make the table entries */
+ x[0] = i = 0; /* first Huffman code is zero */
+ p = v; /* grab values in bit order */
+ h = -1; /* no tables yet--level -1 */
+ w = -l; /* bits decoded == (l * h) */
+ u[0] = (struct huft *)NULL; /* just to keep compilers happy */
+ q = (struct huft *)NULL; /* ditto */
+ z = 0; /* ditto */
+DEBG("h6a ");
+
+ /* go through the bit lengths (k already is bits in shortest code) */
+ for (; k <= g; k++)
+ {
+DEBG("h6b ");
+ a = c[k];
+ while (a--)
+ {
+DEBG("h6b1 ");
+ /* here i is the Huffman code of length k bits for value *p */
+ /* make tables up to required level */
+ while (k > w + l)
+ {
+DEBG1("1 ");
+ h++;
+ w += l; /* previous table always l bits */
+
+ /* compute minimum size table less than or equal to l bits */
+ z = (z = g - w) > (unsigned)l ? l : z; /* upper limit on table size */
+ if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
+ { /* too few codes for k-w bit table */
+DEBG1("2 ");
+ f -= a + 1; /* deduct codes from patterns left */
+ xp = c + k;
+ while (++j < z) /* try smaller tables up to z bits */
+ {
+ if ((f <<= 1) <= *++xp)
+ break; /* enough codes to use up j bits */
+ f -= *xp; /* else deduct codes from patterns */
+ }
+ }
+DEBG1("3 ");
+ z = 1 << j; /* table entries for j-bit table */
+
+ /* allocate and link in new table */
+ if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) ==
+ (struct huft *)NULL)
+ {
+DEBG1("31 ");
+ error("malloc failed\n");
+ if (h)
+ huft_free(u[0]);
+ return 3; /* not enough memory */
+ }
+DEBG1("4 ");
+ hufts += z + 1; /* track memory usage */
+ *t = q + 1; /* link to list for huft_free() */
+ *(t = &(q->v.t)) = (struct huft *)NULL;
+ u[h] = ++q; /* table starts after link */
+
+DEBG1("5 ");
+ /* connect to last table, if there is one */
+ if (h)
+ {
+ x[h] = i; /* save pattern for backing up */
+ r.b = (uch)l; /* bits to dump before this table */
+ r.e = (uch)(16 + j); /* bits in this table */
+ r.v.t = q; /* pointer to this table */
+ j = i >> (w - l); /* (get around Turbo C bug) */
+ u[h-1][j] = r; /* connect to last table */
+ }
+DEBG1("6 ");
+ }
+DEBG("h6c ");
+
+ /* set up table entry in r */
+ r.b = (uch)(k - w);
+ if (p >= v + n)
+ r.e = 99; /* out of values--invalid code */
+ else if (*p < s)
+ {
+ r.e = (uch)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */
+ r.v.n = *p++; /* simple code is just the value */
+ }
+ else
+ {
+ r.e = (uch)e[*p - s]; /* non-simple--look up in lists */
+ r.v.n = d[*p++ - s];
+ }
+DEBG("h6d ");
+
+ /* fill code-like entries with r */
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ q[j] = r;
+
+ /* backwards increment the k-bit code i */
+ for (j = 1 << (k - 1); i & j; j >>= 1)
+ i ^= j;
+ i ^= j;
+
+ /* backup over finished tables */
+ while ((i & ((1 << w) - 1)) != x[h])
+ {
+ h--; /* don't need to update q */
+ w -= l;
+ }
+DEBG("h6e ");
+ }
+DEBG("h6f ");
+ }
+
+DEBG("huft7 ");
+
+ /* Return true (1) if we were given an incomplete table */
+ return y != 0 && g != 1;
+}
+
+
+
+int huft_free(t)
+struct huft *t; /* table to free */
+/* Free the malloc'ed tables built by huft_build(), which makes a linked
+ list of the tables it made, with the links in a dummy first entry of
+ each table. */
+{
+ register struct huft *p, *q;
+
+
+ /* Go through linked list, freeing from the malloced (t[-1]) address. */
+ p = t;
+ while (p != (struct huft *)NULL)
+ {
+ q = (--p)->v.t;
+ free(p);
+ p = q;
+ }
+ return 0;
+}
+
+
+int inflate_codes(tl, td, bl, bd)
+struct huft *tl, *td; /* literal/length and distance decoder tables */
+int bl, bd; /* number of bits decoded by tl[] and td[] */
+/* inflate (decompress) the codes in a deflated (compressed) block.
+ Return an error code or zero if it all goes ok. */
+{
+ register unsigned e; /* table entry flag/number of extra bits */
+ unsigned n, d; /* length and index for copy */
+ unsigned w; /* current window position */
+ struct huft *t; /* pointer to table entry */
+ unsigned ml, md; /* masks for bl and bd bits */
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+
+
+ /* make local copies of globals */
+ b = bb; /* initialize bit buffer */
+ k = bk;
+ w = wp; /* initialize window position */
+
+ /* inflate the coded data */
+ ml = mask_bits[bl]; /* precompute masks for speed */
+ md = mask_bits[bd];
+ for (;;) /* do until end of block */
+ {
+ NEEDBITS((unsigned)bl)
+ if ((e = (t = tl + ((unsigned)b & ml))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ if (e == 16) /* then it's a literal */
+ {
+ slide[w++] = (uch)t->v.n;
+ Tracevv((stderr, "%c", slide[w-1]));
+ if (w == WSIZE)
+ {
+ flush_output(w);
+ w = 0;
+ }
+ }
+ else /* it's an EOB or a length */
+ {
+ /* exit if end of block */
+ if (e == 15)
+ break;
+
+ /* get length of block to copy */
+ NEEDBITS(e)
+ n = t->v.n + ((unsigned)b & mask_bits[e]);
+ DUMPBITS(e);
+
+ /* decode distance of block to copy */
+ NEEDBITS((unsigned)bd)
+ if ((e = (t = td + ((unsigned)b & md))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ NEEDBITS(e)
+ d = w - t->v.n - ((unsigned)b & mask_bits[e]);
+ DUMPBITS(e)
+ Tracevv((stderr,"\\[%d,%d]", w-d, n));
+
+ /* do the copy */
+ do {
+ n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
+#if !defined(NOMEMCPY) && !defined(DEBUG)
+ if (w - d >= e) /* (this test assumes unsigned comparison) */
+ {
+ memcpy(slide + w, slide + d, e);
+ w += e;
+ d += e;
+ }
+ else /* do it slow to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+ do {
+ slide[w++] = slide[d++];
+ Tracevv((stderr, "%c", slide[w-1]));
+ } while (--e);
+ if (w == WSIZE)
+ {
+ flush_output(w);
+ w = 0;
+ }
+ } while (n);
+ }
+ }
+
+
+ /* restore the globals from the locals */
+ wp = w; /* restore global window pointer */
+ bb = b; /* restore global bit buffer */
+ bk = k;
+
+ /* done */
+ return 0;
+}
+
+
+
+int inflate_stored()
+/* "decompress" an inflated type 0 (stored) block. */
+{
+ unsigned n; /* number of bytes in block */
+ unsigned w; /* current window position */
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+
+DEBG("<stor");
+
+ /* make local copies of globals */
+ b = bb; /* initialize bit buffer */
+ k = bk;
+ w = wp; /* initialize window position */
+
+
+ /* go to byte boundary */
+ n = k & 7;
+ DUMPBITS(n);
+
+
+ /* get the length and its complement */
+ NEEDBITS(16)
+ n = ((unsigned)b & 0xffff);
+ DUMPBITS(16)
+ NEEDBITS(16)
+ if (n != (unsigned)((~b) & 0xffff))
+ return 1; /* error in compressed data */
+ DUMPBITS(16)
+
+
+ /* read and output the compressed data */
+ while (n--)
+ {
+ NEEDBITS(8)
+ slide[w++] = (uch)b;
+ if (w == WSIZE)
+ {
+ flush_output(w);
+ w = 0;
+ }
+ DUMPBITS(8)
+ }
+
+
+ /* restore the globals from the locals */
+ wp = w; /* restore global window pointer */
+ bb = b; /* restore global bit buffer */
+ bk = k;
+
+ DEBG(">");
+ return 0;
+}
+
+
+
+int inflate_fixed()
+/* decompress an inflated type 1 (fixed Huffman codes) block. We should
+ either replace this with a custom decoder, or at least precompute the
+ Huffman tables. */
+{
+ int i; /* temporary variable */
+ struct huft *tl; /* literal/length code table */
+ struct huft *td; /* distance code table */
+ int bl; /* lookup bits for tl */
+ int bd; /* lookup bits for td */
+ unsigned l[288]; /* length list for huft_build */
+
+DEBG("<fix");
+
+ /* set up literal table */
+ for (i = 0; i < 144; i++)
+ l[i] = 8;
+ for (; i < 256; i++)
+ l[i] = 9;
+ for (; i < 280; i++)
+ l[i] = 7;
+ for (; i < 288; i++) /* make a complete, but wrong code set */
+ l[i] = 8;
+ bl = 7;
+ if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0)
+ return i;
+
+
+ /* set up distance table */
+ for (i = 0; i < 30; i++) /* make an incomplete code set */
+ l[i] = 5;
+ bd = 5;
+ if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 1)
+ {
+ huft_free(tl);
+
+ DEBG(">");
+ return i;
+ }
+
+
+ /* decompress until an end-of-block code */
+ if (inflate_codes(tl, td, bl, bd))
+ return 1;
+
+
+ /* free the decoding tables, return */
+ huft_free(tl);
+ huft_free(td);
+ return 0;
+}
+
+
+
+int inflate_dynamic()
+/* decompress an inflated type 2 (dynamic Huffman codes) block. */
+{
+ int i; /* temporary variables */
+ unsigned j;
+ unsigned l; /* last length */
+ unsigned m; /* mask for bit lengths table */
+ unsigned n; /* number of lengths to get */
+ struct huft *tl; /* literal/length code table */
+ struct huft *td; /* distance code table */
+ int bl; /* lookup bits for tl */
+ int bd; /* lookup bits for td */
+ unsigned nb; /* number of bit length codes */
+ unsigned nl; /* number of literal/length codes */
+ unsigned nd; /* number of distance codes */
+#ifdef PKZIP_BUG_WORKAROUND
+ unsigned ll[288+32]; /* literal/length and distance code lengths */
+#else
+ unsigned ll[286+30]; /* literal/length and distance code lengths */
+#endif
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+
+DEBG("<dyn");
+
+ /* make local bit buffer */
+ b = bb;
+ k = bk;
+
+
+ /* read in table lengths */
+ NEEDBITS(5)
+ nl = 257 + ((unsigned)b & 0x1f); /* number of literal/length codes */
+ DUMPBITS(5)
+ NEEDBITS(5)
+ nd = 1 + ((unsigned)b & 0x1f); /* number of distance codes */
+ DUMPBITS(5)
+ NEEDBITS(4)
+ nb = 4 + ((unsigned)b & 0xf); /* number of bit length codes */
+ DUMPBITS(4)
+#ifdef PKZIP_BUG_WORKAROUND
+ if (nl > 288 || nd > 32)
+#else
+ if (nl > 286 || nd > 30)
+#endif
+ return 1; /* bad lengths */
+
+DEBG("dyn1 ");
+
+ /* read in bit-length-code lengths */
+ for (j = 0; j < nb; j++)
+ {
+ NEEDBITS(3)
+ ll[border[j]] = (unsigned)b & 7;
+ DUMPBITS(3)
+ }
+ for (; j < 19; j++)
+ ll[border[j]] = 0;
+
+DEBG("dyn2 ");
+
+ /* build decoding table for trees--single level, 7 bit lookup */
+ bl = 7;
+ if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0)
+ {
+ if (i == 1)
+ huft_free(tl);
+ return i; /* incomplete code set */
+ }
+
+DEBG("dyn3 ");
+
+ /* read in literal and distance code lengths */
+ n = nl + nd;
+ m = mask_bits[bl];
+ i = l = 0;
+ while ((unsigned)i < n)
+ {
+ NEEDBITS((unsigned)bl)
+ j = (td = tl + ((unsigned)b & m))->b;
+ DUMPBITS(j)
+ j = td->v.n;
+ if (j < 16) /* length of code in bits (0..15) */
+ ll[i++] = l = j; /* save last length in l */
+ else if (j == 16) /* repeat last length 3 to 6 times */
+ {
+ NEEDBITS(2)
+ j = 3 + ((unsigned)b & 3);
+ DUMPBITS(2)
+ if ((unsigned)i + j > n)
+ return 1;
+ while (j--)
+ ll[i++] = l;
+ }
+ else if (j == 17) /* 3 to 10 zero length codes */
+ {
+ NEEDBITS(3)
+ j = 3 + ((unsigned)b & 7);
+ DUMPBITS(3)
+ if ((unsigned)i + j > n)
+ return 1;
+ while (j--)
+ ll[i++] = 0;
+ l = 0;
+ }
+ else /* j == 18: 11 to 138 zero length codes */
+ {
+ NEEDBITS(7)
+ j = 11 + ((unsigned)b & 0x7f);
+ DUMPBITS(7)
+ if ((unsigned)i + j > n)
+ return 1;
+ while (j--)
+ ll[i++] = 0;
+ l = 0;
+ }
+ }
+
+DEBG("dyn4 ");
+
+ /* free decoding table for trees */
+ huft_free(tl);
+
+DEBG("dyn5 ");
+
+ /* restore the global bit buffer */
+ bb = b;
+ bk = k;
+
+DEBG("dyn5a ");
+
+ /* build the decoding tables for literal/length and distance codes */
+ bl = lbits;
+ if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0)
+ {
+DEBG("dyn5b ");
+ if (i == 1) {
+ error(" incomplete literal tree\n");
+ huft_free(tl);
+ }
+ return i; /* incomplete code set */
+ }
+DEBG("dyn5c ");
+ bd = dbits;
+ if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0)
+ {
+DEBG("dyn5d ");
+ if (i == 1) {
+ error(" incomplete distance tree\n");
+#ifdef PKZIP_BUG_WORKAROUND
+ i = 0;
+ }
+#else
+ huft_free(td);
+ }
+ huft_free(tl);
+ return i; /* incomplete code set */
+#endif
+ }
+
+DEBG("dyn6 ");
+
+ /* decompress until an end-of-block code */
+ if (inflate_codes(tl, td, bl, bd))
+ return 1;
+
+DEBG("dyn7 ");
+
+ /* free the decoding tables, return */
+ huft_free(tl);
+ huft_free(td);
+
+ DEBG(">");
+ return 0;
+}
+
+
+
+int inflate_block(e)
+int *e; /* last block flag */
+/* decompress an inflated block */
+{
+ unsigned t; /* block type */
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+
+ DEBG("<blk");
+
+ /* make local bit buffer */
+ b = bb;
+ k = bk;
+
+
+ /* read in last block bit */
+ NEEDBITS(1)
+ *e = (int)b & 1;
+ DUMPBITS(1)
+
+
+ /* read in block type */
+ NEEDBITS(2)
+ t = (unsigned)b & 3;
+ DUMPBITS(2)
+
+
+ /* restore the global bit buffer */
+ bb = b;
+ bk = k;
+
+ /* inflate that block type */
+ if (t == 2)
+ return inflate_dynamic();
+ if (t == 0)
+ return inflate_stored();
+ if (t == 1)
+ return inflate_fixed();
+
+ DEBG(">");
+
+ /* bad block type */
+ return 2;
+}
+
+
+
+int inflate()
+/* decompress an inflated entry */
+{
+ int e; /* last block flag */
+ int r; /* result code */
+ unsigned h; /* maximum struct huft's malloc'ed */
+
+
+ /* initialize window, bit buffer */
+ wp = 0;
+ bk = 0;
+ bb = 0;
+
+
+ /* decompress until the last block */
+ h = 0;
+ do {
+ hufts = 0;
+ if ((r = inflate_block(&e)) != 0)
+ return r;
+ if (hufts > h)
+ h = hufts;
+ } while (!e);
+
+ /* Undo too much lookahead. The next read will be byte aligned so we
+ * can discard unused bits in the last meaningful byte.
+ */
+ while (bk >= 8) {
+ bk -= 8;
+ inptr--;
+ }
+
+ /* flush out slide */
+ flush_output(wp);
+
+
+ /* return success */
+#ifdef DEBUG
+ fprintf(stderr, "<%u> ", h);
+#endif /* DEBUG */
+ return 0;
+}
--- /dev/null
+/* lzw.h -- define the lzw functions.
+ * Copyright (C) 1992-1993 Jean-loup Gailly.
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+#if !defined(OF) && defined(lint)
+# include "gzip.h"
+#endif
+
+#ifndef BITS
+# define BITS 16
+#endif
+#define INIT_BITS 9 /* Initial number of bits per code */
+
+#define LZW_MAGIC "\037\235" /* Magic header for lzw files, 1F 9D */
+
+#define BIT_MASK 0x1f /* Mask for 'number of compresssion bits' */
+/* Mask 0x20 is reserved to mean a fourth header byte, and 0x40 is free.
+ * It's a pity that old uncompress does not check bit 0x20. That makes
+ * extension of the format actually undesirable because old compress
+ * would just crash on the new format instead of giving a meaningful
+ * error message. It does check the number of bits, but it's more
+ * helpful to say "unsupported format, get a new version" than
+ * "can only handle 16 bits".
+ */
+
+#define BLOCK_MODE 0x80
+/* Block compresssion: if table is full and compression rate is dropping,
+ * clear the dictionary.
+ */
+
+#define LZW_RESERVED 0x60 /* reserved bits */
+
+#define CLEAR 256 /* flush the dictionary */
+#define FIRST (CLEAR+1) /* first free entry */
+
+extern int maxbits; /* max bits per code for LZW */
+extern int block_mode; /* block compress mode -C compatible with 2.0 */
+
+extern void lzw OF((int in, int out));
+extern void unlzw OF((int in, int out));
--- /dev/null
+#include "gzip.h"
+#include "lzw.h"
+
+/*
+ * These are set up by the setup-routine at boot-time:
+ */
+
+struct screen_info {
+ unsigned char orig_x;
+ unsigned char orig_y;
+ unsigned char unused1[2];
+ unsigned short orig_video_page;
+ unsigned char orig_video_mode;
+ unsigned char orig_video_cols;
+ unsigned short orig_video_ega_ax;
+ unsigned short orig_video_ega_bx;
+ unsigned short orig_video_ega_cx;
+ unsigned char orig_video_lines;
+};
+
+/*
+ * This is set up by the setup-routine at boot-time
+ */
+#define EXT_MEM_K (*(unsigned short *)0x90002)
+#define DRIVE_INFO (*(struct drive_info *)0x90080)
+#define SCREEN_INFO (*(struct screen_info *)0x90000)
+#define RAMDISK_SIZE (*(unsigned short *)0x901F8)
+#define ORIG_ROOT_DEV (*(unsigned short *)0x901FC)
+#define AUX_DEVICE_INFO (*(unsigned char *)0x901FF)
+
+#define EOF -1
+
+DECLARE(uch, inbuf, INBUFSIZ);
+DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
+DECLARE(uch, window, WSIZE);
+
+unsigned outcnt;
+unsigned insize;
+unsigned inptr;
+
+extern char input_data[];
+extern int input_len;
+
+int input_ptr;
+
+int method, exit_code, part_nb, last_member;
+int test = 0;
+int force = 0;
+int verbose = 1;
+long bytes_in, bytes_out;
+
+char *output_data;
+unsigned long output_ptr;
+
+extern int end;
+long free_mem_ptr = (long)&end;
+
+int to_stdout = 0;
+int hard_math = 0;
+
+void (*work)(int inf, int outf);
+
+char *vidmem = (char *)0xb8000;
+int vidp = 0;
+int lines, cols;
+
+void *malloc(int size)
+{
+ void *p;
+
+ if (size <0) error("Malloc error\n");
+ if (free_mem_ptr <= 0) error("Memory error\n");
+
+ free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
+
+ p = (void *)free_mem_ptr;
+
+ free_mem_ptr += size;
+
+ if (free_mem_ptr >= (640*1024)) error("\nOut of memory\n");
+
+ if (p == NULL) error("malloc = NULL\n");
+ return p;
+}
+
+void free(void *where)
+{ /* Don't care */
+}
+
+int printk(char *s)
+{
+ int i,n;
+ n = strlen(s);
+ if (!n) n = 10;
+
+ for (i=0;i<n;i++)
+ if (s[i] == '\n')
+ {
+ vidp = ((vidp / (cols*2)) + 1) * cols * 2;
+ } else {
+ vidmem[vidp] = s[i];
+ vidp = vidp + 2;
+ }
+
+ return 1;
+}
+
+__ptr_t memset(__ptr_t s, int c, size_t n)
+{
+ int i;
+ char *ss = (char*)s;
+
+ for (i=0;i<n;i++) ss[i] = c;
+}
+
+__ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src,
+ size_t __n)
+{
+ int i;
+ char *d = (char *)__dest, *s = (char *)__src;
+
+ for (i=0;i<__n;i++) d[i] = s[i];
+}
+
+extern ulg crc_32_tab[]; /* crc table, defined below */
+
+/* ===========================================================================
+ * Run a set of bytes through the crc shift register. If s is a NULL
+ * pointer, then initialize the crc shift register contents instead.
+ * Return the current crc in either case.
+ */
+ulg updcrc(s, n)
+ uch *s; /* pointer to bytes to pump through */
+ unsigned n; /* number of bytes in s[] */
+{
+ register ulg c; /* temporary variable */
+
+ static ulg crc = (ulg)0xffffffffL; /* shift register contents */
+
+ if (s == NULL) {
+ c = 0xffffffffL;
+ } else {
+ c = crc;
+ while (n--) {
+ c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
+ }
+ }
+ crc = c;
+ return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */
+}
+
+/* ===========================================================================
+ * Clear input and output buffers
+ */
+void clear_bufs()
+{
+ outcnt = 0;
+ insize = inptr = 0;
+ bytes_in = bytes_out = 0L;
+}
+
+/* ===========================================================================
+ * Fill the input buffer. This is called only when the buffer is empty
+ * and at least one byte is really needed.
+ */
+int fill_inbuf()
+{
+ int len, i;
+
+ /* Read as much as possible */
+ insize = 0;
+ do {
+ len = INBUFSIZ-insize;
+ if (len > (input_len-input_ptr+1)) len=input_len-input_ptr+1;
+ if (len == 0 || len == EOF) break;
+
+ for (i=0;i<len;i++) inbuf[insize+i] = input_data[input_ptr+i];
+ insize += len;
+ input_ptr += len;
+ } while (insize < INBUFSIZ);
+
+ if (insize == 0) {
+ error("unable to fill buffer\n");
+ }
+ bytes_in += (ulg)insize;
+ inptr = 1;
+ return inbuf[0];
+}
+
+/* ===========================================================================
+ * Write the output window window[0..outcnt-1] and update crc and bytes_out.
+ * (Used for the decompressed data only.)
+ */
+void flush_window()
+{
+ if (outcnt == 0) return;
+ updcrc(window, outcnt);
+
+ memcpy(&output_data[output_ptr], (char *)window, outcnt);
+
+ bytes_out += (ulg)outcnt;
+ output_ptr += (ulg)outcnt;
+ outcnt = 0;
+}
+
+/* ========================================================================
+ * Table of CRC-32's of all single-byte values (made by makecrc.c)
+ */
+ulg crc_32_tab[] = {
+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+ 0x2d02ef8dL
+};
+
+void error(char *x)
+{
+ printk(x);
+ printk(" -- System halted");
+
+ while(1); /* Halt */
+}
+
+#define STACK_SIZE (4096)
+
+long user_stack [STACK_SIZE];
+
+struct {
+ long * a;
+ short b;
+ } stack_start = { & user_stack [STACK_SIZE] , 0x10 };
+
+void decompress_kernel()
+{
+ vidp = 0;
+ vidmem[0] = '0';
+
+ lines = SCREEN_INFO.orig_video_lines;
+ cols = SCREEN_INFO.orig_video_cols;
+
+ if (EXT_MEM_K < 2048) error("At least 2M of memory required by Turbo Ignition\n");
+
+ output_data = (char *)1048576; /* Points to 1M */
+ output_ptr = 0;
+
+ exit_code = 0;
+ test = 0;
+ input_ptr = 0;
+ part_nb = 0;
+
+ clear_bufs();
+
+ printk("Uncompressing Linux: check - ");
+
+ method = get_method(0);
+
+ printk("work - ");
+
+ work(0, 0);
+
+ printk("done.\n\n");
+
+ printk("Now booting the kernel\n");
+}
+
+/* ========================================================================
+ * Check the magic number of the input file and update ofname if an
+ * original name was given and to_stdout is not set.
+ * Return the compression method, -1 for error, -2 for warning.
+ * Set inptr to the offset of the next byte to be processed.
+ * This function may be called repeatedly for an input file consisting
+ * of several contiguous gzip'ed members.
+ * IN assertions: there is at least one remaining compressed member.
+ * If the member is a zip file, it must be the only one.
+ */
+local int get_method(in)
+ int in; /* input file descriptor */
+{
+ uch flags;
+ char magic[2]; /* magic header */
+
+ magic[0] = (char)get_byte();
+ magic[1] = (char)get_byte();
+
+ method = -1; /* unknown yet */
+ part_nb++; /* number of parts in gzip file */
+ last_member = 0;
+ /* assume multiple members in gzip file except for record oriented I/O */
+
+ if (memcmp(magic, GZIP_MAGIC, 2) == 0
+ || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) {
+
+ work = unzip;
+ method = (int)get_byte();
+ flags = (uch)get_byte();
+ if ((flags & ENCRYPTED) != 0) {
+ error("Input is encrypted -- too secret\n");
+ exit_code = ERROR;
+ return -1;
+ }
+ if ((flags & CONTINUATION) != 0) {
+ error("Input is a a multi-part gzip file\n");
+ exit_code = ERROR;
+ if (force <= 1) return -1;
+ }
+ if ((flags & RESERVED) != 0) {
+ error("Input has invalid flags\n");
+ exit_code = ERROR;
+ if (force <= 1) return -1;
+ }
+ (ulg)get_byte(); /* Get timestamp */
+ ((ulg)get_byte()) << 8;
+ ((ulg)get_byte()) << 16;
+ ((ulg)get_byte()) << 24;
+
+ (void)get_byte(); /* Ignore extra flags for the moment */
+ (void)get_byte(); /* Ignore OS type for the moment */
+
+ if ((flags & CONTINUATION) != 0) {
+ unsigned part = (unsigned)get_byte();
+ part |= ((unsigned)get_byte())<<8;
+ if (verbose) {
+ error("Input is not part number 1\n");
+ }
+ }
+ if ((flags & EXTRA_FIELD) != 0) {
+ unsigned len = (unsigned)get_byte();
+ len |= ((unsigned)get_byte())<<8;
+ while (len--) (void)get_byte();
+ }
+
+ /* Get original file name if it was truncated */
+ if ((flags & ORIG_NAME) != 0) {
+ if (to_stdout || part_nb > 1) {
+ /* Discard the old name */
+ while (get_byte() != 0) /* null */ ;
+ } else {
+ } /* to_stdout */
+ } /* orig_name */
+
+ /* Discard file comment if any */
+ if ((flags & COMMENT) != 0) {
+ while (get_byte() != 0) /* null */ ;
+ }
+
+ } else if (memcmp(magic, PKZIP_MAGIC, 2) == 0 && inptr == 2
+ && memcmp(inbuf, PKZIP_MAGIC, 4) == 0) {
+ /* To simplify the code, we support a zip file when alone only.
+ * We are thus guaranteed that the entire local header fits in inbuf.
+ */
+ inptr = 0;
+ work = unzip;
+ if (check_zipfile(in) == -1) return -1;
+ /* check_zipfile may get ofname from the local header */
+ last_member = 1;
+
+ } else if (memcmp(magic, PACK_MAGIC, 2) == 0) {
+ error("packed input");
+ } else if (memcmp(magic, LZW_MAGIC, 2) == 0) {
+ error("compressed input");
+ last_member = 1;
+ }
+ if (method == -1) {
+ error("Corrupted input\n");
+ if (exit_code != ERROR) exit_code = part_nb == 1 ? ERROR : WARNING;
+ return part_nb == 1 ? -1 : -2;
+ }
+ return method;
+}
--- /dev/null
+#include <stdio.h>
+
+int main(int argc, char *argv[])
+{
+ int c, n=0, len=0;
+
+ printf(
+ ".globl _input_data\n"
+ ".data\n"
+ "_input_data:\n");
+
+ while ((c=getchar()) != EOF)
+ {
+ len++;
+ if (!n) printf("\n.byte "); else printf(",");
+ printf("%d", c);
+ n = (n+1) & 0x1f;
+ }
+
+ printf("\n\n");
+
+ fprintf(stderr, "Compressed size %d.\n", len);
+
+
+ printf( ".globl _input_len\n"
+ ".align 2\n"
+ "_input_len:\n"
+ "\t.long %d\n", len);
+
+ exit(0);
+
+}
--- /dev/null
+/* unzip.c -- decompress files in gzip or pkzip format.
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ *
+ * The code in this file is derived from the file funzip.c written
+ * and put in the public domain by Mark Adler.
+ */
+
+/*
+ This version can extract files in gzip or pkzip format.
+ For the latter, only the first entry is extracted, and it has to be
+ either deflated or stored.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: unzip.c,v 0.9 1993/02/10 16:07:22 jloup Exp $";
+#endif
+
+/* #include "tailor.h" */
+#include "gzip.h"
+#include "crypt.h"
+
+#include <stdio.h>
+
+/* PKZIP header definitions */
+#define LOCSIG 0x04034b50L /* four-byte lead-in (lsb first) */
+#define LOCFLG 6 /* offset of bit flag */
+#define CRPFLG 1 /* bit for encrypted entry */
+#define EXTFLG 8 /* bit for extended local header */
+#define LOCHOW 8 /* offset of compression method */
+#define LOCTIM 10 /* file mod time (for decryption) */
+#define LOCCRC 14 /* offset of crc */
+#define LOCSIZ 18 /* offset of compressed size */
+#define LOCLEN 22 /* offset of uncompressed length */
+#define LOCFIL 26 /* offset of file name field length */
+#define LOCEXT 28 /* offset of extra field length */
+#define LOCHDR 30 /* size of local header, including sig */
+#define EXTHDR 16 /* size of extended local header, inc sig */
+
+
+/* Globals */
+
+int decrypt; /* flag to turn on decryption */
+char *key; /* not used--needed to link crypt.c */
+int pkzip = 0; /* set for a pkzip file */
+int extended = 0; /* set if extended local header */
+
+/* ===========================================================================
+ * Check zip file and advance inptr to the start of the compressed data.
+ * Get ofname from the local header if necessary.
+ */
+int check_zipfile(in)
+ int in; /* input file descriptors */
+{
+ uch *h = inbuf + inptr; /* first local header */
+
+ /* ifd = in; */
+
+ /* Check validity of local header, and skip name and extra fields */
+ inptr += LOCHDR + SH(h + LOCFIL) + SH(h + LOCEXT);
+
+ if (inptr > insize || LG(h) != LOCSIG) {
+ error("input not a zip file or empty");
+ }
+ method = h[LOCHOW];
+ if (method != STORED && method != DEFLATED) {
+ error("first entry not deflated or stored--can't extract");
+ }
+
+ /* If entry encrypted, decrypt and validate encryption header */
+ if ((decrypt = h[LOCFLG] & CRPFLG) != 0) {
+ error("encrypted file, not yet supported.\n");
+ exit_code = ERROR;
+ return -1;
+ }
+
+ /* Save flags for unzip() */
+ extended = (h[LOCFLG] & EXTFLG) != 0;
+ pkzip = 1;
+
+ /* Get ofname and time stamp from local header (to be done) */
+ return 0;
+}
+
+/* ===========================================================================
+ * Unzip in to out. This routine works on both gzip and pkzip files.
+ *
+ * IN assertions: the buffer inbuf contains already the beginning of
+ * the compressed data, from offsets inptr to insize-1 included.
+ * The magic header has already been checked. The output buffer is cleared.
+ */
+void unzip(in, out)
+ int in, out; /* input and output file descriptors */
+{
+ ulg orig_crc = 0; /* original crc */
+ ulg orig_len = 0; /* original uncompressed length */
+ int n;
+ uch buf[EXTHDR]; /* extended local header */
+
+ /* ifd = in;
+ ofd = out; */
+
+ updcrc(NULL, 0); /* initialize crc */
+
+ if (pkzip && !extended) { /* crc and length at the end otherwise */
+ orig_crc = LG(inbuf + LOCCRC);
+ orig_len = LG(inbuf + LOCLEN);
+ }
+
+ /* Decompress */
+ if (method == DEFLATED) {
+
+ int res = inflate();
+
+ if (res == 3) {
+ error("out of memory");
+ } else if (res != 0) {
+ error("invalid compressed data--format violated");
+ }
+
+ } else if (pkzip && method == STORED) {
+
+ register ulg n = LG(inbuf + LOCLEN);
+
+ if (n != LG(inbuf + LOCSIZ) - (decrypt ? RAND_HEAD_LEN : 0)) {
+
+ error("invalid compressed data--length mismatch");
+ }
+ while (n--) {
+ uch c = (uch)get_byte();
+#ifdef CRYPT
+ if (decrypt) zdecode(c);
+#endif
+ if (!test) put_char(c);
+ }
+ } else {
+ error("internal error, invalid method");
+ }
+
+ /* Get the crc and original length */
+ if (!pkzip) {
+ /* crc32 (see algorithm.doc)
+ * uncompressed input size modulo 2^32
+ */
+ for (n = 0; n < 8; n++) {
+ buf[n] = (uch)get_byte(); /* may cause an error if EOF */
+ }
+ orig_crc = LG(buf);
+ orig_len = LG(buf+4);
+
+ } else if (extended) { /* If extended header, check it */
+ /* signature - 4bytes: 0x50 0x4b 0x07 0x08
+ * CRC-32 value
+ * compressed size 4-bytes
+ * uncompressed size 4-bytes
+ */
+ for (n = 0; n < EXTHDR; n++) {
+ buf[n] = (uch)get_byte(); /* may cause an error if EOF */
+ }
+ orig_crc = LG(buf+4);
+ orig_len = LG(buf+12);
+ }
+
+ /* Validate decompression */
+ if (orig_crc != updcrc(outbuf, 0)) {
+ error("invalid compressed data--crc error");
+ }
+ if (orig_len != bytes_out) {
+ error("invalid compressed data--length error");
+ }
+
+ /* Check if there are more entries in a pkzip file */
+ if (pkzip && inptr + 4 < insize && LG(inbuf+inptr) == LOCSIG) {
+ error("zip file has more than one entry");
+ }
+ extended = pkzip = 0; /* for next file */
+}
--- /dev/null
+/*
+ * linux/tools/build.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+/*
+ * This file builds a disk-image from three different files:
+ *
+ * - bootsect: max 510 bytes of 8086 machine code, loads the rest
+ * - setup: max 4 sectors of 8086 machine code, sets up system parm
+ * - system: 80386 code for actual system
+ *
+ * It does some checking that all files are of the correct type, and
+ * just writes the result to stdout, removing headers and padding to
+ * the right amount. It also writes some system data to stderr.
+ */
+
+/*
+ * Changes by tytso to allow root device specification
+ */
+
+#include <stdio.h> /* fprintf */
+#include <string.h>
+#include <stdlib.h> /* contains exit */
+#include <sys/types.h> /* unistd.h needs this */
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <unistd.h> /* contains read/write */
+#include <fcntl.h>
+#include <a.out.h>
+#include <linux/config.h>
+
+#define GCC_HEADER 1024
+
+#define STRINGIFY(x) #x
+
+void die(char * str)
+{
+ fprintf(stderr,"%s\n",str);
+ exit(1);
+}
+
+void usage(void)
+{
+ die("Usage: xtract system [ | gzip | piggyback > piggy.s]");
+}
+
+int main(int argc, char ** argv)
+{
+ int i,c,id, sz;
+ char buf[1024];
+ char major_root, minor_root;
+ struct stat sb;
+
+ struct exec *ex = (struct exec *)buf;
+
+ if (argc != 2)
+ usage();
+
+ if ((id=open(argv[1],O_RDONLY,0))<0)
+ die("Unable to open 'system'");
+ if (read(id,buf,GCC_HEADER) != GCC_HEADER)
+ die("Unable to read header of 'system'");
+ if (N_MAGIC(*ex) != ZMAGIC)
+ die("Non-GCC header of 'system'");
+
+ sz = N_SYMOFF(*ex) - GCC_HEADER + 4; /* +4 to get the same result than tools/build */
+
+ fprintf(stderr, "System size is %d\n", sz);
+
+ while (sz)
+ {
+ int l, n;
+
+ l = sz;
+ if (l > sizeof(buf)) l = sizeof(buf);
+
+ if ((n=read(id, buf, l)) !=l)
+ {
+ if (n == -1)
+ perror(argv[1]);
+ else
+ fprintf(stderr, "Unexpected EOF\n");
+
+ die("Can't read system");
+ }
+
+ write(1, buf, l);
+ sz -= l;
+ }
+
+ close(id);
+ return(0);
+}