first commit

This commit is contained in:
寂静的羽夏 2022-08-09 11:52:58 +08:00
parent 1866571ecd
commit 514070a18f
183 changed files with 15257 additions and 61 deletions

View File

@ -8,7 +8,7 @@
## 说明
  本 Bochs 包是基于`linux-0.11-devel-060625`文件制作,其相关文件可以从 [该链接](http://www.oldlinux.org/Linux.old/bochs/) 进行下载。由于原包是用于 Win 平台学习的,没有对 Linux 进行制作,主要是配置文件需要修改。如果直接使用原配置文件, Bochs 无法读取正确的配置,导致错误。
  本 Bochs 包是基于`linux-0.11-gdb-050619.tar.gz`文件制作,其相关文件可以从 [该链接](http://www.oldlinux.org/Linux.old/bochs/) 进行下载。由于原包是用于 Win 平台学习的,没有对 Linux 进行制作,主要是配置文件需要修改。如果直接使用原配置文件, Bochs 无法读取正确的配置,导致错误。
## 相关仓库

View File

@ -29,17 +29,17 @@
00000000000i[ ] SB16 support: no
00000000000i[ ] USB support: no
00000000000i[ ] VGA extension support: vbe
00000000000i[MEM0 ] allocated memory at 0x7f8f62737010. after alignment, vector=0x7f8f62738000
00000000000i[MEM0 ] allocated memory at 0x7fd71f02c010. after alignment, vector=0x7fd71f02d000
00000000000i[MEM0 ] 16.00MB
00000000000i[MEM0 ] mem block size = 0x00100000, blocks=16
00000000000i[MEM0 ] rom at 0xfffe0000/131072 ('/usr/local/share/bochs/BIOS-bochs-latest')
00000000000i[MEM0 ] rom at 0xc0000/40448 ('/usr/local/share/bochs/VGABIOS-lgpl-latest')
00000000000i[CMOS ] Using local time for initial clock
00000000000i[CMOS ] Setting initial clock to: Mon Aug 8 23:25:11 2022 (time0=1659972311)
00000000000i[CMOS ] Setting initial clock to: Tue Aug 9 11:49:10 2022 (time0=1660016950)
00000000000i[DMA ] channel 4 used by cascade
00000000000i[DMA ] channel 2 used by Floppy Drive
00000000000i[FDD ] fd0: 'bootimage-0.11-hd' ro=0, h=2,t=80,spt=18
00000000000i[FDD ] fd1: 'diskb.img' ro=0, h=2,t=80,spt=18
00000000000i[FDD ] fd0: 'linux/Image' ro=0, h=2,t=80,spt=18
00000000000i[FDD ] fd1: 'rootimage-0.11' ro=0, h=2,t=80,spt=18
00000000000i[VGA ] interval=50000
00000000000i[MEM0 ] Register memory access handlers: 0x000a0000 - 0x000bffff
00000000000i[XGUI ] test_alloc_colors: 16 colors available out of 16 colors tried
@ -61,9 +61,7 @@
00000000000i[ ] init_dev of 'keyboard' plugin device by virtual method
00000000000i[KBD ] will paste characters every 1000 keyboard ticks
00000000000i[ ] init_dev of 'harddrv' plugin device by virtual method
00000000000i[HD ] HD on ata0-0: 'hdc-0.11-new.img' 'flat' mode
00000000000i[HD ] translation on ata0-0 set to 'none'
00000000000i[HD ] Using boot sequence disk, none, none
00000000000i[HD ] Using boot sequence floppy, none, none
00000000000i[HD ] Floppy boot signature check is enabled
00000000000i[ ] init_dev of 'serial' plugin device by virtual method
00000000000i[SER ] com1 at 0x03f8 irq 4
@ -117,29 +115,25 @@
00000802750i[BIOS ] Found 1 cpu(s)
00000822019i[BIOS ] bios_table_addr: 0x000fbc18 end=0x000fcc00
00000834696i[BIOS ] bios_table_cur_addr: 0x000fbc18
00000847165i[BIOS ] ata0-0: PCHS=410/16/38 translation=none LCHS=410/16/38
00004727457i[BIOS ] IDE time out
00016726503i[BIOS ] Booting from 0000:7c00
00076400000i[XGUI ] charmap update. Font Height is 16
00079680461i[BIOS ] int13_harddisk: function 15, unmapped device for ELDL=81
01143284000i[ ] dbg: Quit
01143284000i[CPU0 ] CPU is in protected mode (active)
01143284000i[CPU0 ] CS.d_b = 32 bit
01143284000i[CPU0 ] SS.d_b = 32 bit
01143284000i[CPU0 ] | EAX=00018194 EBX=00000003 ECX=0003e400 EDX=00000017
01143284000i[CPU0 ] | ESP=00019148 EBP=0001915c ESI=000e0000 EDI=00019284
01143284000i[CPU0 ] | IOPL=0 id vip vif ac vm rf nt of DF IF tf sf zf af pf cf
01143284000i[CPU0 ] | SEG selector base limit G D
01143284000i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
01143284000i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 00ffffff 1 1
01143284000i[CPU0 ] | DS:0010( 0002| 0| 0) 00000000 00ffffff 1 1
01143284000i[CPU0 ] | SS:0010( 0002| 0| 0) 00000000 00ffffff 1 1
01143284000i[CPU0 ] | ES:0010( 0002| 0| 0) 00000000 00ffffff 1 1
01143284000i[CPU0 ] | FS:0017( 0002| 1| 3) 00000000 0009ffff 1 1
01143284000i[CPU0 ] | GS:0017( 0002| 1| 3) 00000000 0009ffff 1 1
01143284000i[CPU0 ] | EIP=00006bfa (00006bfa)
01143284000i[CPU0 ] | CR0=0x8000001b CR2=0x0805ec0c
01143284000i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
01143284000i[CMOS ] Last time is 1659972596 (Mon Aug 8 23:29:56 2022)
01143284000i[XGUI ] Exit
01143284000i[CTRL ] quit_sim called with exit code 0
00012943036i[BIOS ] Booting from 0000:7c00
00012943097i[ ] dbg: Quit
00012943097i[CPU0 ] CPU is in real mode (active)
00012943097i[CPU0 ] CS.d_b = 16 bit
00012943097i[CPU0 ] SS.d_b = 16 bit
00012943097i[CPU0 ] | EAX=0000aa55 EBX=00000000 ECX=00000000 EDX=00000000
00012943097i[CPU0 ] | ESP=0000ffd6 EBP=00000000 ESI=000e32f8 EDI=0000ffac
00012943097i[CPU0 ] | IOPL=0 id vip vif ac vm rf nt of df if tf SF zf af pf cf
00012943097i[CPU0 ] | SEG selector base limit G D
00012943097i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00012943097i[CPU0 ] | CS:0000( 0004| 0| 0) 00000000 0000ffff 0 0
00012943097i[CPU0 ] | DS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00012943097i[CPU0 ] | SS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00012943097i[CPU0 ] | ES:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00012943097i[CPU0 ] | FS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00012943097i[CPU0 ] | GS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00012943097i[CPU0 ] | EIP=00007c00 (00007c00)
00012943097i[CPU0 ] | CR0=0x60000010 CR2=0x00000000
00012943097i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00012943097i[CMOS ] Last time is 1660016953 (Tue Aug 9 11:49:13 2022)
00012943097i[XGUI ] Exit
00012943097i[CTRL ] quit_sim called with exit code 0

View File

@ -57,13 +57,13 @@ vgaromimage: file=/usr/local/share/bochs/VGABIOS-lgpl-latest
# drive letters such as a: or b: as the path. Raw floppy access is not
# supported on Windows 95 and 98.
#=======================================================================
floppya: 1_44="bootimage-0.11-hd", status=inserted
floppya: 1_44="linux/Image", status=inserted
#=======================================================================
# FLOPPYB:
# See FLOPPYA above for syntax
#=======================================================================
floppyb: 1_44=diskb.img, status=inserted
floppyb: 1_44="rootimage-0.11", status=inserted
#=======================================================================
# BOOT:
@ -71,8 +71,8 @@ floppyb: 1_44=diskb.img, status=inserted
# which can be 'floppy', 'disk', 'cdrom' or 'network' (boot ROM).
# Legacy 'a' and 'c' are also supported.
#=======================================================================
#boot: floppy
boot: disk
boot: floppy
#boot: disk
#=======================================================================
# LOG:
@ -107,25 +107,3 @@ mouse: enabled=0
# If enabled, the keymap file must be specified.
#=======================================================================
keyboard_mapping: enabled=1, map=/usr/local/share/bochs/keymaps/x11-pc-us.map
#=======================================================================
# ATA0, ATA1, ATA2, ATA3
# ATA controller for hard disks and cdroms
#
# ata[0-3]: enabled=[0|1], ioaddr1=addr, ioaddr2=addr, irq=number
#
# These options enables up to 4 ata channels. For each channel
# the two base io addresses and the irq must be specified.
#
# ata0 and ata1 are enabled by default with the values shown below
#=======================================================================
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=disk, path="hdc-0.11-new.img", mode=flat, cylinders=410, heads=16, spt=38
#=======================================================================
# DISKD:
# See DISKC above for syntax
#
# NOTE: diskd and cdromd must not be used together!
#=======================================================================
#diskd: file="diskd.img", cyl=615, heads=6, spt=17

Binary file not shown.

Binary file not shown.

BIN
diska.img

Binary file not shown.

BIN
diskb.img

Binary file not shown.

Binary file not shown.

Binary file not shown.

126
linux/Makefile Normal file
View File

@ -0,0 +1,126 @@
#
# if you want the ram-disk device, define this to be the
# size in blocks.
#
RAMDISK = #-DRAMDISK=512
AS86 =as86 -0 -a
LD86 =ld86 -0
AS =gas
LD =gld
LDFLAGS =-x -M #-s
CC =gcc $(RAMDISK)
CFLAGS =-Wall -O -g -fstrength-reduce -fomit-frame-pointer \
-fcombine-regs #-mstring-insns
CPP =cpp -nostdinc -Iinclude
#
# ROOT_DEV specifies the default root-device when making the image.
# This can be either FLOPPY, /dev/xxxx or empty, in which case the
# default of /dev/hd6 is used by 'build'.
#
ROOT_DEV=/dev/fd1 # /dev/hd1
ARCHIVES=kernel/kernel.o mm/mm.o fs/fs.o
DRIVERS =kernel/blk_drv/blk_drv.a kernel/chr_drv/chr_drv.a
MATH =kernel/math/math.a
LIBS =lib/lib.a
.c.s:
$(CC) $(CFLAGS) \
-nostdinc -Iinclude -S -o $*.s $<
.s.o:
$(AS) -c -o $*.o $<
.c.o:
$(CC) $(CFLAGS) \
-nostdinc -Iinclude -c -o $*.o $<
all: Image
Image: boot/bootsect boot/setup tools/system tools/build
cp -f tools/system system.tmp
strip system.tmp
tools/build boot/bootsect boot/setup system.tmp $(ROOT_DEV) > Image
rm -f system.tmp
sync
disk: Image
dd bs=8192 if=Image of=/dev/PS0
tools/build: tools/build.c
$(CC) $(CFLAGS) \
-o tools/build tools/build.c
boot/head.o: boot/head.s
tools/system: boot/head.o init/main.o \
$(ARCHIVES) $(DRIVERS) $(MATH) $(LIBS)
$(LD) $(LDFLAGS) boot/head.o init/main.o \
$(ARCHIVES) \
$(DRIVERS) \
$(MATH) \
$(LIBS) \
-o tools/system > System.map
kernel/math/math.a:
(cd kernel/math; make)
kernel/blk_drv/blk_drv.a:
(cd kernel/blk_drv; make)
kernel/chr_drv/chr_drv.a:
(cd kernel/chr_drv; make)
kernel/kernel.o:
(cd kernel; make)
mm/mm.o:
(cd mm; make)
fs/fs.o:
(cd fs; make)
lib/lib.a:
(cd lib; make)
boot/setup: boot/setup.s
$(AS86) -o boot/setup.o boot/setup.s
$(LD86) -s -o boot/setup boot/setup.o
boot/bootsect: boot/bootsect.s
$(AS86) -o boot/bootsect.o boot/bootsect.s
$(LD86) -s -o boot/bootsect boot/bootsect.o
tmp.s: boot/bootsect.s tools/system
(echo -n "SYSSIZE = (";ls -l tools/system | grep system \
| cut -c25-31 | tr '\012' ' '; echo "+ 15 ) / 16") > tmp.s
cat boot/bootsect.s >> tmp.s
clean:
rm -f Image System.map tmp_make core boot/bootsect boot/setup
rm -f init/*.o tools/system tools/build boot/*.o
(cd mm;make clean)
(cd fs;make clean)
(cd kernel;make clean)
(cd lib;make clean)
backup: clean
(cd .. ; tar cf - linux | compress - > backup.Z)
sync
dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
(for i in init/*.c;do echo -n "init/";$(CPP) -M $$i;done) >> tmp_make
cp tmp_make Makefile
(cd fs; make dep)
(cd kernel; make dep)
(cd mm; make dep)
### Dependencies:
init/main.o : init/main.c include/unistd.h include/sys/stat.h \
include/sys/types.h include/sys/times.h include/sys/utsname.h \
include/utime.h include/time.h include/linux/tty.h include/termios.h \
include/linux/sched.h include/linux/head.h include/linux/fs.h \
include/linux/mm.h include/signal.h include/asm/system.h include/asm/io.h \
include/stddef.h include/stdarg.h include/fcntl.h

756
linux/System.map Normal file
View File

@ -0,0 +1,756 @@
kernel/blk_drv/blk_drv.a(ll_rw_blk.o) needed due to _ll_rw_block
kernel/blk_drv/blk_drv.a(floppy.o) needed due to _do_floppy
kernel/blk_drv/blk_drv.a(hd.o) needed due to _do_hd
kernel/blk_drv/blk_drv.a(ramdisk.o) needed due to _rd_load
kernel/chr_drv/chr_drv.a(tty_io.o) needed due to _tty_table
kernel/chr_drv/chr_drv.a(console.o) needed due to _con_write
kernel/chr_drv/chr_drv.a(keyboard.o) needed due to _keyboard_interrupt
kernel/chr_drv/chr_drv.a(serial.o) needed due to _rs_init
kernel/chr_drv/chr_drv.a(rs_io.o) needed due to _rs1_interrupt
kernel/chr_drv/chr_drv.a(tty_ioctl.o) needed due to _tty_ioctl
kernel/math/math.a(math_emulate.o) needed due to _math_emulate
lib/lib.a(ctype.o) needed due to __ctype
lib/lib.a(_exit.o) needed due to __exit
lib/lib.a(open.o) needed due to _open
lib/lib.a(close.o) needed due to _close
lib/lib.a(write.o) needed due to _write
lib/lib.a(dup.o) needed due to _dup
lib/lib.a(setsid.o) needed due to _setsid
lib/lib.a(execve.o) needed due to _execve
lib/lib.a(wait.o) needed due to _wait
lib/lib.a(string.o) needed due to _memcpy
Allocating common _drive_info: 20 at 1dd6c
Allocating common _hash_table: 4cc at 1dd8c
Allocating common __ctmp: 4 at 1e258
Allocating common _user_stack: 1000 at 1e25c
Allocating common _file_table: 400 at 1f25c
Allocating common _rd_start: 4 at 1f65c
Allocating common ____strtok: 4 at 1f660
Allocating common _request: 480 at 1f664
Allocating common _errno: 4 at 1fae4
Allocating common _super_block: 360 at 1fae8
Files:
boot/head.o text 0(64b8), data 18000(0), bss 1d1e0(0) hex
init/main.o text 64b8(57c), data 18000(34), bss 1d1e0(400) hex
kernel/kernel.o text 6a34(3fd0), data 18034(1318), bss 1d5e0(700) hex
mm/mm.o text aa04(e8c), data 1934c(f08), bss 1dce0(0) hex
fs/fs.o text b890(543c), data 1a254(758), bss 1dce0(8) hex
kernel/blk_drv/blk_drv.a(ll_rw_blk.o) text 10ccc(2cc), data 1a9ac(3c), bss 1dce8(0) hex
kernel/blk_drv/blk_drv.a(floppy.o) text 10f98(1bd4), data 1a9e8(e8), bss 1dce8(7) hex
kernel/blk_drv/blk_drv.a(hd.o) text 12b6c(1244), data 1aad0(94), bss 1dcef(0) hex
kernel/blk_drv/blk_drv.a(ramdisk.o) text 13db0(4f8), data 1ab64(4), bss 1dcef(0) hex
kernel/chr_drv/chr_drv.a(tty_io.o) text 142a8(924), data 1ab68(253c), bss 1dcef(0) hex
kernel/chr_drv/chr_drv.a(console.o) text 14bcc(141c), data 1d0a4(18), bss 1dcef(7c) hex
kernel/chr_drv/chr_drv.a(keyboard.o) text 15fe8(7e4), data 1d0bc(0), bss 1dd6b(0) hex
kernel/chr_drv/chr_drv.a(serial.o) text 167cc(148), data 1d0bc(0), bss 1dd6b(0) hex
kernel/chr_drv/chr_drv.a(rs_io.o) text 16914(f8), data 1d0bc(0), bss 1dd6b(0) hex
kernel/chr_drv/chr_drv.a(tty_ioctl.o) text 16a0c(374), data 1d0bc(20), bss 1dd6b(0) hex
kernel/math/math.a(math_emulate.o) text 16d80(d4), data 1d0dc(0), bss 1dd6b(0) hex
lib/lib.a(ctype.o) text 16e54(0), data 1d0dc(104), bss 1dd6b(0) hex
lib/lib.a(_exit.o) text 16e54(10), data 1d1e0(0), bss 1dd6b(0) hex
lib/lib.a(open.o) text 16e64(28), data 1d1e0(0), bss 1dd6b(0) hex
lib/lib.a(close.o) text 16e8c(20), data 1d1e0(0), bss 1dd6b(0) hex
lib/lib.a(write.o) text 16eac(28), data 1d1e0(0), bss 1dd6b(0) hex
lib/lib.a(dup.o) text 16ed4(20), data 1d1e0(0), bss 1dd6b(0) hex
lib/lib.a(setsid.o) text 16ef4(18), data 1d1e0(0), bss 1dd6b(0) hex
lib/lib.a(execve.o) text 16f0c(28), data 1d1e0(0), bss 1dd6b(0) hex
lib/lib.a(wait.o) text 16f34(54), data 1d1e0(0), bss 1dd6b(0) hex
lib/lib.a(string.o) text 16f88(340), data 1d1e0(0), bss 1dd6b(0) hex
Global symbols:
_dup: 0x16ed4
_nmi: 0x8e28
_bmap: 0xc3a8
_iput: 0xc3f8
_blk_dev_init: 0x10f6c
_open: 0x16e64
_do_execve: 0xe458
_con_init: 0x15d74
_put_super: 0xd42c
_sys_setgid: 0x9b84
_sys_umask: 0x9f84
_con_write: 0x1500c
_show_task: 0x6a74
_buffer_init: 0xd284
_sys_settimeofday: 0x9f7c
_sys_getgroups: 0x9f0c
_tmp_floppy_area: 0x5000
_get_free_page: 0xaa14
_schedule: 0x6b8c
_copy_mem: 0x8f48
_sys_times: 0x9da4
_release: 0x9fc8
_sys_uname: 0x9f1c
_table_list: 0x1d088
_sysbeepstop: 0x15f84
_bounds: 0x8e3d
_sys_execve: 0x752c
_keyboard_interrupt: 0x15feb
_sys_rmdir: 0xfce4
_vsprintf: 0x970c
_put_page: 0xae5c
_getblk: 0xcdcc
_floppy_init: 0x12ad8
_sys_sigsuspend: 0xa744
_floppy_change: 0x11040
_sys_setgroups: 0x9f14
_sys_setup: 0x12c28
_strtok: 0x1718c
_check_disk_change: 0xcc30
_stack_start: 0x192a4
_free_page: 0xaa80
_sys_pause: 0x6c94
_create_block: 0xc3c0
_page_fault: 0xb858
_drive_info: 0x1dd6c
_do_tty_interrupt: 0x14bb0
_strstr: 0x17140
_truncate: 0x10c28
_hash_table: 0x1dd8c
_do_wp_page: 0xafe0
_strspn: 0x170a4
_hd_interrupt: 0x7554
_unexpected_hd_interrupt: 0x13178
__ctmp: 0x1e258
_system_call: 0x7418
_nr_buffers: 0x1a960
__exit: 0x16e54
_strcat: 0x16fc4
__edata: 0x1d1e0
_strcmp: 0x17014
_double_fault: 0x8e6e
_strchr: 0x17064
_strlen: 0x17174
_strcpy: 0x16f88
_last_pid: 0x192e4
_get_hash_table: 0xcd68
_blk_dev: 0x1a9b0
_rs2_interrupt: 0x1691c
_timer_interrupt: 0x74f4
_setup_rw_floppy: 0x11460
_sys_call_table: 0x18034
_math_error: 0x16e3c
_rd_load: 0x140f4
_find_empty_process: 0x93d4
_tty_write: 0x149e0
_pg_dir: 0x0
_open_namei: 0xf4fc
_rs1_interrupt: 0x16914
_last_task_used_math: 0x191a0
_copy_process: 0x9024
_sys_getrlimit: 0x9f5c
_rd_length: 0x1ab64
_parallel_interrupt: 0x75c6
_do_timer: 0x70a4
_rd_init: 0x13fe0
_ll_rw_block: 0x10f2c
_printk: 0x94a4
_invalidate_buffers: 0xcbac
_floppy_interrupt: 0x7590
_unexpected_floppy_interrupt: 0x12408
_new_inode: 0x107bc
_floppy_deselect: 0x1100c
__etext: 0x18000
_tty_read: 0x1474c
_sys_sgetmask: 0xa710
__ctype: 0x1d0dc
_strrchr: 0x17084
_sys_getpid: 0x7228
_sys_chroot: 0xb9e8
_do_double_fault: 0x7660
_strpbrk: 0x1710c
_tty_init: 0x142a8
_file_write: 0xdec8
_sys_setrlimit: 0x9f64
_sys_getuid: 0x7240
_current: 0x1919c
_jiffies: 0x19194
_divide_error: 0x8dec
_get_super: 0xd394
_do_signal: 0xa888
_file_read: 0xddac
_tty_table: 0x1ab68
_sys_mpx: 0x9c08
_strncpy: 0x16fa0
_sys_access: 0xb8f8
_chr_dev_init: 0x14bc8
_start_buffer: 0x1a958
_user_stack: 0x1e25c
_tty_intr: 0x142b4
_write_verify: 0xb0c4
_coprocessor_error: 0x7494
_do_coprocessor_error: 0x88f8
_sys_dup: 0x109e4
_strncat: 0x16fe8
_get_empty_inode: 0xc52c
_sys_brk: 0x9df0
_do_general_protection: 0x77c0
_general_protection: 0x8eba
_strncmp: 0x17038
_sys_getgid: 0x7260
_overflow: 0x8e36
_strcspn: 0x170d8
_setsid: 0x16ef4
_sync_dev: 0xca9c
_do_int3: 0x7af4
_new_block: 0x10468
_rs_write: 0x168ec
_file_table: 0x1f25c
_read_pipe: 0xec0c
_tty_ioctl: 0x16a20
_sys_readlink: 0xe108
_sys_getrusage: 0x9f6c
_sys_sigaction: 0xa7b8
_do_divide_error: 0x7918
_sys_kill: 0xa010
_memmove: 0x17224
_sys_lock: 0x9c00
_sys_link: 0x100c4
_wait_on_floppy_select: 0x1aacc
_sys_nice: 0x7280
_sys_gtty: 0x9ae4
_do_exit: 0xa29c
_sys_sigpending: 0xa73c
_kernel_mktime: 0xa984
_wait_for_keypress: 0x142f0
_sys_symlink: 0x100bc
_sys_exit: 0xa528
_current_DOR: 0x192dc
_sleep_on: 0x6cc0
_sys_open: 0xbb10
_device_not_available: 0x74b8
_do_device_not_available: 0x821c
_sys_fork: 0x753c
_invalid_TSS: 0x8ea5
_rd_start: 0x1f65c
_sys_acct: 0x9bf0
_sys_ssetmask: 0xa71c
_do_debug: 0x7cb8
_block_read: 0xdb34
_sys_dup2: 0x109c4
__end: 0x1fe48
_sys_stty: 0x9adc
_do_invalid_TSS: 0x84dc
_do_no_page: 0xb498
_sys_getpgrp: 0x9eac
_sys_sync: 0xca34
_sys_prof: 0x9af4
_write: 0x16eac
_reserved: 0x8e52
_sys_stat: 0xe080
_wait_for_request: 0x1a9ac
_mount_root: 0xd8ec
_write_pipe: 0xecec
_sys_getppid: 0x7234
_do_rd_request: 0x13e50
_sys_mkdir: 0xf8cc
_startup_time: 0x19198
_memset: 0x172ac
_sys_setreuid: 0x9c50
_sys_creat: 0xbcdc
_verify_area: 0x8ec4
_sys_time: 0x9c18
_sys_mknod: 0xf748
_sys_break: 0x9acc
_sys_pipe: 0xede4
_sys_phys: 0x9bf8
_sys_read: 0xbe3c
_do_nmi: 0x7b64
_do_hd_request: 0x136c4
_sys_fstat: 0xe0cc
_memcpy: 0x1720c
_sys_ioctl: 0x10ad0
_sys_getegid: 0x7270
_sys_ptrace: 0x9ad4
_do_overflow: 0x7e0c
_free_page_tables: 0xab20
_sys_setregid: 0x9afc
_NR_syscalls: 0x18190
____strtok: 0x1f660
_math_emulate: 0x16dd0
_beepcount: 0x1d0b8
_do_coprocessor_segment_overrun: 0x8384
_coprocessor_segment_overrun: 0x8e4b
_memchr: 0x17280
_floppy_off: 0x6f44
_do_fd_request: 0x12718
_block_write: 0xda44
_memcmp: 0x1725c
_rw_char: 0xdd68
_ROOT_DEV: 0x1a964
_sys_mount: 0xd7b0
_do_floppy_timer: 0x6f54
_request: 0x1f664
_wake_up: 0x6d70
_sys_ftime: 0x9ac4
_copy_to_cooked: 0x14334
_waitpid: 0x16f34
_free_block: 0x102e4
_inode_table: 0x1a254
_get_empty_page: 0xb1bc
_sys_uselib: 0xe110
_sys_geteuid: 0x7250
_math_state_restore: 0x6b30
_breada: 0xd1dc
_panic: 0x9468
_do_bounds: 0x7f60
_do_floppy: 0x1a9e8
_sys_lstat: 0xe0b8
_un_wp_page: 0xaf24
_brelse: 0xd010
_sys_rename: 0x9aec
_etext: 0x18000
_execve: 0x16f0c
_sys_setpgid: 0x9e24
_invalid_op: 0x8e44
_selected: 0x1aacb
_do_stack_segment: 0x8798
_stack_segment: 0x8eb3
_do_hd: 0x1aad0
_copy_page_tables: 0xacb8
_sys_umount: 0xd6c8
_sys_lseek: 0xbd7c
_sys_select: 0x10cc4
_sys_close: 0xbd0c
_invalidate_inodes: 0xc074
_namei: 0xf43c
_sys_waitpid: 0xa540
_sys_alarm: 0x71d4
_sys_chmod: 0xba44
_do_invalid_op: 0x80bc
_free_inode: 0x10690
_sys_chdir: 0xb98c
_sys_fcntl: 0x109f4
_trap_init: 0x8bbc
_sys_chown: 0xbab8
_task: 0x191a4
_interruptible_sleep_on: 0x6d08
_csi_m: 0x14ddc
_get_pipe_inode: 0xc640
_do_segment_not_present: 0x863c
_segment_not_present: 0x8eac
_ticks_to_floppy_on: 0x6d9c
_wait: 0x16f5c
_calc_mem: 0xb7d4
_sys_unlink: 0xff1c
_hd_info: 0x1aadc
_sys_ustat: 0xb890
_hd_init: 0x13d50
_errno: 0x1fae4
_sys_ulimit: 0x9c10
_sys_sethostname: 0x9f54
_bread: 0xd080
_do_reserved: 0x8a70
_rs_init: 0x167cc
_mem_init: 0xb758
_sys_gettimeofday: 0x9f74
_irq13: 0x8e59
_sys_stime: 0x9d60
_floppy_on: 0x6e40
_iget: 0xc6b0
_sys_signal: 0xa74c
_main: 0x664c
_bread_page: 0xd0ec
_init: 0x6884
_add_timer: 0x6ff8
_sys_setsid: 0x9eb8
_debug: 0x8e21
_close: 0x16e8c
_sys_setuid: 0x9cf4
_sys_utime: 0xb898
_show_stat: 0x6ac0
_edata: 0x1d1e0
_sched_init: 0x72bc
_end: 0x1fe48
_gdt: 0x5cb8
_super_block: 0x1fae8
_sync_inodes: 0xc0f8
_idt: 0x54b8
_sys_write: 0xbf6c
_int3: 0x8e2f
Local symbols of boot/head.o:
startup_32: 0x0
setup_idt: 0x6f
setup_gdt: 0x9f
check_x87: 0x5a
after_page_tables: 0x5400
ignore_int: 0x5428
rp_sidt: 0x8c
idt_descr: 0x54aa
gdt_descr: 0x54b2
pg0: 0x1000
pg1: 0x2000
pg2: 0x3000
pg3: 0x4000
setup_paging: 0x5450
int_msg: 0x5414
Local symbols of init/main.o:
gcc_compiled.: 0x64b8
_time_init: 0x64b8
_memory_end: 0x18000
_buffer_memory_end: 0x18004
_main_memory_start: 0x18008
_printf: 0x67b0
_printbuf: 0x1d1e0
_argv_rc: 0x1800c
_envp_rc: 0x18014
_argv: 0x18020
_envp: 0x18028
Local symbols of kernel/kernel.o:
sched.o: 0x6a34
gcc_compiled.: 0x6a34
_init_task: 0x18194
_wait_motor: 0x192ac
_mon_timer: 0x192bc
_moff_timer: 0x192cc
_next_timer: 0x192e0
_timer_list: 0x1d5e0
system_call.o: 0x7404
SIG_CHLD: 0x11
EAX: 0x0
EBX: 0x4
ECX: 0x8
EDX: 0xc
FS: 0x10
ES: 0x14
DS: 0x18
EIP: 0x1c
CS: 0x20
EFLAGS: 0x24
OLDESP: 0x28
OLDSS: 0x2c
state: 0x0
counter: 0x4
priority: 0x8
signal: 0xc
sigaction: 0x10
blocked: 0x210
sa_handler: 0x0
sa_mask: 0x4
sa_flags: 0x8
sa_restorer: 0xc
nr_system_calls: 0x56
bad_sys_call: 0x7404
reschedule: 0x740c
ret_from_sys_call: 0x744d
traps.o: 0x75d0
gcc_compiled.: 0x75d0
asm.o: 0x8dec
no_error_code: 0x8df1
error_code: 0x8e73
fork.o: 0x8ec4
gcc_compiled.: 0x8ec4
panic.o: 0x9434
gcc_compiled.: 0x9434
printk.o: 0x94a4
gcc_compiled.: 0x94a4
_buf: 0x1d8e0
vsprintf.o: 0x94dc
gcc_compiled.: 0x94dc
_number: 0x9528
sys.o: 0x9ac4
gcc_compiled.: 0x9ac4
_thisname.0: 0x192e8
exit.o: 0x9fa4
gcc_compiled.: 0x9fa4
signal.o: 0xa710
gcc_compiled.: 0xa710
mktime.o: 0xa984
gcc_compiled.: 0xa984
_month: 0x19318
Local symbols of mm/mm.o:
memory.o: 0xaa04
gcc_compiled.: 0xaa04
_HIGH_MEMORY: 0x1934c
_mem_map: 0x19350
_try_to_share: 0xb350
page.o: 0xb858
Local symbols of fs/fs.o:
open.o: 0xb890
gcc_compiled.: 0xb890
read_write.o: 0xbd7c
gcc_compiled.: 0xbd7c
inode.o: 0xc054
gcc_compiled.: 0xc054
_write_inode: 0xc92c
__bmap: 0xc174
_last_inode.0: 0x1a954
_read_inode: 0xc81c
file_table.o: 0xca34
gcc_compiled.: 0xca34
buffer.o: 0xca34
gcc_compiled.: 0xca34
_buffer_wait: 0x1a95c
_find_buffer: 0xcd28
_free_list: 0x1dce0
super.o: 0xd330
gcc_compiled.: 0xd330
_lock_super: 0xd330
_free_super: 0xd358
_wait_on_super: 0xd370
_read_super: 0xd4b8
block_dev.o: 0xda44
gcc_compiled.: 0xda44
char_dev.o: 0xdc00
gcc_compiled.: 0xdc00
_rw_ttyx: 0xdc00
_rw_tty: 0xdc2c
_rw_ram: 0xdc68
_rw_mem: 0xdc70
_rw_kmem: 0xdc78
_rw_port: 0xdc80
_rw_memory: 0xdcdc
_crw_table: 0x1a968
file_dev.o: 0xddac
gcc_compiled.: 0xddac
stat.o: 0xe004
gcc_compiled.: 0xe004
_cp_stat: 0xe004
exec.o: 0xe110
gcc_compiled.: 0xe110
_create_tables: 0xe118
_count: 0xe1c8
_copy_strings: 0xe1f8
_change_ldt: 0xe32c
pipe.o: 0xec0c
gcc_compiled.: 0xec0c
namei.o: 0xef28
gcc_compiled.: 0xef28
_permission: 0xef28
_match: 0xef9c
_find_entry: 0xefec
_add_entry: 0xf15c
_get_dir: 0xf2b4
_dir_namei: 0xf3f8
_empty_dir: 0xfb6c
bitmap.o: 0x10238
gcc_compiled.: 0x10238
fcntl.o: 0x1093c
gcc_compiled.: 0x1093c
_dupfd: 0x1093c
ioctl.o: 0x10ad0
gcc_compiled.: 0x10ad0
_ioctl_table: 0x1a988
truncate.o: 0x10b60
gcc_compiled.: 0x10b60
_free_ind: 0x10b60
_free_dind: 0x10bc4
select.o: 0x10cc4
gcc_compiled.: 0x10cc4
Local symbols of kernel/blk_drv/blk_drv.a(ll_rw_blk.o):
gcc_compiled.: 0x10ccc
_make_request: 0x10d18
Local symbols of kernel/blk_drv/blk_drv.a(floppy.o):
gcc_compiled.: 0x10f98
_recalibrate: 0x1a9ec
_reset: 0x1a9f0
_seek: 0x1a9f4
_floppy_type: 0x1a9f8
_cur_spec1: 0x1aab8
_cur_rate: 0x1aabc
_floppy: 0x1aac0
_current_drive: 0x1aac4
_sector: 0x1aac5
_head: 0x1aac6
_track: 0x1aac7
_seek_track: 0x1aac8
_current_track: 0x1aac9
_command: 0x1aaca
_bad_flp_intr: 0x110d8
_rw_interrupt: 0x11210
_reply_buffer: 0x1dce8
_seek_interrupt: 0x117f8
_transfer: 0x11ca4
_recal_interrupt: 0x12300
_reset_interrupt: 0x12504
_floppy_on_interrupt: 0x12b1c
Local symbols of kernel/blk_drv/blk_drv.a(hd.o):
gcc_compiled.: 0x12b6c
_recalibrate: 0x1aad4
_reset: 0x1aad8
_NR_HD: 0x1ab0c
_hd: 0x1ab10
_callable.0: 0x1ab60
_reset_hd: 0x12f94
_recal_intr: 0x13574
_read_intr: 0x13188
_write_intr: 0x13390
Local symbols of kernel/blk_drv/blk_drv.a(ramdisk.o):
gcc_compiled.: 0x13db0
Local symbols of kernel/chr_drv/chr_drv.a(tty_io.o):
gcc_compiled.: 0x142a8
_cr_flag.0: 0x1d0a0
Local symbols of kernel/chr_drv/chr_drv.a(console.o):
gcc_compiled.: 0x14bcc
_state: 0x1d0a4
_ques: 0x1d0a8
_attr: 0x1d0ac
_scrup: 0x14bcc
_video_type: 0x1dd6a
_top: 0x1dd37
_video_num_lines: 0x1dd5e
_bottom: 0x1dd33
_video_size_row: 0x1dd62
_origin: 0x1dd4b
_pos: 0x1dd43
_scr_end: 0x1dd47
_video_mem_end: 0x1dd55
_video_num_columns: 0x1dd66
_video_erase_char: 0x1dd4f
_video_mem_start: 0x1dd59
_video_port_reg: 0x1dd53
_video_port_val: 0x1dd51
_npar: 0x1dd2f
_par: 0x1dcef
_csi_L: 0x14eac
_y: 0x1dd3b
_saved_x: 0x1d0b0
_saved_y: 0x1d0b4
_x: 0x1dd3f
_sysbeep: 0x15f98
_video_page: 0x1dd5d
Local symbols of kernel/chr_drv/chr_drv.a(keyboard.o):
size: 0x400
head: 0x4
tail: 0x8
proc_list: 0xc
buf: 0x10
mode: 0x15fe8
leds: 0x15fe9
e0: 0x15fea
set_e0: 0x1603f
set_e1: 0x16048
key_table: 0x163ae
e0_e1: 0x16014
put_queue: 0x16051
ctrl: 0x1608a
alt: 0x1608e
unctrl: 0x160a2
unalt: 0x160a6
lshift: 0x160bc
unlshift: 0x160c4
rshift: 0x160cc
unrshift: 0x160d4
caps: 0x160dc
set_leds: 0x160fe
kb_wait: 0x167ae
uncaps: 0x16115
scroll: 0x1611d
num: 0x16126
cursor: 0x1612f
cur2: 0x1614f
reboot: 0x167b7
cur: 0x16178
num_table: 0x16192
cur_table: 0x1619f
ok_cur: 0x16184
func: 0x161ac
end_func: 0x161dc
ok_func: 0x161c9
func_table: 0x161dd
key_map: 0x1620d
shift_map: 0x1626e
alt_map: 0x162cf
do_self: 0x16330
none: 0x16398
minus: 0x16399
die: 0x167c9
Local symbols of kernel/chr_drv/chr_drv.a(serial.o):
gcc_compiled.: 0x167cc
Local symbols of kernel/chr_drv/chr_drv.a(rs_io.o):
size: 0x400
rs_addr: 0x0
head: 0x4
tail: 0x8
proc_list: 0xc
buf: 0x10
startup: 0x100
rs_int: 0x16921
rep_int: 0x16939
end: 0x16956
jmp_table: 0x16964
modem_status: 0x16974
write_char: 0x169b4
read_char: 0x16984
line_status: 0x1697c
write_buffer_empty: 0x169f4
Local symbols of kernel/chr_drv/chr_drv.a(tty_ioctl.o):
gcc_compiled.: 0x16a0c
_quotient: 0x1d0bc
Local symbols of kernel/math/math.a(math_emulate.o):
gcc_compiled.: 0x16d80
Local symbols of lib/lib.a(ctype.o):
gcc_compiled.: 0x16e54
Local symbols of lib/lib.a(_exit.o):
gcc_compiled.: 0x16e54
Local symbols of lib/lib.a(open.o):
gcc_compiled.: 0x16e64
Local symbols of lib/lib.a(close.o):
gcc_compiled.: 0x16e8c
Local symbols of lib/lib.a(write.o):
gcc_compiled.: 0x16eac
Local symbols of lib/lib.a(dup.o):
gcc_compiled.: 0x16ed4
Local symbols of lib/lib.a(setsid.o):
gcc_compiled.: 0x16ef4
Local symbols of lib/lib.a(execve.o):
gcc_compiled.: 0x16f0c
Local symbols of lib/lib.a(wait.o):
gcc_compiled.: 0x16f34
Local symbols of lib/lib.a(string.o):
gcc_compiled.: 0x16f88

BIN
linux/boot/bootsect Executable file

Binary file not shown.

BIN
linux/boot/bootsect.o Normal file

Binary file not shown.

260
linux/boot/bootsect.s Normal file
View File

@ -0,0 +1,260 @@
!
! SYS_SIZE is the number of clicks (16 bytes) to be loaded.
! 0x3000 is 0x30000 bytes = 196kB, more than enough for current
! versions of linux
!
SYSSIZE = 0x3000
!
! bootsect.s (C) 1991 Linus Torvalds
!
! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
! iself out of the way to address 0x90000, and jumps there.
!
! It then loads 'setup' directly after itself (0x90200), and the system
! at 0x10000, using BIOS interrupts.
!
! NOTE! currently system is at most 8*65536 bytes long. This should be no
! problem, even in the future. I want to keep it simple. This 512 kB
! kernel size should be enough, especially as this doesn't contain the
! buffer cache as in minix
!
! The loader has been made as simple as possible, and continuos
! read errors will result in a unbreakable loop. Reboot by hand. It
! loads pretty fast by getting whole sectors at a time whenever possible.
.globl begtext, begdata, begbss, endtext, enddata, endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text
SETUPLEN = 4 ! nr of setup-sectors
BOOTSEG = 0x07c0 ! original address of boot-sector
INITSEG = 0x9000 ! we move boot here - out of the way
SETUPSEG = 0x9020 ! setup starts here
SYSSEG = 0x1000 ! system loaded at 0x10000 (65536).
ENDSEG = SYSSEG + SYSSIZE ! where to stop loading
! ROOT_DEV: 0x000 - same type of floppy as boot.
! 0x301 - first partition on first drive etc
ROOT_DEV = 0x306
entry start
start:
mov ax,#BOOTSEG
mov ds,ax
mov ax,#INITSEG
mov es,ax
mov cx,#256
sub si,si
sub di,di
rep
movw
jmpi go,INITSEG
go: mov ax,cs
mov ds,ax
mov es,ax
! put stack at 0x9ff00.
mov ss,ax
mov sp,#0xFF00 ! arbitrary value >>512
! load the setup-sectors directly after the bootblock.
! Note that 'es' is already set up.
load_setup:
mov dx,#0x0000 ! drive 0, head 0
mov cx,#0x0002 ! sector 2, track 0
mov bx,#0x0200 ! address = 512, in INITSEG
mov ax,#0x0200+SETUPLEN ! service 2, nr of sectors
int 0x13 ! read it
jnc ok_load_setup ! ok - continue
mov dx,#0x0000
mov ax,#0x0000 ! reset the diskette
int 0x13
j load_setup
ok_load_setup:
! Get disk drive parameters, specifically nr of sectors/track
mov dl,#0x00
mov ax,#0x0800 ! AH=8 is get drive parameters
int 0x13
mov ch,#0x00
seg cs
mov sectors,cx
mov ax,#INITSEG
mov es,ax
! Print some inane message
mov ah,#0x03 ! read cursor pos
xor bh,bh
int 0x10
mov cx,#24
mov bx,#0x0007 ! page 0, attribute 7 (normal)
mov bp,#msg1
mov ax,#0x1301 ! write string, move cursor
int 0x10
! ok, we've written the message, now
! we want to load the system (at 0x10000)
mov ax,#SYSSEG
mov es,ax ! segment of 0x010000
call read_it
call kill_motor
! After that we check which root-device to use. If the device is
! defined (!= 0), nothing is done and the given device is used.
! Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending
! on the number of sectors that the BIOS reports currently.
seg cs
mov ax,root_dev
cmp ax,#0
jne root_defined
seg cs
mov bx,sectors
mov ax,#0x0208 ! /dev/ps0 - 1.2Mb
cmp bx,#15
je root_defined
mov ax,#0x021c ! /dev/PS0 - 1.44Mb
cmp bx,#18
je root_defined
undef_root:
jmp undef_root
root_defined:
seg cs
mov root_dev,ax
! after that (everyting loaded), we jump to
! the setup-routine loaded directly after
! the bootblock:
jmpi 0,SETUPSEG
! This routine loads the system at address 0x10000, making sure
! no 64kB boundaries are crossed. We try to load it as fast as
! possible, loading whole tracks whenever we can.
!
! in: es - starting address segment (normally 0x1000)
!
sread: .word 1+SETUPLEN ! sectors read of current track
head: .word 0 ! current head
track: .word 0 ! current track
read_it:
mov ax,es
test ax,#0x0fff
die: jne die ! es must be at 64kB boundary
xor bx,bx ! bx is starting address within segment
rp_read:
mov ax,es
cmp ax,#ENDSEG ! have we loaded all yet?
jb ok1_read
ret
ok1_read:
seg cs
mov ax,sectors
sub ax,sread
mov cx,ax
shl cx,#9
add cx,bx
jnc ok2_read
je ok2_read
xor ax,ax
sub ax,bx
shr ax,#9
ok2_read:
call read_track
mov cx,ax
add ax,sread
seg cs
cmp ax,sectors
jne ok3_read
mov ax,#1
sub ax,head
jne ok4_read
inc track
ok4_read:
mov head,ax
xor ax,ax
ok3_read:
mov sread,ax
shl cx,#9
add bx,cx
jnc rp_read
mov ax,es
add ax,#0x1000
mov es,ax
xor bx,bx
jmp rp_read
read_track:
push ax
push bx
push cx
push dx
mov dx,track
mov cx,sread
inc cx
mov ch,dl
mov dx,head
mov dh,dl
mov dl,#0
and dx,#0x0100
mov ah,#2
int 0x13
jc bad_rt
pop dx
pop cx
pop bx
pop ax
ret
bad_rt: mov ax,#0
mov dx,#0
int 0x13
pop dx
pop cx
pop bx
pop ax
jmp read_track
/*
* This procedure turns off the floppy drive motor, so
* that we enter the kernel in a known state, and
* don't have to worry about it later.
*/
kill_motor:
push dx
mov dx,#0x3f2
mov al,#0
outb
pop dx
ret
sectors:
.word 0
msg1:
.byte 13,10
.ascii "Loading system ..."
.byte 13,10,13,10
.org 508
root_dev:
.word ROOT_DEV
boot_flag:
.word 0xAA55
.text
endtext:
.data
enddata:
.bss
endbss:

BIN
linux/boot/head.o Normal file

Binary file not shown.

238
linux/boot/head.s Normal file
View File

@ -0,0 +1,238 @@
/*
* linux/boot/head.s
*
* (C) 1991 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
.globl _idt,_gdt,_pg_dir,_tmp_floppy_area
_pg_dir:
startup_32:
movl $0x10,%eax
mov %ax,%ds
mov %ax,%es
mov %ax,%fs
mov %ax,%gs
lss _stack_start,%esp
call setup_idt
call setup_gdt
movl $0x10,%eax # reload all the segment registers
mov %ax,%ds # after changing gdt. CS was already
mov %ax,%es # reloaded in 'setup_gdt'
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
/*
* NOTE! 486 should set bit 16, to check for write-protect in supervisor
* mode. Then it would be unnecessary with the "verify_area()"-calls.
* 486 users probably want to set the NE (#5) bit also, so as to use
* int 16 for math errors.
*/
movl %cr0,%eax # check math chip
andl $0x80000011,%eax # Save PG,PE,ET
/* "orl $0x10020,%eax" here for 486 might be good */
orl $2,%eax # set MP
movl %eax,%cr0
call check_x87
jmp after_page_tables
/*
* We depend on ET to be correct. This checks for 287/387.
*/
check_x87:
fninit
fstsw %ax
cmpb $0,%al
je 1f /* no coprocessor: have to set bits */
movl %cr0,%eax
xorl $6,%eax /* reset MP, set EM */
movl %eax,%cr0
ret
.align 2
1: .byte 0xDB,0xE4 /* fsetpm for 287, ignored by 387 */
ret
/*
* setup_idt
*
* sets up a idt with 256 entries pointing to
* ignore_int, interrupt gates. It then loads
* idt. Everything that wants to install itself
* in the idt-table may do so themselves. Interrupts
* are enabled elsewhere, when we can be relatively
* sure everything is ok. This routine will be over-
* written by the page tables.
*/
setup_idt:
lea ignore_int,%edx
movl $0x00080000,%eax
movw %dx,%ax /* selector = 0x0008 = cs */
movw $0x8E00,%dx /* interrupt gate - dpl=0, present */
lea _idt,%edi
mov $256,%ecx
rp_sidt:
movl %eax,(%edi)
movl %edx,4(%edi)
addl $8,%edi
dec %ecx
jne rp_sidt
lidt idt_descr
ret
/*
* setup_gdt
*
* This routines sets up a new gdt and loads it.
* Only two entries are currently built, the same
* ones that were built in init.s. The routine
* is VERY complicated at two whole lines, so this
* rather long comment is certainly needed :-).
* This routine will beoverwritten by the page tables.
*/
setup_gdt:
lgdt gdt_descr
ret
/*
* I put the kernel page tables right after the page directory,
* using 4 of them to span 16 Mb of physical memory. People with
* more than 16MB will have to expand this.
*/
.org 0x1000
pg0:
.org 0x2000
pg1:
.org 0x3000
pg2:
.org 0x4000
pg3:
.org 0x5000
/*
* tmp_floppy_area is used by the floppy-driver when DMA cannot
* reach to a buffer-block. It needs to be aligned, so that it isn't
* on a 64kB border.
*/
_tmp_floppy_area:
.fill 1024,1,0
after_page_tables:
pushl $0 # These are the parameters to main :-)
pushl $0
pushl $0
pushl $L6 # return address for main, if it decides to.
pushl $_main
jmp setup_paging
L6:
jmp L6 # main should never return here, but
# just in case, we know what happens.
/* This is the default interrupt "handler" :-) */
int_msg:
.asciz "Unknown interrupt\n\r"
.align 2
ignore_int:
pushl %eax
pushl %ecx
pushl %edx
push %ds
push %es
push %fs
movl $0x10,%eax
mov %ax,%ds
mov %ax,%es
mov %ax,%fs
pushl $int_msg
call _printk
popl %eax
pop %fs
pop %es
pop %ds
popl %edx
popl %ecx
popl %eax
iret
/*
* Setup_paging
*
* This routine sets up paging by setting the page bit
* in cr0. The page tables are set up, identity-mapping
* the first 16MB. The pager assumes that no illegal
* addresses are produced (ie >4Mb on a 4Mb machine).
*
* NOTE! Although all physical memory should be identity
* mapped by this routine, only the kernel page functions
* use the >1Mb addresses directly. All "normal" functions
* use just the lower 1Mb, or the local data space, which
* will be mapped to some other place - mm keeps track of
* that.
*
* For those with more memory than 16 Mb - tough luck. I've
* not got it, why should you :-) The source is here. Change
* it. (Seriously - it shouldn't be too difficult. Mostly
* change some constants etc. I left it at 16Mb, as my machine
* even cannot be extended past that (ok, but it was cheap :-)
* I've tried to show which constants to change by having
* some kind of marker at them (search for "16Mb"), but I
* won't guarantee that's all :-( )
*/
.align 2
setup_paging:
movl $1024*5,%ecx /* 5 pages - pg_dir+4 page tables */
xorl %eax,%eax
xorl %edi,%edi /* pg_dir is at 0x000 */
cld;rep;stosl
movl $pg0+7,_pg_dir /* set present bit/user r/w */
movl $pg1+7,_pg_dir+4 /* --------- " " --------- */
movl $pg2+7,_pg_dir+8 /* --------- " " --------- */
movl $pg3+7,_pg_dir+12 /* --------- " " --------- */
movl $pg3+4092,%edi
movl $0xfff007,%eax /* 16Mb - 4096 + 7 (r/w user,p) */
std
1: stosl /* fill pages backwards - more efficient :-) */
subl $0x1000,%eax
jge 1b
xorl %eax,%eax /* pg_dir is at 0x0000 */
movl %eax,%cr3 /* cr3 - page directory start */
movl %cr0,%eax
orl $0x80000000,%eax
movl %eax,%cr0 /* set paging (PG) bit */
ret /* this also flushes prefetch-queue */
.align 2
.word 0
idt_descr:
.word 256*8-1 # idt contains 256 entries
.long _idt
.align 2
.word 0
gdt_descr:
.word 256*8-1 # so does gdt (not that that's any
.long _gdt # magic number, but it works for me :^)
.align 3
_idt: .fill 256,8,0 # idt is uninitialized
_gdt: .quad 0x0000000000000000 /* NULL descriptor */
.quad 0x00c09a0000000fff /* 16Mb */
.quad 0x00c0920000000fff /* 16Mb */
.quad 0x0000000000000000 /* TEMPORARY - don't use */
.fill 252,8,0 /* space for LDT's and TSS's etc */

BIN
linux/boot/setup Executable file

Binary file not shown.

BIN
linux/boot/setup.o Normal file

Binary file not shown.

231
linux/boot/setup.s Normal file
View File

@ -0,0 +1,231 @@
!
! setup.s (C) 1991 Linus Torvalds
!
! setup.s is responsible for getting the system data from the BIOS,
! and putting them into the appropriate places in system memory.
! both setup.s and system has been loaded by the bootblock.
!
! This code asks the bios for memory/disk/other parameters, and
! puts them in a "safe" place: 0x90000-0x901FF, ie where the
! boot-block used to be. It is then up to the protected mode
! system to read them from there before the area is overwritten
! for buffer-blocks.
!
! NOTE! These had better be the same as in bootsect.s!
INITSEG = 0x9000 ! we move boot here - out of the way
SYSSEG = 0x1000 ! system loaded at 0x10000 (65536).
SETUPSEG = 0x9020 ! this is the current segment
.globl begtext, begdata, begbss, endtext, enddata, endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text
entry start
start:
! ok, the read went well so we get current cursor position and save it for
! posterity.
mov ax,#INITSEG ! this is done in bootsect already, but...
mov ds,ax
mov ah,#0x03 ! read cursor pos
xor bh,bh
int 0x10 ! save it in known place, con_init fetches
mov [0],dx ! it from 0x90000.
! Get memory size (extended mem, kB)
mov ah,#0x88
int 0x15
mov [2],ax
! Get video-card data:
mov ah,#0x0f
int 0x10
mov [4],bx ! bh = display page
mov [6],ax ! al = video mode, ah = window width
! check for EGA/VGA and some config parameters
mov ah,#0x12
mov bl,#0x10
int 0x10
mov [8],ax
mov [10],bx
mov [12],cx
! Get hd0 data
mov ax,#0x0000
mov ds,ax
lds si,[4*0x41]
mov ax,#INITSEG
mov es,ax
mov di,#0x0080
mov cx,#0x10
rep
movsb
! Get hd1 data
mov ax,#0x0000
mov ds,ax
lds si,[4*0x46]
mov ax,#INITSEG
mov es,ax
mov di,#0x0090
mov cx,#0x10
rep
movsb
! Check that there IS a hd1 :-)
mov ax,#0x01500
mov dl,#0x81
int 0x13
jc no_disk1
cmp ah,#3
je is_disk1
no_disk1:
mov ax,#INITSEG
mov es,ax
mov di,#0x0090
mov cx,#0x10
mov ax,#0x00
rep
stosb
is_disk1:
! now we want to move to protected mode ...
cli ! no interrupts allowed !
! first we move the system to it's rightful place
mov ax,#0x0000
cld ! 'direction'=0, movs moves forward
do_move:
mov es,ax ! destination segment
add ax,#0x1000
cmp ax,#0x9000
jz end_move
mov ds,ax ! source segment
sub di,di
sub si,si
mov cx,#0x8000
rep
movsw
jmp do_move
! then we load the segment descriptors
end_move:
mov ax,#SETUPSEG ! right, forgot this at first. didn't work :-)
mov ds,ax
lidt idt_48 ! load idt with 0,0
lgdt gdt_48 ! load gdt with whatever appropriate
! that was painless, now we enable A20
call empty_8042
mov al,#0xD1 ! command write
out #0x64,al
call empty_8042
mov al,#0xDF ! A20 on
out #0x60,al
call empty_8042
! well, that went ok, I hope. Now we have to reprogram the interrupts :-(
! we put them right after the intel-reserved hardware interrupts, at
! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
! messed this up with the original PC, and they haven't been able to
! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
! which is used for the internal hardware interrupts as well. We just
! have to reprogram the 8259's, and it isn't fun.
mov al,#0x11 ! initialization sequence
out #0x20,al ! send it to 8259A-1
.word 0x00eb,0x00eb ! jmp $+2, jmp $+2
out #0xA0,al ! and to 8259A-2
.word 0x00eb,0x00eb
mov al,#0x20 ! start of hardware int's (0x20)
out #0x21,al
.word 0x00eb,0x00eb
mov al,#0x28 ! start of hardware int's 2 (0x28)
out #0xA1,al
.word 0x00eb,0x00eb
mov al,#0x04 ! 8259-1 is master
out #0x21,al
.word 0x00eb,0x00eb
mov al,#0x02 ! 8259-2 is slave
out #0xA1,al
.word 0x00eb,0x00eb
mov al,#0x01 ! 8086 mode for both
out #0x21,al
.word 0x00eb,0x00eb
out #0xA1,al
.word 0x00eb,0x00eb
mov al,#0xFF ! mask off all interrupts for now
out #0x21,al
.word 0x00eb,0x00eb
out #0xA1,al
! well, that certainly wasn't fun :-(. Hopefully it works, and we don't
! need no steenking BIOS anyway (except for the initial loading :-).
! The BIOS-routine wants lots of unnecessary data, and it's less
! "interesting" anyway. This is how REAL programmers do it.
!
! Well, now's the time to actually move into protected mode. To make
! things as simple as possible, we do no register set-up or anything,
! we let the gnu-compiled 32-bit programs do that. We just jump to
! absolute address 0x00000, in 32-bit protected mode.
mov ax,#0x0001 ! protected mode (PE) bit
lmsw ax ! This is it!
jmpi 0,8 ! jmp offset 0 of segment 8 (cs)
! This routine checks that the keyboard command queue is empty
! No timeout is used - if this hangs there is something wrong with
! the machine, and we probably couldn't proceed anyway.
empty_8042:
.word 0x00eb,0x00eb
in al,#0x64 ! 8042 status port
test al,#2 ! is input buffer full?
jnz empty_8042 ! yes - loop
ret
gdt:
.word 0,0,0,0 ! dummy
.word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb)
.word 0x0000 ! base address=0
.word 0x9A00 ! code read/exec
.word 0x00C0 ! granularity=4096, 386
.word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb)
.word 0x0000 ! base address=0
.word 0x9200 ! data read/write
.word 0x00C0 ! granularity=4096, 386
idt_48:
.word 0 ! idt limit=0
.word 0,0 ! idt base=0L
gdt_48:
.word 0x800 ! gdt limit=2048, 256 GDT entries
.word 512+gdt,0x9 ! gdt base = 0X9xxxx
.text
endtext:
.data
enddata:
.bss
endbss:

