aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@cc.helsinki.fi>1993-02-22 21:22:01 +0000
committerNicolas Pitre <nico@cam.org>2007-08-19 14:19:12 -0400
commit56cac397826c13fb61390c9ca3fa5354a7b80ca5 (patch)
treebfea3a2a0e1e187ee4a34b2a8ef082488889103d
parent1680d965ceb874b34ebbc3788fdb1b0dd594f043 (diff)
downloadarchive-56cac397826c13fb61390c9ca3fa5354a7b80ca5.tar.gz
linux 0.99 patchlevel 6v0.99-pl6
I'm starting soon to run out of patchlevel numbers for 0.99, but I made a new release anyway (and long-time linux hackers remember my less than completely logical numbering: when I run out of numbers I'll start using alphabetical characters and other fun characters to indicate new versions :-) 0.99pl6 is mainly a syncronization release: it fixes a few bugs and changes the behaviour of 'vhangup()' to be more standard. The vhangup() changes will break some init/login stuff that depended on the earlier incorrect behaviour - not everybody may want to use pl6 until you are sure your init/login will work happily with it. Better do these things before 1.0 than to break it later. Patchlevel 6 also changes the vfs functions for special devices as well as adding a 'fsync' field to the inode-operations structure. Thus ext2fs and xfs need updating. Remy and Xia? The special file and fifo handling code is no longer supposed to be in the fs-dependent layer, but is handled by the vfs routines, as it's the same for all "normal" filesystems. Ok, here are the actual changes/features of pl6: - the kernel can be loaded in gzipped format and de-compressed at startup beyond the 1MB mark. Good for bootable rootdisks. Patches mainly by Hannu Savolainen. - I finally enabled NMI's everywhere (except at the bootup sequence), so if you have memory errors, they will hopefully now result in kernel messages ("NMI received..") - the device registration code for special devices. Special files are now registered with a special "register_[chr|blk]dev()" function. - consolidated fifo/special dev handling - vhangup patches. Note that these may break init/login badly, at least if you are using poeigl-1.7. Be careful that you don't get totally locked out of your machine. - the procfs NULL-dereferencing bugfix (michaelkjohnson) - literal next character handling (very losely based on a patch I received: I essentially rewrote it with final fixes by jrs). - fpu-emu bugfixes by Bill Metzenthen - fixes the "internal error 112" bug as well as a sign bug with zero. - fdomain driver fixes - various other minor fixes (wrongly replying to bad ip messages etc) I'm still not sure about the 387 error detection code: I have had a couple of messages that would suggest that some early clone 387's have problems with math exceptions in protected mode. With the new (as of 99pl5) test at startup this can lead to problems at boot-time. Please mail me directly if you seem to have problems with this (it should be obvious in pl6 due to debugging messages at startup). Linus
-rw-r--r--Makefile37
-rw-r--r--boot/setup.S2
-rw-r--r--fs/Makefile2
-rw-r--r--fs/devices.c146
-rw-r--r--fs/ext/Makefile2
-rw-r--r--fs/ext/blkdev.c69
-rw-r--r--fs/ext/chrdev.c70
-rw-r--r--fs/ext/dir.c3
-rw-r--r--fs/ext/fifo.c28
-rw-r--r--fs/ext/file.c3
-rw-r--r--fs/ext/inode.c6
-rw-r--r--fs/ext/namei.c6
-rw-r--r--fs/fifo.c19
-rw-r--r--fs/inode.c2
-rw-r--r--fs/isofs/Makefile3
-rw-r--r--fs/isofs/blkdev.c68
-rw-r--r--fs/isofs/chrdev.c69
-rw-r--r--fs/isofs/dir.c3
-rw-r--r--fs/isofs/fifo.c28
-rw-r--r--fs/isofs/file.c3
-rw-r--r--fs/isofs/inode.c6
-rw-r--r--fs/minix/Makefile2
-rw-r--r--fs/minix/blkdev.c63
-rw-r--r--fs/minix/chrdev.c64
-rw-r--r--fs/minix/dir.c3
-rw-r--r--fs/minix/fifo.c28
-rw-r--r--fs/minix/file.c3
-rw-r--r--fs/minix/inode.c13
-rw-r--r--fs/minix/namei.c6
-rw-r--r--fs/msdos/dir.c3
-rw-r--r--fs/msdos/file.c3
-rw-r--r--fs/nfs/Makefile2
-rw-r--r--fs/nfs/blkdev.c63
-rw-r--r--fs/nfs/chrdev.c64
-rw-r--r--fs/nfs/dir.c9
-rw-r--r--fs/nfs/fifo.c28
-rw-r--r--fs/nfs/file.c3
-rw-r--r--fs/open.c97
-rw-r--r--fs/pipe.c9
-rw-r--r--fs/proc/array.c13
-rw-r--r--fs/proc/base.c3
-rw-r--r--fs/proc/fd.c3
-rw-r--r--fs/proc/kmsg.c3
-rw-r--r--fs/proc/mem.c3
-rw-r--r--fs/proc/root.c3
-rw-r--r--fs/super.c3
-rw-r--r--include/linux/dirent.h2
-rw-r--r--include/linux/fd.h3
-rw-r--r--include/linux/fs.h16
-rw-r--r--include/linux/sched.h6
-rw-r--r--include/linux/tty.h3
-rw-r--r--init/main.c12
-rw-r--r--kernel/FPU-emu/Makefile2
-rw-r--r--kernel/FPU-emu/fpu_trig.c4
-rw-r--r--kernel/FPU-emu/reg_add_sub.c69
-rw-r--r--kernel/FPU-emu/version.h2
-rw-r--r--kernel/blk_drv/blk.h9
-rw-r--r--kernel/blk_drv/floppy.c15
-rw-r--r--kernel/blk_drv/hd.c7
-rw-r--r--kernel/blk_drv/ll_rw_blk.c18
-rw-r--r--kernel/blk_drv/ramdisk.c5
-rw-r--r--kernel/blk_drv/scsi/fdomain.c28
-rw-r--r--kernel/blk_drv/scsi/sd.c5
-rw-r--r--kernel/blk_drv/scsi/sr.c5
-rw-r--r--kernel/blk_drv/scsi/st.c5
-rw-r--r--kernel/blk_drv/scsi/wd7000.c19
-rw-r--r--kernel/chr_drv/console.c4
-rw-r--r--kernel/chr_drv/keyboard.c2
-rw-r--r--kernel/chr_drv/lp.c3
-rw-r--r--kernel/chr_drv/mem.c3
-rw-r--r--kernel/chr_drv/mouse.c4
-rw-r--r--kernel/chr_drv/serial.c6
-rw-r--r--kernel/chr_drv/tty_io.c66
-rw-r--r--mm/memory.c9
-rw-r--r--net/tcp/dev.c2
-rw-r--r--net/tcp/ip.c2
-rw-r--r--tools/build.c42
-rw-r--r--zBoot/Makefile36
-rw-r--r--zBoot/crypt.h12
-rw-r--r--zBoot/gzip.h284
-rw-r--r--zBoot/head.S38
-rw-r--r--zBoot/inflate.c995
-rw-r--r--zBoot/lzw.h42
-rw-r--r--zBoot/misc.c417
-rw-r--r--zBoot/piggyback.c32
-rw-r--r--zBoot/unzip.c178
-rw-r--r--zBoot/xtract.c95
87 files changed, 2659 insertions, 917 deletions
diff --git a/Makefile b/Makefile
index 0ef7fab..6aa6b99 100644
--- a/Makefile
+++ b/Makefile
@@ -147,17 +147,14 @@ tools/./version.h: tools/version.h
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
@@ -200,6 +197,33 @@ boot/bootsect: boot/bootsect.s
$(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
@@ -210,10 +234,11 @@ kernel: dummy
$(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
diff --git a/boot/setup.S b/boot/setup.S
index b8db58f..83f3101 100644
--- a/boot/setup.S
+++ b/boot/setup.S
@@ -146,6 +146,8 @@ no_psmouse:
! 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
diff --git a/fs/Makefile b/fs/Makefile
index 3d93208..8a32ef8 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -35,7 +35,7 @@ endif
.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
diff --git a/fs/devices.c b/fs/devices.c
new file mode 100644
index 0000000..b3bb1c5
--- /dev/null
+++ b/fs/devices.c
@@ -0,0 +1,146 @@
+/*
+ * 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 */
+};
diff --git a/fs/ext/Makefile b/fs/ext/Makefile
index 205c05f..4d241db 100644
--- a/fs/ext/Makefile
+++ b/fs/ext/Makefile
@@ -15,7 +15,7 @@
$(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)
diff --git a/fs/ext/blkdev.c b/fs/ext/blkdev.c
deleted file mode 100644
index 2f96b8e..0000000
--- a/fs/ext/blkdev.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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 */
-};
diff --git a/fs/ext/chrdev.c b/fs/ext/chrdev.c
deleted file mode 100644
index 360be86..0000000
--- a/fs/ext/chrdev.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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 */
-};
-
diff --git a/fs/ext/dir.c b/fs/ext/dir.c
index b10152c..da09fb4 100644
--- a/fs/ext/dir.c
+++ b/fs/ext/dir.c
@@ -36,7 +36,8 @@ static struct file_operations ext_dir_operations = {
NULL, /* ioctl - default */
NULL, /* mmap */
NULL, /* no special open code */
- NULL /* no special release code */
+ NULL, /* no special release code */
+ NULL /* fsync */
};
/*
diff --git a/fs/ext/fifo.c b/fs/ext/fifo.c
deleted file mode 100644
index a1b04e1..0000000
--- a/fs/ext/fifo.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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 */
-};
diff --git a/fs/ext/file.c b/fs/ext/file.c
index ad50245..804e6fb 100644
--- a/fs/ext/file.c
+++ b/fs/ext/file.c
@@ -47,7 +47,8 @@ static struct file_operations ext_file_operations = {
NULL, /* ioctl - default */
NULL, /* mmap */
NULL, /* no special open is needed */
- NULL /* release */
+ NULL, /* release */
+ NULL /* fsync */
};
struct inode_operations ext_file_inode_operations = {
diff --git a/fs/ext/inode.c b/fs/ext/inode.c
index 3837002..33942a1 100644
--- a/fs/ext/inode.c
+++ b/fs/ext/inode.c
@@ -372,11 +372,11 @@ void ext_read_inode(struct inode * inode)
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;
diff --git a/fs/ext/namei.c b/fs/ext/namei.c
index bfb0171..1421b54 100644
--- a/fs/ext/namei.c
+++ b/fs/ext/namei.c
@@ -369,11 +369,11 @@ int ext_mknod(struct inode * dir, const char * name, int len, int mode, int rdev
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;
diff --git a/fs/fifo.c b/fs/fifo.c
index 3918251..3ca5fc3 100644
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -112,5 +112,24 @@ struct file_operations def_fifo_fops = {
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 */
+};
diff --git a/fs/inode.c b/fs/inode.c
index 276513a..b83c789 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -177,6 +177,8 @@ void sync_inodes(dev_t dev)
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);
diff --git a/fs/isofs/Makefile b/fs/isofs/Makefile
index 06fffff..1417145 100644
--- a/fs/isofs/Makefile
+++ b/fs/isofs/Makefile
@@ -14,8 +14,7 @@
.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)
diff --git a/fs/isofs/blkdev.c b/fs/isofs/blkdev.c
deleted file mode 100644
index ce1b791..0000000
--- a/fs/isofs/blkdev.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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 */
-};
diff --git a/fs/isofs/chrdev.c b/fs/isofs/chrdev.c
deleted file mode 100644
index e584b48..0000000
--- a/fs/isofs/chrdev.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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 */
-};
-
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index 99943f6..fd906db 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -29,7 +29,8 @@ static struct file_operations isofs_dir_operations = {
NULL, /* select - default */
NULL, /* ioctl - default */
NULL, /* no special open code */
- NULL /* no special release code */
+ NULL, /* no special release code */
+ NULL /* fsync */
};
/*
diff --git a/fs/isofs/fifo.c b/fs/isofs/fifo.c
deleted file mode 100644
index da03133..0000000
--- a/fs/isofs/fifo.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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 */
-};
diff --git a/fs/isofs/file.c b/fs/isofs/file.c
index effca2d..223e7d0 100644
--- a/fs/isofs/file.c
+++ b/fs/isofs/file.c
@@ -43,7 +43,8 @@ static struct file_operations isofs_file_operations = {
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 = {
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 39b00fa..233146e 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -412,11 +412,11 @@ void isofs_read_inode(struct inode * inode)
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;
diff --git a/fs/minix/Makefile b/fs/minix/Makefile
index aac5242..80109a0 100644
--- a/fs/minix/Makefile
+++ b/fs/minix/Makefile
@@ -15,7 +15,7 @@
$(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)
diff --git a/fs/minix/blkdev.c b/fs/minix/blkdev.c
deleted file mode 100644
index 2e4f03a..0000000
--- a/fs/minix/blkdev.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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 */
-};
diff --git a/fs/minix/chrdev.c b/fs/minix/chrdev.c
deleted file mode 100644
index 622e745..0000000
--- a/fs/minix/chrdev.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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 */
-};
-
diff --git a/fs/minix/dir.c b/fs/minix/dir.c
index 2a162bb..b2535ba 100644
--- a/fs/minix/dir.c
+++ b/fs/minix/dir.c
@@ -29,7 +29,8 @@ static struct file_operations minix_dir_operations = {
NULL, /* ioctl - default */
NULL, /* mmap */
NULL, /* no special open code */
- NULL /* no special release code */
+ NULL, /* no special release code */
+ NULL /* default fsync */
};
/*
diff --git a/fs/minix/fifo.c b/fs/minix/fifo.c
deleted file mode 100644
index 5da93b0..0000000
--- a/fs/minix/fifo.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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 */
-};
diff --git a/fs/minix/file.c b/fs/minix/file.c
index 026a884..6f70ac6 100644
--- a/fs/minix/file.c
+++ b/fs/minix/file.c
@@ -41,7 +41,8 @@ static struct file_operations minix_file_operations = {
NULL, /* ioctl - default */
NULL, /* mmap */
NULL, /* no special open is needed */
- NULL /* release */
+ NULL, /* release */
+ NULL /* fsync */
};
struct inode_operations minix_file_inode_operations = {
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 32cfd77..76d4bc4 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -345,11 +345,11 @@ void minix_read_inode(struct inode * inode)
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;
@@ -373,8 +373,11 @@ void minix_write_inode(struct inode * inode)
}
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;
diff --git a/fs/minix/namei.c b/fs/minix/namei.c
index c2ba87f..5af220e 100644
--- a/fs/minix/namei.c
+++ b/fs/minix/namei.c
@@ -261,11 +261,11 @@ int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rd
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;
diff --git a/fs/msdos/dir.c b/fs/msdos/dir.c
index caf5b43..12a5a45 100644
--- a/fs/msdos/dir.c
+++ b/fs/msdos/dir.c
@@ -31,7 +31,8 @@ static struct file_operations msdos_dir_operations = {
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 = {
diff --git a/fs/msdos/file.c b/fs/msdos/file.c
index 1406028..ec446fb 100644
--- a/fs/msdos/file.c
+++ b/fs/msdos/file.c
@@ -34,7 +34,8 @@ static struct file_operations msdos_file_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 = {
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index f422bfa..f4fdd2f 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -15,7 +15,7 @@
$(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)
diff --git a/fs/nfs/blkdev.c b/fs/nfs/blkdev.c
deleted file mode 100644
index 3b7c956..0000000
--- a/fs/nfs/blkdev.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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 */
-};
diff --git a/fs/nfs/chrdev.c b/fs/nfs/chrdev.c
deleted file mode 100644
index 844094d..0000000
--- a/fs/nfs/chrdev.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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 */
-};
-
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index f1a3304..0ea79ad 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -46,7 +46,8 @@ static struct file_operations nfs_dir_operations = {
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 = {
@@ -627,11 +628,11 @@ void nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
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;
diff --git a/fs/nfs/fifo.c b/fs/nfs/fifo.c
deleted file mode 100644
index 635b9b6..0000000
--- a/fs/nfs/fifo.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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 */
-};
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index d3d4c67..cbf27b3 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -29,7 +29,8 @@ static struct file_operations nfs_file_operations = {
NULL, /* ioctl - default */
NULL, /* mmap */
NULL, /* no special open is needed */
- NULL /* release */
+ NULL, /* release */
+ NULL /* fsync */
};
struct inode_operations nfs_file_inode_operations = {
diff --git a/fs/open.c b/fs/open.c
index 9aa632f..ebd7d9a 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -21,14 +21,6 @@
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;
@@ -452,102 +444,19 @@ int sys_close(unsigned int fd)
}
/*
- * 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;
}
-
diff --git a/fs/pipe.c b/fs/pipe.c
index 6ac34c1..ac8b9eb 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -179,7 +179,8 @@ struct file_operations read_pipe_fops = {
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 = {
@@ -191,7 +192,8 @@ 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 = {
@@ -203,7 +205,8 @@ 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)
diff --git a/fs/proc/array.c b/fs/proc/array.c
index b3ed0b9..e9e6cf2 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -181,7 +181,7 @@ static int get_stat(int pid, char * buffer)
{
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)
@@ -198,6 +198,11 @@ static int get_stat(int pid, char * buffer)
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",
@@ -208,8 +213,7 @@ static int get_stat(int pid, char * buffer)
(*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,
@@ -354,7 +358,8 @@ static struct file_operations proc_array_operations = {
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 = {
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 487b925..51009b6 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -25,7 +25,8 @@ static struct file_operations proc_base_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 */
};
/*
diff --git a/fs/proc/fd.c b/fs/proc/fd.c
index e353ba2..25f7b46 100644
--- a/fs/proc/fd.c
+++ b/fs/proc/fd.c
@@ -25,7 +25,8 @@ static struct file_operations proc_fd_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 */
};
/*
diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c
index 8f29d36..3ef339f 100644
--- a/fs/proc/kmsg.c
+++ b/fs/proc/kmsg.c
@@ -54,7 +54,8 @@ static struct file_operations proc_kmsg_operations = {
NULL, /* kmsg_ioctl */
NULL, /* mmap */
kmsg_open,
- kmsg_release
+ kmsg_release,
+ NULL /* can't fsync */
};
struct inode_operations proc_kmsg_inode_operations = {
diff --git a/fs/proc/mem.c b/fs/proc/mem.c
index 1068f04..368e28f 100644
--- a/fs/proc/mem.c
+++ b/fs/proc/mem.c
@@ -149,7 +149,8 @@ static struct file_operations proc_mem_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 = {
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 3dbec2d..aa07cf7 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -25,7 +25,8 @@ static struct file_operations proc_root_operations = {
NULL, /* ioctl - default */
NULL, /* mmap */
NULL, /* no special open code */
- NULL /* no special release code */
+ NULL, /* no special release code */
+ NULL /* no fsync */
};
/*
diff --git a/fs/super.c b/fs/super.c
index a5acab0..f5dd73c 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -24,6 +24,7 @@
*/
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);
@@ -67,6 +68,8 @@ void sync_supers(dev_t dev)
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;
diff --git a/include/linux/dirent.h b/include/linux/dirent.h
index 01d16c8..219faf1 100644
--- a/include/linux/dirent.h
+++ b/include/linux/dirent.h
@@ -1,6 +1,8 @@
#ifndef _LINUX_DIRENT_H
#define _LINUX_DIRENT_H
+#include <linux/limits.h>
+
struct dirent {
long d_ino;
off_t d_off;
diff --git a/include/linux/fd.h b/include/linux/fd.h
index 4828db0..12332f3 100644
--- a/include/linux/fd.h
+++ b/include/linux/fd.h
@@ -11,6 +11,9 @@
#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 */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index ebcdae4..24904ac 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -109,7 +109,7 @@ extern unsigned long inode_init(unsigned long start, unsigned long end);
*
* 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)
@@ -260,6 +260,7 @@ struct file_operations {
int (*mmap) (void);
int (*open) (struct inode *, struct file *);
void (*release) (struct inode *, struct file *);
+ int (*fsync) (struct inode *, struct file *);
};
struct inode_operations {
@@ -296,8 +297,17 @@ struct file_system_type {
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);
diff --git a/include/linux/sched.h b/include/linux/sched.h
index e3a0835..460dd72 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -217,7 +217,7 @@ struct task_struct {
/*
* 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, \
@@ -244,8 +244,8 @@ struct task_struct {
/* 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,\
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 55066a4..767c347 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -138,6 +138,7 @@ extern int get_tty_queue(struct tty_queue * queue);
#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)
@@ -188,7 +189,7 @@ struct tty_struct {
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;
diff --git a/init/main.c b/init/main.c
index 803ab09..f8ac1af 100644
--- a/init/main.c
+++ b/init/main.c
@@ -220,8 +220,13 @@ void start_kernel(void)
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);
@@ -260,11 +265,14 @@ void start_kernel(void)
*/
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 */
diff --git a/kernel/FPU-emu/Makefile b/kernel/FPU-emu/Makefile
index 8ae26fb..2a1e34c 100644
--- a/kernel/FPU-emu/Makefile
+++ b/kernel/FPU-emu/Makefile
@@ -37,7 +37,7 @@ math.a: $(OBJS)
sync
clean:
- rm -f core *.o *.a *.s *~
+ rm -f core *.o *.a *.s
dep:
$(CPP) -M *.c *.S > .depend
diff --git a/kernel/FPU-emu/fpu_trig.c b/kernel/FPU-emu/fpu_trig.c
index 0def167..27e80c5 100644
--- a/kernel/FPU-emu/fpu_trig.c
+++ b/kernel/FPU-emu/fpu_trig.c
@@ -79,8 +79,10 @@ static void single_arg_error(void)
/* 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);
diff --git a/kernel/FPU-emu/reg_add_sub.c b/kernel/FPU-emu/reg_add_sub.c
index 6167fe6..e1e2283 100644
--- a/kernel/FPU-emu/reg_add_sub.c
+++ b/kernel/FPU-emu/reg_add_sub.c
@@ -17,7 +17,8 @@
#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)
@@ -41,28 +42,55 @@ 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)
@@ -97,7 +125,11 @@ void reg_sub(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);
+ }
}
switch (a->sign*2 + b->sign)
@@ -109,6 +141,13 @@ void reg_sub(FPU_REG *a, FPU_REG *b, FPU_REG *dest)
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);
@@ -130,7 +169,23 @@ void reg_sub(FPU_REG *a, FPU_REG *b, FPU_REG *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);
diff --git a/kernel/FPU-emu/version.h b/kernel/FPU-emu/version.h
index cccf328..26c52df 100644
--- a/kernel/FPU-emu/version.h
+++ b/kernel/FPU-emu/version.h
@@ -8,5 +8,5 @@
| |
+---------------------------------------------------------------------------*/
-#define FPU_VERSION "wm-FPU-emu version BETA 1.0"
+#define FPU_VERSION "wm-FPU-emu version BETA 1.1"
diff --git a/kernel/blk_drv/blk.h b/kernel/blk_drv/blk.h
index dbd9718..1fb05b8 100644
--- a/kernel/blk_drv/blk.h
+++ b/kernel/blk_drv/blk.h
@@ -1,7 +1,8 @@
#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
@@ -62,12 +63,12 @@ struct sec_size {
#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);
diff --git a/kernel/blk_drv/floppy.c b/kernel/blk_drv/floppy.c
index e8dd20f..382b837 100644
--- a/kernel/blk_drv/floppy.c
+++ b/kernel/blk_drv/floppy.c
@@ -1091,6 +1091,14 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
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;
@@ -1140,7 +1148,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
}
#define CMOS_READ(addr) ({ \
-outb_p(0x80|addr,0x70); \
+outb_p(addr,0x70); \
inb_p(0x71); \
})
@@ -1258,9 +1266,12 @@ static struct sigaction floppy_sigaction = {
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();
diff --git a/kernel/blk_drv/hd.c b/kernel/blk_drv/hd.c
index fa0cac7..632eae8 100644
--- a/kernel/blk_drv/hd.c
+++ b/kernel/blk_drv/hd.c
@@ -43,7 +43,7 @@ static int revalidate_hddisk(int, int);
static inline unsigned char CMOS_READ(unsigned char addr)
{
- outb_p(0x80|addr,0x70);
+ outb_p(addr,0x70);
return inb_p(0x71);
}
@@ -684,8 +684,11 @@ static struct file_operations hd_fops = {
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;
diff --git a/kernel/blk_drv/ll_rw_blk.c b/kernel/blk_drv/ll_rw_blk.c
index 51759d2..99d09be 100644
--- a/kernel/blk_drv/ll_rw_blk.c
+++ b/kernel/blk_drv/ll_rw_blk.c
@@ -31,13 +31,13 @@ struct wait_queue * wait_for_request = NULL;
/* 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 */
@@ -57,11 +57,11 @@ struct blk_dev_struct blk_dev[NR_BLK_DEV] = {
*
* 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)
{
@@ -69,7 +69,7 @@ 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));
}
@@ -79,7 +79,7 @@ void set_device_ro(int dev,int flag)
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));
}
@@ -222,7 +222,7 @@ void ll_rw_page(int rw, int dev, int page, char * buffer)
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;
}
@@ -289,7 +289,7 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bh[])
}
};
- 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++)
@@ -332,7 +332,7 @@ void ll_rw_swap_file(int rw, int dev, unsigned int *b, int nb, char *buf)
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;
}
diff --git a/kernel/blk_drv/ramdisk.c b/kernel/blk_drv/ramdisk.c
index 3bdcf5d..a151827 100644
--- a/kernel/blk_drv/ramdisk.c
+++ b/kernel/blk_drv/ramdisk.c
@@ -67,8 +67,11 @@ long rd_init(long mem_start, int length)
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;
diff --git a/kernel/blk_drv/scsi/fdomain.c b/kernel/blk_drv/scsi/fdomain.c
index 35d7b60..e9a74db 100644
--- a/kernel/blk_drv/scsi/fdomain.c
+++ b/kernel/blk_drv/scsi/fdomain.c
@@ -1,6 +1,6 @@
/* 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
*
@@ -108,7 +108,7 @@
#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 */
@@ -169,7 +169,6 @@ static int this_host = 0;
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,
@@ -646,7 +645,6 @@ void my_done( int error )
{
if (in_command) {
in_command = 0;
- in_interrupt_code = 0;
outb( 0x00, Interrupt_Cntl_port );
fdomain_make_bus_idle();
current_SC->result = error;
@@ -664,14 +662,14 @@ void fdomain_16x0_intr( int unused )
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))
@@ -693,12 +691,6 @@ void fdomain_16x0_intr( int unused )
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 ) );
@@ -735,7 +727,6 @@ void fdomain_16x0_intr( int unused )
/* 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 );
@@ -756,7 +747,6 @@ void fdomain_16x0_intr( int unused )
}
}
current_SC->SCp.phase = in_other;
- in_interrupt_code = 0;
outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
#if RESELECTION
outb( 0x88, SCSI_Cntl_port );
@@ -979,7 +969,6 @@ void fdomain_16x0_intr( int unused )
#endif
} else {
- in_interrupt_code = 0;
if (current_SC->SCp.phase & disconnect) {
outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port );
outb( 0x00, SCSI_Cntl_port );
@@ -1239,9 +1228,8 @@ int fdomain_16x0_abort( Scsi_Cmnd *SCpnt, int code )
#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,
diff --git a/kernel/blk_drv/scsi/sd.c b/kernel/blk_drv/scsi/sd.c
index ca3c935..1481795 100644
--- a/kernel/blk_drv/scsi/sd.c
+++ b/kernel/blk_drv/scsi/sd.c
@@ -761,7 +761,10 @@ unsigned long sd_init(unsigned long memory_start, unsigned long memory_end)
{
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;
diff --git a/kernel/blk_drv/scsi/sr.c b/kernel/blk_drv/scsi/sr.c
index 63a7509..5b483fc 100644
--- a/kernel/blk_drv/scsi/sr.c
+++ b/kernel/blk_drv/scsi/sr.c
@@ -601,7 +601,10 @@ unsigned long sr_init(unsigned long memory_start, unsigned long memory_end)
{
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;
diff --git a/kernel/blk_drv/scsi/st.c b/kernel/blk_drv/scsi/st.c
index 703c75c..ec8f77d 100644
--- a/kernel/blk_drv/scsi/st.c
+++ b/kernel/blk_drv/scsi/st.c
@@ -1224,7 +1224,10 @@ unsigned long st_init(unsigned long mem_start, unsigned long mem_end)
{
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
diff --git a/kernel/blk_drv/scsi/wd7000.c b/kernel/blk_drv/scsi/wd7000.c
index 704fc82..db402ad 100644
--- a/kernel/blk_drv/scsi/wd7000.c
+++ b/kernel/blk_drv/scsi/wd7000.c
@@ -506,24 +506,7 @@ void wd7000_revision(void)
}
-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;
diff --git a/kernel/chr_drv/console.c b/kernel/chr_drv/console.c
index cfd4a51..c722e84 100644
--- a/kernel/chr_drv/console.c
+++ b/kernel/chr_drv/console.c
@@ -226,8 +226,8 @@ static char * translations[] = {
"\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"
diff --git a/kernel/chr_drv/keyboard.c b/kernel/chr_drv/keyboard.c
index c44e57b..803491f 100644
--- a/kernel/chr_drv/keyboard.c
+++ b/kernel/chr_drv/keyboard.c
@@ -154,7 +154,7 @@ static void put_queue(int ch)
struct tty_queue *qp;
unsigned long new_head;
- wake_up_interruptible(&keypress_wait);
+ wake_up(&keypress_wait);
if (!tty)
return;
qp = &tty->read_q;
diff --git a/kernel/chr_drv/lp.c b/kernel/chr_drv/lp.c
index 2faccb7..f7bcf21 100644
--- a/kernel/chr_drv/lp.c
+++ b/kernel/chr_drv/lp.c
@@ -233,7 +233,8 @@ long lp_init(long kmem_start)
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 */
diff --git a/kernel/chr_drv/mem.c b/kernel/chr_drv/mem.c
index 967efe0..186e830 100644
--- a/kernel/chr_drv/mem.c
+++ b/kernel/chr_drv/mem.c
@@ -336,7 +336,8 @@ static struct file_operations memory_fops = {
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);
diff --git a/kernel/chr_drv/mouse.c b/kernel/chr_drv/mouse.c
index a67c567..9a03f09 100644
--- a/kernel/chr_drv/mouse.c
+++ b/kernel/chr_drv/mouse.c
@@ -18,6 +18,7 @@
#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
@@ -90,6 +91,7 @@ unsigned long mouse_init(unsigned long kmem_start)
#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;
}
diff --git a/kernel/chr_drv/serial.c b/kernel/chr_drv/serial.c
index 7da8ca6..c6af7c6 100644
--- a/kernel/chr_drv/serial.c
+++ b/kernel/chr_drv/serial.c
@@ -524,7 +524,6 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
if (info->blocked_open) {
shutdown(info);
startup(info);
- wake_up_interruptible(&info->open_wait);
return;
}
if (info->flags & ASYNC_INITIALIZED) {
@@ -737,7 +736,8 @@ static int set_serial_info(struct async_struct * info,
}
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;
@@ -1275,7 +1275,7 @@ long rs_init(long kmem_start)
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) {
diff --git a/kernel/chr_drv/tty_io.c b/kernel/chr_drv/tty_io.c
index 4a91925..ed8f18f 100644
--- a/kernel/chr_drv/tty_io.c
+++ b/kernel/chr_drv/tty_io.c
@@ -213,6 +213,7 @@ static struct file_operations hung_up_tty_fops = {
void tty_hangup(struct tty_struct * tty)
{
struct file * filp;
+ struct task_struct **p;
int dev;
if (!tty)
@@ -233,6 +234,12 @@ void tty_hangup(struct tty_struct * 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)
@@ -463,9 +470,10 @@ void copy_to_cooked(struct tty_struct * tty)
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 ||
@@ -485,8 +493,7 @@ void copy_to_cooked(struct tty_struct * tty)
}
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) &&
@@ -505,39 +512,42 @@ void copy_to_cooked(struct tty_struct * tty)
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;
@@ -553,9 +563,15 @@ void copy_to_cooked(struct tty_struct * tty)
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);
@@ -644,6 +660,10 @@ static int read_chan(struct tty_struct * tty, struct file * file, char * buf, in
}
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);
@@ -680,8 +700,6 @@ static int read_chan(struct tty_struct * tty, struct file * file, char * buf, in
TTY_WRITE_FLUSH(tty->link);
if (!EMPTY(&tty->secondary))
continue;
- if (hung_up(file))
- break;
current->state = TASK_INTERRUPTIBLE;
if (EMPTY(&tty->secondary))
schedule();
@@ -819,7 +837,8 @@ static int tty_read(struct inode * inode, struct file * file, char * buf, int co
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))
@@ -1391,9 +1410,10 @@ long tty_init(long kmem_start)
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;
diff --git a/mm/memory.c b/mm/memory.c
index bde475b..c9b973a 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -917,6 +917,7 @@ void mem_init(unsigned long start_low_mem,
int datapages = 0;
unsigned long tmp;
unsigned short * p;
+ extern int etext;
cli();
end_mem &= 0xfffff000;
@@ -946,10 +947,10 @@ void mem_init(unsigned long start_low_mem,
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;
@@ -959,7 +960,7 @@ void mem_init(unsigned long start_low_mem,
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,
diff --git a/net/tcp/dev.c b/net/tcp/dev.c
index 438cfd6..90ce81f 100644
--- a/net/tcp/dev.c
+++ b/net/tcp/dev.c
@@ -481,6 +481,8 @@ dev_tint( struct device *dev)
sti();
/* this will send it through the process again. */
dev->queue_xmit (skb, dev, -i-1);
+ if (dev->tbusy)
+ return;
}
}
}
diff --git a/net/tcp/ip.c b/net/tcp/ip.c
index e83b865..584765a 100644
--- a/net/tcp/ip.c
+++ b/net/tcp/ip.c
@@ -834,7 +834,7 @@ ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
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);
diff --git a/tools/build.c b/tools/build.c
index 8dd7ccf..86ba0c3 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -29,6 +29,7 @@
#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
@@ -83,8 +84,9 @@ void usage(void)
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;
@@ -116,9 +118,9 @@ int main(int argc, char ** argv)
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'");
@@ -145,9 +147,9 @@ int main(int argc, char ** argv)
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'");
@@ -156,6 +158,8 @@ int main(int argc, char ** argv)
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)
@@ -176,14 +180,28 @@ int main(int argc, char ** argv)
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);
}
diff --git a/zBoot/Makefile b/zBoot/Makefile
new file mode 100644
index 0000000..35081f8
--- /dev/null
+++ b/zBoot/Makefile
@@ -0,0 +1,36 @@
+
+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
diff --git a/zBoot/crypt.h b/zBoot/crypt.h
new file mode 100644
index 0000000..f4aac50
--- /dev/null
+++ b/zBoot/crypt.h
@@ -0,0 +1,12 @@
+/* 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
diff --git a/zBoot/gzip.h b/zBoot/gzip.h
new file mode 100644
index 0000000..2f738b9
--- /dev/null
+++ b/zBoot/gzip.h
@@ -0,0 +1,284 @@
+/* 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));
diff --git a/zBoot/head.S b/zBoot/head.S
new file mode 100644
index 0000000..eb27b2b
--- /dev/null
+++ b/zBoot/head.S
@@ -0,0 +1,38 @@
+/*
+ * 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
diff --git a/zBoot/inflate.c b/zBoot/inflate.c
new file mode 100644
index 0000000..b261914
--- /dev/null
+++ b/zBoot/inflate.c
@@ -0,0 +1,995 @@
+#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;
+}
diff --git a/zBoot/lzw.h b/zBoot/lzw.h
new file mode 100644
index 0000000..b1901f7
--- /dev/null
+++ b/zBoot/lzw.h
@@ -0,0 +1,42 @@
+/* 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));
diff --git a/zBoot/misc.c b/zBoot/misc.c
new file mode 100644
index 0000000..d641ba4
--- /dev/null
+++ b/zBoot/misc.c
@@ -0,0 +1,417 @@
+#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;
+}
diff --git a/zBoot/piggyback.c b/zBoot/piggyback.c
new file mode 100644
index 0000000..907cb9b
--- /dev/null
+++ b/zBoot/piggyback.c
@@ -0,0 +1,32 @@
+#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);
+
+}
diff --git a/zBoot/unzip.c b/zBoot/unzip.c
new file mode 100644
index 0000000..d752b5e
--- /dev/null
+++ b/zBoot/unzip.c
@@ -0,0 +1,178 @@
+/* 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 */
+}
diff --git a/zBoot/xtract.c b/zBoot/xtract.c
new file mode 100644
index 0000000..40f3af1
--- /dev/null
+++ b/zBoot/xtract.c
@@ -0,0 +1,95 @@
+/*
+ * 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);
+}