100
linux/fs/Makefile Normal file
View File

@ -0,0 +1,100 @@
AR =gar
AS =gas
CC =gcc
LD =gld
CFLAGS =-Wall -O g -fstrength-reduce -fcombine-regs -fomit-frame-pointer \
-nostdinc -I../include
CPP =gcc -E -nostdinc -I../include
.c.s:
$(CC) $(CFLAGS) \
-S -o $*.s $<
.c.o:
$(CC) $(CFLAGS) \
-c -o $*.o $<
.s.o:
$(AS) -o $*.o $<
OBJS= open.o read_write.o inode.o file_table.o buffer.o super.o \
block_dev.o char_dev.o file_dev.o stat.o exec.o pipe.o namei.o \
bitmap.o fcntl.o ioctl.o truncate.o select.o
fs.o: $(OBJS)
$(LD) -r -o fs.o $(OBJS)
clean:
rm -f core *.o *.a tmp_make
for i in *.c;do rm -f `basename $$i .c`.s;done
dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
(for i in *.c;do $(CPP) -M $$i;done) >> tmp_make
cp tmp_make Makefile
### Dependencies:
bitmap.o : bitmap.c ../include/string.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h
block_dev.o : block_dev.c ../include/errno.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
../include/asm/segment.h ../include/asm/system.h
buffer.o : buffer.c ../include/stdarg.h ../include/linux/config.h \
../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
../include/sys/types.h ../include/linux/mm.h ../include/signal.h \
../include/linux/kernel.h ../include/asm/system.h ../include/asm/io.h
char_dev.o : char_dev.c ../include/errno.h ../include/sys/types.h \
../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
../include/asm/segment.h ../include/asm/io.h
exec.o : exec.c ../include/errno.h ../include/string.h \
../include/sys/stat.h ../include/sys/types.h ../include/a.out.h \
../include/linux/fs.h ../include/linux/sched.h ../include/linux/head.h \
../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
../include/asm/segment.h
fcntl.o : fcntl.c ../include/string.h ../include/errno.h \
../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
../include/sys/types.h ../include/linux/mm.h ../include/signal.h \
../include/linux/kernel.h ../include/asm/segment.h ../include/fcntl.h \
../include/sys/stat.h
file_dev.o : file_dev.c ../include/errno.h ../include/fcntl.h \
../include/sys/types.h ../include/linux/sched.h ../include/linux/head.h \
../include/linux/fs.h ../include/linux/mm.h ../include/signal.h \
../include/linux/kernel.h ../include/asm/segment.h
file_table.o : file_table.c ../include/linux/fs.h ../include/sys/types.h
inode.o : inode.c ../include/string.h ../include/sys/stat.h \
../include/sys/types.h ../include/linux/sched.h ../include/linux/head.h \
../include/linux/fs.h ../include/linux/mm.h ../include/signal.h \
../include/linux/kernel.h ../include/asm/system.h
ioctl.o : ioctl.c ../include/string.h ../include/errno.h \
../include/sys/stat.h ../include/sys/types.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
../include/signal.h
namei.o : namei.c ../include/linux/sched.h ../include/linux/head.h \
../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \
../include/signal.h ../include/linux/kernel.h ../include/asm/segment.h \
../include/string.h ../include/fcntl.h ../include/errno.h \
../include/const.h ../include/sys/stat.h
open.o : open.c ../include/string.h ../include/errno.h ../include/fcntl.h \
../include/sys/types.h ../include/utime.h ../include/sys/stat.h \
../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
../include/linux/mm.h ../include/signal.h ../include/linux/tty.h \
../include/termios.h ../include/linux/kernel.h ../include/asm/segment.h
pipe.o : pipe.c ../include/signal.h ../include/sys/types.h \
../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
../include/linux/mm.h ../include/asm/segment.h
read_write.o : read_write.c ../include/sys/stat.h ../include/sys/types.h \
../include/errno.h ../include/linux/kernel.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
../include/signal.h ../include/asm/segment.h
stat.o : stat.c ../include/errno.h ../include/sys/stat.h \
../include/sys/types.h ../include/linux/fs.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/mm.h ../include/signal.h \
../include/linux/kernel.h ../include/asm/segment.h
super.o : super.c ../include/linux/config.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
../include/asm/system.h ../include/errno.h ../include/sys/stat.h
truncate.o : truncate.c ../include/linux/sched.h ../include/linux/head.h \
../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \
../include/signal.h ../include/sys/stat.h

168
linux/fs/bitmap.c Normal file
View File

@ -0,0 +1,168 @@
/*
* linux/fs/bitmap.c
*
* (C) 1991 Linus Torvalds
*/
/* bitmap.c contains the code that handles the inode and block bitmaps */
#include <string.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#define clear_block(addr) \
__asm__("cld\n\t" \
"rep\n\t" \
"stosl" \
::"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr)):"cx","di")
#define set_bit(nr,addr) ({\
register int res __asm__("ax"); \
__asm__ __volatile__("btsl %2,%3\n\tsetb %%al": \
"=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \
res;})
#define clear_bit(nr,addr) ({\
register int res __asm__("ax"); \
__asm__ __volatile__("btrl %2,%3\n\tsetnb %%al": \
"=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \
res;})
#define find_first_zero(addr) ({ \
int __res; \
__asm__("cld\n" \
"1:\tlodsl\n\t" \
"notl %%eax\n\t" \
"bsfl %%eax,%%edx\n\t" \
"je 2f\n\t" \
"addl %%edx,%%ecx\n\t" \
"jmp 3f\n" \
"2:\taddl $32,%%ecx\n\t" \
"cmpl $8192,%%ecx\n\t" \
"jl 1b\n" \
"3:" \
:"=c" (__res):"c" (0),"S" (addr):"ax","dx","si"); \
__res;})
void free_block(int dev, int block)
{
struct super_block * sb;
struct buffer_head * bh;
if (!(sb = get_super(dev)))
panic("trying to free block on nonexistent device");
if (block < sb->s_firstdatazone || block >= sb->s_nzones)
panic("trying to free block not in datazone");
bh = get_hash_table(dev,block);
if (bh) {
if (bh->b_count != 1) {
printk("trying to free block (%04x:%d), count=%d\n",
dev,block,bh->b_count);
return;
}
bh->b_dirt=0;
bh->b_uptodate=0;
brelse(bh);
}
block -= sb->s_firstdatazone - 1 ;
if (clear_bit(block&8191,sb->s_zmap[block/8192]->b_data)) {
printk("block (%04x:%d) ",dev,block+sb->s_firstdatazone-1);
panic("free_block: bit already cleared");
}
sb->s_zmap[block/8192]->b_dirt = 1;
}
int new_block(int dev)
{
struct buffer_head * bh;
struct super_block * sb;
int i,j;
if (!(sb = get_super(dev)))
panic("trying to get new block from nonexistant device");
j = 8192;
for (i=0 ; i<8 ; i++)
if (bh=sb->s_zmap[i])
if ((j=find_first_zero(bh->b_data))<8192)
break;
if (i>=8 || !bh || j>=8192)
return 0;
if (set_bit(j,bh->b_data))
panic("new_block: bit already set");
bh->b_dirt = 1;
j += i*8192 + sb->s_firstdatazone-1;
if (j >= sb->s_nzones)
return 0;
if (!(bh=getblk(dev,j)))
panic("new_block: cannot get block");
if (bh->b_count != 1)
panic("new block: count is != 1");
clear_block(bh->b_data);
bh->b_uptodate = 1;
bh->b_dirt = 1;
brelse(bh);
return j;
}
void free_inode(struct m_inode * inode)
{
struct super_block * sb;
struct buffer_head * bh;
if (!inode)
return;
if (!inode->i_dev) {
memset(inode,0,sizeof(*inode));
return;
}
if (inode->i_count>1) {
printk("trying to free inode with count=%d\n",inode->i_count);
panic("free_inode");
}
if (inode->i_nlinks)
panic("trying to free inode with links");
if (!(sb = get_super(inode->i_dev)))
panic("trying to free inode on nonexistent device");
if (inode->i_num < 1 || inode->i_num > sb->s_ninodes)
panic("trying to free inode 0 or nonexistant inode");
if (!(bh=sb->s_imap[inode->i_num>>13]))
panic("nonexistent imap in superblock");
if (clear_bit(inode->i_num&8191,bh->b_data))
printk("free_inode: bit already cleared.\n\r");
bh->b_dirt = 1;
memset(inode,0,sizeof(*inode));
}
struct m_inode * new_inode(int dev)
{
struct m_inode * inode;
struct super_block * sb;
struct buffer_head * bh;
int i,j;
if (!(inode=get_empty_inode()))
return NULL;
if (!(sb = get_super(dev)))
panic("new_inode with unknown device");
j = 8192;
for (i=0 ; i<8 ; i++)
if (bh=sb->s_imap[i])
if ((j=find_first_zero(bh->b_data))<8192)
break;
if (!bh || j >= 8192 || j+i*8192 > sb->s_ninodes) {
iput(inode);
return NULL;
}
if (set_bit(j,bh->b_data))
panic("new_inode: bit already set");
bh->b_dirt = 1;
inode->i_count=1;
inode->i_nlinks=1;
inode->i_dev=dev;
inode->i_uid=current->euid;
inode->i_gid=current->egid;
inode->i_dirt=1;
inode->i_num = j + i*8192;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
return inode;
}

BIN
linux/fs/bitmap.o Normal file

Binary file not shown.

73
linux/fs/block_dev.c Normal file
View File

@ -0,0 +1,73 @@
/*
* linux/fs/block_dev.c
*
* (C) 1991 Linus Torvalds
*/
#include <errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/segment.h>
#include <asm/system.h>
int block_write(int dev, long * pos, char * buf, int count)
{
int block = *pos >> BLOCK_SIZE_BITS;
int offset = *pos & (BLOCK_SIZE-1);
int chars;
int written = 0;
struct buffer_head * bh;
register char * p;
while (count>0) {
chars = BLOCK_SIZE - offset;
if (chars > count)
chars=count;
if (chars == BLOCK_SIZE)
bh = getblk(dev,block);
else
bh = breada(dev,block,block+1,block+2,-1);
block++;
if (!bh)
return written?written:-EIO;
p = offset + bh->b_data;
offset = 0;
*pos += chars;
written += chars;
count -= chars;
while (chars-->0)
*(p++) = get_fs_byte(buf++);
bh->b_dirt = 1;
brelse(bh);
}
return written;
}
int block_read(int dev, unsigned long * pos, char * buf, int count)
{
int block = *pos >> BLOCK_SIZE_BITS;
int offset = *pos & (BLOCK_SIZE-1);
int chars;
int read = 0;
struct buffer_head * bh;
register char * p;
while (count>0) {
chars = BLOCK_SIZE-offset;
if (chars > count)
chars = count;
if (!(bh = breada(dev,block,block+1,block+2,-1)))
return read?read:-EIO;
block++;
p = offset + bh->b_data;
offset = 0;
*pos += chars;
read += chars;
count -= chars;
while (chars-->0)
put_fs_byte(*(p++),buf++);
brelse(bh);
}
return read;
}

BIN
linux/fs/block_dev.o Normal file

Binary file not shown.

381
linux/fs/buffer.c Normal file
View File

@ -0,0 +1,381 @@
/*
* linux/fs/buffer.c
*
* (C) 1991 Linus Torvalds
*/
/*
* 'buffer.c' implements the buffer-cache functions. Race-conditions have
* been avoided by NEVER letting a interrupt change a buffer (except for the
* data, of course), but instead letting the caller do it. NOTE! As interrupts
* can wake up a caller, some cli-sti sequences are needed to check for
* sleep-on-calls. These should be extremely quick, though (I hope).
*/
/*
* NOTE! There is one discordant note here: checking floppies for
* disk change. This is where it fits best, I think, as it should
* invalidate changed floppy-disk-caches.
*/
#include <stdarg.h>
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/system.h>
#include <asm/io.h>
extern int end;
struct buffer_head * start_buffer = (struct buffer_head *) &end;
struct buffer_head * hash_table[NR_HASH];
static struct buffer_head * free_list;
static struct task_struct * buffer_wait = NULL;
int NR_BUFFERS = 0;
static inline void wait_on_buffer(struct buffer_head * bh)
{
cli();
while (bh->b_lock)
sleep_on(&bh->b_wait);
sti();
}
int sys_sync(void)
{
int i;
struct buffer_head * bh;
sync_inodes(); /* write out inodes into buffers */
bh = start_buffer;
for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
wait_on_buffer(bh);
if (bh->b_dirt)
ll_rw_block(WRITE,bh);
}
return 0;
}
int sync_dev(int dev)
{
int i;
struct buffer_head * bh;
bh = start_buffer;
for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
if (bh->b_dev != dev)
continue;
wait_on_buffer(bh);
if (bh->b_dev == dev && bh->b_dirt)
ll_rw_block(WRITE,bh);
}
sync_inodes();
bh = start_buffer;
for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
if (bh->b_dev != dev)
continue;
wait_on_buffer(bh);
if (bh->b_dev == dev && bh->b_dirt)
ll_rw_block(WRITE,bh);
}
return 0;
}
void inline invalidate_buffers(int dev)
{
int i;
struct buffer_head * bh;
bh = start_buffer;
for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
if (bh->b_dev != dev)
continue;
wait_on_buffer(bh);
if (bh->b_dev == dev)
bh->b_uptodate = bh->b_dirt = 0;
}
}
/*
* This routine checks whether a floppy has been changed, and
* invalidates all buffer-cache-entries in that case. This
* is a relatively slow routine, so we have to try to minimize using
* it. Thus it is called only upon a 'mount' or 'open'. This
* is the best way of combining speed and utility, I think.
* People changing diskettes in the middle of an operation deserve
* to loose :-)
*
* NOTE! Although currently this is only for floppies, the idea is
* that any additional removable block-device will use this routine,
* and that mount/open needn't know that floppies/whatever are
* special.
*/
void check_disk_change(int dev)
{
int i;
if (MAJOR(dev) != 2)
return;
if (!floppy_change(dev & 0x03))
return;
for (i=0 ; i<NR_SUPER ; i++)
if (super_block[i].s_dev == dev)
put_super(super_block[i].s_dev);
invalidate_inodes(dev);
invalidate_buffers(dev);
}
#define _hashfn(dev,block) (((unsigned)(dev^block))%NR_HASH)
#define hash(dev,block) hash_table[_hashfn(dev,block)]
static inline void remove_from_queues(struct buffer_head * bh)
{
/* remove from hash-queue */
if (bh->b_next)
bh->b_next->b_prev = bh->b_prev;
if (bh->b_prev)
bh->b_prev->b_next = bh->b_next;
if (hash(bh->b_dev,bh->b_blocknr) == bh)
hash(bh->b_dev,bh->b_blocknr) = bh->b_next;
/* remove from free list */
if (!(bh->b_prev_free) || !(bh->b_next_free))
panic("Free block list corrupted");
bh->b_prev_free->b_next_free = bh->b_next_free;
bh->b_next_free->b_prev_free = bh->b_prev_free;
if (free_list == bh)
free_list = bh->b_next_free;
}
static inline void insert_into_queues(struct buffer_head * bh)
{
/* put at end of free list */
bh->b_next_free = free_list;
bh->b_prev_free = free_list->b_prev_free;
free_list->b_prev_free->b_next_free = bh;
free_list->b_prev_free = bh;
/* put the buffer in new hash-queue if it has a device */
bh->b_prev = NULL;
bh->b_next = NULL;
if (!bh->b_dev)
return;
bh->b_next = hash(bh->b_dev,bh->b_blocknr);
hash(bh->b_dev,bh->b_blocknr) = bh;
bh->b_next->b_prev = bh;
}
static struct buffer_head * find_buffer(int dev, int block)
{
struct buffer_head * tmp;
for (tmp = hash(dev,block) ; tmp != NULL ; tmp = tmp->b_next)
if (tmp->b_dev==dev && tmp->b_blocknr==block)
return tmp;
return NULL;
}
/*
* Why like this, I hear you say... The reason is race-conditions.
* As we don't lock buffers (unless we are readint them, that is),
* something might happen to it while we sleep (ie a read-error
* will force it bad). This shouldn't really happen currently, but
* the code is ready.
*/
struct buffer_head * get_hash_table(int dev, int block)
{
struct buffer_head * bh;
for (;;) {
if (!(bh=find_buffer(dev,block)))
return NULL;
bh->b_count++;
wait_on_buffer(bh);
if (bh->b_dev == dev && bh->b_blocknr == block)
return bh;
bh->b_count--;
}
}
/*
* Ok, this is getblk, and it isn't very clear, again to hinder
* race-conditions. Most of the code is seldom used, (ie repeating),
* so it should be much more efficient than it looks.
*
* The algoritm is changed: hopefully better, and an elusive bug removed.
*/
#define BADNESS(bh) (((bh)->b_dirt<<1)+(bh)->b_lock)
struct buffer_head * getblk(int dev,int block)
{
struct buffer_head * tmp, * bh;
repeat:
if (bh = get_hash_table(dev,block))
return bh;
tmp = free_list;
do {
if (tmp->b_count)
continue;
if (!bh || BADNESS(tmp)<BADNESS(bh)) {
bh = tmp;
if (!BADNESS(tmp))
break;
}
/* and repeat until we find something good */
} while ((tmp = tmp->b_next_free) != free_list);
if (!bh) {
sleep_on(&buffer_wait);
goto repeat;
}
wait_on_buffer(bh);
if (bh->b_count)
goto repeat;
while (bh->b_dirt) {
sync_dev(bh->b_dev);
wait_on_buffer(bh);
if (bh->b_count)
goto repeat;
}
/* NOTE!! While we slept waiting for this block, somebody else might */
/* already have added "this" block to the cache. check it */
if (find_buffer(dev,block))
goto repeat;
/* OK, FINALLY we know that this buffer is the only one of it's kind, */
/* and that it's unused (b_count=0), unlocked (b_lock=0), and clean */
bh->b_count=1;
bh->b_dirt=0;
bh->b_uptodate=0;
remove_from_queues(bh);
bh->b_dev=dev;
bh->b_blocknr=block;
insert_into_queues(bh);
return bh;
}
void brelse(struct buffer_head * buf)
{
if (!buf)
return;
wait_on_buffer(buf);
if (!(buf->b_count--))
panic("Trying to free free buffer");
wake_up(&buffer_wait);
}
/*
* bread() reads a specified block and returns the buffer that contains
* it. It returns NULL if the block was unreadable.
*/
struct buffer_head * bread(int dev,int block)
{
struct buffer_head * bh;
if (!(bh=getblk(dev,block)))
panic("bread: getblk returned NULL\n");
if (bh->b_uptodate)
return bh;
ll_rw_block(READ,bh);
wait_on_buffer(bh);
if (bh->b_uptodate)
return bh;
brelse(bh);
return NULL;
}
#define COPYBLK(from,to) \
__asm__("cld\n\t" \
"rep\n\t" \
"movsl\n\t" \
::"c" (BLOCK_SIZE/4),"S" (from),"D" (to) \
:"cx","di","si")
/*
* bread_page reads four buffers into memory at the desired address. It's
* a function of its own, as there is some speed to be got by reading them
* all at the same time, not waiting for one to be read, and then another
* etc.
*/
void bread_page(unsigned long address,int dev,int b[4])
{
struct buffer_head * bh[4];
int i;
for (i=0 ; i<4 ; i++)
if (b[i]) {
if (bh[i] = getblk(dev,b[i]))
if (!bh[i]->b_uptodate)
ll_rw_block(READ,bh[i]);
} else
bh[i] = NULL;
for (i=0 ; i<4 ; i++,address += BLOCK_SIZE)
if (bh[i]) {
wait_on_buffer(bh[i]);
if (bh[i]->b_uptodate)
COPYBLK((unsigned long) bh[i]->b_data,address);
brelse(bh[i]);
}
}
/*
* Ok, breada can be used as bread, but additionally to mark other
* blocks for reading as well. End the argument list with a negative
* number.
*/
struct buffer_head * breada(int dev,int first, ...)
{
va_list args;
struct buffer_head * bh, *tmp;
va_start(args,first);
if (!(bh=getblk(dev,first)))
panic("bread: getblk returned NULL\n");
if (!bh->b_uptodate)
ll_rw_block(READ,bh);
while ((first=va_arg(args,int))>=0) {
tmp=getblk(dev,first);
if (tmp) {
if (!tmp->b_uptodate)
ll_rw_block(READA,bh);
tmp->b_count--;
}
}
va_end(args);
wait_on_buffer(bh);
if (bh->b_uptodate)
return bh;
brelse(bh);
return (NULL);
}
void buffer_init(long buffer_end)
{
struct buffer_head * h = start_buffer;
void * b;
int i;
if (buffer_end == 1<<20)
b = (void *) (640*1024);
else
b = (void *) buffer_end;
while ( (b -= BLOCK_SIZE) >= ((void *) (h+1)) ) {
h->b_dev = 0;
h->b_dirt = 0;
h->b_count = 0;
h->b_lock = 0;
h->b_uptodate = 0;
h->b_wait = NULL;
h->b_next = NULL;
h->b_prev = NULL;
h->b_data = (char *) b;
h->b_prev_free = h-1;
h->b_next_free = h+1;
h++;
NR_BUFFERS++;
if (b == (void *) 0x100000)
b = (void *) 0xA0000;
}
h--;
free_list = start_buffer;
free_list->b_prev_free = h;
h->b_next_free = free_list;
for (i=0;i<NR_HASH;i++)
hash_table[i]=NULL;
}

BIN
linux/fs/buffer.o Normal file

Binary file not shown.

104
linux/fs/char_dev.c Normal file
View File

@ -0,0 +1,104 @@
/*
* linux/fs/char_dev.c
*
* (C) 1991 Linus Torvalds
*/
#include <errno.h>
#include <sys/types.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/segment.h>
#include <asm/io.h>
extern int tty_read(unsigned minor,char * buf,int count);
extern int tty_write(unsigned minor,char * buf,int count);
typedef (*crw_ptr)(int rw,unsigned minor,char * buf,int count,off_t * pos);
static int rw_ttyx(int rw,unsigned minor,char * buf,int count,off_t * pos)
{
return ((rw==READ)?tty_read(minor,buf,count):
tty_write(minor,buf,count));
}
static int rw_tty(int rw,unsigned minor,char * buf,int count, off_t * pos)
{
if (current->tty<0)
return -EPERM;
return rw_ttyx(rw,current->tty,buf,count,pos);
}
static int rw_ram(int rw,char * buf, int count, off_t *pos)
{
return -EIO;
}
static int rw_mem(int rw,char * buf, int count, off_t * pos)
{
return -EIO;
}
static int rw_kmem(int rw,char * buf, int count, off_t * pos)
{
return -EIO;
}
static int rw_port(int rw,char * buf, int count, off_t * pos)
{
int i=*pos;
while (count-->0 && i<65536) {
if (rw==READ)
put_fs_byte(inb(i),buf++);
else
outb(get_fs_byte(buf++),i);
i++;
}
i -= *pos;
*pos += i;
return i;
}
static int rw_memory(int rw, unsigned minor, char * buf, int count, off_t * pos)
{
switch(minor) {
case 0:
return rw_ram(rw,buf,count,pos);
case 1:
return rw_mem(rw,buf,count,pos);
case 2:
return rw_kmem(rw,buf,count,pos);
case 3:
return (rw==READ)?0:count; /* rw_null */
case 4:
return rw_port(rw,buf,count,pos);
default:
return -EIO;
}
}
#define NRDEVS ((sizeof (crw_table))/(sizeof (crw_ptr)))
static crw_ptr crw_table[]={
NULL, /* nodev */
rw_memory, /* /dev/mem etc */
NULL, /* /dev/fd */
NULL, /* /dev/hd */
rw_ttyx, /* /dev/ttyx */
rw_tty, /* /dev/tty */
NULL, /* /dev/lp */
NULL}; /* unnamed pipes */
int rw_char(int rw,int dev, char * buf, int count, off_t * pos)
{
crw_ptr call_addr;
if (MAJOR(dev)>=NRDEVS)
return -ENODEV;
if (!(call_addr=crw_table[MAJOR(dev)]))
return -ENODEV;
return call_addr(rw,MINOR(dev),buf,count,pos);
}

BIN
linux/fs/char_dev.o Normal file

Binary file not shown.

359
linux/fs/exec.c Normal file
View File

@ -0,0 +1,359 @@
/*
* linux/fs/exec.c
*
* (C) 1991 Linus Torvalds
*/
/*
* #!-checking implemented by tytso.
*/
/*
* Demand-loading implemented 01.12.91 - no need to read anything but
* the header into memory. The inode of the executable is put into
* "current->executable", and page faults do the actual loading. Clean.
*
* Once more I can proudly say that linux stood up to being changed: it
* was less than 2 hours work to get demand-loading completely implemented.
*/
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <a.out.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <asm/segment.h>
extern int sys_exit(int exit_code);
extern int sys_close(int fd);
/*
* MAX_ARG_PAGES defines the number of pages allocated for arguments
* and envelope for the new program. 32 should suffice, this gives
* a maximum env+arg of 128kB !
*/
#define MAX_ARG_PAGES 32
int sys_uselib()
{
return -ENOSYS;
}
/*
* create_tables() parses the env- and arg-strings in new user
* memory and creates the pointer tables from them, and puts their
* addresses on the "stack", returning the new stack pointer value.
*/
static unsigned long * create_tables(char * p,int argc,int envc)
{
unsigned long *argv,*envp;
unsigned long * sp;
sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
sp -= envc+1;
envp = sp;
sp -= argc+1;
argv = sp;
put_fs_long((unsigned long)envp,--sp);
put_fs_long((unsigned long)argv,--sp);
put_fs_long((unsigned long)argc,--sp);
while (argc-->0) {
put_fs_long((unsigned long) p,argv++);
while (get_fs_byte(p++)) /* nothing */ ;
}
put_fs_long(0,argv);
while (envc-->0) {
put_fs_long((unsigned long) p,envp++);
while (get_fs_byte(p++)) /* nothing */ ;
}
put_fs_long(0,envp);
return sp;
}
/*
* count() counts the number of arguments/envelopes
*/
static int count(char ** argv)
{
int i=0;
char ** tmp;
if (tmp = argv)
while (get_fs_long((unsigned long *) (tmp++)))
i++;
return i;
}
/*
* 'copy_string()' copies argument/envelope strings from user
* memory to free pages in kernel mem. These are in a format ready
* to be put directly into the top of new user memory.
*
* Modified by TYT, 11/24/91 to add the from_kmem argument, which specifies
* whether the string and the string array are from user or kernel segments:
*
* from_kmem argv * argv **
* 0 user space user space
* 1 kernel space user space
* 2 kernel space kernel space
*
* We do this by playing games with the fs segment register. Since it
* it is expensive to load a segment register, we try to avoid calling
* set_fs() unless we absolutely have to.
*/
static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
unsigned long p, int from_kmem)
{
char *tmp, *pag;
int len, offset = 0;
unsigned long old_fs, new_fs;
if (!p)
return 0; /* bullet-proofing */
new_fs = get_ds();
old_fs = get_fs();
if (from_kmem==2)
set_fs(new_fs);
while (argc-- > 0) {
if (from_kmem == 1)
set_fs(new_fs);
if (!(tmp = (char *)get_fs_long(((unsigned long *)argv)+argc)))
panic("argc is wrong");
if (from_kmem == 1)
set_fs(old_fs);
len=0; /* remember zero-padding */
do {
len++;
} while (get_fs_byte(tmp++));
if (p-len < 0) { /* this shouldn't happen - 128kB */
set_fs(old_fs);
return 0;
}
while (len) {
--p; --tmp; --len;
if (--offset < 0) {
offset = p % PAGE_SIZE;
if (from_kmem==2)
set_fs(old_fs);
if (!(pag = (char *) page[p/PAGE_SIZE]) &&
!(pag = (char *) page[p/PAGE_SIZE] =
(unsigned long *) get_free_page()))
return 0;
if (from_kmem==2)
set_fs(new_fs);
}
*(pag + offset) = get_fs_byte(tmp);
}
}
if (from_kmem==2)
set_fs(old_fs);
return p;
}
static unsigned long change_ldt(unsigned long text_size,unsigned long * page)
{
unsigned long code_limit,data_limit,code_base,data_base;
int i;
code_limit = text_size+PAGE_SIZE -1;
code_limit &= 0xFFFFF000;
data_limit = 0x4000000;
code_base = get_base(current->ldt[1]);
data_base = code_base;
set_base(current->ldt[1],code_base);
set_limit(current->ldt[1],code_limit);
set_base(current->ldt[2],data_base);
set_limit(current->ldt[2],data_limit);
/* make sure fs points to the NEW data segment */
__asm__("pushl $0x17\n\tpop %%fs"::);
data_base += data_limit;
for (i=MAX_ARG_PAGES-1 ; i>=0 ; i--) {
data_base -= PAGE_SIZE;
if (page[i])
put_page(page[i],data_base);
}
return data_limit;
}
/*
* 'do_execve()' executes a new program.
*/
int do_execve(unsigned long * eip,long tmp,char * filename,
char ** argv, char ** envp)
{
struct m_inode * inode;
struct buffer_head * bh;
struct exec ex;
unsigned long page[MAX_ARG_PAGES];
int i,argc,envc;
int e_uid, e_gid;
int retval;
int sh_bang = 0;
unsigned long p=PAGE_SIZE*MAX_ARG_PAGES-4;
if ((0xffff & eip[1]) != 0x000f)
panic("execve called from supervisor mode");
for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
page[i]=0;
if (!(inode=namei(filename))) /* get executables inode */
return -ENOENT;
argc = count(argv);
envc = count(envp);
restart_interp:
if (!S_ISREG(inode->i_mode)) { /* must be regular file */
retval = -EACCES;
goto exec_error2;
}
i = inode->i_mode;
e_uid = (i & S_ISUID) ? inode->i_uid : current->euid;
e_gid = (i & S_ISGID) ? inode->i_gid : current->egid;
if (current->euid == inode->i_uid)
i >>= 6;
else if (current->egid == inode->i_gid)
i >>= 3;
if (!(i & 1) &&
!((inode->i_mode & 0111) && suser())) {
retval = -ENOEXEC;
goto exec_error2;
}
if (!(bh = bread(inode->i_dev,inode->i_zone[0]))) {
retval = -EACCES;
goto exec_error2;
}
ex = *((struct exec *) bh->b_data); /* read exec-header */
if ((bh->b_data[0] == '#') && (bh->b_data[1] == '!') && (!sh_bang)) {
/*
* This section does the #! interpretation.
* Sorta complicated, but hopefully it will work. -TYT
*/
char buf[1023], *cp, *interp, *i_name, *i_arg;
unsigned long old_fs;
strncpy(buf, bh->b_data+2, 1022);
brelse(bh);
iput(inode);
buf[1022] = '\0';
if (cp = strchr(buf, '\n')) {
*cp = '\0';
for (cp = buf; (*cp == ' ') || (*cp == '\t'); cp++);
}
if (!cp || *cp == '\0') {
retval = -ENOEXEC; /* No interpreter name found */
goto exec_error1;
}
interp = i_name = cp;
i_arg = 0;
for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) {
if (*cp == '/')
i_name = cp+1;
}
if (*cp) {
*cp++ = '\0';
i_arg = cp;
}
/*
* OK, we've parsed out the interpreter name and
* (optional) argument.
*/
if (sh_bang++ == 0) {
p = copy_strings(envc, envp, page, p, 0);
p = copy_strings(--argc, argv+1, page, p, 0);
}
/*
* Splice in (1) the interpreter's name for argv[0]
* (2) (optional) argument to interpreter
* (3) filename of shell script
*
* This is done in reverse order, because of how the
* user environment and arguments are stored.
*/
p = copy_strings(1, &filename, page, p, 1);
argc++;
if (i_arg) {
p = copy_strings(1, &i_arg, page, p, 2);
argc++;
}
p = copy_strings(1, &i_name, page, p, 2);
argc++;
if (!p) {
retval = -ENOMEM;
goto exec_error1;
}
/*
* OK, now restart the process with the interpreter's inode.
*/
old_fs = get_fs();
set_fs(get_ds());
if (!(inode=namei(interp))) { /* get executables inode */
set_fs(old_fs);
retval = -ENOENT;
goto exec_error1;
}
set_fs(old_fs);
goto restart_interp;
}
brelse(bh);
if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize || ex.a_drsize ||
ex.a_text+ex.a_data+ex.a_bss>0x3000000 ||
inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
retval = -ENOEXEC;
goto exec_error2;
}
if (N_TXTOFF(ex) != BLOCK_SIZE) {
printk("%s: N_TXTOFF != BLOCK_SIZE. See a.out.h.", filename);
retval = -ENOEXEC;
goto exec_error2;
}
if (!sh_bang) {
p = copy_strings(envc,envp,page,p,0);
p = copy_strings(argc,argv,page,p,0);
if (!p) {
retval = -ENOMEM;
goto exec_error2;
}
}
/* OK, This is the point of no return */
if (current->executable)
iput(current->executable);
current->executable = inode;
for (i=0 ; i<32 ; i++)
current->sigaction[i].sa_handler = NULL;
for (i=0 ; i<NR_OPEN ; i++)
if ((current->close_on_exec>>i)&1)
sys_close(i);
current->close_on_exec = 0;
free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
if (last_task_used_math == current)
last_task_used_math = NULL;
current->used_math = 0;
p += change_ldt(ex.a_text,page)-MAX_ARG_PAGES*PAGE_SIZE;
p = (unsigned long) create_tables((char *)p,argc,envc);
current->brk = ex.a_bss +
(current->end_data = ex.a_data +
(current->end_code = ex.a_text));
current->start_stack = p & 0xfffff000;
current->euid = e_uid;
current->egid = e_gid;
i = ex.a_text+ex.a_data;
while (i&0xfff)
put_fs_byte(0,(char *) (i++));
eip[0] = ex.a_entry; /* eip, magic happens :-) */
eip[3] = p; /* stack pointer */
return 0;
exec_error2:
iput(inode);
exec_error1:
for (i=0 ; i<MAX_ARG_PAGES ; i++)
free_page(page[i]);
return(retval);
}

BIN
linux/fs/exec.o Normal file

Binary file not shown.

75
linux/fs/fcntl.c Normal file
View File

@ -0,0 +1,75 @@
/*
* linux/fs/fcntl.c
*
* (C) 1991 Linus Torvalds
*/
#include <string.h>
#include <errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/segment.h>
#include <fcntl.h>
#include <sys/stat.h>
extern int sys_close(int fd);
static int dupfd(unsigned int fd, unsigned int arg)
{
if (fd >= NR_OPEN || !current->filp[fd])
return -EBADF;
if (arg >= NR_OPEN)
return -EINVAL;
while (arg < NR_OPEN)
if (current->filp[arg])
arg++;
else
break;
if (arg >= NR_OPEN)
return -EMFILE;
current->close_on_exec &= ~(1<<arg);
(current->filp[arg] = current->filp[fd])->f_count++;
return arg;
}
int sys_dup2(unsigned int oldfd, unsigned int newfd)
{
sys_close(newfd);
return dupfd(oldfd,newfd);
}
int sys_dup(unsigned int fildes)
{
return dupfd(fildes,0);
}
int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
{
struct file * filp;
if (fd >= NR_OPEN || !(filp = current->filp[fd]))
return -EBADF;
switch (cmd) {
case F_DUPFD:
return dupfd(fd,arg);
case F_GETFD:
return (current->close_on_exec>>fd)&1;
case F_SETFD:
if (arg&1)
current->close_on_exec |= (1<<fd);
else
current->close_on_exec &= ~(1<<fd);
return 0;
case F_GETFL:
return filp->f_flags;
case F_SETFL:
filp->f_flags &= ~(O_APPEND | O_NONBLOCK);
filp->f_flags |= arg & (O_APPEND | O_NONBLOCK);
return 0;
case F_GETLK: case F_SETLK: case F_SETLKW:
return -1;
default:
return -1;
}
}

BIN
linux/fs/fcntl.o Normal file

Binary file not shown.

90
linux/fs/file_dev.c Normal file
View File

@ -0,0 +1,90 @@
/*
* linux/fs/file_dev.c
*
* (C) 1991 Linus Torvalds
*/
#include <errno.h>
#include <fcntl.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/segment.h>
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
int file_read(struct m_inode * inode, struct file * filp, char * buf, int count)
{
int left,chars,nr;
struct buffer_head * bh;
if ((left=count)<=0)
return 0;
while (left) {
if (nr = bmap(inode,(filp->f_pos)/BLOCK_SIZE)) {
if (!(bh=bread(inode->i_dev,nr)))
break;
} else
bh = NULL;
nr = filp->f_pos % BLOCK_SIZE;
chars = MIN( BLOCK_SIZE-nr , left );
filp->f_pos += chars;
left -= chars;
if (bh) {
char * p = nr + bh->b_data;
while (chars-->0)
put_fs_byte(*(p++),buf++);
brelse(bh);
} else {
while (chars-->0)
put_fs_byte(0,buf++);
}
}
inode->i_atime = CURRENT_TIME;
return (count-left)?(count-left):-ERROR;
}
int file_write(struct m_inode * inode, struct file * filp, char * buf, int count)
{
off_t pos;
int block,c;
struct buffer_head * bh;
char * p;
int i=0;
/*
* ok, append may not work when many processes are writing at the same time
* but so what. That way leads to madness anyway.
*/
if (filp->f_flags & O_APPEND)
pos = inode->i_size;
else
pos = filp->f_pos;
while (i<count) {
if (!(block = create_block(inode,pos/BLOCK_SIZE)))
break;
if (!(bh=bread(inode->i_dev,block)))
break;
c = pos % BLOCK_SIZE;
p = c + bh->b_data;
bh->b_dirt = 1;
c = BLOCK_SIZE-c;
if (c > count-i) c = count-i;
pos += c;
if (pos > inode->i_size) {
inode->i_size = pos;
inode->i_dirt = 1;
}
i += c;
while (c-->0)
*(p++) = get_fs_byte(buf++);
brelse(bh);
}
inode->i_mtime = CURRENT_TIME;
if (!(filp->f_flags & O_APPEND)) {
filp->f_pos = pos;
inode->i_ctime = CURRENT_TIME;
}
return (i?i:-1);
}

BIN
linux/fs/file_dev.o Normal file

Binary file not shown.

9
linux/fs/file_table.c Normal file
View File

@ -0,0 +1,9 @@
/*
* linux/fs/file_table.c
*
* (C) 1991 Linus Torvalds
*/
#include <linux/fs.h>
struct file file_table[NR_FILE];

BIN
linux/fs/file_table.o Normal file

Binary file not shown.

BIN
linux/fs/fs.o Executable file

Binary file not shown.

338
linux/fs/inode.c Normal file
View File

@ -0,0 +1,338 @@
/*
* linux/fs/inode.c
*
* (C) 1991 Linus Torvalds
*/
#include <string.h>
#include <sys/stat.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <asm/system.h>
struct m_inode inode_table[NR_INODE]={{0,},};
static void read_inode(struct m_inode * inode);
static void write_inode(struct m_inode * inode);
static inline void wait_on_inode(struct m_inode * inode)
{
cli();
while (inode->i_lock)
sleep_on(&inode->i_wait);
sti();
}
static inline void lock_inode(struct m_inode * inode)
{
cli();
while (inode->i_lock)
sleep_on(&inode->i_wait);
inode->i_lock=1;
sti();
}
static inline void unlock_inode(struct m_inode * inode)
{
inode->i_lock=0;
wake_up(&inode->i_wait);
}
void invalidate_inodes(int dev)
{
int i;
struct m_inode * inode;
inode = 0+inode_table;
for(i=0 ; i<NR_INODE ; i++,inode++) {
wait_on_inode(inode);
if (inode->i_dev == dev) {
if (inode->i_count)
printk("inode in use on removed disk\n\r");
inode->i_dev = inode->i_dirt = 0;
}
}
}
void sync_inodes(void)
{
int i;
struct m_inode * inode;
inode = 0+inode_table;
for(i=0 ; i<NR_INODE ; i++,inode++) {
wait_on_inode(inode);
if (inode->i_dirt && !inode->i_pipe)
write_inode(inode);
}
}
static int _bmap(struct m_inode * inode,int block,int create)
{
struct buffer_head * bh;
int i;
if (block<0)
panic("_bmap: block<0");
if (block >= 7+512+512*512)
panic("_bmap: block>big");
if (block<7) {
if (create && !inode->i_zone[block])
if (inode->i_zone[block]=new_block(inode->i_dev)) {
inode->i_ctime=CURRENT_TIME;
inode->i_dirt=1;
}
return inode->i_zone[block];
}
block -= 7;
if (block<512) {
if (create && !inode->i_zone[7])
if (inode->i_zone[7]=new_block(inode->i_dev)) {
inode->i_dirt=1;
inode->i_ctime=CURRENT_TIME;
}
if (!inode->i_zone[7])
return 0;
if (!(bh = bread(inode->i_dev,inode->i_zone[7])))
return 0;
i = ((unsigned short *) (bh->b_data))[block];
if (create && !i)
if (i=new_block(inode->i_dev)) {
((unsigned short *) (bh->b_data))[block]=i;
bh->b_dirt=1;
}
brelse(bh);
return i;
}
block -= 512;
if (create && !inode->i_zone[8])
if (inode->i_zone[8]=new_block(inode->i_dev)) {
inode->i_dirt=1;
inode->i_ctime=CURRENT_TIME;
}
if (!inode->i_zone[8])
return 0;
if (!(bh=bread(inode->i_dev,inode->i_zone[8])))
return 0;
i = ((unsigned short *)bh->b_data)[block>>9];
if (create && !i)
if (i=new_block(inode->i_dev)) {
((unsigned short *) (bh->b_data))[block>>9]=i;
bh->b_dirt=1;
}
brelse(bh);
if (!i)
return 0;
if (!(bh=bread(inode->i_dev,i)))
return 0;
i = ((unsigned short *)bh->b_data)[block&511];
if (create && !i)
if (i=new_block(inode->i_dev)) {
((unsigned short *) (bh->b_data))[block&511]=i;
bh->b_dirt=1;
}
brelse(bh);
return i;
}
int bmap(struct m_inode * inode,int block)
{
return _bmap(inode,block,0);
}
int create_block(struct m_inode * inode, int block)
{
return _bmap(inode,block,1);
}
void iput(struct m_inode * inode)
{
if (!inode)
return;
wait_on_inode(inode);
if (!inode->i_count)
panic("iput: trying to free free inode");
if (inode->i_pipe) {
wake_up(&inode->i_wait);
if (--inode->i_count)
return;
free_page(inode->i_size);
inode->i_count=0;
inode->i_dirt=0;
inode->i_pipe=0;
return;
}
if (!inode->i_dev) {
inode->i_count--;
return;
}
if (S_ISBLK(inode->i_mode)) {
sync_dev(inode->i_zone[0]);
wait_on_inode(inode);
}
repeat:
if (inode->i_count>1) {
inode->i_count--;
return;
}
if (!inode->i_nlinks) {
truncate(inode);
free_inode(inode);
return;
}
if (inode->i_dirt) {
write_inode(inode); /* we can sleep - so do again */
wait_on_inode(inode);
goto repeat;
}
inode->i_count--;
return;
}
struct m_inode * get_empty_inode(void)
{
struct m_inode * inode;
static struct m_inode * last_inode = inode_table;
int i;
do {
inode = NULL;
for (i = NR_INODE; i ; i--) {
if (++last_inode >= inode_table + NR_INODE)
last_inode = inode_table;
if (!last_inode->i_count) {
inode = last_inode;
if (!inode->i_dirt && !inode->i_lock)
break;
}
}
if (!inode) {
for (i=0 ; i<NR_INODE ; i++)
printk("%04x: %6d\t",inode_table[i].i_dev,
inode_table[i].i_num);
panic("No free inodes in mem");
}
wait_on_inode(inode);
while (inode->i_dirt) {
write_inode(inode);
wait_on_inode(inode);
}
} while (inode->i_count);
memset(inode,0,sizeof(*inode));
inode->i_count = 1;
return inode;
}
struct m_inode * get_pipe_inode(void)
{
struct m_inode * inode;
if (!(inode = get_empty_inode()))
return NULL;
if (!(inode->i_size=get_free_page())) {
inode->i_count = 0;
return NULL;
}
inode->i_count = 2; /* sum of readers/writers */
PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
inode->i_pipe = 1;
return inode;
}
struct m_inode * iget(int dev,int nr)
{
struct m_inode * inode, * empty;
if (!dev)
panic("iget with dev==0");
empty = get_empty_inode();
inode = inode_table;
while (inode < NR_INODE+inode_table) {
if (inode->i_dev != dev || inode->i_num != nr) {
inode++;
continue;
}
wait_on_inode(inode);
if (inode->i_dev != dev || inode->i_num != nr) {
inode = inode_table;
continue;
}
inode->i_count++;
if (inode->i_mount) {
int i;
for (i = 0 ; i<NR_SUPER ; i++)
if (super_block[i].s_imount==inode)
break;
if (i >= NR_SUPER) {
printk("Mounted inode hasn't got sb\n");
if (empty)
iput(empty);
return inode;
}
iput(inode);
dev = super_block[i].s_dev;
nr = ROOT_INO;
inode = inode_table;
continue;
}
if (empty)
iput(empty);
return inode;
}
if (!empty)
return (NULL);
inode=empty;
inode->i_dev = dev;
inode->i_num = nr;
read_inode(inode);
return inode;
}
static void read_inode(struct m_inode * inode)
{
struct super_block * sb;
struct buffer_head * bh;
int block;
lock_inode(inode);
if (!(sb=get_super(inode->i_dev)))
panic("trying to read inode without dev");
block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks +
(inode->i_num-1)/INODES_PER_BLOCK;
if (!(bh=bread(inode->i_dev,block)))
panic("unable to read i-node block");
*(struct d_inode *)inode =
((struct d_inode *)bh->b_data)
[(inode->i_num-1)%INODES_PER_BLOCK];
brelse(bh);
unlock_inode(inode);
}
static void write_inode(struct m_inode * inode)
{
struct super_block * sb;
struct buffer_head * bh;
int block;
lock_inode(inode);
if (!inode->i_dirt || !inode->i_dev) {
unlock_inode(inode);
return;
}
if (!(sb=get_super(inode->i_dev)))
panic("trying to write inode without device");
block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks +
(inode->i_num-1)/INODES_PER_BLOCK;
if (!(bh=bread(inode->i_dev,block)))
panic("unable to read i-node block");
((struct d_inode *)bh->b_data)
[(inode->i_num-1)%INODES_PER_BLOCK] =
*(struct d_inode *)inode;
bh->b_dirt=1;
inode->i_dirt=0;
brelse(bh);
unlock_inode(inode);
}

BIN
linux/fs/inode.o Normal file

Binary file not shown.

46
linux/fs/ioctl.c Normal file
View File

@ -0,0 +1,46 @@
/*
* linux/fs/ioctl.c
*
* (C) 1991 Linus Torvalds
*/
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <linux/sched.h>
extern int tty_ioctl(int dev, int cmd, int arg);
typedef int (*ioctl_ptr)(int dev,int cmd,int arg);
#define NRDEVS ((sizeof (ioctl_table))/(sizeof (ioctl_ptr)))
static ioctl_ptr ioctl_table[]={
NULL, /* nodev */
NULL, /* /dev/mem */
NULL, /* /dev/fd */
NULL, /* /dev/hd */
tty_ioctl, /* /dev/ttyx */
tty_ioctl, /* /dev/tty */
NULL, /* /dev/lp */
NULL}; /* named pipes */
int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
{
struct file * filp;
int dev,mode;
if (fd >= NR_OPEN || !(filp = current->filp[fd]))
return -EBADF;
mode=filp->f_inode->i_mode;
if (!S_ISCHR(mode) && !S_ISBLK(mode))
return -EINVAL;
dev = filp->f_inode->i_zone[0];
if (MAJOR(dev) >= NRDEVS)
return -ENODEV;
if (!ioctl_table[MAJOR(dev)])
return -ENOTTY;
return ioctl_table[MAJOR(dev)](dev,cmd,arg);
}

BIN
linux/fs/ioctl.o Normal file

Binary file not shown.

783
linux/fs/namei.c Normal file
View File

@ -0,0 +1,783 @@
/*
* linux/fs/namei.c
*
* (C) 1991 Linus Torvalds
*/
/*
* Some corrections by tytso.
*/
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/segment.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <const.h>
#include <sys/stat.h>
#define ACC_MODE(x) ("\004\002\006\377"[(x)&O_ACCMODE])
/*
* comment out this line if you want names > NAME_LEN chars to be
* truncated. Else they will be disallowed.
*/
/* #define NO_TRUNCATE */
#define MAY_EXEC 1
#define MAY_WRITE 2
#define MAY_READ 4
/*
* permission()
*
* is used to check for read/write/execute permissions on a file.
* I don't know if we should look at just the euid or both euid and
* uid, but that should be easily changed.
*/
static int permission(struct m_inode * inode,int mask)
{
int mode = inode->i_mode;
/* special case: not even root can read/write a deleted file */
if (inode->i_dev && !inode->i_nlinks)
return 0;
else if (current->euid==inode->i_uid)
mode >>= 6;
else if (current->egid==inode->i_gid)
mode >>= 3;
if (((mode & mask & 0007) == mask) || suser())
return 1;
return 0;
}
/*
* ok, we cannot use strncmp, as the name is not in our data space.
* Thus we'll have to use match. No big problem. Match also makes
* some sanity tests.
*
* NOTE! unlike strncmp, match returns 1 for success, 0 for failure.
*/
static int match(int len,const char * name,struct dir_entry * de)
{
register int same __asm__("ax");
if (!de || !de->inode || len > NAME_LEN)
return 0;
if (len < NAME_LEN && de->name[len])
return 0;
__asm__("cld\n\t"
"fs ; repe ; cmpsb\n\t"
"setz %%al"
:"=a" (same)
:"0" (0),"S" ((long) name),"D" ((long) de->name),"c" (len)
:"cx","di","si");
return same;
}
/*
* find_entry()
*
* finds an entry in the specified directory with the wanted name. It
* returns the cache buffer in which the entry was found, and the entry
* itself (as a parameter - res_dir). It does NOT read the inode of the
* entry - you'll have to do that yourself if you want to.
*
* This also takes care of the few special cases due to '..'-traversal
* over a pseudo-root and a mount point.
*/
static struct buffer_head * find_entry(struct m_inode ** dir,
const char * name, int namelen, struct dir_entry ** res_dir)
{
int entries;
int block,i;
struct buffer_head * bh;
struct dir_entry * de;
struct super_block * sb;
#ifdef NO_TRUNCATE
if (namelen > NAME_LEN)
return NULL;
#else
if (namelen > NAME_LEN)
namelen = NAME_LEN;
#endif
entries = (*dir)->i_size / (sizeof (struct dir_entry));
*res_dir = NULL;
if (!namelen)
return NULL;
/* check for '..', as we might have to do some "magic" for it */
if (namelen==2 && get_fs_byte(name)=='.' && get_fs_byte(name+1)=='.') {
/* '..' in a pseudo-root results in a faked '.' (just change namelen) */
if ((*dir) == current->root)
namelen=1;
else if ((*dir)->i_num == ROOT_INO) {
/* '..' over a mount-point results in 'dir' being exchanged for the mounted
directory-inode. NOTE! We set mounted, so that we can iput the new dir */
sb=get_super((*dir)->i_dev);
if (sb->s_imount) {
iput(*dir);
(*dir)=sb->s_imount;
(*dir)->i_count++;
}
}
}
if (!(block = (*dir)->i_zone[0]))
return NULL;
if (!(bh = bread((*dir)->i_dev,block)))
return NULL;
i = 0;
de = (struct dir_entry *) bh->b_data;
while (i < entries) {
if ((char *)de >= BLOCK_SIZE+bh->b_data) {
brelse(bh);
bh = NULL;
if (!(block = bmap(*dir,i/DIR_ENTRIES_PER_BLOCK)) ||
!(bh = bread((*dir)->i_dev,block))) {
i += DIR_ENTRIES_PER_BLOCK;
continue;
}
de = (struct dir_entry *) bh->b_data;
}
if (match(namelen,name,de)) {
*res_dir = de;
return bh;
}
de++;
i++;
}
brelse(bh);
return NULL;
}
/*
* add_entry()
*
* adds a file entry to the specified directory, using the same
* semantics as find_entry(). It returns NULL if it failed.
*
* NOTE!! The inode part of 'de' is left at 0 - which means you
* may not sleep between calling this and putting something into
* the entry, as someone else might have used it while you slept.
*/
static struct buffer_head * add_entry(struct m_inode * dir,
const char * name, int namelen, struct dir_entry ** res_dir)
{
int block,i;
struct buffer_head * bh;
struct dir_entry * de;
*res_dir = NULL;
#ifdef NO_TRUNCATE
if (namelen > NAME_LEN)
return NULL;
#else
if (namelen > NAME_LEN)
namelen = NAME_LEN;
#endif
if (!namelen)
return NULL;
if (!(block = dir->i_zone[0]))
return NULL;
if (!(bh = bread(dir->i_dev,block)))
return NULL;
i = 0;
de = (struct dir_entry *) bh->b_data;
while (1) {
if ((char *)de >= BLOCK_SIZE+bh->b_data) {
brelse(bh);
bh = NULL;
block = create_block(dir,i/DIR_ENTRIES_PER_BLOCK);
if (!block)
return NULL;
if (!(bh = bread(dir->i_dev,block))) {
i += DIR_ENTRIES_PER_BLOCK;
continue;
}
de = (struct dir_entry *) bh->b_data;
}
if (i*sizeof(struct dir_entry) >= dir->i_size) {
de->inode=0;
dir->i_size = (i+1)*sizeof(struct dir_entry);
dir->i_dirt = 1;
dir->i_ctime = CURRENT_TIME;
}
if (!de->inode) {
dir->i_mtime = CURRENT_TIME;
for (i=0; i < NAME_LEN ; i++)
de->name[i]=(i<namelen)?get_fs_byte(name+i):0;
bh->b_dirt = 1;
*res_dir = de;
return bh;
}
de++;
i++;
}
brelse(bh);
return NULL;
}
/*
* get_dir()
*
* Getdir traverses the pathname until it hits the topmost directory.
* It returns NULL on failure.
*/
static struct m_inode * get_dir(const char * pathname)
{
char c;
const char * thisname;
struct m_inode * inode;
struct buffer_head * bh;
int namelen,inr,idev;
struct dir_entry * de;
if (!current->root || !current->root->i_count)
panic("No root inode");
if (!current->pwd || !current->pwd->i_count)
panic("No cwd inode");
if ((c=get_fs_byte(pathname))=='/') {
inode = current->root;
pathname++;
} else if (c)
inode = current->pwd;
else
return NULL; /* empty name is bad */
inode->i_count++;
while (1) {
thisname = pathname;
if (!S_ISDIR(inode->i_mode) || !permission(inode,MAY_EXEC)) {
iput(inode);
return NULL;
}
for(namelen=0;(c=get_fs_byte(pathname++))&&(c!='/');namelen++)
/* nothing */ ;
if (!c)
return inode;
if (!(bh = find_entry(&inode,thisname,namelen,&de))) {
iput(inode);
return NULL;
}
inr = de->inode;
idev = inode->i_dev;
brelse(bh);
iput(inode);
if (!(inode = iget(idev,inr)))
return NULL;
}
}
/*
* dir_namei()
*
* dir_namei() returns the inode of the directory of the
* specified name, and the name within that directory.
*/
static struct m_inode * dir_namei(const char * pathname,
int * namelen, const char ** name)
{
char c;
const char * basename;
struct m_inode * dir;
if (!(dir = get_dir(pathname)))
return NULL;
basename = pathname;
while (c=get_fs_byte(pathname++))
if (c=='/')
basename=pathname;
*namelen = pathname-basename-1;
*name = basename;
return dir;
}
/*
* namei()
*
* is used by most simple commands to get the inode of a specified name.
* Open, link etc use their own routines, but this is enough for things
* like 'chmod' etc.
*/
struct m_inode * namei(const char * pathname)
{
const char * basename;
int inr,dev,namelen;
struct m_inode * dir;
struct buffer_head * bh;
struct dir_entry * de;
if (!(dir = dir_namei(pathname,&namelen,&basename)))
return NULL;
if (!namelen) /* special case: '/usr/' etc */
return dir;
bh = find_entry(&dir,basename,namelen,&de);
if (!bh) {
iput(dir);
return NULL;
}
inr = de->inode;
dev = dir->i_dev;
brelse(bh);
iput(dir);
dir=iget(dev,inr);
if (dir) {
dir->i_atime=CURRENT_TIME;
dir->i_dirt=1;
}
return dir;
}
/*
* open_namei()
*
* namei for open - this is in fact almost the whole open-routine.
*/
int open_namei(const char * pathname, int flag, int mode,
struct m_inode ** res_inode)
{
const char * basename;
int inr,dev,namelen;
struct m_inode * dir, *inode;
struct buffer_head * bh;
struct dir_entry * de;
if ((flag & O_TRUNC) && !(flag & O_ACCMODE))
flag |= O_WRONLY;
mode &= 0777 & ~current->umask;
mode |= I_REGULAR;
if (!(dir = dir_namei(pathname,&namelen,&basename)))
return -ENOENT;
if (!namelen) { /* special case: '/usr/' etc */
if (!(flag & (O_ACCMODE|O_CREAT|O_TRUNC))) {
*res_inode=dir;
return 0;
}
iput(dir);
return -EISDIR;
}
bh = find_entry(&dir,basename,namelen,&de);
if (!bh) {
if (!(flag & O_CREAT)) {
iput(dir);
return -ENOENT;
}
if (!permission(dir,MAY_WRITE)) {
iput(dir);
return -EACCES;
}
inode = new_inode(dir->i_dev);
if (!inode) {
iput(dir);
return -ENOSPC;
}
inode->i_uid = current->euid;
inode->i_mode = mode;
inode->i_dirt = 1;
bh = add_entry(dir,basename,namelen,&de);
if (!bh) {
inode->i_nlinks--;
iput(inode);
iput(dir);
return -ENOSPC;
}
de->inode = inode->i_num;
bh->b_dirt = 1;
brelse(bh);
iput(dir);
*res_inode = inode;
return 0;
}
inr = de->inode;
dev = dir->i_dev;
brelse(bh);
iput(dir);
if (flag & O_EXCL)
return -EEXIST;
if (!(inode=iget(dev,inr)))
return -EACCES;
if ((S_ISDIR(inode->i_mode) && (flag & O_ACCMODE)) ||
!permission(inode,ACC_MODE(flag))) {
iput(inode);
return -EPERM;
}
inode->i_atime = CURRENT_TIME;
if (flag & O_TRUNC)
truncate(inode);
*res_inode = inode;
return 0;
}
int sys_mknod(const char * filename, int mode, int dev)
{
const char * basename;
int namelen;
struct m_inode * dir, * inode;
struct buffer_head * bh;
struct dir_entry * de;
if (!suser())
return -EPERM;
if (!(dir = dir_namei(filename,&namelen,&basename)))
return -ENOENT;
if (!namelen) {
iput(dir);
return -ENOENT;
}
if (!permission(dir,MAY_WRITE)) {
iput(dir);
return -EPERM;
}
bh = find_entry(&dir,basename,namelen,&de);
if (bh) {
brelse(bh);
iput(dir);
return -EEXIST;
}
inode = new_inode(dir->i_dev);
if (!inode) {
iput(dir);
return -ENOSPC;
}
inode->i_mode = mode;
if (S_ISBLK(mode) || S_ISCHR(mode))
inode->i_zone[0] = dev;
inode->i_mtime = inode->i_atime = CURRENT_TIME;
inode->i_dirt = 1;
bh = add_entry(dir,basename,namelen,&de);
if (!bh) {
iput(dir);
inode->i_nlinks=0;
iput(inode);
return -ENOSPC;
}
de->inode = inode->i_num;
bh->b_dirt = 1;
iput(dir);
iput(inode);
brelse(bh);
return 0;
}
int sys_mkdir(const char * pathname, int mode)
{
const char * basename;
int namelen;
struct m_inode * dir, * inode;
struct buffer_head * bh, *dir_block;
struct dir_entry * de;
if (!suser())
return -EPERM;
if (!(dir = dir_namei(pathname,&namelen,&basename)))
return -ENOENT;
if (!namelen) {
iput(dir);
return -ENOENT;
}
if (!permission(dir,MAY_WRITE)) {
iput(dir);
return -EPERM;
}
bh = find_entry(&dir,basename,namelen,&de);
if (bh) {
brelse(bh);
iput(dir);
return -EEXIST;
}
inode = new_inode(dir->i_dev);
if (!inode) {
iput(dir);
return -ENOSPC;
}
inode->i_size = 32;
inode->i_dirt = 1;
inode->i_mtime = inode->i_atime = CURRENT_TIME;
if (!(inode->i_zone[0]=new_block(inode->i_dev))) {
iput(dir);
inode->i_nlinks--;
iput(inode);
return -ENOSPC;
}
inode->i_dirt = 1;
if (!(dir_block=bread(inode->i_dev,inode->i_zone[0]))) {
iput(dir);
free_block(inode->i_dev,inode->i_zone[0]);
inode->i_nlinks--;
iput(inode);
return -ERROR;
}
de = (struct dir_entry *) dir_block->b_data;
de->inode=inode->i_num;
strcpy(de->name,".");
de++;
de->inode = dir->i_num;
strcpy(de->name,"..");
inode->i_nlinks = 2;
dir_block->b_dirt = 1;
brelse(dir_block);
inode->i_mode = I_DIRECTORY | (mode & 0777 & ~current->umask);
inode->i_dirt = 1;
bh = add_entry(dir,basename,namelen,&de);
if (!bh) {
iput(dir);
free_block(inode->i_dev,inode->i_zone[0]);
inode->i_nlinks=0;
iput(inode);
return -ENOSPC;
}
de->inode = inode->i_num;
bh->b_dirt = 1;
dir->i_nlinks++;
dir->i_dirt = 1;
iput(dir);
iput(inode);
brelse(bh);
return 0;
}
/*
* routine to check that the specified directory is empty (for rmdir)
*/
static int empty_dir(struct m_inode * inode)
{
int nr,block;
int len;
struct buffer_head * bh;
struct dir_entry * de;
len = inode->i_size / sizeof (struct dir_entry);
if (len<2 || !inode->i_zone[0] ||
!(bh=bread(inode->i_dev,inode->i_zone[0]))) {
printk("warning - bad directory on dev %04x\n",inode->i_dev);
return 0;
}
de = (struct dir_entry *) bh->b_data;
if (de[0].inode != inode->i_num || !de[1].inode ||
strcmp(".",de[0].name) || strcmp("..",de[1].name)) {
printk("warning - bad directory on dev %04x\n",inode->i_dev);
return 0;
}
nr = 2;
de += 2;
while (nr<len) {
if ((void *) de >= (void *) (bh->b_data+BLOCK_SIZE)) {
brelse(bh);
block=bmap(inode,nr/DIR_ENTRIES_PER_BLOCK);
if (!block) {
nr += DIR_ENTRIES_PER_BLOCK;
continue;
}
if (!(bh=bread(inode->i_dev,block)))
return 0;
de = (struct dir_entry *) bh->b_data;
}
if (de->inode) {
brelse(bh);
return 0;
}
de++;
nr++;
}
brelse(bh);
return 1;
}
int sys_rmdir(const char * name)
{
const char * basename;
int namelen;
struct m_inode * dir, * inode;
struct buffer_head * bh;
struct dir_entry * de;
if (!suser())
return -EPERM;
if (!(dir = dir_namei(name,&namelen,&basename)))
return -ENOENT;
if (!namelen) {
iput(dir);
return -ENOENT;
}
if (!permission(dir,MAY_WRITE)) {
iput(dir);
return -EPERM;
}
bh = find_entry(&dir,basename,namelen,&de);
if (!bh) {
iput(dir);
return -ENOENT;
}
if (!(inode = iget(dir->i_dev, de->inode))) {
iput(dir);
brelse(bh);
return -EPERM;
}
if ((dir->i_mode & S_ISVTX) && current->euid &&
inode->i_uid != current->euid) {
iput(dir);
iput(inode);
brelse(bh);
return -EPERM;
}
if (inode->i_dev != dir->i_dev || inode->i_count>1) {
iput(dir);
iput(inode);
brelse(bh);
return -EPERM;
}
if (inode == dir) { /* we may not delete ".", but "../dir" is ok */
iput(inode);
iput(dir);
brelse(bh);
return -EPERM;
}
if (!S_ISDIR(inode->i_mode)) {
iput(inode);
iput(dir);
brelse(bh);
return -ENOTDIR;
}
if (!empty_dir(inode)) {
iput(inode);
iput(dir);
brelse(bh);
return -ENOTEMPTY;
}
if (inode->i_nlinks != 2)
printk("empty directory has nlink!=2 (%d)",inode->i_nlinks);
de->inode = 0;
bh->b_dirt = 1;
brelse(bh);
inode->i_nlinks=0;
inode->i_dirt=1;
dir->i_nlinks--;
dir->i_ctime = dir->i_mtime = CURRENT_TIME;
dir->i_dirt=1;
iput(dir);
iput(inode);
return 0;
}
int sys_unlink(const char * name)
{
const char * basename;
int namelen;
struct m_inode * dir, * inode;
struct buffer_head * bh;
struct dir_entry * de;
if (!(dir = dir_namei(name,&namelen,&basename)))
return -ENOENT;
if (!namelen) {
iput(dir);
return -ENOENT;
}
if (!permission(dir,MAY_WRITE)) {
iput(dir);
return -EPERM;
}
bh = find_entry(&dir,basename,namelen,&de);
if (!bh) {
iput(dir);
return -ENOENT;
}
if (!(inode = iget(dir->i_dev, de->inode))) {
iput(dir);
brelse(bh);
return -ENOENT;
}
if ((dir->i_mode & S_ISVTX) && !suser() &&
current->euid != inode->i_uid &&
current->euid != dir->i_uid) {
iput(dir);
iput(inode);
brelse(bh);
return -EPERM;
}
if (S_ISDIR(inode->i_mode)) {
iput(inode);
iput(dir);
brelse(bh);
return -EPERM;
}
if (!inode->i_nlinks) {
printk("Deleting nonexistent file (%04x:%d), %d\n",
inode->i_dev,inode->i_num,inode->i_nlinks);
inode->i_nlinks=1;
}
de->inode = 0;
bh->b_dirt = 1;
brelse(bh);
inode->i_nlinks--;
inode->i_dirt = 1;
inode->i_ctime = CURRENT_TIME;
iput(inode);
iput(dir);
return 0;
}
int sys_symlink()
{
return -ENOSYS;
}
int sys_link(const char * oldname, const char * newname)
{
struct dir_entry * de;
struct m_inode * oldinode, * dir;
struct buffer_head * bh;
const char * basename;
int namelen;
oldinode=namei(oldname);
if (!oldinode)
return -ENOENT;
if (S_ISDIR(oldinode->i_mode)) {
iput(oldinode);
return -EPERM;
}
dir = dir_namei(newname,&namelen,&basename);
if (!dir) {
iput(oldinode);
return -EACCES;
}
if (!namelen) {
iput(oldinode);
iput(dir);
return -EPERM;
}
if (dir->i_dev != oldinode->i_dev) {
iput(dir);
iput(oldinode);
return -EXDEV;
}
if (!permission(dir,MAY_WRITE)) {
iput(dir);
iput(oldinode);
return -EACCES;
}
bh = find_entry(&dir,basename,namelen,&de);
if (bh) {
brelse(bh);
iput(dir);
iput(oldinode);
return -EEXIST;
}
bh = add_entry(dir,basename,namelen,&de);
if (!bh) {
iput(dir);
iput(oldinode);
return -ENOSPC;
}
de->inode = oldinode->i_num;
bh->b_dirt = 1;
brelse(bh);
iput(dir);
oldinode->i_nlinks++;
oldinode->i_ctime = CURRENT_TIME;
oldinode->i_dirt = 1;
iput(oldinode);
return 0;
}

BIN
linux/fs/namei.o Normal file

Binary file not shown.

208
linux/fs/open.c Normal file
View File

@ -0,0 +1,208 @@
/*
* linux/fs/open.c
*
* (C) 1991 Linus Torvalds
*/
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <utime.h>
#include <sys/stat.h>
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/kernel.h>
#include <asm/segment.h>
int sys_ustat(int dev, struct ustat * ubuf)
{
return -ENOSYS;
}
int sys_utime(char * filename, struct utimbuf * times)
{
struct m_inode * inode;
long actime,modtime;
if (!(inode=namei(filename)))
return -ENOENT;
if (times) {
actime = get_fs_long((unsigned long *) &times->actime);
modtime = get_fs_long((unsigned long *) &times->modtime);
} else
actime = modtime = CURRENT_TIME;
inode->i_atime = actime;
inode->i_mtime = modtime;
inode->i_dirt = 1;
iput(inode);
return 0;
}
/*
* XXX should we use the real or effective uid? BSD uses the real uid,
* so as to make this call useful to setuid programs.
*/
int sys_access(const char * filename,int mode)
{
struct m_inode * inode;
int res, i_mode;
mode &= 0007;
if (!(inode=namei(filename)))
return -EACCES;
i_mode = res = inode->i_mode & 0777;
iput(inode);
if (current->uid == inode->i_uid)
res >>= 6;
else if (current->gid == inode->i_gid)
res >>= 6;
if ((res & 0007 & mode) == mode)
return 0;
/*
* XXX we are doing this test last because we really should be
* swapping the effective with the real user id (temporarily),
* and then calling suser() routine. If we do call the
* suser() routine, it needs to be called last.
*/
if ((!current->uid) &&
(!(mode & 1) || (i_mode & 0111)))
return 0;
return -EACCES;
}
int sys_chdir(const char * filename)
{
struct m_inode * inode;
if (!(inode = namei(filename)))
return -ENOENT;
if (!S_ISDIR(inode->i_mode)) {
iput(inode);
return -ENOTDIR;
}
iput(current->pwd);
current->pwd = inode;
return (0);
}
int sys_chroot(const char * filename)
{
struct m_inode * inode;
if (!(inode=namei(filename)))
return -ENOENT;
if (!S_ISDIR(inode->i_mode)) {
iput(inode);
return -ENOTDIR;
}
iput(current->root);
current->root = inode;
return (0);
}
int sys_chmod(const char * filename,int mode)
{
struct m_inode * inode;
if (!(inode=namei(filename)))
return -ENOENT;
if ((current->euid != inode->i_uid) && !suser()) {
iput(inode);
return -EACCES;
}
inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
inode->i_dirt = 1;
iput(inode);
return 0;
}
int sys_chown(const char * filename,int uid,int gid)
{
struct m_inode * inode;
if (!(inode=namei(filename)))
return -ENOENT;
if (!suser()) {
iput(inode);
return -EACCES;
}
inode->i_uid=uid;
inode->i_gid=gid;
inode->i_dirt=1;
iput(inode);
return 0;
}
int sys_open(const char * filename,int flag,int mode)
{
struct m_inode * inode;
struct file * f;
int i,fd;
mode &= 0777 & ~current->umask;
for(fd=0 ; fd<NR_OPEN ; fd++)
if (!current->filp[fd])
break;
if (fd>=NR_OPEN)
return -EINVAL;
current->close_on_exec &= ~(1<<fd);
f=0+file_table;
for (i=0 ; i<NR_FILE ; i++,f++)
if (!f->f_count) break;
if (i>=NR_FILE)
return -EINVAL;
(current->filp[fd]=f)->f_count++;
if ((i=open_namei(filename,flag,mode,&inode))<0) {
current->filp[fd]=NULL;
f->f_count=0;
return i;
}
/* ttys are somewhat special (ttyxx major==4, tty major==5) */
if (S_ISCHR(inode->i_mode))
if (MAJOR(inode->i_zone[0])==4) {
if (current->leader && current->tty<0) {
current->tty = MINOR(inode->i_zone[0]);
tty_table[current->tty].pgrp = current->pgrp;
}
} else if (MAJOR(inode->i_zone[0])==5)
if (current->tty<0) {
iput(inode);
current->filp[fd]=NULL;
f->f_count=0;
return -EPERM;
}
/* Likewise with block-devices: check for floppy_change */
if (S_ISBLK(inode->i_mode))
check_disk_change(inode->i_zone[0]);
f->f_mode = inode->i_mode;
f->f_flags = flag;
f->f_count = 1;
f->f_inode = inode;
f->f_pos = 0;
return (fd);
}
int sys_creat(const char * pathname, int mode)
{
return sys_open(pathname, O_CREAT | O_TRUNC, mode);
}
int sys_close(unsigned int fd)
{
struct file * filp;
if (fd >= NR_OPEN)
return -EINVAL;
current->close_on_exec &= ~(1<<fd);
if (!(filp = current->filp[fd]))
return -EINVAL;
current->filp[fd] = NULL;
if (filp->f_count == 0)
panic("Close: file count is 0");
if (--filp->f_count)
return (0);
iput(filp->f_inode);
return (0);
}

BIN
linux/fs/open.o Normal file

Binary file not shown.

111
linux/fs/pipe.c Normal file
View File

@ -0,0 +1,111 @@
/*
* linux/fs/pipe.c
*
* (C) 1991 Linus Torvalds
*/
#include <signal.h>
#include <linux/sched.h>
#include <linux/mm.h> /* for get_free_page */
#include <asm/segment.h>
int read_pipe(struct m_inode * inode, char * buf, int count)
{
int chars, size, read = 0;
while (count>0) {
while (!(size=PIPE_SIZE(*inode))) {
wake_up(&inode->i_wait);
if (inode->i_count != 2) /* are there any writers? */
return read;
sleep_on(&inode->i_wait);
}
chars = PAGE_SIZE-PIPE_TAIL(*inode);
if (chars > count)
chars = count;
if (chars > size)
chars = size;
count -= chars;
read += chars;
size = PIPE_TAIL(*inode);
PIPE_TAIL(*inode) += chars;
PIPE_TAIL(*inode) &= (PAGE_SIZE-1);
while (chars-->0)
put_fs_byte(((char *)inode->i_size)[size++],buf++);
}
wake_up(&inode->i_wait);
return read;
}
int write_pipe(struct m_inode * inode, char * buf, int count)
{
int chars, size, written = 0;
while (count>0) {
while (!(size=(PAGE_SIZE-1)-PIPE_SIZE(*inode))) {
wake_up(&inode->i_wait);
if (inode->i_count != 2) { /* no readers */
current->signal |= (1<<(SIGPIPE-1));
return written?written:-1;
}
sleep_on(&inode->i_wait);
}
chars = PAGE_SIZE-PIPE_HEAD(*inode);
if (chars > count)
chars = count;
if (chars > size)
chars = size;
count -= chars;
written += chars;
size = PIPE_HEAD(*inode);
PIPE_HEAD(*inode) += chars;
PIPE_HEAD(*inode) &= (PAGE_SIZE-1);
while (chars-->0)
((char *)inode->i_size)[size++]=get_fs_byte(buf++);
}
wake_up(&inode->i_wait);
return written;
}
int sys_pipe(unsigned long * fildes)
{
struct m_inode * inode;
struct file * f[2];
int fd[2];
int i,j;
j=0;
for(i=0;j<2 && i<NR_FILE;i++)
if (!file_table[i].f_count)
(f[j++]=i+file_table)->f_count++;
if (j==1)
f[0]->f_count=0;
if (j<2)
return -1;
j=0;
for(i=0;j<2 && i<NR_OPEN;i++)
if (!current->filp[i]) {
current->filp[ fd[j]=i ] = f[j];
j++;
}
if (j==1)
current->filp[fd[0]]=NULL;
if (j<2) {
f[0]->f_count=f[1]->f_count=0;
return -1;
}
if (!(inode=get_pipe_inode())) {
current->filp[fd[0]] =
current->filp[fd[1]] = NULL;
f[0]->f_count = f[1]->f_count = 0;
return -1;
}
f[0]->f_inode = f[1]->f_inode = inode;
f[0]->f_pos = f[1]->f_pos = 0;
f[0]->f_mode = 1; /* read */
f[1]->f_mode = 2; /* write */
put_fs_long(fd[0],0+fildes);
put_fs_long(fd[1],1+fildes);
return 0;
}

BIN
linux/fs/pipe.o Normal file

Binary file not shown.

103
linux/fs/read_write.c Normal file
View File

@ -0,0 +1,103 @@
/*
* linux/fs/read_write.c
*
* (C) 1991 Linus Torvalds
*/
#include <sys/stat.h>
#include <errno.h>
#include <sys/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <asm/segment.h>
extern int rw_char(int rw,int dev, char * buf, int count, off_t * pos);
extern int read_pipe(struct m_inode * inode, char * buf, int count);
extern int write_pipe(struct m_inode * inode, char * buf, int count);
extern int block_read(int dev, off_t * pos, char * buf, int count);
extern int block_write(int dev, off_t * pos, char * buf, int count);
extern int file_read(struct m_inode * inode, struct file * filp,
char * buf, int count);
extern int file_write(struct m_inode * inode, struct file * filp,
char * buf, int count);
int sys_lseek(unsigned int fd,off_t offset, int origin)
{
struct file * file;
int tmp;
if (fd >= NR_OPEN || !(file=current->filp[fd]) || !(file->f_inode)
|| !IS_SEEKABLE(MAJOR(file->f_inode->i_dev)))
return -EBADF;
if (file->f_inode->i_pipe)
return -ESPIPE;
switch (origin) {
case 0:
if (offset<0) return -EINVAL;
file->f_pos=offset;
break;
case 1:
if (file->f_pos+offset<0) return -EINVAL;
file->f_pos += offset;
break;
case 2:
if ((tmp=file->f_inode->i_size+offset) < 0)
return -EINVAL;
file->f_pos = tmp;
break;
default:
return -EINVAL;
}
return file->f_pos;
}
int sys_read(unsigned int fd,char * buf,int count)
{
struct file * file;
struct m_inode * inode;
if (fd>=NR_OPEN || count<0 || !(file=current->filp[fd]))
return -EINVAL;
if (!count)
return 0;
verify_area(buf,count);
inode = file->f_inode;
if (inode->i_pipe)
return (file->f_mode&1)?read_pipe(inode,buf,count):-EIO;
if (S_ISCHR(inode->i_mode))
return rw_char(READ,inode->i_zone[0],buf,count,&file->f_pos);
if (S_ISBLK(inode->i_mode))
return block_read(inode->i_zone[0],&file->f_pos,buf,count);
if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode)) {
if (count+file->f_pos > inode->i_size)
count = inode->i_size - file->f_pos;
if (count<=0)
return 0;
return file_read(inode,file,buf,count);
}
printk("(Read)inode->i_mode=%06o\n\r",inode->i_mode);
return -EINVAL;
}
int sys_write(unsigned int fd,char * buf,int count)
{
struct file * file;
struct m_inode * inode;
if (fd>=NR_OPEN || count <0 || !(file=current->filp[fd]))
return -EINVAL;
if (!count)
return 0;
inode=file->f_inode;
if (inode->i_pipe)
return (file->f_mode&2)?write_pipe(inode,buf,count):-EIO;
if (S_ISCHR(inode->i_mode))
return rw_char(WRITE,inode->i_zone[0],buf,count,&file->f_pos);
if (S_ISBLK(inode->i_mode))
return block_write(inode->i_zone[0],&file->f_pos,buf,count);
if (S_ISREG(inode->i_mode))
return file_write(inode,file,buf,count);
printk("(Write)inode->i_mode=%06o\n\r",inode->i_mode);
return -EINVAL;
}

BIN
linux/fs/read_write.o Normal file

Binary file not shown.

10
linux/fs/select.c Normal file
View File

@ -0,0 +1,10 @@
/* nothing , only the stub */
/* gohigh */
#include <errno.h>
int sys_select()
{
return -ENOSYS;
}

BIN
linux/fs/select.o Normal file

Binary file not shown.

66
linux/fs/stat.c Normal file
View File

@ -0,0 +1,66 @@
/*
* linux/fs/stat.c
*
* (C) 1991 Linus Torvalds
*/
#include <errno.h>
#include <sys/stat.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/segment.h>
static void cp_stat(struct m_inode * inode, struct stat * statbuf)
{
struct stat tmp;
int i;
verify_area(statbuf,sizeof (* statbuf));
tmp.st_dev = inode->i_dev;
tmp.st_ino = inode->i_num;
tmp.st_mode = inode->i_mode;
tmp.st_nlink = inode->i_nlinks;
tmp.st_uid = inode->i_uid;
tmp.st_gid = inode->i_gid;
tmp.st_rdev = inode->i_zone[0];
tmp.st_size = inode->i_size;
tmp.st_atime = inode->i_atime;
tmp.st_mtime = inode->i_mtime;
tmp.st_ctime = inode->i_ctime;
for (i=0 ; i<sizeof (tmp) ; i++)
put_fs_byte(((char *) &tmp)[i],&((char *) statbuf)[i]);
}
int sys_stat(char * filename, struct stat * statbuf)
{
struct m_inode * inode;
if (!(inode=namei(filename)))
return -ENOENT;
cp_stat(inode,statbuf);
iput(inode);
return 0;
}
int sys_lstat(char * filename, struct stat * statbuf)
{
return sys_stat(filename, statbuf);
}
int sys_fstat(unsigned int fd, struct stat * statbuf)
{
struct file * f;
struct m_inode * inode;
if (fd >= NR_OPEN || !(f=current->filp[fd]) || !(inode=f->f_inode))
return -EBADF;
cp_stat(inode,statbuf);
return 0;
}
int sys_readlink()
{
return -ENOSYS;
}

BIN
linux/fs/stat.o Normal file

Binary file not shown.

281
linux/fs/super.c Normal file
View File

@ -0,0 +1,281 @@
/*
* linux/fs/super.c
*
* (C) 1991 Linus Torvalds
*/
/*
* super.c contains code to handle the super-block tables.
*/
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/system.h>
#include <errno.h>
#include <sys/stat.h>
int sync_dev(int dev);
void wait_for_keypress(void);
/* set_bit uses setb, as gas doesn't recognize setc */
#define set_bit(bitnr,addr) ({ \
register int __res __asm__("ax"); \
__asm__("bt %2,%3;setb %%al":"=a" (__res):"a" (0),"r" (bitnr),"m" (*(addr))); \
__res; })
struct super_block super_block[NR_SUPER];
/* this is initialized in init/main.c */
int ROOT_DEV = 0;
static void lock_super(struct super_block * sb)
{
cli();
while (sb->s_lock)
sleep_on(&(sb->s_wait));
sb->s_lock = 1;
sti();
}
static void free_super(struct super_block * sb)
{
cli();
sb->s_lock = 0;
wake_up(&(sb->s_wait));
sti();
}
static void wait_on_super(struct super_block * sb)
{
cli();
while (sb->s_lock)
sleep_on(&(sb->s_wait));
sti();
}
struct super_block * get_super(int dev)
{
struct super_block * s;
if (!dev)
return NULL;
s = 0+super_block;
while (s < NR_SUPER+super_block)
if (s->s_dev == dev) {
wait_on_super(s);
if (s->s_dev == dev)
return s;
s = 0+super_block;
} else
s++;
return NULL;
}
void put_super(int dev)
{
struct super_block * sb;
struct m_inode * inode;
int i;
if (dev == ROOT_DEV) {
printk("root diskette changed: prepare for armageddon\n\r");
return;
}
if (!(sb = get_super(dev)))
return;
if (sb->s_imount) {
printk("Mounted disk changed - tssk, tssk\n\r");
return;
}
lock_super(sb);
sb->s_dev = 0;
for(i=0;i<I_MAP_SLOTS;i++)
brelse(sb->s_imap[i]);
for(i=0;i<Z_MAP_SLOTS;i++)
brelse(sb->s_zmap[i]);
free_super(sb);
return;
}
static struct super_block * read_super(int dev)
{
struct super_block * s;
struct buffer_head * bh;
int i,block;
if (!dev)
return NULL;
check_disk_change(dev);
if (s = get_super(dev))
return s;
for (s = 0+super_block ;; s++) {
if (s >= NR_SUPER+super_block)
return NULL;
if (!s->s_dev)
break;
}
s->s_dev = dev;
s->s_isup = NULL;
s->s_imount = NULL;
s->s_time = 0;
s->s_rd_only = 0;
s->s_dirt = 0;
lock_super(s);
if (!(bh = bread(dev,1))) {
s->s_dev=0;
free_super(s);
return NULL;
}
*((struct d_super_block *) s) =
*((struct d_super_block *) bh->b_data);
brelse(bh);
if (s->s_magic != SUPER_MAGIC) {
s->s_dev = 0;
free_super(s);
return NULL;
}
for (i=0;i<I_MAP_SLOTS;i++)
s->s_imap[i] = NULL;
for (i=0;i<Z_MAP_SLOTS;i++)
s->s_zmap[i] = NULL;
block=2;
for (i=0 ; i < s->s_imap_blocks ; i++)
if (s->s_imap[i]=bread(dev,block))
block++;
else
break;
for (i=0 ; i < s->s_zmap_blocks ; i++)
if (s->s_zmap[i]=bread(dev,block))
block++;
else
break;
if (block != 2+s->s_imap_blocks+s->s_zmap_blocks) {
for(i=0;i<I_MAP_SLOTS;i++)
brelse(s->s_imap[i]);
for(i=0;i<Z_MAP_SLOTS;i++)
brelse(s->s_zmap[i]);
s->s_dev=0;
free_super(s);
return NULL;
}
s->s_imap[0]->b_data[0] |= 1;
s->s_zmap[0]->b_data[0] |= 1;
free_super(s);
return s;
}
int sys_umount(char * dev_name)
{
struct m_inode * inode;
struct super_block * sb;
int dev;
if (!(inode=namei(dev_name)))
return -ENOENT;
dev = inode->i_zone[0];
if (!S_ISBLK(inode->i_mode)) {
iput(inode);
return -ENOTBLK;
}
iput(inode);
if (dev==ROOT_DEV)
return -EBUSY;
if (!(sb=get_super(dev)) || !(sb->s_imount))
return -ENOENT;
if (!sb->s_imount->i_mount)
printk("Mounted inode has i_mount=0\n");
for (inode=inode_table+0 ; inode<inode_table+NR_INODE ; inode++)
if (inode->i_dev==dev && inode->i_count)
return -EBUSY;
sb->s_imount->i_mount=0;
iput(sb->s_imount);
sb->s_imount = NULL;
iput(sb->s_isup);
sb->s_isup = NULL;
put_super(dev);
sync_dev(dev);
return 0;
}
int sys_mount(char * dev_name, char * dir_name, int rw_flag)
{
struct m_inode * dev_i, * dir_i;
struct super_block * sb;
int dev;
if (!(dev_i=namei(dev_name)))
return -ENOENT;
dev = dev_i->i_zone[0];
if (!S_ISBLK(dev_i->i_mode)) {
iput(dev_i);
return -EPERM;
}
iput(dev_i);
if (!(dir_i=namei(dir_name)))
return -ENOENT;
if (dir_i->i_count != 1 || dir_i->i_num == ROOT_INO) {
iput(dir_i);
return -EBUSY;
}
if (!S_ISDIR(dir_i->i_mode)) {
iput(dir_i);
return -EPERM;
}
if (!(sb=read_super(dev))) {
iput(dir_i);
return -EBUSY;
}
if (sb->s_imount) {
iput(dir_i);
return -EBUSY;
}
if (dir_i->i_mount) {
iput(dir_i);
return -EPERM;
}
sb->s_imount=dir_i;
dir_i->i_mount=1;
dir_i->i_dirt=1; /* NOTE! we don't iput(dir_i) */
return 0; /* we do that in umount */
}
void mount_root(void)
{
int i,free;
struct super_block * p;
struct m_inode * mi;
if (32 != sizeof (struct d_inode))
panic("bad i-node size");
for(i=0;i<NR_FILE;i++)
file_table[i].f_count=0;
if (MAJOR(ROOT_DEV) == 2) {
printk("Insert root floppy and press ENTER");
wait_for_keypress();
}
for(p = &super_block[0] ; p < &super_block[NR_SUPER] ; p++) {
p->s_dev = 0;
p->s_lock = 0;
p->s_wait = NULL;
}
if (!(p=read_super(ROOT_DEV)))
panic("Unable to mount root");
if (!(mi=iget(ROOT_DEV,ROOT_INO)))
panic("Unable to read root i-node");
mi->i_count += 3 ; /* NOTE! it is logically used 4 times, not 1 */
p->s_isup = p->s_imount = mi;
current->pwd = mi;
current->root = mi;
free=0;
i=p->s_nzones;
while (-- i >= 0)
if (!set_bit(i&8191,p->s_zmap[i>>13]->b_data))
free++;
printk("%d/%d free blocks\n\r",free,p->s_nzones);
free=0;
i=p->s_ninodes+1;
while (-- i >= 0)
if (!set_bit(i&8191,p->s_imap[i>>13]->b_data))
free++;
printk("%d/%d free inodes\n\r",free,p->s_ninodes);
}

BIN
linux/fs/super.o Normal file

Binary file not shown.

65
linux/fs/truncate.c Normal file
View File

@ -0,0 +1,65 @@
/*
* linux/fs/truncate.c
*
* (C) 1991 Linus Torvalds
*/
#include <linux/sched.h>
#include <sys/stat.h>
static void free_ind(int dev,int block)
{
struct buffer_head * bh;
unsigned short * p;
int i;
if (!block)
return;
if (bh=bread(dev,block)) {
p = (unsigned short *) bh->b_data;
for (i=0;i<512;i++,p++)
if (*p)
free_block(dev,*p);
brelse(bh);
}
free_block(dev,block);
}
static void free_dind(int dev,int block)
{
struct buffer_head * bh;
unsigned short * p;
int i;
if (!block)
return;
if (bh=bread(dev,block)) {
p = (unsigned short *) bh->b_data;
for (i=0;i<512;i++,p++)
if (*p)
free_ind(dev,*p);
brelse(bh);
}
free_block(dev,block);
}
void truncate(struct m_inode * inode)
{
int i;
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)))
return;
for (i=0;i<7;i++)
if (inode->i_zone[i]) {
free_block(inode->i_dev,inode->i_zone[i]);
inode->i_zone[i]=0;
}
free_ind(inode->i_dev,inode->i_zone[7]);
free_dind(inode->i_dev,inode->i_zone[8]);
inode->i_zone[7] = inode->i_zone[8] = 0;
inode->i_size = 0;
inode->i_dirt = 1;
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
}

BIN
linux/fs/truncate.o Normal file

Binary file not shown.

220
linux/include/a.out.h Normal file
View File

@ -0,0 +1,220 @@
#ifndef _A_OUT_H
#define _A_OUT_H
#define __GNU_EXEC_MACROS__
struct exec {
unsigned long a_magic; /* Use macros N_MAGIC, etc for access */
unsigned a_text; /* length of text, in bytes */
unsigned a_data; /* length of data, in bytes */
unsigned a_bss; /* length of uninitialized data area for file, in bytes */
unsigned a_syms; /* length of symbol table data in file, in bytes */
unsigned a_entry; /* start address */
unsigned a_trsize; /* length of relocation info for text, in bytes */
unsigned a_drsize; /* length of relocation info for data, in bytes */
};
#ifndef N_MAGIC
#define N_MAGIC(exec) ((exec).a_magic)
#endif
#ifndef OMAGIC
/* Code indicating object file or impure executable. */
#define OMAGIC 0407
/* Code indicating pure executable. */
#define NMAGIC 0410
/* Code indicating demand-paged executable. */
#define ZMAGIC 0413
#endif /* not OMAGIC */
#ifndef N_BADMAG
#define N_BADMAG(x) \
(N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \
&& N_MAGIC(x) != ZMAGIC)
#endif
#define _N_BADMAG(x) \
(N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \
&& N_MAGIC(x) != ZMAGIC)
#define _N_HDROFF(x) (SEGMENT_SIZE - sizeof (struct exec))
#ifndef N_TXTOFF
#define N_TXTOFF(x) \
(N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : sizeof (struct exec))
#endif
#ifndef N_DATOFF
#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
#endif
#ifndef N_TRELOFF
#define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data)
#endif
#ifndef N_DRELOFF
#define N_DRELOFF(x) (N_TRELOFF(x) + (x).a_trsize)
#endif
#ifndef N_SYMOFF
#define N_SYMOFF(x) (N_DRELOFF(x) + (x).a_drsize)
#endif
#ifndef N_STROFF
#define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms)
#endif
/* Address of text segment in memory after it is loaded. */
#ifndef N_TXTADDR
#define N_TXTADDR(x) 0
#endif
/* Address of data segment in memory after it is loaded.
Note that it is up to you to define SEGMENT_SIZE
on machines not listed here. */
#if defined(vax) || defined(hp300) || defined(pyr)
#define SEGMENT_SIZE PAGE_SIZE
#endif
#ifdef hp300
#define PAGE_SIZE 4096
#endif
#ifdef sony
#define SEGMENT_SIZE 0x2000
#endif /* Sony. */
#ifdef is68k
#define SEGMENT_SIZE 0x20000
#endif
#if defined(m68k) && defined(PORTAR)
#define PAGE_SIZE 0x400
#define SEGMENT_SIZE PAGE_SIZE
#endif
#define PAGE_SIZE 4096
#define SEGMENT_SIZE 1024
#define _N_SEGMENT_ROUND(x) (((x) + SEGMENT_SIZE - 1) & ~(SEGMENT_SIZE - 1))
#define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
#ifndef N_DATADDR
#define N_DATADDR(x) \
(N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \
: (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
#endif
/* Address of bss segment in memory after it is loaded. */
#ifndef N_BSSADDR
#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data)
#endif
#ifndef N_NLIST_DECLARED
struct nlist {
union {
char *n_name;
struct nlist *n_next;
long n_strx;
} n_un;
unsigned char n_type;
char n_other;
short n_desc;
unsigned long n_value;
};
#endif
#ifndef N_UNDF
#define N_UNDF 0
#endif
#ifndef N_ABS
#define N_ABS 2
#endif
#ifndef N_TEXT
#define N_TEXT 4
#endif
#ifndef N_DATA
#define N_DATA 6
#endif
#ifndef N_BSS
#define N_BSS 8
#endif
#ifndef N_COMM
#define N_COMM 18
#endif
#ifndef N_FN
#define N_FN 15
#endif
#ifndef N_EXT
#define N_EXT 1
#endif
#ifndef N_TYPE
#define N_TYPE 036
#endif
#ifndef N_STAB
#define N_STAB 0340
#endif
/* The following type indicates the definition of a symbol as being
an indirect reference to another symbol. The other symbol
appears as an undefined reference, immediately following this symbol.
Indirection is asymmetrical. The other symbol's value will be used
to satisfy requests for the indirect symbol, but not vice versa.
If the other symbol does not have a definition, libraries will
be searched to find a definition. */
#define N_INDR 0xa
/* The following symbols refer to set elements.
All the N_SET[ATDB] symbols with the same name form one set.
Space is allocated for the set in the text section, and each set
element's value is stored into one word of the space.
The first word of the space is the length of the set (number of elements).
The address of the set is made into an N_SETV symbol
whose name is the same as the name of the set.
This symbol acts like a N_DATA global symbol
in that it can satisfy undefined external references. */
/* These appear as input to LD, in a .o file. */
#define N_SETA 0x14 /* Absolute set element symbol */
#define N_SETT 0x16 /* Text set element symbol */
#define N_SETD 0x18 /* Data set element symbol */
#define N_SETB 0x1A /* Bss set element symbol */
/* This is output from LD. */
#define N_SETV 0x1C /* Pointer to set vector in data area. */
#ifndef N_RELOCATION_INFO_DECLARED
/* This structure describes a single relocation to be performed.
The text-relocation section of the file is a vector of these structures,
all of which apply to the text section.
Likewise, the data-relocation section applies to the data section. */
struct relocation_info
{
/* Address (within segment) to be relocated. */
int r_address;
/* The meaning of r_symbolnum depends on r_extern. */
unsigned int r_symbolnum:24;
/* Nonzero means value is a pc-relative offset
and it should be relocated for changes in its own address
as well as for changes in the symbol or section specified. */
unsigned int r_pcrel:1;
/* Length (as exponent of 2) of the field to be relocated.
Thus, a value of 2 indicates 1<<2 bytes. */
unsigned int r_length:2;
/* 1 => relocate with value of symbol.
r_symbolnum is the index of the symbol
in file's the symbol table.
0 => relocate with the address of a segment.
r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS
(the N_EXT bit may be set also, but signifies nothing). */
unsigned int r_extern:1;
/* Four bits that aren't used, but when writing an object file
it is desirable to clear them. */
unsigned int r_pad:4;
};
#endif /* no N_RELOCATION_INFO_DECLARED. */
#endif /* __A_OUT_GNU_H__ */

24
linux/include/asm/io.h Normal file
View File

@ -0,0 +1,24 @@
#define outb(value,port) \
__asm__ ("outb %%al,%%dx"::"a" (value),"d" (port))
#define inb(port) ({ \
unsigned char _v; \
__asm__ volatile ("inb %%dx,%%al":"=a" (_v):"d" (port)); \
_v; \
})
#define outb_p(value,port) \
__asm__ ("outb %%al,%%dx\n" \
"\tjmp 1f\n" \
"1:\tjmp 1f\n" \
"1:"::"a" (value),"d" (port))
#define inb_p(port) ({ \
unsigned char _v; \
__asm__ volatile ("inb %%dx,%%al\n" \
"\tjmp 1f\n" \
"1:\tjmp 1f\n" \
"1:":"=a" (_v):"d" (port)); \
_v; \
})

View File

@ -0,0 +1,14 @@
/*
* NOTE!!! memcpy(dest,src,n) assumes ds=es=normal data segment. This
* goes for all kernel functions (ds=es=kernel space, fs=local data,
* gs=null), as well as for all well-behaving user programs (ds=es=
* user data space). This is NOT a bug, as any user program that changes
* es deserves to die if it isn't careful.
*/
#define memcpy(dest,src,n) ({ \
void * _res = dest; \
__asm__ ("cld;rep;movsb" \
::"D" ((long)(_res)),"S" ((long)(src)),"c" ((long) (n)) \
:"di","si","cx"); \
_res; \
})

View File

@ -0,0 +1,65 @@
extern inline unsigned char get_fs_byte(const char * addr)
{
unsigned register char _v;
__asm__ ("movb %%fs:%1,%0":"=r" (_v):"m" (*addr));
return _v;
}
extern inline unsigned short get_fs_word(const unsigned short *addr)
{
unsigned short _v;
__asm__ ("movw %%fs:%1,%0":"=r" (_v):"m" (*addr));
return _v;
}
extern inline unsigned long get_fs_long(const unsigned long *addr)
{
unsigned long _v;
__asm__ ("movl %%fs:%1,%0":"=r" (_v):"m" (*addr)); \
return _v;
}
extern inline void put_fs_byte(char val,char *addr)
{
__asm__ ("movb %0,%%fs:%1"::"r" (val),"m" (*addr));
}
extern inline void put_fs_word(short val,short * addr)
{
__asm__ ("movw %0,%%fs:%1"::"r" (val),"m" (*addr));
}
extern inline void put_fs_long(unsigned long val,unsigned long * addr)
{
__asm__ ("movl %0,%%fs:%1"::"r" (val),"m" (*addr));
}
/*
* Someone who knows GNU asm better than I should double check the followig.
* It seems to work, but I don't know if I'm doing something subtly wrong.
* --- TYT, 11/24/91
* [ nothing wrong here, Linus ]
*/
extern inline unsigned long get_fs()
{
unsigned short _v;
__asm__("mov %%fs,%%ax":"=a" (_v):);
return _v;
}
extern inline unsigned long get_ds()
{
unsigned short _v;
__asm__("mov %%ds,%%ax":"=a" (_v):);
return _v;
}
extern inline void set_fs(unsigned long val)
{
__asm__("mov %0,%%fs"::"a" ((unsigned short) val));
}

View File

@ -0,0 +1,66 @@
#define move_to_user_mode() \
__asm__ ("movl %%esp,%%eax\n\t" \
"pushl $0x17\n\t" \
"pushl %%eax\n\t" \
"pushfl\n\t" \
"pushl $0x0f\n\t" \
"pushl $1f\n\t" \
"iret\n" \
"1:\tmovl $0x17,%%eax\n\t" \
"movw %%ax,%%ds\n\t" \
"movw %%ax,%%es\n\t" \
"movw %%ax,%%fs\n\t" \
"movw %%ax,%%gs" \
:::"ax")
#define sti() __asm__ ("sti"::)
#define cli() __asm__ ("cli"::)
#define nop() __asm__ ("nop"::)
#define iret() __asm__ ("iret"::)
#define _set_gate(gate_addr,type,dpl,addr) \
__asm__ ("movw %%dx,%%ax\n\t" \
"movw %0,%%dx\n\t" \
"movl %%eax,%1\n\t" \
"movl %%edx,%2" \
: \
: "i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
"o" (*((char *) (gate_addr))), \
"o" (*(4+(char *) (gate_addr))), \
"d" ((char *) (addr)),"a" (0x00080000))
#define set_intr_gate(n,addr) \
_set_gate(&idt[n],14,0,addr)
#define set_trap_gate(n,addr) \
_set_gate(&idt[n],15,0,addr)
#define set_system_gate(n,addr) \
_set_gate(&idt[n],15,3,addr)
#define _set_seg_desc(gate_addr,type,dpl,base,limit) {\
*(gate_addr) = ((base) & 0xff000000) | \
(((base) & 0x00ff0000)>>16) | \
((limit) & 0xf0000) | \
((dpl)<<13) | \
(0x00408000) | \
((type)<<8); \
*((gate_addr)+1) = (((base) & 0x0000ffff)<<16) | \
((limit) & 0x0ffff); }
#define _set_tssldt_desc(n,addr,type) \
__asm__ ("movw $104,%1\n\t" \
"movw %%ax,%2\n\t" \
"rorl $16,%%eax\n\t" \
"movb %%al,%3\n\t" \
"movb $" type ",%4\n\t" \
"movb $0x00,%5\n\t" \
"movb %%ah,%6\n\t" \
"rorl $16,%%eax" \
::"a" (addr), "m" (*(n)), "m" (*(n+2)), "m" (*(n+4)), \
"m" (*(n+5)), "m" (*(n+6)), "m" (*(n+7)) \
)
#define set_tss_desc(n,addr) _set_tssldt_desc(((char *) (n)),addr,"0x89")
#define set_ldt_desc(n,addr) _set_tssldt_desc(((char *) (n)),addr,"0x82")

15
linux/include/const.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef _CONST_H
#define _CONST_H
#define BUFFER_END 0x200000
#define I_TYPE 0170000
#define I_DIRECTORY 0040000
#define I_REGULAR 0100000
#define I_BLOCK_SPECIAL 0060000
#define I_CHAR_SPECIAL 0020000
#define I_NAMED_PIPE 0010000
#define I_SET_UID_BIT 0004000
#define I_SET_GID_BIT 0002000
#endif

34
linux/include/ctype.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef _CTYPE_H
#define _CTYPE_H
#define _U 0x01 /* upper */
#define _L 0x02 /* lower */
#define _D 0x04 /* digit */
#define _C 0x08 /* cntrl */
#define _P 0x10 /* punct */
#define _S 0x20 /* white space (space/lf/tab) */
#define _X 0x40 /* hex digit */
#define _SP 0x80 /* hard space (0x20) */
extern unsigned char _ctype[];
extern char _ctmp;
#define isalnum(c) ((_ctype+1)[c]&(_U|_L|_D))
#define isalpha(c) ((_ctype+1)[c]&(_U|_L))
#define iscntrl(c) ((_ctype+1)[c]&(_C))
#define isdigit(c) ((_ctype+1)[c]&(_D))
#define isgraph(c) ((_ctype+1)[c]&(_P|_U|_L|_D))
#define islower(c) ((_ctype+1)[c]&(_L))
#define isprint(c) ((_ctype+1)[c]&(_P|_U|_L|_D|_SP))
#define ispunct(c) ((_ctype+1)[c]&(_P))
#define isspace(c) ((_ctype+1)[c]&(_S))
#define isupper(c) ((_ctype+1)[c]&(_U))
#define isxdigit(c) ((_ctype+1)[c]&(_D|_X))
#define isascii(c) (((unsigned) c)<=0x7f)
#define toascii(c) (((unsigned) c)&0x7f)
#define tolower(c) (_ctmp=c,isupper(_ctmp)?_ctmp-('A'-'a'):_ctmp)
#define toupper(c) (_ctmp=c,islower(_ctmp)?_ctmp-('a'-'A'):_ctmp)
#endif

60
linux/include/errno.h Normal file
View File

@ -0,0 +1,60 @@
#ifndef _ERRNO_H
#define _ERRNO_H
/*
* ok, as I hadn't got any other source of information about
* possible error numbers, I was forced to use the same numbers
* as minix.
* Hopefully these are posix or something. I wouldn't know (and posix
* isn't telling me - they want $$$ for their f***ing standard).
*
* We don't use the _SIGN cludge of minix, so kernel returns must
* see to the sign by themselves.
*
* NOTE! Remember to change strerror() if you change this file!
*/
extern int errno;
#define ERROR 99
#define EPERM 1
#define ENOENT 2
#define ESRCH 3
#define EINTR 4
#define EIO 5
#define ENXIO 6
#define E2BIG 7
#define ENOEXEC 8
#define EBADF 9
#define ECHILD 10
#define EAGAIN 11
#define ENOMEM 12
#define EACCES 13
#define EFAULT 14
#define ENOTBLK 15
#define EBUSY 16
#define EEXIST 17
#define EXDEV 18
#define ENODEV 19
#define ENOTDIR 20
#define EISDIR 21
#define EINVAL 22
#define ENFILE 23
#define EMFILE 24
#define ENOTTY 25
#define ETXTBSY 26
#define EFBIG 27
#define ENOSPC 28
#define ESPIPE 29
#define EROFS 30
#define EMLINK 31
#define EPIPE 32
#define EDOM 33
#define ERANGE 34
#define EDEADLK 35
#define ENAMETOOLONG 36
#define ENOLCK 37
#define ENOSYS 38
#define ENOTEMPTY 39
#endif

55
linux/include/fcntl.h Normal file
View File

@ -0,0 +1,55 @@
#ifndef _FCNTL_H
#define _FCNTL_H
#include <sys/types.h>
/* open/fcntl - NOCTTY, NDELAY isn't implemented yet */
#define O_ACCMODE 00003
#define O_RDONLY 00
#define O_WRONLY 01
#define O_RDWR 02
#define O_CREAT 00100 /* not fcntl */
#define O_EXCL 00200 /* not fcntl */
#define O_NOCTTY 00400 /* not fcntl */
#define O_TRUNC 01000 /* not fcntl */
#define O_APPEND 02000
#define O_NONBLOCK 04000 /* not fcntl */
#define O_NDELAY O_NONBLOCK
/* Defines for fcntl-commands. Note that currently
* locking isn't supported, and other things aren't really
* tested.
*/
#define F_DUPFD 0 /* dup */
#define F_GETFD 1 /* get f_flags */
#define F_SETFD 2 /* set f_flags */
#define F_GETFL 3 /* more flags (cloexec) */
#define F_SETFL 4
#define F_GETLK 5 /* not implemented */
#define F_SETLK 6
#define F_SETLKW 7
/* for F_[GET|SET]FL */
#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
/* Ok, these are locking features, and aren't implemented at any
* level. POSIX wants them.
*/
#define F_RDLCK 0
#define F_WRLCK 1
#define F_UNLCK 2
/* Once again - not implemented, but ... */
struct flock {
short l_type;
short l_whence;
off_t l_start;
off_t l_len;
pid_t l_pid;
};
extern int creat(const char * filename,mode_t mode);
extern int fcntl(int fildes,int cmd, ...);
extern int open(const char * filename, int flags, ...);
#endif

View File

@ -0,0 +1,48 @@
#ifndef _CONFIG_H
#define _CONFIG_H
/*
* The root-device is no longer hard-coded. You can change the default
* root-device by changing the line ROOT_DEV = XXX in boot/bootsect.s
*/
/*
* define your keyboard here -
* KBD_FINNISH for Finnish keyboards
* KBD_US for US-type
* KBD_GR for German keyboards
* KBD_FR for Frech keyboard
*/
#define KBD_US
/*#define KBD_GR */
/*#define KBD_FR */
/*#define KBD_FINNISH */
/*
* Normally, Linux can get the drive parameters from the BIOS at
* startup, but if this for some unfathomable reason fails, you'd
* be left stranded. For this case, you can define HD_TYPE, which
* contains all necessary info on your harddisk.
*
* The HD_TYPE macro should look like this:
*
* #define HD_TYPE { head, sect, cyl, wpcom, lzone, ctl}
*
* In case of two harddisks, the info should be sepatated by
* commas:
*
* #define HD_TYPE { h,s,c,wpcom,lz,ctl },{ h,s,c,wpcom,lz,ctl }
*/
/*
This is an example, two drives, first is type 2, second is type 3:
#define HD_TYPE { 4,17,615,300,615,8 }, { 6,17,615,300,615,0 }
NOTE: ctl is 0 for all drives with heads<=8, and ctl=8 for drives
with more than 8 heads.
If you want the BIOS to tell what kind of drive you have, just
leave HD_TYPE undefined. This is the normal thing to do.
*/
#endif

View File

@ -0,0 +1,71 @@
/*
* This file contains some defines for the floppy disk controller.
* Various sources. Mostly "IBM Microcomputers: A Programmers
* Handbook", Sanches and Canton.
*/
#ifndef _FDREG_H
#define _FDREG_H
extern int ticks_to_floppy_on(unsigned int nr);
extern void floppy_on(unsigned int nr);
extern void floppy_off(unsigned int nr);
extern void floppy_select(unsigned int nr);
extern void floppy_deselect(unsigned int nr);
/* Fd controller regs. S&C, about page 340 */
#define FD_STATUS 0x3f4
#define FD_DATA 0x3f5
#define FD_DOR 0x3f2 /* Digital Output Register */
#define FD_DIR 0x3f7 /* Digital Input Register (read) */
#define FD_DCR 0x3f7 /* Diskette Control Register (write)*/
/* Bits of main status register */
#define STATUS_BUSYMASK 0x0F /* drive busy mask */
#define STATUS_BUSY 0x10 /* FDC busy */
#define STATUS_DMA 0x20 /* 0- DMA mode */
#define STATUS_DIR 0x40 /* 0- cpu->fdc */
#define STATUS_READY 0x80 /* Data reg ready */
/* Bits of FD_ST0 */
#define ST0_DS 0x03 /* drive select mask */
#define ST0_HA 0x04 /* Head (Address) */
#define ST0_NR 0x08 /* Not Ready */
#define ST0_ECE 0x10 /* Equipment chech error */
#define ST0_SE 0x20 /* Seek end */
#define ST0_INTR 0xC0 /* Interrupt code mask */
/* Bits of FD_ST1 */
#define ST1_MAM 0x01 /* Missing Address Mark */
#define ST1_WP 0x02 /* Write Protect */
#define ST1_ND 0x04 /* No Data - unreadable */
#define ST1_OR 0x10 /* OverRun */
#define ST1_CRC 0x20 /* CRC error in data or addr */
#define ST1_EOC 0x80 /* End Of Cylinder */
/* Bits of FD_ST2 */
#define ST2_MAM 0x01 /* Missing Addess Mark (again) */
#define ST2_BC 0x02 /* Bad Cylinder */
#define ST2_SNS 0x04 /* Scan Not Satisfied */
#define ST2_SEH 0x08 /* Scan Equal Hit */
#define ST2_WC 0x10 /* Wrong Cylinder */
#define ST2_CRC 0x20 /* CRC error in data field */
#define ST2_CM 0x40 /* Control Mark = deleted */
/* Bits of FD_ST3 */
#define ST3_HA 0x04 /* Head (Address) */
#define ST3_TZ 0x10 /* Track Zero signal (1=track 0) */
#define ST3_WP 0x40 /* Write Protect */
/* Values for FD_COMMAND */
#define FD_RECALIBRATE 0x07 /* move to track 0 */
#define FD_SEEK 0x0F /* seek track */
#define FD_READ 0xE6 /* read with MT, MFM, SKip deleted */
#define FD_WRITE 0xC5 /* write with MT, MFM */
#define FD_SENSEI 0x08 /* Sense Interrupt Status */
#define FD_SPECIFY 0x03 /* specify HUT etc */
/* DMA commands */
#define DMA_READ 0x46
#define DMA_WRITE 0x4A
#endif

202
linux/include/linux/fs.h Normal file
View File

@ -0,0 +1,202 @@
/*
* This file has definitions for some important file table
* structures etc.
*/
#ifndef _FS_H
#define _FS_H
#include <sys/types.h>
/* devices are as follows: (same as minix, so we can use the minix
* file system. These are major numbers.)
*
* 0 - unused (nodev)
* 1 - /dev/mem
* 2 - /dev/fd
* 3 - /dev/hd
* 4 - /dev/ttyx
* 5 - /dev/tty
* 6 - /dev/lp
* 7 - unnamed pipes
*/
#define IS_SEEKABLE(x) ((x)>=1 && (x)<=3)
#define READ 0
#define WRITE 1
#define READA 2 /* read-ahead - don't pause */
#define WRITEA 3 /* "write-ahead" - silly, but somewhat useful */
void buffer_init(long buffer_end);
#define MAJOR(a) (((unsigned)(a))>>8)
#define MINOR(a) ((a)&0xff)
#define NAME_LEN 14
#define ROOT_INO 1
#define I_MAP_SLOTS 8
#define Z_MAP_SLOTS 8
#define SUPER_MAGIC 0x137F
#define NR_OPEN 20
#define NR_INODE 32
#define NR_FILE 64
#define NR_SUPER 8
#define NR_HASH 307
#define NR_BUFFERS nr_buffers
#define BLOCK_SIZE 1024
#define BLOCK_SIZE_BITS 10
#ifndef NULL
#define NULL ((void *) 0)
#endif
#define INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct d_inode)))
#define DIR_ENTRIES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct dir_entry)))
#define PIPE_HEAD(inode) ((inode).i_zone[0])
#define PIPE_TAIL(inode) ((inode).i_zone[1])
#define PIPE_SIZE(inode) ((PIPE_HEAD(inode)-PIPE_TAIL(inode))&(PAGE_SIZE-1))
#define PIPE_EMPTY(inode) (PIPE_HEAD(inode)==PIPE_TAIL(inode))
#define PIPE_FULL(inode) (PIPE_SIZE(inode)==(PAGE_SIZE-1))
#define INC_PIPE(head) \
__asm__("incl %0\n\tandl $4095,%0"::"m" (head))
typedef char buffer_block[BLOCK_SIZE];
struct buffer_head {
char * b_data; /* pointer to data block (1024 bytes) */
unsigned long b_blocknr; /* block number */
unsigned short b_dev; /* device (0 = free) */
unsigned char b_uptodate;
unsigned char b_dirt; /* 0-clean,1-dirty */
unsigned char b_count; /* users using this block */
unsigned char b_lock; /* 0 - ok, 1 -locked */
struct task_struct * b_wait;
struct buffer_head * b_prev;
struct buffer_head * b_next;
struct buffer_head * b_prev_free;
struct buffer_head * b_next_free;
};
struct d_inode {
unsigned short i_mode;
unsigned short i_uid;
unsigned long i_size;
unsigned long i_time;
unsigned char i_gid;
unsigned char i_nlinks;
unsigned short i_zone[9];
};
struct m_inode {
unsigned short i_mode;
unsigned short i_uid;
unsigned long i_size;
unsigned long i_mtime;
unsigned char i_gid;
unsigned char i_nlinks;
unsigned short i_zone[9];
/* these are in memory also */
struct task_struct * i_wait;
unsigned long i_atime;
unsigned long i_ctime;
unsigned short i_dev;
unsigned short i_num;
unsigned short i_count;
unsigned char i_lock;
unsigned char i_dirt;
unsigned char i_pipe;
unsigned char i_mount;
unsigned char i_seek;
unsigned char i_update;
};
struct file {
unsigned short f_mode;
unsigned short f_flags;
unsigned short f_count;
struct m_inode * f_inode;
off_t f_pos;
};
struct super_block {
unsigned short s_ninodes;
unsigned short s_nzones;
unsigned short s_imap_blocks;
unsigned short s_zmap_blocks;
unsigned short s_firstdatazone;
unsigned short s_log_zone_size;
unsigned long s_max_size;
unsigned short s_magic;
/* These are only in memory */
struct buffer_head * s_imap[8];
struct buffer_head * s_zmap[8];
unsigned short s_dev;
struct m_inode * s_isup;
struct m_inode * s_imount;
unsigned long s_time;
struct task_struct * s_wait;
unsigned char s_lock;
unsigned char s_rd_only;
unsigned char s_dirt;
};
struct d_super_block {
unsigned short s_ninodes;
unsigned short s_nzones;
unsigned short s_imap_blocks;
unsigned short s_zmap_blocks;
unsigned short s_firstdatazone;
unsigned short s_log_zone_size;
unsigned long s_max_size;
unsigned short s_magic;
};
struct dir_entry {
unsigned short inode;
char name[NAME_LEN];
};
extern struct m_inode inode_table[NR_INODE];
extern struct file file_table[NR_FILE];
extern struct super_block super_block[NR_SUPER];
extern struct buffer_head * start_buffer;
extern int nr_buffers;
extern void check_disk_change(int dev);
extern int floppy_change(unsigned int nr);
extern int ticks_to_floppy_on(unsigned int dev);
extern void floppy_on(unsigned int dev);
extern void floppy_off(unsigned int dev);
extern void truncate(struct m_inode * inode);
extern void sync_inodes(void);
extern void wait_on(struct m_inode * inode);
extern int bmap(struct m_inode * inode,int block);
extern int create_block(struct m_inode * inode,int block);
extern struct m_inode * namei(const char * pathname);
extern int open_namei(const char * pathname, int flag, int mode,
struct m_inode ** res_inode);
extern void iput(struct m_inode * inode);
extern struct m_inode * iget(int dev,int nr);
extern struct m_inode * get_empty_inode(void);
extern struct m_inode * get_pipe_inode(void);
extern struct buffer_head * get_hash_table(int dev, int block);
extern struct buffer_head * getblk(int dev, int block);
extern void ll_rw_block(int rw, struct buffer_head * bh);
extern void brelse(struct buffer_head * buf);
extern struct buffer_head * bread(int dev,int block);
extern void bread_page(unsigned long addr,int dev,int b[4]);
extern struct buffer_head * breada(int dev,int block,...);
extern int new_block(int dev);
extern void free_block(int dev, int block);
extern struct m_inode * new_inode(int dev);
extern void free_inode(struct m_inode * inode);
extern int sync_dev(int dev);
extern struct super_block * get_super(int dev);
extern int ROOT_DEV;
extern void mount_root(void);
#endif

View File

@ -0,0 +1,65 @@
/*
* This file contains some defines for the AT-hd-controller.
* Various sources. Check out some definitions (see comments with
* a ques).
*/
#ifndef _HDREG_H
#define _HDREG_H
/* Hd controller regs. Ref: IBM AT Bios-listing */
#define HD_DATA 0x1f0 /* _CTL when writing */
#define HD_ERROR 0x1f1 /* see err-bits */
#define HD_NSECTOR 0x1f2 /* nr of sectors to read/write */
#define HD_SECTOR 0x1f3 /* starting sector */
#define HD_LCYL 0x1f4 /* starting cylinder */
#define HD_HCYL 0x1f5 /* high byte of starting cyl */
#define HD_CURRENT 0x1f6 /* 101dhhhh , d=drive, hhhh=head */
#define HD_STATUS 0x1f7 /* see status-bits */
#define HD_PRECOMP HD_ERROR /* same io address, read=error, write=precomp */
#define HD_COMMAND HD_STATUS /* same io address, read=status, write=cmd */
#define HD_CMD 0x3f6
/* Bits of HD_STATUS */
#define ERR_STAT 0x01
#define INDEX_STAT 0x02
#define ECC_STAT 0x04 /* Corrected error */
#define DRQ_STAT 0x08
#define SEEK_STAT 0x10
#define WRERR_STAT 0x20
#define READY_STAT 0x40
#define BUSY_STAT 0x80
/* Values for HD_COMMAND */
#define WIN_RESTORE 0x10
#define WIN_READ 0x20
#define WIN_WRITE 0x30
#define WIN_VERIFY 0x40
#define WIN_FORMAT 0x50
#define WIN_INIT 0x60
#define WIN_SEEK 0x70
#define WIN_DIAGNOSE 0x90
#define WIN_SPECIFY 0x91
/* Bits for HD_ERROR */
#define MARK_ERR 0x01 /* Bad address mark ? */
#define TRK0_ERR 0x02 /* couldn't find track 0 */
#define ABRT_ERR 0x04 /* ? */
#define ID_ERR 0x10 /* ? */
#define ECC_ERR 0x40 /* ? */
#define BBD_ERR 0x80 /* ? */
struct partition {
unsigned char boot_ind; /* 0x80 - active (unused) */
unsigned char head; /* ? */
unsigned char sector; /* ? */
unsigned char cyl; /* ? */
unsigned char sys_ind; /* ? */
unsigned char end_head; /* ? */
unsigned char end_sector; /* ? */
unsigned char end_cyl; /* ? */
unsigned int start_sect; /* starting sector counting from 0 */
unsigned int nr_sects; /* nr of sectors in partition */
};
#endif

View File

@ -0,0 +1,20 @@
#ifndef _HEAD_H
#define _HEAD_H
typedef struct desc_struct {
unsigned long a,b;
} desc_table[256];
extern unsigned long pg_dir[1024];
extern desc_table idt,gdt;
#define GDT_NUL 0
#define GDT_CODE 1
#define GDT_DATA 2
#define GDT_TMP 3
#define LDT_NUL 0
#define LDT_CODE 1
#define LDT_DATA 2
#endif

View File

@ -0,0 +1,22 @@
/*
* 'kernel.h' contains some often-used function prototypes etc
*/
void verify_area(void * addr,int count);
volatile void panic(const char * str);
int printf(const char * fmt, ...);
int printk(const char * fmt, ...);
int tty_write(unsigned ch,char * buf,int count);
void * malloc(unsigned int size);
void free_s(void * obj, int size);
#define free(x) free_s((x), 0)
/*
* This is defined as a macro, but at some point this might become a
* real subroutine that sets a flag if it returns true (to do
* BSD-style accounting where the process is flagged if it uses root
* privs). The implication of this is that you should do normal
* permissions checks first, and check suser() last.
*/
#define suser() (current->euid == 0)

10
linux/include/linux/mm.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef _MM_H
#define _MM_H
#define PAGE_SIZE 4096
extern unsigned long get_free_page(void);
extern unsigned long put_page(unsigned long page,unsigned long address);
extern void free_page(unsigned long addr);
#endif

233
linux/include/linux/sched.h Normal file
View File

@ -0,0 +1,233 @@
#ifndef _SCHED_H
#define _SCHED_H
#define NR_TASKS 64
#define HZ 100
#define FIRST_TASK task[0]
#define LAST_TASK task[NR_TASKS-1]
#include <linux/head.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <signal.h>
#if (NR_OPEN > 32)
#error "Currently the close-on-exec-flags are in one word, max 32 files/proc"
#endif
#define TASK_RUNNING 0
#define TASK_INTERRUPTIBLE 1
#define TASK_UNINTERRUPTIBLE 2
#define TASK_ZOMBIE 3
#define TASK_STOPPED 4
#ifndef NULL
#define NULL ((void *) 0)
#endif
extern int copy_page_tables(unsigned long from, unsigned long to, long size);
extern int free_page_tables(unsigned long from, unsigned long size);
extern void sched_init(void);
extern void schedule(void);
extern void trap_init(void);
extern void panic(const char * str);
extern int tty_write(unsigned minor,char * buf,int count);
typedef int (*fn_ptr)();
struct i387_struct {
long cwd;
long swd;
long twd;
long fip;
long fcs;
long foo;
long fos;
long st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */
};
struct tss_struct {
long back_link; /* 16 high bits zero */
long esp0;
long ss0; /* 16 high bits zero */
long esp1;
long ss1; /* 16 high bits zero */
long esp2;
long ss2; /* 16 high bits zero */
long cr3;
long eip;
long eflags;
long eax,ecx,edx,ebx;
long esp;
long ebp;
long esi;
long edi;
long es; /* 16 high bits zero */
long cs; /* 16 high bits zero */
long ss; /* 16 high bits zero */
long ds; /* 16 high bits zero */
long fs; /* 16 high bits zero */
long gs; /* 16 high bits zero */
long ldt; /* 16 high bits zero */
long trace_bitmap; /* bits: trace 0, bitmap 16-31 */
struct i387_struct i387;
};
struct task_struct {
/* these are hardcoded - don't touch */
long state; /* -1 unrunnable, 0 runnable, >0 stopped */
long counter;
long priority;
long signal;
struct sigaction sigaction[32];
long blocked; /* bitmap of masked signals */
/* various fields */
int exit_code;
unsigned long start_code,end_code,end_data,brk,start_stack;
long pid,father,pgrp,session,leader;
unsigned short uid,euid,suid;
unsigned short gid,egid,sgid;
long alarm;
long utime,stime,cutime,cstime,start_time;
unsigned short used_math;
/* file system info */
int tty; /* -1 if no tty, so it must be signed */
unsigned short umask;
struct m_inode * pwd;
struct m_inode * root;
struct m_inode * executable;
unsigned long close_on_exec;
struct file * filp[NR_OPEN];
/* ldt for this task 0 - zero 1 - cs 2 - ds&ss */
struct desc_struct ldt[3];
/* tss for this task */
struct tss_struct tss;
};
/*
* INIT_TASK is used to set up the first task table, touch at
* your own risk!. Base=0, limit=0x9ffff (=640kB)
*/
#define INIT_TASK \
/* state etc */ { 0,15,15, \
/* signals */ 0,{{},},0, \
/* ec,brk... */ 0,0,0,0,0,0, \
/* pid etc.. */ 0,-1,0,0,0, \
/* uid etc */ 0,0,0,0,0,0, \
/* alarm */ 0,0,0,0,0,0, \
/* math */ 0, \
/* fs info */ -1,0022,NULL,NULL,NULL,0, \
/* filp */ {NULL,}, \
{ \
{0,0}, \
/* ldt */ {0x9f,0xc0fa00}, \
{0x9f,0xc0f200}, \
}, \
/*tss*/ {0,PAGE_SIZE+(long)&init_task,0x10,0,0,0,0,(long)&pg_dir,\
0,0,0,0,0,0,0,0, \
0,0,0x17,0x17,0x17,0x17,0x17,0x17, \
_LDT(0),0x80000000, \
{} \
}, \
}
extern struct task_struct *task[NR_TASKS];
extern struct task_struct *last_task_used_math;
extern struct task_struct *current;
extern long volatile jiffies;
extern long startup_time;
#define CURRENT_TIME (startup_time+jiffies/HZ)
extern void add_timer(long jiffies, void (*fn)(void));
extern void sleep_on(struct task_struct ** p);
extern void interruptible_sleep_on(struct task_struct ** p);
extern void wake_up(struct task_struct ** p);
/*
* Entry into gdt where to find first TSS. 0-nul, 1-cs, 2-ds, 3-syscall
* 4-TSS0, 5-LDT0, 6-TSS1 etc ...
*/
#define FIRST_TSS_ENTRY 4
#define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY+1)
#define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3))
#define _LDT(n) ((((unsigned long) n)<<4)+(FIRST_LDT_ENTRY<<3))
#define ltr(n) __asm__("ltr %%ax"::"a" (_TSS(n)))
#define lldt(n) __asm__("lldt %%ax"::"a" (_LDT(n)))
#define str(n) \
__asm__("str %%ax\n\t" \
"subl %2,%%eax\n\t" \
"shrl $4,%%eax" \
:"=a" (n) \
:"a" (0),"i" (FIRST_TSS_ENTRY<<3))
/*
* switch_to(n) should switch tasks to task nr n, first
* checking that n isn't the current task, in which case it does nothing.
* This also clears the TS-flag if the task we switched to has used
* tha math co-processor latest.
*/
#define switch_to(n) {\
struct {long a,b;} __tmp; \
__asm__("cmpl %%ecx,_current\n\t" \
"je 1f\n\t" \
"movw %%dx,%1\n\t" \
"xchgl %%ecx,_current\n\t" \
"ljmp %0\n\t" \
"cmpl %%ecx,_last_task_used_math\n\t" \
"jne 1f\n\t" \
"clts\n" \
"1:" \
::"m" (*&__tmp.a),"m" (*&__tmp.b), \
"d" (_TSS(n)),"c" ((long) task[n])); \
}
#define PAGE_ALIGN(n) (((n)+0xfff)&0xfffff000)
#define _set_base(addr,base) \
__asm__("movw %%dx,%0\n\t" \
"rorl $16,%%edx\n\t" \
"movb %%dl,%1\n\t" \
"movb %%dh,%2" \
::"m" (*((addr)+2)), \
"m" (*((addr)+4)), \
"m" (*((addr)+7)), \
"d" (base) \
:"dx")
#define _set_limit(addr,limit) \
__asm__("movw %%dx,%0\n\t" \
"rorl $16,%%edx\n\t" \
"movb %1,%%dh\n\t" \
"andb $0xf0,%%dh\n\t" \
"orb %%dh,%%dl\n\t" \
"movb %%dl,%1" \
::"m" (*(addr)), \
"m" (*((addr)+6)), \
"d" (limit) \
:"dx")
#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , base )
#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 )
#define _get_base(addr) ({\
unsigned long __base; \
__asm__("movb %3,%%dh\n\t" \
"movb %2,%%dl\n\t" \
"shll $16,%%edx\n\t" \
"movw %1,%%dx" \
:"=d" (__base) \
:"m" (*((addr)+2)), \
"m" (*((addr)+4)), \
"m" (*((addr)+7))); \
__base;})
#define get_base(ldt) _get_base( ((char *)&(ldt)) )
#define get_limit(segment) ({ \
unsigned long __limit; \
__asm__("lsll %1,%0\n\tincl %0":"=r" (__limit):"r" (segment)); \
__limit;})
#endif

111
linux/include/linux/sys.h Normal file
View File

@ -0,0 +1,111 @@
/*
* Why isn't this a .c file? Enquiring minds....
*/
extern int sys_setup();
extern int sys_exit();
extern int sys_fork();
extern int sys_read();
extern int sys_write();
extern int sys_open();
extern int sys_close();
extern int sys_waitpid();
extern int sys_creat();
extern int sys_link();
extern int sys_unlink();
extern int sys_execve();
extern int sys_chdir();
extern int sys_time();
extern int sys_mknod();
extern int sys_chmod();
extern int sys_chown();
extern int sys_break();
extern int sys_stat();
extern int sys_lseek();
extern int sys_getpid();
extern int sys_mount();
extern int sys_umount();
extern int sys_setuid();
extern int sys_getuid();
extern int sys_stime();
extern int sys_ptrace();
extern int sys_alarm();
extern int sys_fstat();
extern int sys_pause();
extern int sys_utime();
extern int sys_stty();
extern int sys_gtty();
extern int sys_access();
extern int sys_nice();
extern int sys_ftime();
extern int sys_sync();
extern int sys_kill();
extern int sys_rename();
extern int sys_mkdir();
extern int sys_rmdir();
extern int sys_dup();
extern int sys_pipe();
extern int sys_times();
extern int sys_prof();
extern int sys_brk();
extern int sys_setgid();
extern int sys_getgid();
extern int sys_signal();
extern int sys_geteuid();
extern int sys_getegid();
extern int sys_acct();
extern int sys_phys();
extern int sys_lock();
extern int sys_ioctl();
extern int sys_fcntl();
extern int sys_mpx();
extern int sys_setpgid();
extern int sys_ulimit();
extern int sys_uname();
extern int sys_umask();
extern int sys_chroot();
extern int sys_ustat();
extern int sys_dup2();
extern int sys_getppid();
extern int sys_getpgrp();
extern int sys_setsid();
extern int sys_sigaction();
extern int sys_sgetmask();
extern int sys_ssetmask();
extern int sys_setreuid();
extern int sys_setregid();
extern int sys_sigpending();
extern int sys_sigsuspend();
extern int sys_sethostname();
extern int sys_setrlimit();
extern int sys_getrlimit();
extern int sys_getrusage();
extern int sys_gettimeofday();
extern int sys_settimeofday();
extern int sys_getgroups();
extern int sys_setgroups();
extern int sys_select();
extern int sys_symlink();
extern int sys_lstat();
extern int sys_readlink();
extern int sys_uselib();
fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
sys_unlink, sys_execve, sys_chdir, sys_time, sys_mknod, sys_chmod,
sys_chown, sys_break, sys_stat, sys_lseek, sys_getpid, sys_mount,
sys_umount, sys_setuid, sys_getuid, sys_stime, sys_ptrace, sys_alarm,
sys_fstat, sys_pause, sys_utime, sys_stty, sys_gtty, sys_access,
sys_nice, sys_ftime, sys_sync, sys_kill, sys_rename, sys_mkdir,
sys_rmdir, sys_dup, sys_pipe, sys_times, sys_prof, sys_brk, sys_setgid,
sys_getgid, sys_signal, sys_geteuid, sys_getegid, sys_acct, sys_phys,
sys_lock, sys_ioctl, sys_fcntl, sys_mpx, sys_setpgid, sys_ulimit,
sys_uname, sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid,
sys_getpgrp, sys_setsid, sys_sigaction, sys_sgetmask, sys_ssetmask,
sys_setreuid,sys_setregid, sys_sigsuspend, sys_sigpending, sys_sethostname,
sys_setrlimit, sys_getrlimit, sys_getrusage, sys_gettimeofday,
sys_settimeofday, sys_getgroups, sys_setgroups, sys_select, sys_symlink,
sys_lstat, sys_readlink, sys_uselib };
/* So we don't have to do any more manual updating.... */
int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr);

77
linux/include/linux/tty.h Normal file
View File

@ -0,0 +1,77 @@
/*
* 'tty.h' defines some structures used by tty_io.c and some defines.
*
* NOTE! Don't touch this without checking that nothing in rs_io.s or
* con_io.s breaks. Some constants are hardwired into the system (mainly
* offsets into 'tty_queue'
*/
#ifndef _TTY_H
#define _TTY_H
#include <termios.h>
#define TTY_BUF_SIZE 1024
struct tty_queue {
unsigned long data;
unsigned long head;
unsigned long tail;
struct task_struct * proc_list;
char buf[TTY_BUF_SIZE];
};
#define INC(a) ((a) = ((a)+1) & (TTY_BUF_SIZE-1))
#define DEC(a) ((a) = ((a)-1) & (TTY_BUF_SIZE-1))
#define EMPTY(a) ((a).head == (a).tail)
#define LEFT(a) (((a).tail-(a).head-1)&(TTY_BUF_SIZE-1))
#define LAST(a) ((a).buf[(TTY_BUF_SIZE-1)&((a).head-1)])
#define FULL(a) (!LEFT(a))
#define CHARS(a) (((a).head-(a).tail)&(TTY_BUF_SIZE-1))
#define GETCH(queue,c) \
(void)({c=(queue).buf[(queue).tail];INC((queue).tail);})
#define PUTCH(c,queue) \
(void)({(queue).buf[(queue).head]=(c);INC((queue).head);})
#define INTR_CHAR(tty) ((tty)->termios.c_cc[VINTR])
#define QUIT_CHAR(tty) ((tty)->termios.c_cc[VQUIT])
#define ERASE_CHAR(tty) ((tty)->termios.c_cc[VERASE])
#define KILL_CHAR(tty) ((tty)->termios.c_cc[VKILL])
#define EOF_CHAR(tty) ((tty)->termios.c_cc[VEOF])
#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])
struct tty_struct {
struct termios termios;
int pgrp;
int stopped;
void (*write)(struct tty_struct * tty);
struct tty_queue read_q;
struct tty_queue write_q;
struct tty_queue secondary;
};
extern struct tty_struct tty_table[];
/* intr=^C quit=^| erase=del kill=^U
eof=^D vtime=\0 vmin=\1 sxtc=\0
start=^Q stop=^S susp=^Z eol=\0
reprint=^R discard=^U werase=^W lnext=^V
eol2=\0
*/
#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
void rs_init(void);
void con_init(void);
void tty_init(void);
int tty_read(unsigned c, char * buf, int n);
int tty_write(unsigned c, char * buf, int n);
void rs_write(struct tty_struct * tty);
void con_write(struct tty_struct * tty);
void copy_to_cooked(struct tty_struct * tty);
#endif

68
linux/include/signal.h Normal file
View File

@ -0,0 +1,68 @@
#ifndef _SIGNAL_H
#define _SIGNAL_H
#include <sys/types.h>
typedef int sig_atomic_t;
typedef unsigned int sigset_t; /* 32 bits */
#define _NSIG 32
#define NSIG _NSIG
#define SIGHUP 1
#define SIGINT 2
#define SIGQUIT 3
#define SIGILL 4
#define SIGTRAP 5
#define SIGABRT 6
#define SIGIOT 6
#define SIGUNUSED 7
#define SIGFPE 8
#define SIGKILL 9
#define SIGUSR1 10
#define SIGSEGV 11
#define SIGUSR2 12
#define SIGPIPE 13
#define SIGALRM 14
#define SIGTERM 15
#define SIGSTKFLT 16
#define SIGCHLD 17
#define SIGCONT 18
#define SIGSTOP 19
#define SIGTSTP 20
#define SIGTTIN 21
#define SIGTTOU 22
/* Ok, I haven't implemented sigactions, but trying to keep headers POSIX */
#define SA_NOCLDSTOP 1
#define SA_NOMASK 0x40000000
#define SA_ONESHOT 0x80000000
#define SIG_BLOCK 0 /* for blocking signals */
#define SIG_UNBLOCK 1 /* for unblocking signals */
#define SIG_SETMASK 2 /* for setting the signal mask */
#define SIG_DFL ((void (*)(int))0) /* default signal handling */
#define SIG_IGN ((void (*)(int))1) /* ignore signal */
struct sigaction {
void (*sa_handler)(int);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};
void (*signal(int _sig, void (*_func)(int)))(int);
int raise(int sig);
int kill(pid_t pid, int sig);
int sigaddset(sigset_t *mask, int signo);
int sigdelset(sigset_t *mask, int signo);
int sigemptyset(sigset_t *mask);
int sigfillset(sigset_t *mask);
int sigismember(sigset_t *mask, int signo); /* 1 - is, 0 - not, -1 error */
int sigpending(sigset_t *set);
int sigprocmask(int how, sigset_t *set, sigset_t *oldset);
int sigsuspend(sigset_t *sigmask);
int sigaction(int sig, struct sigaction *act, struct sigaction *oldact);
#endif /* _SIGNAL_H */

28
linux/include/stdarg.h Executable file
View File

@ -0,0 +1,28 @@
#ifndef _STDARG_H
#define _STDARG_H
typedef char *va_list;
/* Amount of space required in an argument list for an arg of type TYPE.
TYPE may alternatively be an expression whose type is used. */
#define __va_rounded_size(TYPE) \
(((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
#ifndef __sparc__
#define va_start(AP, LASTARG) \
(AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
#else
#define va_start(AP, LASTARG) \
(__builtin_saveregs (), \
AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
#endif
void va_end (va_list); /* Defined in gnulib */
#define va_end(AP)
#define va_arg(AP, TYPE) \
(AP += __va_rounded_size (TYPE), \
*((TYPE *) (AP - __va_rounded_size (TYPE))))
#endif /* _STDARG_H */

19
linux/include/stddef.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef _STDDEF_H
#define _STDDEF_H
#ifndef _PTRDIFF_T
#define _PTRDIFF_T
typedef long ptrdiff_t;
#endif
#ifndef _SIZE_T
#define _SIZE_T
typedef unsigned long size_t;
#endif
#undef NULL
#define NULL ((void *)0)
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif

405
linux/include/string.h Normal file
View File

@ -0,0 +1,405 @@
#ifndef _STRING_H_
#define _STRING_H_
#ifndef NULL
#define NULL ((void *) 0)
#endif
#ifndef _SIZE_T
#define _SIZE_T
typedef unsigned int size_t;
#endif
extern char * strerror(int errno);
/*
* This string-include defines all string functions as inline
* functions. Use gcc. It also assumes ds=es=data space, this should be
* normal. Most of the string-functions are rather heavily hand-optimized,
* see especially strtok,strstr,str[c]spn. They should work, but are not
* very easy to understand. Everything is done entirely within the register
* set, making the functions fast and clean. String instructions have been
* used through-out, making for "slightly" unclear code :-)
*
* (C) 1991 Linus Torvalds
*/
extern inline char * strcpy(char * dest,const char *src)
{
__asm__("cld\n"
"1:\tlodsb\n\t"
"stosb\n\t"
"testb %%al,%%al\n\t"
"jne 1b"
::"S" (src),"D" (dest):"si","di","ax");
return dest;
}
extern inline char * strncpy(char * dest,const char *src,int count)
{
__asm__("cld\n"
"1:\tdecl %2\n\t"
"js 2f\n\t"
"lodsb\n\t"
"stosb\n\t"
"testb %%al,%%al\n\t"
"jne 1b\n\t"
"rep\n\t"
"stosb\n"
"2:"
::"S" (src),"D" (dest),"c" (count):"si","di","ax","cx");
return dest;
}
extern inline char * strcat(char * dest,const char * src)
{
__asm__("cld\n\t"
"repne\n\t"
"scasb\n\t"
"decl %1\n"
"1:\tlodsb\n\t"
"stosb\n\t"
"testb %%al,%%al\n\t"
"jne 1b"
::"S" (src),"D" (dest),"a" (0),"c" (0xffffffff):"si","di","ax","cx");
return dest;
}
extern inline char * strncat(char * dest,const char * src,int count)
{
__asm__("cld\n\t"
"repne\n\t"
"scasb\n\t"
"decl %1\n\t"
"movl %4,%3\n"
"1:\tdecl %3\n\t"
"js 2f\n\t"
"lodsb\n\t"
"stosb\n\t"
"testb %%al,%%al\n\t"
"jne 1b\n"
"2:\txorl %2,%2\n\t"
"stosb"
::"S" (src),"D" (dest),"a" (0),"c" (0xffffffff),"g" (count)
:"si","di","ax","cx");
return dest;
}
extern inline int strcmp(const char * cs,const char * ct)
{
register int __res __asm__("ax");
__asm__("cld\n"
"1:\tlodsb\n\t"
"scasb\n\t"
"jne 2f\n\t"
"testb %%al,%%al\n\t"
"jne 1b\n\t"
"xorl %%eax,%%eax\n\t"
"jmp 3f\n"
"2:\tmovl $1,%%eax\n\t"
"jl 3f\n\t"
"negl %%eax\n"
"3:"
:"=a" (__res):"D" (cs),"S" (ct):"si","di");
return __res;
}
extern inline int strncmp(const char * cs,const char * ct,int count)
{
register int __res __asm__("ax");
__asm__("cld\n"
"1:\tdecl %3\n\t"
"js 2f\n\t"
"lodsb\n\t"
"scasb\n\t"
"jne 3f\n\t"
"testb %%al,%%al\n\t"
"jne 1b\n"
"2:\txorl %%eax,%%eax\n\t"
"jmp 4f\n"
"3:\tmovl $1,%%eax\n\t"
"jl 4f\n\t"
"negl %%eax\n"
"4:"
:"=a" (__res):"D" (cs),"S" (ct),"c" (count):"si","di","cx");
return __res;
}
extern inline char * strchr(const char * s,char c)
{
register char * __res __asm__("ax");
__asm__("cld\n\t"
"movb %%al,%%ah\n"
"1:\tlodsb\n\t"
"cmpb %%ah,%%al\n\t"
"je 2f\n\t"
"testb %%al,%%al\n\t"
"jne 1b\n\t"
"movl $1,%1\n"
"2:\tmovl %1,%0\n\t"
"decl %0"
:"=a" (__res):"S" (s),"0" (c):"si");
return __res;
}
extern inline char * strrchr(const char * s,char c)
{
register char * __res __asm__("dx");
__asm__("cld\n\t"
"movb %%al,%%ah\n"
"1:\tlodsb\n\t"
"cmpb %%ah,%%al\n\t"
"jne 2f\n\t"
"movl %%esi,%0\n\t"
"decl %0\n"
"2:\ttestb %%al,%%al\n\t"
"jne 1b"
:"=d" (__res):"0" (0),"S" (s),"a" (c):"ax","si");
return __res;
}
extern inline int strspn(const char * cs, const char * ct)
{
register char * __res __asm__("si");
__asm__("cld\n\t"
"movl %4,%%edi\n\t"
"repne\n\t"
"scasb\n\t"
"notl %%ecx\n\t"
"decl %%ecx\n\t"
"movl %%ecx,%%edx\n"
"1:\tlodsb\n\t"
"testb %%al,%%al\n\t"
"je 2f\n\t"
"movl %4,%%edi\n\t"
"movl %%edx,%%ecx\n\t"
"repne\n\t"
"scasb\n\t"
"je 1b\n"
"2:\tdecl %0"
:"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
:"ax","cx","dx","di");
return __res-cs;
}
extern inline int strcspn(const char * cs, const char * ct)
{
register char * __res __asm__("si");
__asm__("cld\n\t"
"movl %4,%%edi\n\t"
"repne\n\t"
"scasb\n\t"
"notl %%ecx\n\t"
"decl %%ecx\n\t"
"movl %%ecx,%%edx\n"
"1:\tlodsb\n\t"
"testb %%al,%%al\n\t"
"je 2f\n\t"
"movl %4,%%edi\n\t"
"movl %%edx,%%ecx\n\t"
"repne\n\t"
"scasb\n\t"
"jne 1b\n"
"2:\tdecl %0"
:"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
:"ax","cx","dx","di");
return __res-cs;
}
extern inline char * strpbrk(const char * cs,const char * ct)
{
register char * __res __asm__("si");
__asm__("cld\n\t"
"movl %4,%%edi\n\t"
"repne\n\t"
"scasb\n\t"
"notl %%ecx\n\t"
"decl %%ecx\n\t"
"movl %%ecx,%%edx\n"
"1:\tlodsb\n\t"
"testb %%al,%%al\n\t"
"je 2f\n\t"
"movl %4,%%edi\n\t"
"movl %%edx,%%ecx\n\t"
"repne\n\t"
"scasb\n\t"
"jne 1b\n\t"
"decl %0\n\t"
"jmp 3f\n"
"2:\txorl %0,%0\n"
"3:"
:"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
:"ax","cx","dx","di");
return __res;
}
extern inline char * strstr(const char * cs,const char * ct)
{
register char * __res __asm__("ax");
__asm__("cld\n\t" \
"movl %4,%%edi\n\t"
"repne\n\t"
"scasb\n\t"
"notl %%ecx\n\t"
"decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */
"movl %%ecx,%%edx\n"
"1:\tmovl %4,%%edi\n\t"
"movl %%esi,%%eax\n\t"
"movl %%edx,%%ecx\n\t"
"repe\n\t"
"cmpsb\n\t"
"je 2f\n\t" /* also works for empty string, see above */
"xchgl %%eax,%%esi\n\t"
"incl %%esi\n\t"
"cmpb $0,-1(%%eax)\n\t"
"jne 1b\n\t"
"xorl %%eax,%%eax\n\t"
"2:"
:"=a" (__res):"0" (0),"c" (0xffffffff),"S" (cs),"g" (ct)
:"cx","dx","di","si");
return __res;
}
extern inline int strlen(const char * s)
{
register int __res __asm__("cx");
__asm__("cld\n\t"
"repne\n\t"
"scasb\n\t"
"notl %0\n\t"
"decl %0"
:"=c" (__res):"D" (s),"a" (0),"0" (0xffffffff):"di");
return __res;
}
extern char * ___strtok;
extern inline char * strtok(char * s,const char * ct)
{
register char * __res __asm__("si");
__asm__("testl %1,%1\n\t"
"jne 1f\n\t"
"testl %0,%0\n\t"
"je 8f\n\t"
"movl %0,%1\n"
"1:\txorl %0,%0\n\t"
"movl $-1,%%ecx\n\t"
"xorl %%eax,%%eax\n\t"
"cld\n\t"
"movl %4,%%edi\n\t"
"repne\n\t"
"scasb\n\t"
"notl %%ecx\n\t"
"decl %%ecx\n\t"
"je 7f\n\t" /* empty delimeter-string */
"movl %%ecx,%%edx\n"
"2:\tlodsb\n\t"
"testb %%al,%%al\n\t"
"je 7f\n\t"
"movl %4,%%edi\n\t"
"movl %%edx,%%ecx\n\t"
"repne\n\t"
"scasb\n\t"
"je 2b\n\t"
"decl %1\n\t"
"cmpb $0,(%1)\n\t"
"je 7f\n\t"
"movl %1,%0\n"
"3:\tlodsb\n\t"
"testb %%al,%%al\n\t"
"je 5f\n\t"
"movl %4,%%edi\n\t"
"movl %%edx,%%ecx\n\t"
"repne\n\t"
"scasb\n\t"
"jne 3b\n\t"
"decl %1\n\t"
"cmpb $0,(%1)\n\t"
"je 5f\n\t"
"movb $0,(%1)\n\t"
"incl %1\n\t"
"jmp 6f\n"
"5:\txorl %1,%1\n"
"6:\tcmpb $0,(%0)\n\t"
"jne 7f\n\t"
"xorl %0,%0\n"
"7:\ttestl %0,%0\n\t"
"jne 8f\n\t"
"movl %0,%1\n"
"8:"
:"=b" (__res),"=S" (___strtok)
:"0" (___strtok),"1" (s),"g" (ct)
:"ax","cx","dx","di");
return __res;
}
extern inline void * memcpy(void * dest,const void * src, int n)
{
__asm__("cld\n\t"
"rep\n\t"
"movsb"
::"c" (n),"S" (src),"D" (dest)
:"cx","si","di");
return dest;
}
extern inline void * memmove(void * dest,const void * src, int n)
{
if (dest<src)
__asm__("cld\n\t"
"rep\n\t"
"movsb"
::"c" (n),"S" (src),"D" (dest)
:"cx","si","di");
else
__asm__("std\n\t"
"rep\n\t"
"movsb"
::"c" (n),"S" (src+n-1),"D" (dest+n-1)
:"cx","si","di");
return dest;
}
extern inline int memcmp(const void * cs,const void * ct,int count)
{
register int __res __asm__("ax");
__asm__("cld\n\t"
"repe\n\t"
"cmpsb\n\t"
"je 1f\n\t"
"movl $1,%%eax\n\t"
"jl 1f\n\t"
"negl %%eax\n"
"1:"
:"=a" (__res):"0" (0),"D" (cs),"S" (ct),"c" (count)
:"si","di","cx");
return __res;
}
extern inline void * memchr(const void * cs,char c,int count)
{
register void * __res __asm__("di");
if (!count)
return NULL;
__asm__("cld\n\t"
"repne\n\t"
"scasb\n\t"
"je 1f\n\t"
"movl $1,%0\n"
"1:\tdecl %0"
:"=D" (__res):"a" (c),"D" (cs),"c" (count)
:"cx");
return __res;
}
extern inline void * memset(void * s,char c,int count)
{
__asm__("cld\n\t"
"rep\n\t"
"stosb"
::"a" (c),"D" (s),"c" (count)
:"cx","di");
return s;
}
#endif

60
linux/include/sys/stat.h Normal file
View File

@ -0,0 +1,60 @@
#ifndef _SYS_STAT_H
#define _SYS_STAT_H
#include <sys/types.h>
struct stat {
dev_t st_dev;
ino_t st_ino;
umode_t st_mode;
nlink_t st_nlink;
uid_t st_uid;
gid_t st_gid;
dev_t st_rdev;
off_t st_size;
time_t st_atime;
time_t st_mtime;
time_t st_ctime;
};
#define S_IFMT 00170000
#define S_IFLNK 0120000
#define S_IFREG 0100000
#define S_IFBLK 0060000
#define S_IFDIR 0040000
#define S_IFCHR 0020000
#define S_IFIFO 0010000
#define S_ISUID 0004000
#define S_ISGID 0002000
#define S_ISVTX 0001000
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#define S_IRWXU 00700
#define S_IRUSR 00400
#define S_IWUSR 00200
#define S_IXUSR 00100
#define S_IRWXG 00070
#define S_IRGRP 00040
#define S_IWGRP 00020
#define S_IXGRP 00010
#define S_IRWXO 00007
#define S_IROTH 00004
#define S_IWOTH 00002
#define S_IXOTH 00001
extern int chmod(const char *_path, mode_t mode);
extern int fstat(int fildes, struct stat *stat_buf);
extern int mkdir(const char *_path, mode_t mode);
extern int mkfifo(const char *_path, mode_t mode);
extern int stat(const char *filename, struct stat *stat_buf);
extern mode_t umask(mode_t mask);
#endif

15
linux/include/sys/times.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef _TIMES_H
#define _TIMES_H
#include <sys/types.h>
struct tms {
time_t tms_utime;
time_t tms_stime;
time_t tms_cutime;
time_t tms_cstime;
};
extern time_t times(struct tms * tp);
#endif

46
linux/include/sys/types.h Normal file
View File

@ -0,0 +1,46 @@
#ifndef _SYS_TYPES_H
#define _SYS_TYPES_H
#ifndef _SIZE_T
#define _SIZE_T
typedef unsigned int size_t;
#endif
#ifndef _TIME_T
#define _TIME_T
typedef long time_t;
#endif
#ifndef _PTRDIFF_T
#define _PTRDIFF_T
typedef long ptrdiff_t;
#endif
#ifndef NULL
#define NULL ((void *) 0)
#endif
typedef int pid_t;
typedef unsigned short uid_t;
typedef unsigned char gid_t;
typedef unsigned short dev_t;
typedef unsigned short ino_t;
typedef unsigned short mode_t;
typedef unsigned short umode_t;
typedef unsigned char nlink_t;
typedef int daddr_t;
typedef long off_t;
typedef unsigned char u_char;
typedef unsigned short ushort;
typedef struct { int quot,rem; } div_t;
typedef struct { long quot,rem; } ldiv_t;
struct ustat {
daddr_t f_tfree;
ino_t f_tinode;
char f_fname[6];
char f_fpack[6];
};
#endif

View File

@ -0,0 +1,16 @@
#ifndef _SYS_UTSNAME_H
#define _SYS_UTSNAME_H
#include <sys/types.h>
struct utsname {
char sysname[9];
char nodename[9];
char release[9];
char version[9];
char machine[9];
};
extern int uname(struct utsname * utsbuf);
#endif

23
linux/include/sys/wait.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef _SYS_WAIT_H
#define _SYS_WAIT_H
#include <sys/types.h>
#define _LOW(v) ( (v) & 0377)
#define _HIGH(v) ( ((v) >> 8) & 0377)
/* options for waitpid, WUNTRACED not supported */
#define WNOHANG 1
#define WUNTRACED 2
#define WIFEXITED(s) (!((s)&0xFF)
#define WIFSTOPPED(s) (((s)&0xFF)==0x7F)
#define WEXITSTATUS(s) (((s)>>8)&0xFF)
#define WTERMSIG(s) ((s)&0x7F)
#define WSTOPSIG(s) (((s)>>8)&0xFF)
#define WIFSIGNALED(s) (((unsigned int)(s)-1 & 0xFFFF) < 0xFF)
pid_t wait(int *stat_loc);
pid_t waitpid(pid_t pid, int *stat_loc, int options);
#endif

228
linux/include/termios.h Normal file
View File

@ -0,0 +1,228 @@
#ifndef _TERMIOS_H
#define _TERMIOS_H
#define TTY_BUF_SIZE 1024
/* 0x54 is just a magic number to make these relatively uniqe ('T') */
#define TCGETS 0x5401
#define TCSETS 0x5402
#define TCSETSW 0x5403
#define TCSETSF 0x5404
#define TCGETA 0x5405
#define TCSETA 0x5406
#define TCSETAW 0x5407
#define TCSETAF 0x5408
#define TCSBRK 0x5409
#define TCXONC 0x540A
#define TCFLSH 0x540B
#define TIOCEXCL 0x540C
#define TIOCNXCL 0x540D
#define TIOCSCTTY 0x540E
#define TIOCGPGRP 0x540F
#define TIOCSPGRP 0x5410
#define TIOCOUTQ 0x5411
#define TIOCSTI 0x5412
#define TIOCGWINSZ 0x5413
#define TIOCSWINSZ 0x5414
#define TIOCMGET 0x5415
#define TIOCMBIS 0x5416
#define TIOCMBIC 0x5417
#define TIOCMSET 0x5418
#define TIOCGSOFTCAR 0x5419
#define TIOCSSOFTCAR 0x541A
#define TIOCINQ 0x541B
struct winsize {
unsigned short ws_row;
unsigned short ws_col;
unsigned short ws_xpixel;
unsigned short ws_ypixel;
};
#define NCC 8
struct termio {
unsigned short c_iflag; /* input mode flags */
unsigned short c_oflag; /* output mode flags */
unsigned short c_cflag; /* control mode flags */
unsigned short c_lflag; /* local mode flags */
unsigned char c_line; /* line discipline */
unsigned char c_cc[NCC]; /* control characters */
};
#define NCCS 17
struct termios {
unsigned long c_iflag; /* input mode flags */
unsigned long c_oflag; /* output mode flags */
unsigned long c_cflag; /* control mode flags */
unsigned long c_lflag; /* local mode flags */
unsigned char c_line; /* line discipline */
unsigned char c_cc[NCCS]; /* control characters */
};
/* c_cc characters */
#define VINTR 0
#define VQUIT 1
#define VERASE 2
#define VKILL 3
#define VEOF 4
#define VTIME 5
#define VMIN 6
#define VSWTC 7
#define VSTART 8
#define VSTOP 9
#define VSUSP 10
#define VEOL 11
#define VREPRINT 12
#define VDISCARD 13
#define VWERASE 14
#define VLNEXT 15
#define VEOL2 16
/* c_iflag bits */
#define IGNBRK 0000001
#define BRKINT 0000002
#define IGNPAR 0000004
#define PARMRK 0000010
#define INPCK 0000020
#define ISTRIP 0000040
#define INLCR 0000100
#define IGNCR 0000200
#define ICRNL 0000400
#define IUCLC 0001000
#define IXON 0002000
#define IXANY 0004000
#define IXOFF 0010000
#define IMAXBEL 0020000
/* c_oflag bits */
#define OPOST 0000001
#define OLCUC 0000002
#define ONLCR 0000004
#define OCRNL 0000010
#define ONOCR 0000020
#define ONLRET 0000040
#define OFILL 0000100
#define OFDEL 0000200
#define NLDLY 0000400
#define NL0 0000000
#define NL1 0000400
#define CRDLY 0003000
#define CR0 0000000
#define CR1 0001000
#define CR2 0002000
#define CR3 0003000
#define TABDLY 0014000
#define TAB0 0000000
#define TAB1 0004000
#define TAB2 0010000
#define TAB3 0014000
#define XTABS 0014000
#define BSDLY 0020000
#define BS0 0000000
#define BS1 0020000
#define VTDLY 0040000
#define VT0 0000000
#define VT1 0040000
#define FFDLY 0040000
#define FF0 0000000
#define FF1 0040000
/* c_cflag bit meaning */
#define CBAUD 0000017
#define B0 0000000 /* hang up */
#define B50 0000001
#define B75 0000002
#define B110 0000003
#define B134 0000004
#define B150 0000005
#define B200 0000006
#define B300 0000007
#define B600 0000010
#define B1200 0000011
#define B1800 0000012
#define B2400 0000013
#define B4800 0000014
#define B9600 0000015
#define B19200 0000016
#define B38400 0000017
#define EXTA B19200
#define EXTB B38400
#define CSIZE 0000060
#define CS5 0000000
#define CS6 0000020
#define CS7 0000040
#define CS8 0000060
#define CSTOPB 0000100
#define CREAD 0000200
#define CPARENB 0000400
#define CPARODD 0001000
#define HUPCL 0002000
#define CLOCAL 0004000
#define CIBAUD 03600000 /* input baud rate (not used) */
#define CRTSCTS 020000000000 /* flow control */
#define PARENB CPARENB
#define PARODD CPARODD
/* c_lflag bits */
#define ISIG 0000001
#define ICANON 0000002
#define XCASE 0000004
#define ECHO 0000010
#define ECHOE 0000020
#define ECHOK 0000040
#define ECHONL 0000100
#define NOFLSH 0000200
#define TOSTOP 0000400
#define ECHOCTL 0001000
#define ECHOPRT 0002000
#define ECHOKE 0004000
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
/* modem lines */
#define TIOCM_LE 0x001
#define TIOCM_DTR 0x002
#define TIOCM_RTS 0x004
#define TIOCM_ST 0x008
#define TIOCM_SR 0x010
#define TIOCM_CTS 0x020
#define TIOCM_CAR 0x040
#define TIOCM_RNG 0x080
#define TIOCM_DSR 0x100
#define TIOCM_CD TIOCM_CAR
#define TIOCM_RI TIOCM_RNG
/* tcflow() and TCXONC use these */
#define TCOOFF 0
#define TCOON 1
#define TCIOFF 2
#define TCION 3
/* tcflush() and TCFLSH use these */
#define TCIFLUSH 0
#define TCOFLUSH 1
#define TCIOFLUSH 2
/* tcsetattr uses these */
#define TCSANOW 0
#define TCSADRAIN 1
#define TCSAFLUSH 2
typedef int speed_t;
extern speed_t cfgetispeed(struct termios *termios_p);
extern speed_t cfgetospeed(struct termios *termios_p);
extern int cfsetispeed(struct termios *termios_p, speed_t speed);
extern int cfsetospeed(struct termios *termios_p, speed_t speed);
extern int tcdrain(int fildes);
extern int tcflow(int fildes, int action);
extern int tcflush(int fildes, int queue_selector);
extern int tcgetattr(int fildes, struct termios *termios_p);
extern int tcsendbreak(int fildes, int duration);
extern int tcsetattr(int fildes, int optional_actions,
struct termios *termios_p);
#endif

42
linux/include/time.h Normal file
View File

@ -0,0 +1,42 @@
#ifndef _TIME_H
#define _TIME_H
#ifndef _TIME_T
#define _TIME_T
typedef long time_t;
#endif
#ifndef _SIZE_T
#define _SIZE_T
typedef unsigned int size_t;
#endif
#define CLOCKS_PER_SEC 100
typedef long clock_t;
struct tm {
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
};
clock_t clock(void);
time_t time(time_t * tp);
double difftime(time_t time2, time_t time1);
time_t mktime(struct tm * tp);
char * asctime(const struct tm * tp);
char * ctime(const time_t * tp);
struct tm * gmtime(const time_t *tp);
struct tm *localtime(const time_t * tp);
size_t strftime(char * s, size_t smax, const char * fmt, const struct tm * tp);
void tzset(void);
#endif

267
linux/include/unistd.h Normal file
View File

@ -0,0 +1,267 @@
#ifndef _UNISTD_H
#define _UNISTD_H
/* ok, this may be a joke, but I'm working on it */
#define _POSIX_VERSION 198808L
#define _POSIX_CHOWN_RESTRICTED /* only root can do a chown (I think..) */
#define _POSIX_NO_TRUNC /* no pathname truncation (but see in kernel) */
#define _POSIX_VDISABLE '\0' /* character to disable things like ^C */
/*#define _POSIX_SAVED_IDS */ /* we'll get to this yet */
/*#define _POSIX_JOB_CONTROL */ /* we aren't there quite yet. Soon hopefully */
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
#ifndef NULL
#define NULL ((void *)0)
#endif
/* access */
#define F_OK 0
#define X_OK 1
#define W_OK 2
#define R_OK 4
/* lseek */
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
/* _SC stands for System Configuration. We don't use them much */
#define _SC_ARG_MAX 1
#define _SC_CHILD_MAX 2
#define _SC_CLOCKS_PER_SEC 3
#define _SC_NGROUPS_MAX 4
#define _SC_OPEN_MAX 5
#define _SC_JOB_CONTROL 6
#define _SC_SAVED_IDS 7
#define _SC_VERSION 8
/* more (possibly) configurable things - now pathnames */
#define _PC_LINK_MAX 1
#define _PC_MAX_CANON 2
#define _PC_MAX_INPUT 3
#define _PC_NAME_MAX 4
#define _PC_PATH_MAX 5
#define _PC_PIPE_BUF 6
#define _PC_NO_TRUNC 7
#define _PC_VDISABLE 8
#define _PC_CHOWN_RESTRICTED 9
#include <sys/stat.h>
#include <sys/times.h>
#include <sys/utsname.h>
#include <utime.h>
#ifdef __LIBRARY__
#define __NR_setup 0 /* used only by init, to get system going */
#define __NR_exit 1
#define __NR_fork 2
#define __NR_read 3
#define __NR_write 4
#define __NR_open 5
#define __NR_close 6
#define __NR_waitpid 7
#define __NR_creat 8
#define __NR_link 9
#define __NR_unlink 10
#define __NR_execve 11
#define __NR_chdir 12
#define __NR_time 13
#define __NR_mknod 14
#define __NR_chmod 15
#define __NR_chown 16
#define __NR_break 17
#define __NR_stat 18
#define __NR_lseek 19
#define __NR_getpid 20
#define __NR_mount 21
#define __NR_umount 22
#define __NR_setuid 23
#define __NR_getuid 24
#define __NR_stime 25
#define __NR_ptrace 26
#define __NR_alarm 27
#define __NR_fstat 28
#define __NR_pause 29
#define __NR_utime 30
#define __NR_stty 31
#define __NR_gtty 32
#define __NR_access 33
#define __NR_nice 34
#define __NR_ftime 35
#define __NR_sync 36
#define __NR_kill 37
#define __NR_rename 38
#define __NR_mkdir 39
#define __NR_rmdir 40
#define __NR_dup 41
#define __NR_pipe 42
#define __NR_times 43
#define __NR_prof 44
#define __NR_brk 45
#define __NR_setgid 46
#define __NR_getgid 47
#define __NR_signal 48
#define __NR_geteuid 49
#define __NR_getegid 50
#define __NR_acct 51
#define __NR_phys 52
#define __NR_lock 53
#define __NR_ioctl 54
#define __NR_fcntl 55
#define __NR_mpx 56
#define __NR_setpgid 57
#define __NR_ulimit 58
#define __NR_uname 59
#define __NR_umask 60
#define __NR_chroot 61
#define __NR_ustat 62
#define __NR_dup2 63
#define __NR_getppid 64
#define __NR_getpgrp 65
#define __NR_setsid 66
#define __NR_sigaction 67
#define __NR_sgetmask 68
#define __NR_ssetmask 69
#define __NR_setreuid 70
#define __NR_setregid 71
#define __NR_sigsuspend 72
#define __NR_sigpending 73
#define __NR_sethostname 74
#define __NR_setrlimit 75
#define __NR_getrlimit 76
#define __NR_getrusage 77
#define __NR_gettimeofday 78
#define __NR_settimeofday 79
#define __NR_getgroups 80
#define __NR_setgroups 81
#define __NR_select 82
#define __NR_symlink 83
#define __NR_lstat 84
#define __NR_readlink 85
#define __NR_uselib 86
#define _syscall0(type,name) \
type name(void) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name)); \
if (__res >= 0) \
return (type) __res; \
errno = -__res; \
return -1; \
}
#define _syscall1(type,name,atype,a) \
type name(atype a) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(a))); \
if (__res >= 0) \
return (type) __res; \
errno = -__res; \
return -1; \
}
#define _syscall2(type,name,atype,a,btype,b) \
type name(atype a,btype b) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b))); \
if (__res >= 0) \
return (type) __res; \
errno = -__res; \
return -1; \
}
#define _syscall3(type,name,atype,a,btype,b,ctype,c) \
type name(atype a,btype b,ctype c) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)),"d" ((long)(c))); \
if (__res>=0) \
return (type) __res; \
errno=-__res; \
return -1; \
}
#endif /* __LIBRARY__ */
extern int errno;
int access(const char * filename, mode_t mode);
int acct(const char * filename);
int alarm(int sec);
int brk(void * end_data_segment);
void * sbrk(ptrdiff_t increment);
int chdir(const char * filename);
int chmod(const char * filename, mode_t mode);
int chown(const char * filename, uid_t owner, gid_t group);
int chroot(const char * filename);
int close(int fildes);
int creat(const char * filename, mode_t mode);
int dup(int fildes);
int execve(const char * filename, char ** argv, char ** envp);
int execv(const char * pathname, char ** argv);
int execvp(const char * file, char ** argv);
int execl(const char * pathname, char * arg0, ...);
int execlp(const char * file, char * arg0, ...);
int execle(const char * pathname, char * arg0, ...);
volatile void exit(int status);
volatile void _exit(int status);
int fcntl(int fildes, int cmd, ...);
int fork(void);
int getpid(void);
int getuid(void);
int geteuid(void);
int getgid(void);
int getegid(void);
int ioctl(int fildes, int cmd, ...);
int kill(pid_t pid, int signal);
int link(const char * filename1, const char * filename2);
int lseek(int fildes, off_t offset, int origin);
int mknod(const char * filename, mode_t mode, dev_t dev);
int mount(const char * specialfile, const char * dir, int rwflag);
int nice(int val);
int open(const char * filename, int flag, ...);
int pause(void);
int pipe(int * fildes);
int read(int fildes, char * buf, off_t count);
int setpgrp(void);
int setpgid(pid_t pid,pid_t pgid);
int setuid(uid_t uid);
int setgid(gid_t gid);
void (*signal(int sig, void (*fn)(int)))(int);
int stat(const char * filename, struct stat * stat_buf);
int fstat(int fildes, struct stat * stat_buf);
int stime(time_t * tptr);
int sync(void);
time_t time(time_t * tloc);
time_t times(struct tms * tbuf);
int ulimit(int cmd, long limit);
mode_t umask(mode_t mask);
int umount(const char * specialfile);
int uname(struct utsname * name);
int unlink(const char * filename);
int ustat(dev_t dev, struct ustat * ubuf);
int utime(const char * filename, struct utimbuf * times);
pid_t waitpid(pid_t pid,int * wait_stat,int options);
pid_t wait(int * wait_stat);
int write(int fildes, const char * buf, off_t count);
int dup2(int oldfd, int newfd);
int getppid(void);
pid_t getpgrp(void);
pid_t setsid(void);
#endif

13
linux/include/utime.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef _UTIME_H
#define _UTIME_H
#include <sys/types.h> /* I know - shouldn't do this, but .. */
struct utimbuf {
time_t actime;
time_t modtime;
};
extern int utime(const char *filename, struct utimbuf *times);
#endif

209
linux/init/main.c Normal file
View File

@ -0,0 +1,209 @@
/*
* linux/init/main.c
*
* (C) 1991 Linus Torvalds
*/
#define __LIBRARY__
#include <unistd.h>
#include <time.h>
/*
* we need this inline - forking from kernel space will result
* in NO COPY ON WRITE (!!!), until an execve is executed. This
* is no problem, but for the stack. This is handled by not letting
* main() use the stack at all after fork(). Thus, no function
* calls - which means inline code for fork too, as otherwise we
* would use the stack upon exit from 'fork()'.
*
* Actually only pause and fork are needed inline, so that there
* won't be any messing with the stack from main(), but we define
* some others too.
*/
static inline _syscall0(int,fork)
static inline _syscall0(int,pause)
static inline _syscall1(int,setup,void *,BIOS)
static inline _syscall0(int,sync)
#include <linux/tty.h>
#include <linux/sched.h>
#include <linux/head.h>
#include <asm/system.h>
#include <asm/io.h>
#include <stddef.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <linux/fs.h>
static char printbuf[1024];
extern int vsprintf();
extern void init(void);
extern void blk_dev_init(void);
extern void chr_dev_init(void);
extern void hd_init(void);
extern void floppy_init(void);
extern void mem_init(long start, long end);
extern long rd_init(long mem_start, int length);
extern long kernel_mktime(struct tm * tm);
extern long startup_time;
/*
* 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 ORIG_ROOT_DEV (*(unsigned short *)0x901FC)
/*
* Yeah, yeah, it's ugly, but I cannot find how to do this correctly
* and this seems to work. I anybody has more info on the real-time
* clock I'd be interested. Most of this was trial and error, and some
* bios-listing reading. Urghh.
*/
#define CMOS_READ(addr) ({ \
outb_p(0x80|addr,0x70); \
inb_p(0x71); \
})
#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
static void time_init(void)
{
struct tm time;
do {
time.tm_sec = CMOS_READ(0);
time.tm_min = CMOS_READ(2);
time.tm_hour = CMOS_READ(4);
time.tm_mday = CMOS_READ(7);
time.tm_mon = CMOS_READ(8);
time.tm_year = CMOS_READ(9);
} while (time.tm_sec != CMOS_READ(0));
BCD_TO_BIN(time.tm_sec);
BCD_TO_BIN(time.tm_min);
BCD_TO_BIN(time.tm_hour);
BCD_TO_BIN(time.tm_mday);
BCD_TO_BIN(time.tm_mon);
BCD_TO_BIN(time.tm_year);
time.tm_mon--;
startup_time = kernel_mktime(&time);
}
static long memory_end = 0;
static long buffer_memory_end = 0;
static long main_memory_start = 0;
struct drive_info { char dummy[32]; } drive_info;
void main(void) /* This really IS void, no error here. */
{ /* The startup routine assumes (well, ...) this */
/*
* Interrupts are still disabled. Do necessary setups, then
* enable them
*/
ROOT_DEV = ORIG_ROOT_DEV;
drive_info = DRIVE_INFO;
memory_end = (1<<20) + (EXT_MEM_K<<10);
memory_end &= 0xfffff000;
if (memory_end > 16*1024*1024)
memory_end = 16*1024*1024;
if (memory_end > 12*1024*1024)
buffer_memory_end = 4*1024*1024;
else if (memory_end > 6*1024*1024)
buffer_memory_end = 2*1024*1024;
else
buffer_memory_end = 1*1024*1024;
main_memory_start = buffer_memory_end;
#ifdef RAMDISK
main_memory_start += rd_init(main_memory_start, RAMDISK*1024);
#endif
mem_init(main_memory_start,memory_end);
trap_init();
blk_dev_init();
chr_dev_init();
tty_init();
time_init();
sched_init();
buffer_init(buffer_memory_end);
hd_init();
floppy_init();
sti();
move_to_user_mode();
if (!fork()) { /* we count on this going ok */
init();
}
/*
* NOTE!! For any other task 'pause()' would mean we have to get a
* signal to awaken, but task0 is the sole exception (see 'schedule()')
* as task 0 gets activated at every idle moment (when no other tasks
* can run). For task0 'pause()' just means we go check if some other
* task can run, and if not we return here.
*/
for(;;) pause();
}
static int printf(const char *fmt, ...)
{
va_list args;
int i;
va_start(args, fmt);
write(1,printbuf,i=vsprintf(printbuf, fmt, args));
va_end(args);
return i;
}
static char * argv_rc[] = { "/bin/sh", NULL };
static char * envp_rc[] = { "HOME=/", NULL, NULL };
static char * argv[] = { "-/bin/sh",NULL };
static char * envp[] = { "HOME=/usr/root", NULL, NULL };
void init(void)
{
int pid,i;
setup((void *) &drive_info);
(void) open("/dev/tty0",O_RDWR,0);
(void) dup(0);
(void) dup(0);
printf("%d buffers = %d bytes buffer space\n\r",NR_BUFFERS,
NR_BUFFERS*BLOCK_SIZE);
printf("Free mem: %d bytes\n\r",memory_end-main_memory_start);
if (!(pid=fork())) {
close(0);
if (open("/etc/rc",O_RDONLY,0))
_exit(1);
execve("/bin/sh",argv_rc,envp_rc);
_exit(2);
}
if (pid>0)
while (pid != wait(&i))
/* nothing */;
while (1) {
if ((pid=fork())<0) {
printf("Fork failed in init\r\n");
continue;
}
if (!pid) {
close(0);close(1);close(2);
setsid();
(void) open("/dev/tty0",O_RDWR,0);
(void) dup(0);
(void) dup(0);
_exit(execve("/bin/sh",argv,envp));
}
while (1)
if (pid == wait(&i))
break;
printf("\n\rchild %d died with code %04x\n\r",pid,i);
sync();
}
_exit(0); /* NOTE! _exit, not exit() */
}

BIN
linux/init/main.o Normal file

Binary file not shown.

83
linux/kernel/Makefile Normal file
View File

@ -0,0 +1,83 @@
#
# Makefile for the FREAX-kernel.
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
AR =gar
AS =gas
LD =gld
LDFLAGS =-x #-s
CC =gcc
CFLAGS =-Wall -O -g -fstrength-reduce -fomit-frame-pointer -fcombine-regs \
-finline-functions -nostdinc -I../include
CPP =gcc -E -nostdinc -I../include
.c.s:
$(CC) $(CFLAGS) \
-S -o $*.s $<
.s.o:
$(AS) -c -o $*.o $<
.c.o:
$(CC) $(CFLAGS) \
-c -o $*.o $<
OBJS = sched.o system_call.o traps.o asm.o fork.o \
panic.o printk.o vsprintf.o sys.o exit.o \
signal.o mktime.o
kernel.o: $(OBJS)
$(LD) -r -o kernel.o $(OBJS)
sync
clean:
rm -f core *.o *.a tmp_make keyboard.s
for i in *.c;do rm -f `basename $$i .c`.s;done
(cd chr_drv; make clean)
(cd blk_drv; make clean)
(cd math; make clean)
dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
(for i in *.c;do echo -n `echo $$i | sed 's,\.c,\.s,'`" "; \
$(CPP) -M $$i;done) >> tmp_make
cp tmp_make Makefile
(cd chr_drv; make dep)
(cd blk_drv; make dep)
### Dependencies:
exit.s exit.o : exit.c ../include/errno.h ../include/signal.h \
../include/sys/types.h ../include/sys/wait.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
../include/linux/kernel.h ../include/linux/tty.h ../include/termios.h \
../include/asm/segment.h
fork.s fork.o : fork.c ../include/errno.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
../include/asm/segment.h ../include/asm/system.h
mktime.s mktime.o : mktime.c ../include/time.h
panic.s panic.o : panic.c ../include/linux/kernel.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
../include/linux/mm.h ../include/signal.h
printk.s printk.o : printk.c ../include/stdarg.h ../include/stddef.h \
../include/linux/kernel.h
sched.s sched.o : sched.c ../include/linux/sched.h ../include/linux/head.h \
../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \
../include/signal.h ../include/linux/kernel.h ../include/linux/sys.h \
../include/linux/fdreg.h ../include/asm/system.h ../include/asm/io.h \
../include/asm/segment.h
signal.s signal.o : signal.c ../include/linux/sched.h ../include/linux/head.h \
../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \
../include/signal.h ../include/linux/kernel.h ../include/asm/segment.h
sys.s sys.o : sys.c ../include/errno.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
../include/linux/mm.h ../include/signal.h ../include/linux/tty.h \
../include/termios.h ../include/linux/kernel.h ../include/asm/segment.h \
../include/sys/times.h ../include/sys/utsname.h
traps.s traps.o : traps.c ../include/string.h ../include/linux/head.h \
../include/linux/sched.h ../include/linux/fs.h ../include/sys/types.h \
../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
../include/asm/system.h ../include/asm/segment.h ../include/asm/io.h
vsprintf.s vsprintf.o : vsprintf.c ../include/stdarg.h ../include/string.h

BIN
linux/kernel/asm.o Normal file

Binary file not shown.

146
linux/kernel/asm.s Normal file
View File

@ -0,0 +1,146 @@
/*
* linux/kernel/asm.s
*
* (C) 1991 Linus Torvalds
*/
/*
* asm.s contains the low-level code for most hardware faults.
* page_exception is handled by the mm, so that isn't here. This
* file also handles (hopefully) fpu-exceptions due to TS-bit, as
* the fpu must be properly saved/resored. This hasn't been tested.
*/
.globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
.globl _double_fault,_coprocessor_segment_overrun
.globl _invalid_TSS,_segment_not_present,_stack_segment
.globl _general_protection,_coprocessor_error,_irq13,_reserved
_divide_error:
pushl $_do_divide_error
no_error_code:
xchgl %eax,(%esp)
pushl %ebx
pushl %ecx
pushl %edx
pushl %edi
pushl %esi
pushl %ebp
push %ds
push %es
push %fs
pushl $0 # "error code"
lea 44(%esp),%edx
pushl %edx
movl $0x10,%edx
mov %dx,%ds
mov %dx,%es
mov %dx,%fs
call *%eax
addl $8,%esp
pop %fs
pop %es
pop %ds
popl %ebp
popl %esi
popl %edi
popl %edx
popl %ecx
popl %ebx
popl %eax
iret
_debug:
pushl $_do_int3 # _do_debug
jmp no_error_code
_nmi:
pushl $_do_nmi
jmp no_error_code
_int3:
pushl $_do_int3
jmp no_error_code
_overflow:
pushl $_do_overflow
jmp no_error_code
_bounds:
pushl $_do_bounds
jmp no_error_code
_invalid_op:
pushl $_do_invalid_op
jmp no_error_code
_coprocessor_segment_overrun:
pushl $_do_coprocessor_segment_overrun
jmp no_error_code
_reserved:
pushl $_do_reserved
jmp no_error_code
_irq13:
pushl %eax
xorb %al,%al
outb %al,$0xF0
movb $0x20,%al
outb %al,$0x20
jmp 1f
1: jmp 1f
1: outb %al,$0xA0
popl %eax
jmp _coprocessor_error
_double_fault:
pushl $_do_double_fault
error_code:
xchgl %eax,4(%esp) # error code <-> %eax
xchgl %ebx,(%esp) # &function <-> %ebx
pushl %ecx
pushl %edx
pushl %edi
pushl %esi
pushl %ebp
push %ds
push %es
push %fs
pushl %eax # error code
lea 44(%esp),%eax # offset
pushl %eax
movl $0x10,%eax
mov %ax,%ds
mov %ax,%es
mov %ax,%fs
call *%ebx
addl $8,%esp
pop %fs
pop %es
pop %ds
popl %ebp
popl %esi
popl %edi
popl %edx
popl %ecx
popl %ebx
popl %eax
iret
_invalid_TSS:
pushl $_do_invalid_TSS
jmp error_code
_segment_not_present:
pushl $_do_segment_not_present
jmp error_code
_stack_segment:
pushl $_do_stack_segment
jmp error_code
_general_protection:
pushl $_do_general_protection
jmp error_code

View File

@ -0,0 +1,58 @@
#
# Makefile for the FREAX-kernel block device drivers.
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
AR =gar
AS =gas
LD =gld
LDFLAGS =-x #-s
CC =gcc
CFLAGS =-Wall -O -g -fstrength-reduce -fomit-frame-pointer -fcombine-regs \
-finline-functions -nostdinc -I../../include
CPP =gcc -E -nostdinc -I../../include
.c.s:
$(CC) $(CFLAGS) \
-S -o $*.s $<
.s.o:
$(AS) -c -o $*.o $<
.c.o:
$(CC) $(CFLAGS) \
-c -o $*.o $<
OBJS = ll_rw_blk.o floppy.o hd.o ramdisk.o
blk_drv.a: $(OBJS)
$(AR) rcs blk_drv.a $(OBJS)
sync
clean:
rm -f core *.o *.a tmp_make
for i in *.c;do rm -f `basename $$i .c`.s;done
dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
(for i in *.c;do echo -n `echo $$i | sed 's,\.c,\.s,'`" "; \
$(CPP) -M $$i;done) >> tmp_make
cp tmp_make Makefile
### Dependencies:
floppy.s floppy.o : floppy.c ../../include/linux/sched.h ../../include/linux/head.h \
../../include/linux/fs.h ../../include/sys/types.h ../../include/linux/mm.h \
../../include/signal.h ../../include/linux/kernel.h \
../../include/linux/fdreg.h ../../include/asm/system.h \
../../include/asm/io.h ../../include/asm/segment.h blk.h
hd.s hd.o : hd.c ../../include/linux/config.h ../../include/linux/sched.h \
../../include/linux/head.h ../../include/linux/fs.h \
../../include/sys/types.h ../../include/linux/mm.h ../../include/signal.h \
../../include/linux/kernel.h ../../include/linux/hdreg.h \
../../include/asm/system.h ../../include/asm/io.h \
../../include/asm/segment.h blk.h
ll_rw_blk.s ll_rw_blk.o : ll_rw_blk.c ../../include/errno.h ../../include/linux/sched.h \
../../include/linux/head.h ../../include/linux/fs.h \
../../include/sys/types.h ../../include/linux/mm.h ../../include/signal.h \
../../include/linux/kernel.h ../../include/asm/system.h blk.h

140
linux/kernel/blk_drv/blk.h Normal file
View File

@ -0,0 +1,140 @@
#ifndef _BLK_H
#define _BLK_H
#define NR_BLK_DEV 7
/*
* NR_REQUEST is the number of entries in the request-queue.
* NOTE that writes may use only the low 2/3 of these: reads
* take precedence.
*
* 32 seems to be a reasonable number: enough to get some benefit
* from the elevator-mechanism, but not so much as to lock a lot of
* buffers when they are in the queue. 64 seems to be too many (easily
* long pauses in reading when heavy writing/syncing is going on)
*/
#define NR_REQUEST 32
/*
* Ok, this is an expanded form so that we can use the same
* request for paging requests when that is implemented. In
* paging, 'bh' is NULL, and 'waiting' is used to wait for
* read/write completion.
*/
struct request {
int dev; /* -1 if no request */
int cmd; /* READ or WRITE */
int errors;
unsigned long sector;
unsigned long nr_sectors;
char * buffer;
struct task_struct * waiting;
struct buffer_head * bh;
struct request * next;
};
/*
* This is used in the elevator algorithm: Note that
* reads always go before writes. This is natural: reads
* are much more time-critical than writes.
*/
#define IN_ORDER(s1,s2) \
((s1)->cmd<(s2)->cmd || (s1)->cmd==(s2)->cmd && \
((s1)->dev < (s2)->dev || ((s1)->dev == (s2)->dev && \
(s1)->sector < (s2)->sector)))
struct blk_dev_struct {
void (*request_fn)(void);
struct request * current_request;
};
extern struct blk_dev_struct blk_dev[NR_BLK_DEV];
extern struct request request[NR_REQUEST];
extern struct task_struct * wait_for_request;
#ifdef MAJOR_NR
/*
* Add entries as needed. Currently the only block devices
* supported are hard-disks and floppies.
*/
#if (MAJOR_NR == 1)
/* ram disk */
#define DEVICE_NAME "ramdisk"
#define DEVICE_REQUEST do_rd_request
#define DEVICE_NR(device) ((device) & 7)
#define DEVICE_ON(device)
#define DEVICE_OFF(device)
#elif (MAJOR_NR == 2)
/* floppy */
#define DEVICE_NAME "floppy"
#define DEVICE_INTR do_floppy
#define DEVICE_REQUEST do_fd_request
#define DEVICE_NR(device) ((device) & 3)
#define DEVICE_ON(device) floppy_on(DEVICE_NR(device))
#define DEVICE_OFF(device) floppy_off(DEVICE_NR(device))
#elif (MAJOR_NR == 3)
/* harddisk */
#define DEVICE_NAME "harddisk"
#define DEVICE_INTR do_hd
#define DEVICE_REQUEST do_hd_request
#define DEVICE_NR(device) (MINOR(device)/5)
#define DEVICE_ON(device)
#define DEVICE_OFF(device)
#elif
/* unknown blk device */
#error "unknown blk device"
#endif
#define CURRENT (blk_dev[MAJOR_NR].current_request)
#define CURRENT_DEV DEVICE_NR(CURRENT->dev)
#ifdef DEVICE_INTR
void (*DEVICE_INTR)(void) = NULL;
#endif
static void (DEVICE_REQUEST)(void);
extern inline void unlock_buffer(struct buffer_head * bh)
{
if (!bh->b_lock)
printk(DEVICE_NAME ": free buffer being unlocked\n");
bh->b_lock=0;
wake_up(&bh->b_wait);
}
extern inline void end_request(int uptodate)
{
DEVICE_OFF(CURRENT->dev);
if (CURRENT->bh) {
CURRENT->bh->b_uptodate = uptodate;
unlock_buffer(CURRENT->bh);
}
if (!uptodate) {
printk(DEVICE_NAME " I/O error\n\r");
printk("dev %04x, block %d\n\r",CURRENT->dev,
CURRENT->bh->b_blocknr);
}
wake_up(&CURRENT->waiting);
wake_up(&wait_for_request);
CURRENT->dev = -1;
CURRENT = CURRENT->next;
}
#define INIT_REQUEST \
repeat: \
if (!CURRENT) \
return; \
if (MAJOR(CURRENT->dev) != MAJOR_NR) \
panic(DEVICE_NAME ": request list destroyed"); \
if (CURRENT->bh) { \
if (!CURRENT->bh->b_lock) \
panic(DEVICE_NAME ": block not locked"); \
}
#endif
#endif

Binary file not shown.

View File

@ -0,0 +1,462 @@
/*
* linux/kernel/floppy.c
*
* (C) 1991 Linus Torvalds
*/
/*
* 02.12.91 - Changed to static variables to indicate need for reset
* and recalibrate. This makes some things easier (output_byte reset
* checking etc), and means less interrupt jumping in case of errors,
* so the code is hopefully easier to understand.
*/
/*
* This file is certainly a mess. I've tried my best to get it working,
* but I don't like programming floppies, and I have only one anyway.
* Urgel. I should check for more errors, and do more graceful error
* recovery. Seems there are problems with several drives. I've tried to
* correct them. No promises.
*/
/*
* As with hd.c, all routines within this file can (and will) be called
* by interrupts, so extreme caution is needed. A hardware interrupt
* handler may not sleep, or a kernel panic will happen. Thus I cannot
* call "floppy-on" directly, but have to set a special timer interrupt
* etc.
*
* Also, I'm not certain this works on more than 1 floppy. Bugs may
* abund.
*/
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/fdreg.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/segment.h>
#define MAJOR_NR 2
#include "blk.h"
static int recalibrate = 0;
static int reset = 0;
static int seek = 0;
extern unsigned char current_DOR;
#define immoutb_p(val,port) \
__asm__("outb %0,%1\n\tjmp 1f\n1:\tjmp 1f\n1:"::"a" ((char) (val)),"i" (port))
#define TYPE(x) ((x)>>2)
#define DRIVE(x) ((x)&0x03)
/*
* Note that MAX_ERRORS=8 doesn't imply that we retry every bad read
* max 8 times - some types of errors increase the errorcount by 2,
* so we might actually retry only 5-6 times before giving up.
*/
#define MAX_ERRORS 8
/*
* globals used by 'result()'
*/
#define MAX_REPLIES 7
static unsigned char reply_buffer[MAX_REPLIES];
#define ST0 (reply_buffer[0])
#define ST1 (reply_buffer[1])
#define ST2 (reply_buffer[2])
#define ST3 (reply_buffer[3])
/*
* This struct defines the different floppy types. Unlike minix
* linux doesn't have a "search for right type"-type, as the code
* for that is convoluted and weird. I've got enough problems with
* this driver as it is.
*
* The 'stretch' tells if the tracks need to be boubled for some
* types (ie 360kB diskette in 1.2MB drive etc). Others should
* be self-explanatory.
*/
static struct floppy_struct {
unsigned int size, sect, head, track, stretch;
unsigned char gap,rate,spec1;
} floppy_type[] = {
{ 0, 0,0, 0,0,0x00,0x00,0x00 }, /* no testing */
{ 720, 9,2,40,0,0x2A,0x02,0xDF }, /* 360kB PC diskettes */
{ 2400,15,2,80,0,0x1B,0x00,0xDF }, /* 1.2 MB AT-diskettes */
{ 720, 9,2,40,1,0x2A,0x02,0xDF }, /* 360kB in 720kB drive */
{ 1440, 9,2,80,0,0x2A,0x02,0xDF }, /* 3.5" 720kB diskette */
{ 720, 9,2,40,1,0x23,0x01,0xDF }, /* 360kB in 1.2MB drive */
{ 1440, 9,2,80,0,0x23,0x01,0xDF }, /* 720kB in 1.2MB drive */
{ 2880,18,2,80,0,0x1B,0x00,0xCF }, /* 1.44MB diskette */
};
/*
* Rate is 0 for 500kb/s, 2 for 300kbps, 1 for 250kbps
* Spec1 is 0xSH, where S is stepping rate (F=1ms, E=2ms, D=3ms etc),
* H is head unload time (1=16ms, 2=32ms, etc)
*
* Spec2 is (HLD<<1 | ND), where HLD is head load time (1=2ms, 2=4 ms etc)
* and ND is set means no DMA. Hardcoded to 6 (HLD=6ms, use DMA).
*/
extern void floppy_interrupt(void);
extern char tmp_floppy_area[1024];
/*
* These are global variables, as that's the easiest way to give
* information to interrupts. They are the data used for the current
* request.
*/
static int cur_spec1 = -1;
static int cur_rate = -1;
static struct floppy_struct * floppy = floppy_type;
static unsigned char current_drive = 0;
static unsigned char sector = 0;
static unsigned char head = 0;
static unsigned char track = 0;
static unsigned char seek_track = 0;
static unsigned char current_track = 255;
static unsigned char command = 0;
unsigned char selected = 0;
struct task_struct * wait_on_floppy_select = NULL;
void floppy_deselect(unsigned int nr)
{
if (nr != (current_DOR & 3))
printk("floppy_deselect: drive not selected\n\r");
selected = 0;
wake_up(&wait_on_floppy_select);
}
/*
* floppy-change is never called from an interrupt, so we can relax a bit
* here, sleep etc. Note that floppy-on tries to set current_DOR to point
* to the desired drive, but it will probably not survive the sleep if
* several floppies are used at the same time: thus the loop.
*/
int floppy_change(unsigned int nr)
{
repeat:
floppy_on(nr);
while ((current_DOR & 3) != nr && selected)
interruptible_sleep_on(&wait_on_floppy_select);
if ((current_DOR & 3) != nr)
goto repeat;
if (inb(FD_DIR) & 0x80) {
floppy_off(nr);
return 1;
}
floppy_off(nr);
return 0;
}
#define copy_buffer(from,to) \
__asm__("cld ; rep ; movsl" \
::"c" (BLOCK_SIZE/4),"S" ((long)(from)),"D" ((long)(to)) \
:"cx","di","si")
static void setup_DMA(void)
{
long addr = (long) CURRENT->buffer;
cli();
if (addr >= 0x100000) {
addr = (long) tmp_floppy_area;
if (command == FD_WRITE)
copy_buffer(CURRENT->buffer,tmp_floppy_area);
}
/* mask DMA 2 */
immoutb_p(4|2,10);
/* output command byte. I don't know why, but everyone (minix, */
/* sanches & canton) output this twice, first to 12 then to 11 */
__asm__("outb %%al,$12\n\tjmp 1f\n1:\tjmp 1f\n1:\t"
"outb %%al,$11\n\tjmp 1f\n1:\tjmp 1f\n1:"::
"a" ((char) ((command == FD_READ)?DMA_READ:DMA_WRITE)));
/* 8 low bits of addr */
immoutb_p(addr,4);
addr >>= 8;
/* bits 8-15 of addr */
immoutb_p(addr,4);
addr >>= 8;
/* bits 16-19 of addr */
immoutb_p(addr,0x81);
/* low 8 bits of count-1 (1024-1=0x3ff) */
immoutb_p(0xff,5);
/* high 8 bits of count-1 */
immoutb_p(3,5);
/* activate DMA 2 */
immoutb_p(0|2,10);
sti();
}
static void output_byte(char byte)
{
int counter;
unsigned char status;
if (reset)
return;
for(counter = 0 ; counter < 10000 ; counter++) {
status = inb_p(FD_STATUS) & (STATUS_READY | STATUS_DIR);
if (status == STATUS_READY) {
outb(byte,FD_DATA);
return;
}
}
reset = 1;
printk("Unable to send byte to FDC\n\r");
}
static int result(void)
{
int i = 0, counter, status;
if (reset)
return -1;
for (counter = 0 ; counter < 10000 ; counter++) {
status = inb_p(FD_STATUS)&(STATUS_DIR|STATUS_READY|STATUS_BUSY);
if (status == STATUS_READY)
return i;
if (status == (STATUS_DIR|STATUS_READY|STATUS_BUSY)) {
if (i >= MAX_REPLIES)
break;
reply_buffer[i++] = inb_p(FD_DATA);
}
}
reset = 1;
printk("Getstatus times out\n\r");
return -1;
}
static void bad_flp_intr(void)
{
CURRENT->errors++;
if (CURRENT->errors > MAX_ERRORS) {
floppy_deselect(current_drive);
end_request(0);
}
if (CURRENT->errors > MAX_ERRORS/2)
reset = 1;
else
recalibrate = 1;
}
/*
* Ok, this interrupt is called after a DMA read/write has succeeded,
* so we check the results, and copy any buffers.
*/
static void rw_interrupt(void)
{
if (result() != 7 || (ST0 & 0xf8) || (ST1 & 0xbf) || (ST2 & 0x73)) {
if (ST1 & 0x02) {
printk("Drive %d is write protected\n\r",current_drive);
floppy_deselect(current_drive);
end_request(0);
} else
bad_flp_intr();
do_fd_request();
return;
}
if (command == FD_READ && (unsigned long)(CURRENT->buffer) >= 0x100000)
copy_buffer(tmp_floppy_area,CURRENT->buffer);
floppy_deselect(current_drive);
end_request(1);
do_fd_request();
}
inline void setup_rw_floppy(void)
{
setup_DMA();
do_floppy = rw_interrupt;
output_byte(command);
output_byte(head<<2 | current_drive);
output_byte(track);
output_byte(head);
output_byte(sector);
output_byte(2); /* sector size = 512 */
output_byte(floppy->sect);
output_byte(floppy->gap);
output_byte(0xFF); /* sector size (0xff when n!=0 ?) */
if (reset)
do_fd_request();
}
/*
* This is the routine called after every seek (or recalibrate) interrupt
* from the floppy controller. Note that the "unexpected interrupt" routine
* also does a recalibrate, but doesn't come here.
*/
static void seek_interrupt(void)
{
/* sense drive status */
output_byte(FD_SENSEI);
if (result() != 2 || (ST0 & 0xF8) != 0x20 || ST1 != seek_track) {
bad_flp_intr();
do_fd_request();
return;
}
current_track = ST1;
setup_rw_floppy();
}
/*
* This routine is called when everything should be correctly set up
* for the transfer (ie floppy motor is on and the correct floppy is
* selected).
*/
static void transfer(void)
{
if (cur_spec1 != floppy->spec1) {
cur_spec1 = floppy->spec1;
output_byte(FD_SPECIFY);
output_byte(cur_spec1); /* hut etc */
output_byte(6); /* Head load time =6ms, DMA */
}
if (cur_rate != floppy->rate)
outb_p(cur_rate = floppy->rate,FD_DCR);
if (reset) {
do_fd_request();
return;
}
if (!seek) {
setup_rw_floppy();
return;
}
do_floppy = seek_interrupt;
if (seek_track) {
output_byte(FD_SEEK);
output_byte(head<<2 | current_drive);
output_byte(seek_track);
} else {
output_byte(FD_RECALIBRATE);
output_byte(head<<2 | current_drive);
}
if (reset)
do_fd_request();
}
/*
* Special case - used after a unexpected interrupt (or reset)
*/
static void recal_interrupt(void)
{
output_byte(FD_SENSEI);
if (result()!=2 || (ST0 & 0xE0) == 0x60)
reset = 1;
else
recalibrate = 0;
do_fd_request();
}
void unexpected_floppy_interrupt(void)
{
output_byte(FD_SENSEI);
if (result()!=2 || (ST0 & 0xE0) == 0x60)
reset = 1;
else
recalibrate = 1;
}
static void recalibrate_floppy(void)
{
recalibrate = 0;
current_track = 0;
do_floppy = recal_interrupt;
output_byte(FD_RECALIBRATE);
output_byte(head<<2 | current_drive);
if (reset)
do_fd_request();
}
static void reset_interrupt(void)
{
output_byte(FD_SENSEI);
(void) result();
output_byte(FD_SPECIFY);
output_byte(cur_spec1); /* hut etc */
output_byte(6); /* Head load time =6ms, DMA */
do_fd_request();
}
/*
* reset is done by pulling bit 2 of DOR low for a while.
*/
static void reset_floppy(void)
{
int i;
reset = 0;
cur_spec1 = -1;
cur_rate = -1;
recalibrate = 1;
printk("Reset-floppy called\n\r");
cli();
do_floppy = reset_interrupt;
outb_p(current_DOR & ~0x04,FD_DOR);
for (i=0 ; i<100 ; i++)
__asm__("nop");
outb(current_DOR,FD_DOR);
sti();
}
static void floppy_on_interrupt(void)
{
/* We cannot do a floppy-select, as that might sleep. We just force it */
selected = 1;
if (current_drive != (current_DOR & 3)) {
current_DOR &= 0xFC;
current_DOR |= current_drive;
outb(current_DOR,FD_DOR);
add_timer(2,&transfer);
} else
transfer();
}
void do_fd_request(void)
{
unsigned int block;
seek = 0;
if (reset) {
reset_floppy();
return;
}
if (recalibrate) {
recalibrate_floppy();
return;
}
INIT_REQUEST;
floppy = (MINOR(CURRENT->dev)>>2) + floppy_type;
if (current_drive != CURRENT_DEV)
seek = 1;
current_drive = CURRENT_DEV;
block = CURRENT->sector;
if (block+2 > floppy->size) {
end_request(0);
goto repeat;
}
sector = block % floppy->sect;
block /= floppy->sect;
head = block % floppy->head;
track = block / floppy->head;
seek_track = track << floppy->stretch;
if (seek_track != current_track)
seek = 1;
sector++;
if (CURRENT->cmd == READ)
command = FD_READ;
else if (CURRENT->cmd == WRITE)
command = FD_WRITE;
else
panic("do_fd_request: unknown command");
add_timer(ticks_to_floppy_on(current_drive),&floppy_on_interrupt);
}
void floppy_init(void)
{
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
set_trap_gate(0x26,&floppy_interrupt);
outb(inb_p(0x21)&~0x40,0x21);
}

Binary file not shown.

349
linux/kernel/blk_drv/hd.c Normal file
View File

@ -0,0 +1,349 @@
/*
* linux/kernel/hd.c
*
* (C) 1991 Linus Torvalds
*/
/*
* This is the low-level hd interrupt support. It traverses the
* request-list, using interrupts to jump between functions. As
* all the functions are called within interrupts, we may not
* sleep. Special care is recommended.
*
* modified by Drew Eckhardt to check nr of hd's from the CMOS.
*/
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/hdreg.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/segment.h>
#define MAJOR_NR 3
#include "blk.h"
#define CMOS_READ(addr) ({ \
outb_p(0x80|addr,0x70); \
inb_p(0x71); \
})
/* Max read/write errors/sector */
#define MAX_ERRORS 7
#define MAX_HD 2
static void recal_intr(void);
static int recalibrate = 1;
static int reset = 1;
/*
* This struct defines the HD's and their types.
*/
struct hd_i_struct {
int head,sect,cyl,wpcom,lzone,ctl;
};
#ifdef HD_TYPE
struct hd_i_struct hd_info[] = { HD_TYPE };
#define NR_HD ((sizeof (hd_info))/(sizeof (struct hd_i_struct)))
#else
struct hd_i_struct hd_info[] = { {0,0,0,0,0,0},{0,0,0,0,0,0} };
static int NR_HD = 0;
#endif
static struct hd_struct {
long start_sect;
long nr_sects;
} hd[5*MAX_HD]={{0,0},};
#define port_read(port,buf,nr) \
__asm__("cld;rep;insw"::"d" (port),"D" (buf),"c" (nr):"cx","di")
#define port_write(port,buf,nr) \
__asm__("cld;rep;outsw"::"d" (port),"S" (buf),"c" (nr):"cx","si")
extern void hd_interrupt(void);
extern void rd_load(void);
/* This may be used only once, enforced by 'static int callable' */
int sys_setup(void * BIOS)
{
static int callable = 1;
int i,drive;
unsigned char cmos_disks;
struct partition *p;
struct buffer_head * bh;
if (!callable)
return -1;
callable = 0;
#ifndef HD_TYPE
for (drive=0 ; drive<2 ; drive++) {
hd_info[drive].cyl = *(unsigned short *) BIOS;
hd_info[drive].head = *(unsigned char *) (2+BIOS);
hd_info[drive].wpcom = *(unsigned short *) (5+BIOS);
hd_info[drive].ctl = *(unsigned char *) (8+BIOS);
hd_info[drive].lzone = *(unsigned short *) (12+BIOS);
hd_info[drive].sect = *(unsigned char *) (14+BIOS);
BIOS += 16;
}
if (hd_info[1].cyl)
NR_HD=2;
else
NR_HD=1;
#endif
for (i=0 ; i<NR_HD ; i++) {
hd[i*5].start_sect = 0;
hd[i*5].nr_sects = hd_info[i].head*
hd_info[i].sect*hd_info[i].cyl;
}
/*
We querry CMOS about hard disks : it could be that
we have a SCSI/ESDI/etc controller that is BIOS
compatable with ST-506, and thus showing up in our
BIOS table, but not register compatable, and therefore
not present in CMOS.
Furthurmore, we will assume that our ST-506 drives
<if any> are the primary drives in the system, and
the ones reflected as drive 1 or 2.
The first drive is stored in the high nibble of CMOS
byte 0x12, the second in the low nibble. This will be
either a 4 bit drive type or 0xf indicating use byte 0x19
for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.
Needless to say, a non-zero value means we have
an AT controller hard disk for that drive.
*/
if ((cmos_disks = CMOS_READ(0x12)) & 0xf0)
if (cmos_disks & 0x0f)
NR_HD = 2;
else
NR_HD = 1;
else
NR_HD = 0;
for (i = NR_HD ; i < 2 ; i++) {
hd[i*5].start_sect = 0;
hd[i*5].nr_sects = 0;
}
for (drive=0 ; drive<NR_HD ; drive++) {
if (!(bh = bread(0x300 + drive*5,0))) {
printk("Unable to read partition table of drive %d\n\r",
drive);
panic("");
}
if (bh->b_data[510] != 0x55 || (unsigned char)
bh->b_data[511] != 0xAA) {
printk("Bad partition table on drive %d\n\r",drive);
panic("");
}
p = 0x1BE + (void *)bh->b_data;
for (i=1;i<5;i++,p++) {
hd[i+5*drive].start_sect = p->start_sect;
hd[i+5*drive].nr_sects = p->nr_sects;
}
brelse(bh);
}
if (NR_HD)
printk("Partition table%s ok.\n\r",(NR_HD>1)?"s":"");
rd_load();
mount_root();
return (0);
}
static int controller_ready(void)
{
int retries=10000;
while (--retries && (inb_p(HD_STATUS)&0xc0)!=0x40);
return (retries);
}
static int win_result(void)
{
int i=inb_p(HD_STATUS);
if ((i & (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT))
== (READY_STAT | SEEK_STAT))
return(0); /* ok */
if (i&1) i=inb(HD_ERROR);
return (1);
}
static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
unsigned int head,unsigned int cyl,unsigned int cmd,
void (*intr_addr)(void))
{
register int port asm("dx");
if (drive>1 || head>15)
panic("Trying to write bad sector");
if (!controller_ready())
panic("HD controller not ready");
do_hd = intr_addr;
outb_p(hd_info[drive].ctl,HD_CMD);
port=HD_DATA;
outb_p(hd_info[drive].wpcom>>2,++port);
outb_p(nsect,++port);
outb_p(sect,++port);
outb_p(cyl,++port);
outb_p(cyl>>8,++port);
outb_p(0xA0|(drive<<4)|head,++port);
outb(cmd,++port);
}
static int drive_busy(void)
{
unsigned int i;
for (i = 0; i < 10000; i++)
if (READY_STAT == (inb_p(HD_STATUS) & (BUSY_STAT|READY_STAT)))
break;
i = inb(HD_STATUS);
i &= BUSY_STAT | READY_STAT | SEEK_STAT;
if (i == READY_STAT | SEEK_STAT)
return(0);
printk("HD controller times out\n\r");
return(1);
}
static void reset_controller(void)
{
int i;
outb(4,HD_CMD);
for(i = 0; i < 100; i++) nop();
outb(hd_info[0].ctl & 0x0f ,HD_CMD);
if (drive_busy())
printk("HD-controller still busy\n\r");
if ((i = inb(HD_ERROR)) != 1)
printk("HD-controller reset failed: %02x\n\r",i);
}
static void reset_hd(int nr)
{
reset_controller();
hd_out(nr,hd_info[nr].sect,hd_info[nr].sect,hd_info[nr].head-1,
hd_info[nr].cyl,WIN_SPECIFY,&recal_intr);
}
void unexpected_hd_interrupt(void)
{
printk("Unexpected HD interrupt\n\r");
}
static void bad_rw_intr(void)
{
if (++CURRENT->errors >= MAX_ERRORS)
end_request(0);
if (CURRENT->errors > MAX_ERRORS/2)
reset = 1;
}
static void read_intr(void)
{
if (win_result()) {
bad_rw_intr();
do_hd_request();
return;
}
port_read(HD_DATA,CURRENT->buffer,256);
CURRENT->errors = 0;
CURRENT->buffer += 512;
CURRENT->sector++;
if (--CURRENT->nr_sectors) {
do_hd = &read_intr;
return;
}
end_request(1);
do_hd_request();
}
static void write_intr(void)
{
if (win_result()) {
bad_rw_intr();
do_hd_request();
return;
}
if (--CURRENT->nr_sectors) {
CURRENT->sector++;
CURRENT->buffer += 512;
do_hd = &write_intr;
port_write(HD_DATA,CURRENT->buffer,256);
return;
}
end_request(1);
do_hd_request();
}
static void recal_intr(void)
{
if (win_result())
bad_rw_intr();
do_hd_request();
}
void do_hd_request(void)
{
int i,r;
unsigned int block,dev;
unsigned int sec,head,cyl;
unsigned int nsect;
INIT_REQUEST;
dev = MINOR(CURRENT->dev);
block = CURRENT->sector;
if (dev >= 5*NR_HD || block+2 > hd[dev].nr_sects) {
end_request(0);
goto repeat;
}
block += hd[dev].start_sect;
dev /= 5;
__asm__("divl %4":"=a" (block),"=d" (sec):"0" (block),"1" (0),
"r" (hd_info[dev].sect));
__asm__("divl %4":"=a" (cyl),"=d" (head):"0" (block),"1" (0),
"r" (hd_info[dev].head));
sec++;
nsect = CURRENT->nr_sectors;
if (reset) {
reset = 0;
recalibrate = 1;
reset_hd(CURRENT_DEV);
return;
}
if (recalibrate) {
recalibrate = 0;
hd_out(dev,hd_info[CURRENT_DEV].sect,0,0,0,
WIN_RESTORE,&recal_intr);
return;
}
if (CURRENT->cmd == WRITE) {
hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
for(i=0 ; i<3000 && !(r=inb_p(HD_STATUS)&DRQ_STAT) ; i++)
/* nothing */ ;
if (!r) {
bad_rw_intr();
goto repeat;
}
port_write(HD_DATA,CURRENT->buffer,256);
} else if (CURRENT->cmd == READ) {
hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr);
} else
panic("unknown hd-command");
}
void hd_init(void)
{
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
set_intr_gate(0x2E,&hd_interrupt);
outb_p(inb_p(0x21)&0xfb,0x21);
outb(inb_p(0xA1)&0xbf,0xA1);
}

Some files were not shown because too many files have changed in this diff Show More