From 690396344035bb23640ebcbc97850952b227412f Mon Sep 17 00:00:00 2001 From: jiangzhikang <1351816101@qq.com> Date: Fri, 9 Jul 2021 00:54:29 +0800 Subject: [PATCH] jiangzhikang --- os/os/linux/.vscode/settings.json | 9 + os/os/linux/Image | Bin 0 -> 138404 bytes os/os/linux/Image.bkp | Bin 0 -> 131556 bytes os/os/linux/Makefile | 125 +++ os/os/linux/System.map | 598 +++++++++++++ os/os/linux/System.map.2 | 1082 +++++++++++++++++++++++ os/os/linux/boot/bootsect | Bin 0 -> 544 bytes os/os/linux/boot/bootsect.o | Bin 0 -> 923 bytes os/os/linux/boot/bootsect.s | 260 ++++++ os/os/linux/boot/head.o | Bin 0 -> 27012 bytes os/os/linux/boot/head.s | 240 +++++ os/os/linux/boot/setup | Bin 0 -> 344 bytes os/os/linux/boot/setup.o | Bin 0 -> 596 bytes os/os/linux/boot/setup.s | 231 +++++ os/os/linux/execve2.patch | 41 + os/os/linux/fs/Makefile | 101 +++ os/os/linux/fs/bitmap.c | 168 ++++ os/os/linux/fs/bitmap.o | Bin 0 -> 10280 bytes os/os/linux/fs/block_dev.c | 73 ++ os/os/linux/fs/block_dev.o | Bin 0 -> 7296 bytes os/os/linux/fs/buffer.c | 384 ++++++++ os/os/linux/fs/buffer.o | Bin 0 -> 13348 bytes os/os/linux/fs/char_dev.c | 104 +++ os/os/linux/fs/char_dev.o | Bin 0 -> 8288 bytes os/os/linux/fs/exec.c | 359 ++++++++ os/os/linux/fs/exec.o | Bin 0 -> 14932 bytes os/os/linux/fs/fcntl.c | 75 ++ os/os/linux/fs/fcntl.o | Bin 0 -> 6748 bytes os/os/linux/fs/file_dev.c | 90 ++ os/os/linux/fs/file_dev.o | Bin 0 -> 7828 bytes os/os/linux/fs/file_table.c | 9 + os/os/linux/fs/file_table.o | Bin 0 -> 2644 bytes os/os/linux/fs/fs.o | Bin 0 -> 142933 bytes os/os/linux/fs/inode.c | 340 +++++++ os/os/linux/fs/inode.o | Bin 0 -> 14072 bytes os/os/linux/fs/ioctl.c | 46 + os/os/linux/fs/ioctl.o | Bin 0 -> 5828 bytes os/os/linux/fs/namei.c | 783 ++++++++++++++++ os/os/linux/fs/namei.o | Bin 0 -> 20756 bytes os/os/linux/fs/open.c | 208 +++++ os/os/linux/fs/open.o | Bin 0 -> 11184 bytes os/os/linux/fs/pipe.c | 111 +++ os/os/linux/fs/pipe.o | Bin 0 -> 8104 bytes os/os/linux/fs/read_write.c | 103 +++ os/os/linux/fs/read_write.o | Bin 0 -> 7520 bytes os/os/linux/fs/select.c | 10 + os/os/linux/fs/select.o | Bin 0 -> 1776 bytes os/os/linux/fs/stat.c | 66 ++ os/os/linux/fs/stat.o | Bin 0 -> 7212 bytes os/os/linux/fs/super.c | 282 ++++++ os/os/linux/fs/super.o | Bin 0 -> 12284 bytes os/os/linux/fs/truncate.c | 65 ++ os/os/linux/fs/truncate.o | Bin 0 -> 6848 bytes os/os/linux/include/a.out.h | 220 +++++ os/os/linux/include/asm/io.h | 24 + os/os/linux/include/asm/memory.h | 15 + os/os/linux/include/asm/segment.h | 65 ++ os/os/linux/include/asm/system.h | 66 ++ os/os/linux/include/const.h | 15 + os/os/linux/include/ctype.h | 34 + os/os/linux/include/errno.h | 60 ++ os/os/linux/include/fcntl.h | 55 ++ os/os/linux/include/linux/config.h | 48 + os/os/linux/include/linux/fdreg.h | 71 ++ os/os/linux/include/linux/fs.h | 202 +++++ os/os/linux/include/linux/hdreg.h | 65 ++ os/os/linux/include/linux/head.h | 20 + os/os/linux/include/linux/kernel.h | 22 + os/os/linux/include/linux/mm.h | 10 + os/os/linux/include/linux/sched.h | 239 +++++ os/os/linux/include/linux/sys.h | 116 +++ os/os/linux/include/linux/tty.h | 77 ++ os/os/linux/include/new0.h | 30 + os/os/linux/include/signal.h | 68 ++ os/os/linux/include/stdarg.h | 28 + os/os/linux/include/stddef.h | 19 + os/os/linux/include/string.h | 405 +++++++++ os/os/linux/include/sys/stat.h | 60 ++ os/os/linux/include/sys/times.h | 15 + os/os/linux/include/sys/types.h | 46 + os/os/linux/include/sys/utsname.h | 16 + os/os/linux/include/sys/wait.h | 23 + os/os/linux/include/termios.h | 228 +++++ os/os/linux/include/time.h | 42 + os/os/linux/include/unistd.h | 276 ++++++ os/os/linux/include/utime.h | 13 + os/os/linux/init/main.c | 216 +++++ os/os/linux/init/main.o | Bin 0 -> 12208 bytes os/os/linux/kernel/Makefile | 83 ++ os/os/linux/kernel/asm.o | Bin 0 -> 1740 bytes os/os/linux/kernel/asm.s | 146 +++ os/os/linux/kernel/blk_drv/Makefile | 58 ++ os/os/linux/kernel/blk_drv/blk.h | 140 +++ os/os/linux/kernel/blk_drv/blk_drv.a | Bin 0 -> 52212 bytes os/os/linux/kernel/blk_drv/floppy.c | 463 ++++++++++ os/os/linux/kernel/blk_drv/floppy.o | Bin 0 -> 16612 bytes os/os/linux/kernel/blk_drv/hd.c | 351 ++++++++ os/os/linux/kernel/blk_drv/hd.o | Bin 0 -> 15520 bytes os/os/linux/kernel/blk_drv/ll_rw_blk.c | 165 ++++ os/os/linux/kernel/blk_drv/ll_rw_blk.o | Bin 0 -> 8740 bytes os/os/linux/kernel/blk_drv/ramdisk.c | 126 +++ os/os/linux/kernel/blk_drv/ramdisk.o | Bin 0 -> 10664 bytes os/os/linux/kernel/chr_drv/Makefile | 68 ++ os/os/linux/kernel/chr_drv/chr_drv.a | Bin 0 -> 68902 bytes os/os/linux/kernel/chr_drv/console.c | 710 +++++++++++++++ os/os/linux/kernel/chr_drv/console.o | Bin 0 -> 20896 bytes os/os/linux/kernel/chr_drv/keyboard.2.o | Bin 0 -> 6024 bytes os/os/linux/kernel/chr_drv/keyboard.2.s | 466 ++++++++++ os/os/linux/kernel/chr_drv/keyboard.S | 588 ++++++++++++ os/os/linux/kernel/chr_drv/rs_io.o | Bin 0 -> 1320 bytes os/os/linux/kernel/chr_drv/rs_io.s | 147 +++ os/os/linux/kernel/chr_drv/serial.c | 59 ++ os/os/linux/kernel/chr_drv/serial.o | Bin 0 -> 6752 bytes os/os/linux/kernel/chr_drv/tty_io.c | 349 ++++++++ os/os/linux/kernel/chr_drv/tty_io.o | Bin 0 -> 22504 bytes os/os/linux/kernel/chr_drv/tty_ioctl.c | 204 +++++ os/os/linux/kernel/chr_drv/tty_ioctl.o | Bin 0 -> 10648 bytes os/os/linux/kernel/exec2.o | Bin 0 -> 15272 bytes os/os/linux/kernel/execve2.c | 359 ++++++++ os/os/linux/kernel/execve2.o | Bin 0 -> 15064 bytes os/os/linux/kernel/exit.c | 197 +++++ os/os/linux/kernel/exit.o | Bin 0 -> 11164 bytes os/os/linux/kernel/fork.c | 148 ++++ os/os/linux/kernel/fork.o | Bin 0 -> 9640 bytes os/os/linux/kernel/getdents.c | 96 ++ os/os/linux/kernel/getdents.o | Bin 0 -> 7672 bytes os/os/linux/kernel/kernel.o | Bin 0 -> 109562 bytes os/os/linux/kernel/math/Makefile | 43 + os/os/linux/kernel/math/math.a | Bin 0 -> 6628 bytes os/os/linux/kernel/math/math_emulate.c | 42 + os/os/linux/kernel/math/math_emulate.o | Bin 0 -> 6464 bytes os/os/linux/kernel/mktime.c | 58 ++ os/os/linux/kernel/mktime.o | Bin 0 -> 2872 bytes os/os/linux/kernel/panic.c | 24 + os/os/linux/kernel/panic.o | Bin 0 -> 5424 bytes os/os/linux/kernel/pipe2.c | 55 ++ os/os/linux/kernel/pipe2.o | Bin 0 -> 6280 bytes os/os/linux/kernel/printk.c | 41 + os/os/linux/kernel/printk.o | Bin 0 -> 2424 bytes os/os/linux/kernel/sched.c | 412 +++++++++ os/os/linux/kernel/sched.o | Bin 0 -> 22936 bytes os/os/linux/kernel/signal.c | 129 +++ os/os/linux/kernel/signal.o | Bin 0 -> 8960 bytes os/os/linux/kernel/sys.c | 299 +++++++ os/os/linux/kernel/sys.o | Bin 0 -> 13576 bytes os/os/linux/kernel/system_call.o | Bin 0 -> 2640 bytes os/os/linux/kernel/system_call.s | 298 +++++++ os/os/linux/kernel/traps.c | 208 +++++ os/os/linux/kernel/traps.o | Bin 0 -> 12972 bytes os/os/linux/kernel/vsprintf.c | 233 +++++ os/os/linux/kernel/vsprintf.o | Bin 0 -> 6156 bytes os/os/linux/lib/Makefile | 73 ++ os/os/linux/lib/_exit.c | 13 + os/os/linux/lib/_exit.o | Bin 0 -> 1988 bytes os/os/linux/lib/close.c | 10 + os/os/linux/lib/close.o | Bin 0 -> 2220 bytes os/os/linux/lib/ctype.c | 35 + os/os/linux/lib/ctype.o | Bin 0 -> 1908 bytes os/os/linux/lib/dup.c | 10 + os/os/linux/lib/dup.o | Bin 0 -> 2196 bytes os/os/linux/lib/errno.c | 7 + os/os/linux/lib/errno.o | Bin 0 -> 1472 bytes os/os/linux/lib/execve.c | 10 + os/os/linux/lib/execve.o | Bin 0 -> 2336 bytes os/os/linux/lib/lib.a | Bin 0 -> 34138 bytes os/os/linux/lib/malloc.c | 232 +++++ os/os/linux/lib/malloc.o | Bin 0 -> 4880 bytes os/os/linux/lib/open.c | 25 + os/os/linux/lib/open.o | Bin 0 -> 2364 bytes os/os/linux/lib/setsid.c | 10 + os/os/linux/lib/setsid.o | Bin 0 -> 2240 bytes os/os/linux/lib/string.c | 14 + os/os/linux/lib/string.o | Bin 0 -> 6380 bytes os/os/linux/lib/wait.c | 16 + os/os/linux/lib/wait.o | Bin 0 -> 2580 bytes os/os/linux/lib/write.c | 10 + os/os/linux/lib/write.o | Bin 0 -> 2372 bytes os/os/linux/mm/Makefile | 38 + os/os/linux/mm/memory.c | 468 ++++++++++ os/os/linux/mm/memory.o | Bin 0 -> 13816 bytes os/os/linux/mm/mm.o | Bin 0 -> 13936 bytes os/os/linux/mm/page.o | Bin 0 -> 640 bytes os/os/linux/mm/page.s | 40 + os/os/linux/myls.c | 24 + os/os/linux/tools/build | Bin 0 -> 15144 bytes os/os/linux/tools/build.c | 171 ++++ os/os/linux/tools/system | Bin 0 -> 306090 bytes 187 files changed, 16843 insertions(+) create mode 100644 os/os/linux/.vscode/settings.json create mode 100644 os/os/linux/Image create mode 100644 os/os/linux/Image.bkp create mode 100644 os/os/linux/Makefile create mode 100644 os/os/linux/System.map create mode 100644 os/os/linux/System.map.2 create mode 100644 os/os/linux/boot/bootsect create mode 100644 os/os/linux/boot/bootsect.o create mode 100644 os/os/linux/boot/bootsect.s create mode 100644 os/os/linux/boot/head.o create mode 100644 os/os/linux/boot/head.s create mode 100644 os/os/linux/boot/setup create mode 100644 os/os/linux/boot/setup.o create mode 100644 os/os/linux/boot/setup.s create mode 100644 os/os/linux/execve2.patch create mode 100644 os/os/linux/fs/Makefile create mode 100644 os/os/linux/fs/bitmap.c create mode 100644 os/os/linux/fs/bitmap.o create mode 100644 os/os/linux/fs/block_dev.c create mode 100644 os/os/linux/fs/block_dev.o create mode 100644 os/os/linux/fs/buffer.c create mode 100644 os/os/linux/fs/buffer.o create mode 100644 os/os/linux/fs/char_dev.c create mode 100644 os/os/linux/fs/char_dev.o create mode 100644 os/os/linux/fs/exec.c create mode 100644 os/os/linux/fs/exec.o create mode 100644 os/os/linux/fs/fcntl.c create mode 100644 os/os/linux/fs/fcntl.o create mode 100644 os/os/linux/fs/file_dev.c create mode 100644 os/os/linux/fs/file_dev.o create mode 100644 os/os/linux/fs/file_table.c create mode 100644 os/os/linux/fs/file_table.o create mode 100644 os/os/linux/fs/fs.o create mode 100644 os/os/linux/fs/inode.c create mode 100644 os/os/linux/fs/inode.o create mode 100644 os/os/linux/fs/ioctl.c create mode 100644 os/os/linux/fs/ioctl.o create mode 100644 os/os/linux/fs/namei.c create mode 100644 os/os/linux/fs/namei.o create mode 100644 os/os/linux/fs/open.c create mode 100644 os/os/linux/fs/open.o create mode 100644 os/os/linux/fs/pipe.c create mode 100644 os/os/linux/fs/pipe.o create mode 100644 os/os/linux/fs/read_write.c create mode 100644 os/os/linux/fs/read_write.o create mode 100644 os/os/linux/fs/select.c create mode 100644 os/os/linux/fs/select.o create mode 100644 os/os/linux/fs/stat.c create mode 100644 os/os/linux/fs/stat.o create mode 100644 os/os/linux/fs/super.c create mode 100644 os/os/linux/fs/super.o create mode 100644 os/os/linux/fs/truncate.c create mode 100644 os/os/linux/fs/truncate.o create mode 100644 os/os/linux/include/a.out.h create mode 100644 os/os/linux/include/asm/io.h create mode 100644 os/os/linux/include/asm/memory.h create mode 100644 os/os/linux/include/asm/segment.h create mode 100644 os/os/linux/include/asm/system.h create mode 100644 os/os/linux/include/const.h create mode 100644 os/os/linux/include/ctype.h create mode 100644 os/os/linux/include/errno.h create mode 100644 os/os/linux/include/fcntl.h create mode 100644 os/os/linux/include/linux/config.h create mode 100644 os/os/linux/include/linux/fdreg.h create mode 100644 os/os/linux/include/linux/fs.h create mode 100644 os/os/linux/include/linux/hdreg.h create mode 100644 os/os/linux/include/linux/head.h create mode 100644 os/os/linux/include/linux/kernel.h create mode 100644 os/os/linux/include/linux/mm.h create mode 100644 os/os/linux/include/linux/sched.h create mode 100644 os/os/linux/include/linux/sys.h create mode 100644 os/os/linux/include/linux/tty.h create mode 100644 os/os/linux/include/new0.h create mode 100644 os/os/linux/include/signal.h create mode 100644 os/os/linux/include/stdarg.h create mode 100644 os/os/linux/include/stddef.h create mode 100644 os/os/linux/include/string.h create mode 100644 os/os/linux/include/sys/stat.h create mode 100644 os/os/linux/include/sys/times.h create mode 100644 os/os/linux/include/sys/types.h create mode 100644 os/os/linux/include/sys/utsname.h create mode 100644 os/os/linux/include/sys/wait.h create mode 100644 os/os/linux/include/termios.h create mode 100644 os/os/linux/include/time.h create mode 100644 os/os/linux/include/unistd.h create mode 100644 os/os/linux/include/utime.h create mode 100644 os/os/linux/init/main.c create mode 100644 os/os/linux/init/main.o create mode 100644 os/os/linux/kernel/Makefile create mode 100644 os/os/linux/kernel/asm.o create mode 100644 os/os/linux/kernel/asm.s create mode 100644 os/os/linux/kernel/blk_drv/Makefile create mode 100644 os/os/linux/kernel/blk_drv/blk.h create mode 100644 os/os/linux/kernel/blk_drv/blk_drv.a create mode 100644 os/os/linux/kernel/blk_drv/floppy.c create mode 100644 os/os/linux/kernel/blk_drv/floppy.o create mode 100644 os/os/linux/kernel/blk_drv/hd.c create mode 100644 os/os/linux/kernel/blk_drv/hd.o create mode 100644 os/os/linux/kernel/blk_drv/ll_rw_blk.c create mode 100644 os/os/linux/kernel/blk_drv/ll_rw_blk.o create mode 100644 os/os/linux/kernel/blk_drv/ramdisk.c create mode 100644 os/os/linux/kernel/blk_drv/ramdisk.o create mode 100644 os/os/linux/kernel/chr_drv/Makefile create mode 100644 os/os/linux/kernel/chr_drv/chr_drv.a create mode 100644 os/os/linux/kernel/chr_drv/console.c create mode 100644 os/os/linux/kernel/chr_drv/console.o create mode 100644 os/os/linux/kernel/chr_drv/keyboard.2.o create mode 100644 os/os/linux/kernel/chr_drv/keyboard.2.s create mode 100644 os/os/linux/kernel/chr_drv/keyboard.S create mode 100644 os/os/linux/kernel/chr_drv/rs_io.o create mode 100644 os/os/linux/kernel/chr_drv/rs_io.s create mode 100644 os/os/linux/kernel/chr_drv/serial.c create mode 100644 os/os/linux/kernel/chr_drv/serial.o create mode 100644 os/os/linux/kernel/chr_drv/tty_io.c create mode 100644 os/os/linux/kernel/chr_drv/tty_io.o create mode 100644 os/os/linux/kernel/chr_drv/tty_ioctl.c create mode 100644 os/os/linux/kernel/chr_drv/tty_ioctl.o create mode 100644 os/os/linux/kernel/exec2.o create mode 100644 os/os/linux/kernel/execve2.c create mode 100644 os/os/linux/kernel/execve2.o create mode 100644 os/os/linux/kernel/exit.c create mode 100644 os/os/linux/kernel/exit.o create mode 100644 os/os/linux/kernel/fork.c create mode 100644 os/os/linux/kernel/fork.o create mode 100644 os/os/linux/kernel/getdents.c create mode 100644 os/os/linux/kernel/getdents.o create mode 100644 os/os/linux/kernel/kernel.o create mode 100644 os/os/linux/kernel/math/Makefile create mode 100644 os/os/linux/kernel/math/math.a create mode 100644 os/os/linux/kernel/math/math_emulate.c create mode 100644 os/os/linux/kernel/math/math_emulate.o create mode 100644 os/os/linux/kernel/mktime.c create mode 100644 os/os/linux/kernel/mktime.o create mode 100644 os/os/linux/kernel/panic.c create mode 100644 os/os/linux/kernel/panic.o create mode 100644 os/os/linux/kernel/pipe2.c create mode 100644 os/os/linux/kernel/pipe2.o create mode 100644 os/os/linux/kernel/printk.c create mode 100644 os/os/linux/kernel/printk.o create mode 100644 os/os/linux/kernel/sched.c create mode 100644 os/os/linux/kernel/sched.o create mode 100644 os/os/linux/kernel/signal.c create mode 100644 os/os/linux/kernel/signal.o create mode 100644 os/os/linux/kernel/sys.c create mode 100644 os/os/linux/kernel/sys.o create mode 100644 os/os/linux/kernel/system_call.o create mode 100644 os/os/linux/kernel/system_call.s create mode 100644 os/os/linux/kernel/traps.c create mode 100644 os/os/linux/kernel/traps.o create mode 100644 os/os/linux/kernel/vsprintf.c create mode 100644 os/os/linux/kernel/vsprintf.o create mode 100644 os/os/linux/lib/Makefile create mode 100644 os/os/linux/lib/_exit.c create mode 100644 os/os/linux/lib/_exit.o create mode 100644 os/os/linux/lib/close.c create mode 100644 os/os/linux/lib/close.o create mode 100644 os/os/linux/lib/ctype.c create mode 100644 os/os/linux/lib/ctype.o create mode 100644 os/os/linux/lib/dup.c create mode 100644 os/os/linux/lib/dup.o create mode 100644 os/os/linux/lib/errno.c create mode 100644 os/os/linux/lib/errno.o create mode 100644 os/os/linux/lib/execve.c create mode 100644 os/os/linux/lib/execve.o create mode 100644 os/os/linux/lib/lib.a create mode 100644 os/os/linux/lib/malloc.c create mode 100644 os/os/linux/lib/malloc.o create mode 100644 os/os/linux/lib/open.c create mode 100644 os/os/linux/lib/open.o create mode 100644 os/os/linux/lib/setsid.c create mode 100644 os/os/linux/lib/setsid.o create mode 100644 os/os/linux/lib/string.c create mode 100644 os/os/linux/lib/string.o create mode 100644 os/os/linux/lib/wait.c create mode 100644 os/os/linux/lib/wait.o create mode 100644 os/os/linux/lib/write.c create mode 100644 os/os/linux/lib/write.o create mode 100644 os/os/linux/mm/Makefile create mode 100644 os/os/linux/mm/memory.c create mode 100644 os/os/linux/mm/memory.o create mode 100644 os/os/linux/mm/mm.o create mode 100644 os/os/linux/mm/page.o create mode 100644 os/os/linux/mm/page.s create mode 100644 os/os/linux/myls.c create mode 100644 os/os/linux/tools/build create mode 100644 os/os/linux/tools/build.c create mode 100644 os/os/linux/tools/system diff --git a/os/os/linux/.vscode/settings.json b/os/os/linux/.vscode/settings.json new file mode 100644 index 0000000..be9f164 --- /dev/null +++ b/os/os/linux/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "files.associations": { + "*.json": "c", + "*.o": "plaintext", + "new.h": "c", + "new0.h": "c", + "errno.h": "c" + } +} \ No newline at end of file diff --git a/os/os/linux/Image b/os/os/linux/Image new file mode 100644 index 0000000000000000000000000000000000000000..62185d12845e99a4b3199211bbf903536613322b GIT binary patch literal 138404 zcmeEv3w%`7wfC7YApr(wlu<`J%AkV|b;PK#4K>K9X&Y_YMn$Dc6|cypma5f^XsaPO zq2@4#=6bQ$T3ey?VITHdr8VFy0ZOQk8tp@T)f6qAaj3Ow6)knX|9`E0&YTJ1Veh@) z@B4mtqRcsa@3q%nd+oK?-h1tJ_U`SgS+=>?>RHye#_~;hYfABr@4gbTte%@TE!(`T zZ`t4jR&lLmt*Nr^x2k&mRgX`&YAnLNmi73A!q$86Qv3LXpIKAweWv>a%j!{e#m7Ty zBG&yi)`K&Ay}k*LhkC8hvcBALR_+(p)RjAY(=97~;MDA)$WdFB`FpT!Y;P3L{o1Mu z?@e8`!}p41#d@kO{@v8~gJLlK-m%Z!)HmHqUFlmtb>(#5QKN6Q?Ed~gjPX5l)tI)L zWBaCT?$3?M)gy8glBS+Gdb%&YU$4(PYV>VZ+Fu-fyS3^z>)5_kw_42f=vDXJ)K^WC zj(x81{noS2I5T^|?N)Z5TdkA3ew#huHmmD*_gIU!SiaS$?UmK%edhdG>rr3S`tb=2 z6dpTs?dzlNwq8ANy=9Fb+j99ub3b?4zs9b*_Nul^z7U%_b?W%BBgA#qW+~Y>VkuPuuuqo2L|~ zytT∾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 Cri=yv literal 0 HcmV?d00001 diff --git a/os/os/linux/Makefile b/os/os/linux/Makefile new file mode 100644 index 0000000..ecbcf30 --- /dev/null +++ b/os/os/linux/Makefile @@ -0,0 +1,125 @@ +# +# 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 =as +LD =ld +LDFLAGS =-m elf_i386 -Ttext 0 -e startup_32 -Map=System.map.2 -N +CC =gcc -march=i386 $(RAMDISK) +CFLAGS =-w -g -fstrength-reduce -fomit-frame-pointer -fno-stack-protector -mcld +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= + +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) -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 + nm tools/system | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw]\)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort >System.map + +kernel/math/math.a: FORCE + (cd kernel/math; make) + +kernel/blk_drv/blk_drv.a: FORCE + (cd kernel/blk_drv; make) + +kernel/chr_drv/chr_drv.a: FORCE + (cd kernel/chr_drv; make) + +kernel/kernel.o: FORCE + (cd kernel; make) + +mm/mm.o: FORCE + (cd mm; make) + +fs/fs.o: FORCE + (cd fs; make) + +lib/lib.a: FORCE + (cd lib; make) + +FORCE: + +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 System.map.2 + rm -f 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) + +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 diff --git a/os/os/linux/System.map b/os/os/linux/System.map new file mode 100644 index 0000000..a25824e --- /dev/null +++ b/os/os/linux/System.map @@ -0,0 +1,598 @@ +00000000 T pg_dir +00000000 T startup_32 +0000005a t check_x87 +00000073 t setup_idt +00000090 t rp_sidt +000000a3 t setup_gdt +00001000 t pg0 +00002000 t pg1 +00003000 t pg2 +00004000 t pg3 +00005000 T tmp_floppy_area +00005412 t L6 +00005414 t int_msg +00005428 t ignore_int +00005450 t setup_paging +000054ae t idt_descr +000054b6 t gdt_descr +000054c0 T idt +00005cc0 T gdt +000064c0 T fork +000064ef T pause +0000651e T setup +00006555 T sync +00006584 t time_init +00006799 T main +0000690c t printf +0000695b T init +00006bd3 T print_nr +00006c04 T show_task +00006c89 T show_stat +00006ccf T math_state_restore +00006d2d T schedule +00006edf T sys_pause +00006ef5 T sleep_on +00006f54 T interruptible_sleep_on +0000700f T ticks_to_floppy_on +000070da T floppy_on +00007109 T floppy_off +00007119 T do_floppy_timer +00007311 T do_timer +00007400 T sys_alarm +0000747f T sys_getpid +0000748b T sys_getppid +00007497 T sys_getuid +000074a6 T sys_geteuid +000074b6 T sys_getgid +000074c6 T sys_getegid +000074d5 T sys_nice +00007500 T sched_init +00007690 t bad_sys_call +00007698 t reschedule +000076a4 T system_call +000076df t ret_from_sys_call +00007728 T coprocessor_error +0000774a T device_not_available +00007784 T timer_interrupt +000077bc T sys_execve +000077cc T sys_execve2 +000077dc T sys_fork +000077f4 T hd_interrupt +00007830 T floppy_interrupt +00007866 T parallel_interrupt +0000786d t _get_base +0000789f t die +00007a81 T do_double_fault +00007aa4 T do_general_protection +00007ac7 T do_divide_error +00007aea T do_int3 +00007bb2 T do_nmi +00007bd5 T do_debug +00007bf8 T do_overflow +00007c1b T do_bounds +00007c3e T do_invalid_op +00007c61 T do_device_not_available +00007c84 T do_coprocessor_segment_overrun +00007ca7 T do_invalid_TSS +00007cca T do_segment_not_present +00007ced T do_stack_segment +00007d10 T do_coprocessor_error +00007d44 T do_reserved +00007d67 T trap_init +0000804b T divide_error +00008050 t no_error_code +00008080 T debug +00008087 T nmi +0000808e T int3 +00008095 T overflow +0000809c T bounds +000080a3 T invalid_op +000080aa T coprocessor_segment_overrun +000080b1 T reserved +000080b8 T irq13 +000080cd T double_fault +000080d2 t error_code +00008104 T invalid_TSS +0000810b T segment_not_present +00008112 T stack_segment +00008119 T general_protection +00008120 t _get_base +00008152 T verify_area +000081b9 T copy_mem +00008313 T copy_process +000087c0 T find_empty_process +00008854 T panic +0000888f t put_fs_long +0000889b T sys_pipe2 +00008aa8 T printk +00008af9 t skip_atoi +00008b54 t number +00008dc5 T vsprintf +00009251 t get_fs_long +00009267 t put_fs_byte +0000927f t put_fs_long +0000928b T sys_ftime +00009291 T sys_break +00009297 T sys_ptrace +0000929d T sys_stty +000092a3 T sys_gtty +000092a9 T sys_rename +000092af T sys_prof +000092b5 T sys_setregid +0000936e T sys_setgid +00009405 T sys_acct +0000940b T sys_phys +00009411 T sys_lock +00009417 T sys_mpx +0000941d T sys_ulimit +00009423 T sys_time +0000947f T sys_setreuid +00009561 T sys_setuid +000095f6 T sys_stime +0000964c T sys_times +000096ec T sys_brk +0000972e T sys_setpgid +00009807 T sys_getpgrp +00009813 T sys_setsid +0000988d T sys_getgroups +00009893 T sys_setgroups +00009899 T sys_uname +00009902 T sys_sethostname +00009908 T sys_getrlimit +0000990e T sys_setrlimit +00009914 T sys_getrusage +0000991a T sys_gettimeofday +00009920 T sys_settimeofday +00009926 T sys_umask +00009959 T sys_sleep +00009992 t _get_base +000099c4 t get_fs_byte +000099d2 t get_fs_long +000099e8 t put_fs_byte +00009a00 t put_fs_long +00009a0c t get_fs +00009a20 t get_ds +00009a34 t set_fs +00009a3b t create_tables +00009b86 t count +00009bc5 t copy_strings +00009d81 t change_ldt +00009f04 T do_execve2 +0000a9d6 t _get_base +0000aa08 t put_fs_long +0000aa14 T release +0000aa78 t send_sig +0000aaf7 t kill_session +0000ab51 T sys_kill +0000ad01 t tell_father +0000ad8b T do_exit +0000afbf T sys_exit +0000afd8 T sys_waitpid +0000b1fe t get_fs_byte +0000b20c t put_fs_byte +0000b224 t put_fs_long +0000b230 T sys_sgetmask +0000b23c T sys_ssetmask +0000b268 T sys_sigpending +0000b26e T sys_sigsuspend +0000b274 t save_old +0000b2c7 t get_new +0000b307 T sys_signal +0000b38b T sys_sigaction +0000b495 T do_signal +0000b681 T kernel_mktime +0000b7c6 t put_fs_byte +0000b7de T sys_getdents +0000b921 T sys_getcwd +0000baf0 t oom +0000bb0f T get_free_page +0000bb4b T free_page +0000bbba T free_page_tables +0000bcb9 T copy_page_tables +0000be3a T put_page +0000bf26 T un_wp_page +0000bfde T do_wp_page +0000c069 T get_empty_page +0000c0a9 t try_to_share +0000c23b t share_page +0000c2ef T do_no_page +0000c484 T do_no_pagex +0000c5e6 T mem_init +0000c65a T calc_mem +0000c74f T page_fault +0000c786 t get_fs_long +0000c79c T sys_ustat +0000c7a2 T sys_utime +0000c84f T sys_access +0000c92b T sys_chdir +0000c99f T sys_chroot +0000ca13 T sys_chmod +0000caad T sys_chown +0000cb28 T sys_open +0000cdcb T sys_creat +0000cdee T sys_close +0000cebd T sys_lseek +0000cfd4 T sys_read +0000d1c7 T sys_write +0000d375 t lock_inode +0000d3a2 t unlock_inode +0000d3c0 T invalidate_inodes +0000d42f T sync_inodes +0000d486 t _bmap +0000d872 T bmap +0000d895 T create_block +0000d8b8 T iput +0000da27 T get_empty_inode +0000db7c T get_pipe_inode +0000dbf1 T iget +0000ddb6 t read_inode +0000dfec T sys_sync +0000e04f T sync_dev +0000e148 T invalidate_buffers +0000e1ba T check_disk_change +0000e264 t remove_from_queues +0000e35b t insert_into_queues +0000e420 t find_buffer +0000e488 T get_hash_table +0000e50a T getblk +0000e6a8 T brelse +0000e6f1 T bread +0000e776 T bread_page +0000e898 T breada +0000e98d T buffer_init +0000eabc t lock_super +0000eae9 t free_super +0000eb2e T get_super +0000eb9d T put_super +0000ec70 t read_super +0000efb3 T sys_umount +0000f114 T sys_mount +0000f285 T mount_root +0000f493 t get_fs_byte +0000f4a1 t put_fs_byte +0000f4b9 T block_write +0000f60b T block_read +0000f736 t get_fs_byte +0000f744 t put_fs_byte +0000f75c t rw_ttyx +0000f7a4 t rw_tty +0000f7f4 t rw_ram +0000f7fa t rw_mem +0000f800 t rw_kmem +0000f806 t rw_port +0000f8a0 t rw_memory +0000f976 T rw_char +0000f9e0 t get_fs_byte +0000f9ee t put_fs_byte +0000fa06 T file_read +0000fbb1 T file_write +0000fdab t put_fs_byte +0000fdc3 t cp_stat +0000fe9a T sys_stat +0000fee4 T sys_lstat +0000feff T sys_fstat +0000ff5c T sys_readlink +0000ff62 t _get_base +0000ff94 t get_fs_byte +0000ffa2 t get_fs_long +0000ffb8 t put_fs_byte +0000ffd0 t put_fs_long +0000ffdc t get_fs +0000fff0 t get_ds +00010004 t set_fs +0001000b T sys_uselib +00010011 t create_tables +0001015c t count +0001019b t copy_strings +00010357 t change_ldt +000104da T do_execve +00010f5c t get_fs_byte +00010f6a t put_fs_byte +00010f82 t put_fs_long +00010f8e T read_pipe +00011263 T sys_pipe +00011465 t get_fs_byte +00011473 t permission +00011514 t match +0001157c t find_entry +000119d6 t get_dir +00011bc3 t dir_namei +00011c42 T namei +00011d58 T open_namei +000120ab T sys_mknod +000122db T sys_mkdir +0001268c t empty_dir +0001286a T sys_rmdir +00012bc2 T sys_unlink +00012e63 T sys_symlink +00012e69 T sys_link +000130c3 T free_block +00013235 T new_block +000133d9 T free_inode +00013540 T new_inode +0001371a t dupfd +000137f4 T sys_dup2 +0001381b T sys_dup +00013836 T sys_fcntl +00013975 T sys_ioctl +00013a46 t free_ind +00013ae5 t free_dind +00013b84 T truncate +00013cb9 T sys_select +00013cbf t lock_buffer +00013cec t unlock_buffer +00013ede t make_request +00014082 T ll_rw_block +000140db T blk_dev_init +00014129 t unlock_buffer +0001415e t end_request +0001420f T floppy_deselect +00014246 T floppy_change +000142cc t setup_DMA +00014382 t output_byte +000143f8 t result +000144b5 t bad_flp_intr +00014514 t rw_interrupt +00014603 T setup_rw_floppy +000146c4 t seek_interrupt +0001471d t transfer +00014852 t recal_interrupt +0001489c T unexpected_floppy_interrupt +000148e1 t recalibrate_floppy +00014943 t reset_interrupt +00014988 t reset_floppy +00014a05 t floppy_on_interrupt +00014a70 t do_fd_request +00014c74 T floppy_init +00014cc6 t unlock_buffer +00014cfb t end_request +00014d9a T sys_setup +0001514d t controller_ready +000151e1 t hd_out +000152ce t drive_busy +00015334 t reset_controller +000153b1 t reset_hd +00015449 T unexpected_hd_interrupt +0001545c t bad_rw_intr +0001549a t read_intr +000155c0 t recal_intr +000155da t do_hd_request +000158db T hd_init +00015955 t unlock_buffer +0001598a t end_request +00015a29 t do_rd_request +00015b5f T rd_init +00015bb5 T rd_load +00015e61 t get_fs_byte +00015e6f t put_fs_byte +00015e87 T tty_init +00015e98 T tty_intr +00015f0c t sleep_if_empty +00015f44 t sleep_if_full +00015fb8 T copy_to_cooked +00016573 T tty_read +000168e1 T tty_write +00016af3 T do_tty_interrupt +00016b1b T chr_dev_init +00016b1c t gotoxy +00016b6a t set_origin +00016bd0 t scrup +00016dc0 t scrdown +00016eb7 t lf +00016eed t ri +00016f23 t cr +00016f44 t del +00016f76 t csi_J +00017007 t csi_K +000170b9 T csi_m +00017120 t set_cursor +00017186 t respond +000171de t insert_char +00017241 t insert_line +00017285 t delete_char +000172e3 t delete_line +00017327 t csi_at +00017365 t csi_L +000173a3 t csi_P +000173e1 t csi_M +0001741f t save_cur +00017434 t restore_cur +00017453 T con_write +00017ae1 T con_init +00017d18 T sysbeepstop +00017d41 t sysbeep +00017d9f t mode +00017da0 t leds +00017da1 t e0 +00017da2 T keyboard_interrupt +00017dcb t e0_e1 +00017df6 t set_e0 +00017dff t set_e1 +00017e08 t put_queue +00017e41 t ctrl +00017e59 t unctrl +00017e5d t unalt +00017e73 t lshift +00017e7b t unlshift +00017e83 t rshift +00017e8b t unrshift +00017e93 t caps +00017eb5 t set_leds +00017ecb t uncaps +00017ed3 t scroll +00017edc t num +00017ee5 t cursor +00017f05 t cur2 +00017f2e t cur +00017f3a t ok_cur +00017f48 t num_table +00017f55 t cur_table +00017f62 t func +00017f7f t ok_func +00017f92 t end_func +00017f93 t func_table +00017fc3 t key_map +00018024 t shift_map +000180e6 t do_self +0001814e t none +0001814f t minus +00018164 t key_table +00018564 t kb_wait +0001856d t reboot +0001857f t die +00018581 t init +000185f6 T rs_init +00018679 T rs_write +000186c8 T rs1_interrupt +000186d0 T rs2_interrupt +000186d5 t rs_int +000186ec t rep_int +00018709 t end +00018717 t jmp_table +00018728 t modem_status +00018730 t line_status +00018738 t read_char +000187bf t get_fs_byte +000187cd t get_fs_long +000187e3 t put_fs_byte +000187fb t put_fs_long +00018807 t change_speed +00018885 t flush +00018897 t send_break +00018898 t get_termios +000188f4 t set_termios +00018944 t get_termio +00018a0c t set_termio +00018ad0 T tty_ioctl +00018dce t get_fs_byte +00018ddc T math_emulate +00018ebf T math_error +00018edf T _exit +00018eef T open +00018f38 T close +00018fac T dup +00018fe3 T setsid +00019012 T execve +000190af T strcpy +000190cb T strncpy +000190f0 T strcat +0001911b T strncat +00019150 T strcmp +00019177 T strncmp +000191a5 T strchr +000191d2 T strrchr +00019201 T strspn +0001923e T strcspn +0001927b T strpbrk +000192b2 T strstr +000192eb T strlen +0001930e T strtok +00019391 T memcpy +000193b1 T memmove +00019405 T memcmp +0001942f T memchr +00019467 T memset +0001d5e8 d envp_rc +0001d5fc d envp +0001d620 D sys_call_table +0001d790 D NR_syscalls +0001d7a0 d init_task +0001e7a0 D current +0001e7c0 D task +0001e8c0 D stack_start +0001e8c8 D current_DOR +0001e8e0 d thisname.1955 +0001e920 d month +0001e960 d last_inode.1935 +0001e964 D start_buffer +0001e980 d crw_table +0001e9a0 d ioctl_table +0001e9c0 d floppy_type +0001ea80 d cur_spec1 +0001ea84 d cur_rate +0001ea88 d floppy +0001ea8c d current_track +0001ea90 d callable.1844 +0001eaa0 D tty_table +00020fc0 D table_list +00020fe0 d quotient +00021000 D _ctype +00021101 B __bss_start +00021101 D _edata +00021120 b printbuf +00021520 b memory_end +00021524 b buffer_memory_end +00021528 b main_memory_start +00021540 B jiffies +00021544 B startup_time +00021548 B last_task_used_math +0002155c b mon_timer +0002156c b moff_timer +00021580 b timer_list +00021880 b next_timer +00021884 B last_pid +000218a0 b buf +00021ca0 b HIGH_MEMORY +00021cc0 b mem_map +00022bc0 B inode_table +000232c0 B nr_buffers +000232c4 b free_list +000232c8 b buffer_wait +000232cc B ROOT_DEV +00023300 B blk_dev +00023338 B do_floppy +0002333c B selected +00023344 b recalibrate +00023348 b reset +0002334c b seek +00023350 b reply_buffer +00023357 b current_drive +00023358 b sector +00023359 b head +0002335a b track +0002335b b seek_track +0002335c b command +00023360 B do_hd +00023380 B hd_info +000233b0 b recalibrate +000233b4 b reset +000233b8 b NR_HD +000233c0 b hd +00023410 B rd_length +00023414 b cr_flag.1923 +00023420 B beepcount +00023424 b video_type +00023428 b video_num_columns +0002342c b video_size_row +00023430 b video_num_lines +00023434 b video_page +00023438 b video_mem_start +0002343c b video_mem_end +00023440 b video_port_reg +00023442 b video_port_val +00023444 b video_erase_char +00023448 b origin +0002344c b scr_end +00023450 b pos +00023454 b x +00023458 b y +0002345c b top +00023460 b bottom +00023464 b state +00023468 b npar +00023480 b par +000234c0 b ques +000234c4 b saved_x +000234c8 b saved_y +000234e0 B drive_info +00023500 B user_stack +00024500 B hash_table +000249e0 B super_block +00024d40 B file_table +00025140 B request +000255c0 B rd_start +000255c4 B _ctmp +000255c8 B errno +000255cc B ___strtok +000255d0 B end +000255d0 B _end diff --git a/os/os/linux/System.map.2 b/os/os/linux/System.map.2 new file mode 100644 index 0000000..f550302 --- /dev/null +++ b/os/os/linux/System.map.2 @@ -0,0 +1,1082 @@ +Archive member included to satisfy reference by file (symbol) + +kernel/blk_drv/blk_drv.a(ll_rw_blk.o) + fs/fs.o (ll_rw_block) +kernel/blk_drv/blk_drv.a(floppy.o) + kernel/kernel.o (do_floppy) +kernel/blk_drv/blk_drv.a(hd.o) + kernel/kernel.o (do_hd) +kernel/blk_drv/blk_drv.a(ramdisk.o) + kernel/blk_drv/blk_drv.a(hd.o) (rd_load) +kernel/chr_drv/chr_drv.a(tty_io.o) + kernel/kernel.o (tty_table) +kernel/chr_drv/chr_drv.a(console.o) + kernel/chr_drv/chr_drv.a(tty_io.o) (con_write) +kernel/chr_drv/chr_drv.a(keyboard.2.o) + kernel/chr_drv/chr_drv.a(console.o) (keyboard_interrupt) +kernel/chr_drv/chr_drv.a(serial.o) + kernel/chr_drv/chr_drv.a(tty_io.o) (rs_init) +kernel/chr_drv/chr_drv.a(rs_io.o) + kernel/chr_drv/chr_drv.a(serial.o) (rs1_interrupt) +kernel/chr_drv/chr_drv.a(tty_ioctl.o) + fs/fs.o (tty_ioctl) +kernel/math/math.a(math_emulate.o) + kernel/kernel.o (math_emulate) +lib/lib.a(ctype.o) kernel/chr_drv/chr_drv.a(tty_io.o) (_ctmp) +lib/lib.a(_exit.o) init/main.o (_exit) +lib/lib.a(open.o) init/main.o (open) +lib/lib.a(close.o) init/main.o (close) +lib/lib.a(errno.o) init/main.o (errno) +lib/lib.a(write.o) init/main.o (write) +lib/lib.a(dup.o) init/main.o (dup) +lib/lib.a(setsid.o) init/main.o (setsid) +lib/lib.a(execve.o) init/main.o (execve) +lib/lib.a(wait.o) init/main.o (wait) +lib/lib.a(string.o) kernel/kernel.o (strncpy) + +分配公共符号 +公共符号 大小 文件 + +errno 0x4 lib/lib.a(errno.o) +hash_table 0x4cc fs/fs.o +___strtok 0x4 lib/lib.a(string.o) +rd_start 0x4 kernel/blk_drv/blk_drv.a(ramdisk.o) +request 0x480 kernel/blk_drv/blk_drv.a(ll_rw_blk.o) +user_stack 0x1000 kernel/kernel.o +_ctmp 0x1 lib/lib.a(ctype.o) +super_block 0x360 fs/fs.o +drive_info 0x20 init/main.o +file_table 0x400 fs/fs.o + +Discarded input sections + + .note.GNU-stack + 0x0000000000000000 0x0 init/main.o + .note.GNU-stack + 0x0000000000000000 0x0 kernel/kernel.o + .note.GNU-stack + 0x0000000000000000 0x0 mm/mm.o + .note.GNU-stack + 0x0000000000000000 0x0 fs/fs.o + .note.GNU-stack + 0x0000000000000000 0x0 kernel/blk_drv/blk_drv.a(ll_rw_blk.o) + .note.GNU-stack + 0x0000000000000000 0x0 kernel/blk_drv/blk_drv.a(floppy.o) + .note.GNU-stack + 0x0000000000000000 0x0 kernel/blk_drv/blk_drv.a(hd.o) + .note.GNU-stack + 0x0000000000000000 0x0 kernel/blk_drv/blk_drv.a(ramdisk.o) + .note.GNU-stack + 0x0000000000000000 0x0 kernel/chr_drv/chr_drv.a(tty_io.o) + .note.GNU-stack + 0x0000000000000000 0x0 kernel/chr_drv/chr_drv.a(console.o) + .note.GNU-stack + 0x0000000000000000 0x0 kernel/chr_drv/chr_drv.a(serial.o) + .note.GNU-stack + 0x0000000000000000 0x0 kernel/chr_drv/chr_drv.a(tty_ioctl.o) + .note.GNU-stack + 0x0000000000000000 0x0 kernel/math/math.a(math_emulate.o) + .note.GNU-stack + 0x0000000000000000 0x0 lib/lib.a(ctype.o) + .note.GNU-stack + 0x0000000000000000 0x0 lib/lib.a(_exit.o) + .note.GNU-stack + 0x0000000000000000 0x0 lib/lib.a(open.o) + .note.GNU-stack + 0x0000000000000000 0x0 lib/lib.a(close.o) + .note.GNU-stack + 0x0000000000000000 0x0 lib/lib.a(errno.o) + .note.GNU-stack + 0x0000000000000000 0x0 lib/lib.a(write.o) + .note.GNU-stack + 0x0000000000000000 0x0 lib/lib.a(dup.o) + .note.GNU-stack + 0x0000000000000000 0x0 lib/lib.a(setsid.o) + .note.GNU-stack + 0x0000000000000000 0x0 lib/lib.a(execve.o) + .note.GNU-stack + 0x0000000000000000 0x0 lib/lib.a(wait.o) + .note.GNU-stack + 0x0000000000000000 0x0 lib/lib.a(string.o) + +内存配置 + +名称 来源 长度 属性 +*default* 0x0000000000000000 0xffffffffffffffff + +Linker script and memory map + +段 .text 的地址设置为 0x0 +LOAD boot/head.o +LOAD init/main.o +LOAD kernel/kernel.o +LOAD mm/mm.o +LOAD fs/fs.o +LOAD kernel/blk_drv/blk_drv.a +LOAD kernel/chr_drv/chr_drv.a +LOAD kernel/math/math.a +LOAD lib/lib.a + 0x0000000008048000 PROVIDE (__executable_start, 0x8048000) + 0x0000000008048074 . = (0x8048000 + SIZEOF_HEADERS) + +.interp + *(.interp) + +.note.gnu.build-id + *(.note.gnu.build-id) + +.hash + *(.hash) + +.gnu.hash + *(.gnu.hash) + +.dynsym + *(.dynsym) + +.dynstr + *(.dynstr) + +.gnu.version + *(.gnu.version) + +.gnu.version_d + *(.gnu.version_d) + +.gnu.version_r + *(.gnu.version_r) + +.rel.init + *(.rel.init) + +.rel.text 0x0000000008048074 0x0 + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + .rel.text 0x0000000000000000 0x0 boot/head.o + +.rel.fini + *(.rel.fini) + +.rel.rodata + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + +.rel.data.rel.ro + *(.rel.data.rel.ro .rel.data.rel.ro.* .rel.gnu.linkonce.d.rel.ro.*) + +.rel.data 0x0000000008048074 0x0 + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + .rel.data 0x0000000000000000 0x0 boot/head.o + +.rel.tdata + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + +.rel.tbss + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + +.rel.ctors + *(.rel.ctors) + +.rel.dtors + *(.rel.dtors) + +.rel.got + *(.rel.got) + +.rel.bss + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + +.rel.ifunc + *(.rel.ifunc) + +.rel.plt 0x0000000008048074 0x0 + *(.rel.plt) + 0x0000000008048074 PROVIDE (__rel_iplt_start, .) + *(.rel.iplt) + .rel.iplt 0x0000000000000000 0x0 boot/head.o + 0x0000000008048074 PROVIDE (__rel_iplt_end, .) + +.init + *(SORT(.init)) + +.plt 0x0000000008048080 0x0 + *(.plt) + *(.iplt) + .iplt 0x0000000000000000 0x0 boot/head.o + +.text 0x0000000000000000 0x1948b + *(.text.unlikely .text.*_unlikely .text.unlikely.*) + *(.text.exit .text.exit.*) + *(.text.startup .text.startup.*) + *(.text.hot .text.hot.*) + *(.text .stub .text.* .gnu.linkonce.t.*) + .text 0x0000000000000000 0x64c0 boot/head.o + 0x0000000000000000 startup_32 + 0x0000000000000000 pg_dir + 0x0000000000005000 tmp_floppy_area + 0x00000000000054c0 idt + 0x0000000000005cc0 gdt + .text 0x00000000000064c0 0x744 init/main.o + 0x00000000000064c0 fork + 0x00000000000064ef pause + 0x000000000000651e setup + 0x0000000000006555 sync + 0x0000000000006799 main + 0x000000000000695b init + 0x0000000000006bd3 print_nr + .text 0x0000000000006c04 0x4eec kernel/kernel.o + 0x0000000000006c04 show_task + 0x0000000000006c89 show_stat + 0x0000000000006ccf math_state_restore + 0x0000000000006d2d schedule + 0x0000000000006edf sys_pause + 0x0000000000006ef5 sleep_on + 0x0000000000006f54 interruptible_sleep_on + 0x0000000000006fe7 wake_up + 0x000000000000700f ticks_to_floppy_on + 0x00000000000070da floppy_on + 0x0000000000007109 floppy_off + 0x0000000000007119 do_floppy_timer + 0x00000000000071ed add_timer + 0x0000000000007311 do_timer + 0x0000000000007400 sys_alarm + 0x000000000000747f sys_getpid + 0x000000000000748b sys_getppid + 0x0000000000007497 sys_getuid + 0x00000000000074a6 sys_geteuid + 0x00000000000074b6 sys_getgid + 0x00000000000074c6 sys_getegid + 0x00000000000074d5 sys_nice + 0x0000000000007500 sched_init + 0x00000000000076a4 system_call + 0x0000000000007728 coprocessor_error + 0x000000000000774a device_not_available + 0x0000000000007784 timer_interrupt + 0x00000000000077bc sys_execve + 0x00000000000077cc sys_execve2 + 0x00000000000077dc sys_fork + 0x00000000000077f4 hd_interrupt + 0x0000000000007830 floppy_interrupt + 0x0000000000007866 parallel_interrupt + 0x0000000000007a81 do_double_fault + 0x0000000000007aa4 do_general_protection + 0x0000000000007ac7 do_divide_error + 0x0000000000007aea do_int3 + 0x0000000000007bb2 do_nmi + 0x0000000000007bd5 do_debug + 0x0000000000007bf8 do_overflow + 0x0000000000007c1b do_bounds + 0x0000000000007c3e do_invalid_op + 0x0000000000007c61 do_device_not_available + 0x0000000000007c84 do_coprocessor_segment_overrun + 0x0000000000007ca7 do_invalid_TSS + 0x0000000000007cca do_segment_not_present + 0x0000000000007ced do_stack_segment + 0x0000000000007d10 do_coprocessor_error + 0x0000000000007d44 do_reserved + 0x0000000000007d67 trap_init + 0x000000000000804b divide_error + 0x0000000000008080 debug + 0x0000000000008087 nmi + 0x000000000000808e int3 + 0x0000000000008095 overflow + 0x000000000000809c bounds + 0x00000000000080a3 invalid_op + 0x00000000000080aa coprocessor_segment_overrun + 0x00000000000080b1 reserved + 0x00000000000080b8 irq13 + 0x00000000000080cd double_fault + 0x0000000000008104 invalid_TSS + 0x000000000000810b segment_not_present + 0x0000000000008112 stack_segment + 0x0000000000008119 general_protection + 0x0000000000008152 verify_area + 0x00000000000081b9 copy_mem + 0x0000000000008313 copy_process + 0x00000000000087c0 find_empty_process + 0x0000000000008854 panic + 0x000000000000889b sys_pipe2 + 0x0000000000008aa8 printk + 0x0000000000008dc5 vsprintf + 0x000000000000928b sys_ftime + 0x0000000000009291 sys_break + 0x0000000000009297 sys_ptrace + 0x000000000000929d sys_stty + 0x00000000000092a3 sys_gtty + 0x00000000000092a9 sys_rename + 0x00000000000092af sys_prof + 0x00000000000092b5 sys_setregid + 0x000000000000936e sys_setgid + 0x0000000000009405 sys_acct + 0x000000000000940b sys_phys + 0x0000000000009411 sys_lock + 0x0000000000009417 sys_mpx + 0x000000000000941d sys_ulimit + 0x0000000000009423 sys_time + 0x000000000000947f sys_setreuid + 0x0000000000009561 sys_setuid + 0x00000000000095f6 sys_stime + 0x000000000000964c sys_times + 0x00000000000096ec sys_brk + 0x000000000000972e sys_setpgid + 0x0000000000009807 sys_getpgrp + 0x0000000000009813 sys_setsid + 0x000000000000988d sys_getgroups + 0x0000000000009893 sys_setgroups + 0x0000000000009899 sys_uname + 0x0000000000009902 sys_sethostname + 0x0000000000009908 sys_getrlimit + 0x000000000000990e sys_setrlimit + 0x0000000000009914 sys_getrusage + 0x000000000000991a sys_gettimeofday + 0x0000000000009920 sys_settimeofday + 0x0000000000009926 sys_umask + 0x0000000000009959 sys_sleep + 0x0000000000009f04 do_execve2 + 0x000000000000aa14 release + 0x000000000000ab51 sys_kill + 0x000000000000ad8b do_exit + 0x000000000000afbf sys_exit + 0x000000000000afd8 sys_waitpid + 0x000000000000b230 sys_sgetmask + 0x000000000000b23c sys_ssetmask + 0x000000000000b268 sys_sigpending + 0x000000000000b26e sys_sigsuspend + 0x000000000000b307 sys_signal + 0x000000000000b38b sys_sigaction + 0x000000000000b495 do_signal + 0x000000000000b681 kernel_mktime + 0x000000000000b7de sys_getdents + 0x000000000000b921 sys_getcwd + .text 0x000000000000baf0 0xc96 mm/mm.o + 0x000000000000bb0f get_free_page + 0x000000000000bb4b free_page + 0x000000000000bbba free_page_tables + 0x000000000000bcb9 copy_page_tables + 0x000000000000be3a put_page + 0x000000000000bf26 un_wp_page + 0x000000000000bfde do_wp_page + 0x000000000000c010 write_verify + 0x000000000000c069 get_empty_page + 0x000000000000c2ef do_no_page + 0x000000000000c484 do_no_pagex + 0x000000000000c5e6 mem_init + 0x000000000000c65a calc_mem + 0x000000000000c74f page_fault + .text 0x000000000000c786 0x7539 fs/fs.o + 0x000000000000c79c sys_ustat + 0x000000000000c7a2 sys_utime + 0x000000000000c84f sys_access + 0x000000000000c92b sys_chdir + 0x000000000000c99f sys_chroot + 0x000000000000ca13 sys_chmod + 0x000000000000caad sys_chown + 0x000000000000cb28 sys_open + 0x000000000000cdcb sys_creat + 0x000000000000cdee sys_close + 0x000000000000cebd sys_lseek + 0x000000000000cfd4 sys_read + 0x000000000000d1c7 sys_write + 0x000000000000d3c0 invalidate_inodes + 0x000000000000d42f sync_inodes + 0x000000000000d872 bmap + 0x000000000000d895 create_block + 0x000000000000d8b8 iput + 0x000000000000da27 get_empty_inode + 0x000000000000db7c get_pipe_inode + 0x000000000000dbf1 iget + 0x000000000000dfec sys_sync + 0x000000000000e04f sync_dev + 0x000000000000e148 invalidate_buffers + 0x000000000000e1ba check_disk_change + 0x000000000000e488 get_hash_table + 0x000000000000e50a getblk + 0x000000000000e6a8 brelse + 0x000000000000e6f1 bread + 0x000000000000e776 bread_page + 0x000000000000e898 breada + 0x000000000000e98d buffer_init + 0x000000000000eb2e get_super + 0x000000000000eb9d put_super + 0x000000000000efb3 sys_umount + 0x000000000000f114 sys_mount + 0x000000000000f285 mount_root + 0x000000000000f4b9 block_write + 0x000000000000f60b block_read + 0x000000000000f976 rw_char + 0x000000000000fa06 file_read + 0x000000000000fbb1 file_write + 0x000000000000fe9a sys_stat + 0x000000000000fee4 sys_lstat + 0x000000000000feff sys_fstat + 0x000000000000ff5c sys_readlink + 0x000000000001000b sys_uselib + 0x00000000000104da do_execve + 0x0000000000010f8e read_pipe + 0x00000000000110e4 write_pipe + 0x0000000000011263 sys_pipe + 0x0000000000011c42 namei + 0x0000000000011d58 open_namei + 0x00000000000120ab sys_mknod + 0x00000000000122db sys_mkdir + 0x000000000001286a sys_rmdir + 0x0000000000012bc2 sys_unlink + 0x0000000000012e63 sys_symlink + 0x0000000000012e69 sys_link + 0x00000000000130c3 free_block + 0x0000000000013235 new_block + 0x00000000000133d9 free_inode + 0x0000000000013540 new_inode + 0x00000000000137f4 sys_dup2 + 0x000000000001381b sys_dup + 0x0000000000013836 sys_fcntl + 0x0000000000013975 sys_ioctl + 0x0000000000013b84 truncate + 0x0000000000013cb9 sys_select + .text 0x0000000000013cbf 0x46a kernel/blk_drv/blk_drv.a(ll_rw_blk.o) + 0x0000000000014082 ll_rw_block + 0x00000000000140db blk_dev_init + .text 0x0000000000014129 0xb9d kernel/blk_drv/blk_drv.a(floppy.o) + 0x000000000001420f floppy_deselect + 0x0000000000014246 floppy_change + 0x0000000000014603 setup_rw_floppy + 0x000000000001489c unexpected_floppy_interrupt + 0x0000000000014c74 floppy_init + .text 0x0000000000014cc6 0xc8f kernel/blk_drv/blk_drv.a(hd.o) + 0x0000000000014d9a sys_setup + 0x0000000000015449 unexpected_hd_interrupt + 0x00000000000158db hd_init + .text 0x0000000000015955 0x50c kernel/blk_drv/blk_drv.a(ramdisk.o) + 0x0000000000015b5f rd_init + 0x0000000000015bb5 rd_load + .text 0x0000000000015e61 0xcbb kernel/chr_drv/chr_drv.a(tty_io.o) + 0x0000000000015e87 tty_init + 0x0000000000015e98 tty_intr + 0x0000000000015fa5 wait_for_keypress + 0x0000000000015fb8 copy_to_cooked + 0x0000000000016573 tty_read + 0x00000000000168e1 tty_write + 0x0000000000016af3 do_tty_interrupt + 0x0000000000016b1b chr_dev_init + .text 0x0000000000016b1c 0x1283 kernel/chr_drv/chr_drv.a(console.o) + 0x00000000000170b9 csi_m + 0x0000000000017453 con_write + 0x0000000000017ae1 con_init + 0x0000000000017d18 sysbeepstop + .text 0x0000000000017d9f 0x7e2 kernel/chr_drv/chr_drv.a(keyboard.2.o) + 0x0000000000017da2 keyboard_interrupt + .text 0x0000000000018581 0x145 kernel/chr_drv/chr_drv.a(serial.o) + 0x00000000000185f6 rs_init + 0x0000000000018679 rs_write + *fill* 0x00000000000186c6 0x2 + .text 0x00000000000186c8 0xf7 kernel/chr_drv/chr_drv.a(rs_io.o) + 0x00000000000186c8 rs1_interrupt + 0x00000000000186d0 rs2_interrupt + .text 0x00000000000187bf 0x60f kernel/chr_drv/chr_drv.a(tty_ioctl.o) + 0x0000000000018ad0 tty_ioctl + .text 0x0000000000018dce 0x111 kernel/math/math.a(math_emulate.o) + 0x0000000000018ddc math_emulate + 0x0000000000018ebf math_error + .text 0x0000000000018edf 0x0 lib/lib.a(ctype.o) + .text 0x0000000000018edf 0x10 lib/lib.a(_exit.o) + 0x0000000000018edf _exit + .text 0x0000000000018eef 0x49 lib/lib.a(open.o) + 0x0000000000018eef open + .text 0x0000000000018f38 0x37 lib/lib.a(close.o) + 0x0000000000018f38 close + .text 0x0000000000018f6f 0x0 lib/lib.a(errno.o) + .text 0x0000000000018f6f 0x3d lib/lib.a(write.o) + 0x0000000000018f6f write + .text 0x0000000000018fac 0x37 lib/lib.a(dup.o) + 0x0000000000018fac dup + .text 0x0000000000018fe3 0x2f lib/lib.a(setsid.o) + 0x0000000000018fe3 setsid + .text 0x0000000000019012 0x3d lib/lib.a(execve.o) + 0x0000000000019012 execve + .text 0x000000000001904f 0x60 lib/lib.a(wait.o) + 0x000000000001904f waitpid + 0x000000000001908c wait + .text 0x00000000000190af 0x3dc lib/lib.a(string.o) + 0x00000000000190af strcpy + 0x00000000000190cb strncpy + 0x00000000000190f0 strcat + 0x000000000001911b strncat + 0x0000000000019150 strcmp + 0x0000000000019177 strncmp + 0x00000000000191a5 strchr + 0x00000000000191d2 strrchr + 0x0000000000019201 strspn + 0x000000000001923e strcspn + 0x000000000001927b strpbrk + 0x00000000000192b2 strstr + 0x00000000000192eb strlen + 0x000000000001930e strtok + 0x0000000000019391 memcpy + 0x00000000000193b1 memmove + 0x0000000000019405 memcmp + 0x000000000001942f memchr + 0x0000000000019467 memset + *(.gnu.warning) + +.fini + *(SORT(.fini)) + 0x000000000001948b PROVIDE (__etext, .) + 0x000000000001948b PROVIDE (_etext, .) + 0x000000000001948b PROVIDE (etext, .) + +.rodata 0x000000000001948c 0x146e + *(.rodata .rodata.* .gnu.linkonce.r.*) + .rodata 0x000000000001948c 0xc9 init/main.o + *fill* 0x0000000000019555 0x3 + .rodata 0x0000000000019558 0x498 kernel/kernel.o + .rodata 0x00000000000199f0 0x1b5 mm/mm.o + *fill* 0x0000000000019ba5 0x3 + .rodata 0x0000000000019ba8 0x62c fs/fs.o + .rodata 0x000000000001a1d4 0x7a kernel/blk_drv/blk_drv.a(ll_rw_blk.o) + *fill* 0x000000000001a24e 0x2 + .rodata 0x000000000001a250 0x133 kernel/blk_drv/blk_drv.a(floppy.o) + *fill* 0x000000000001a383 0x1 + .rodata 0x000000000001a384 0x19b kernel/blk_drv/blk_drv.a(hd.o) + *fill* 0x000000000001a51f 0x1 + .rodata 0x000000000001a520 0x188 kernel/blk_drv/blk_drv.a(ramdisk.o) + .rodata 0x000000000001a6a8 0x17d kernel/chr_drv/chr_drv.a(console.o) + *fill* 0x000000000001a825 0x3 + .rodata 0x000000000001a828 0x80 kernel/chr_drv/chr_drv.a(tty_ioctl.o) + .rodata 0x000000000001a8a8 0x52 kernel/math/math.a(math_emulate.o) + +.rodata1 + *(.rodata1) + +.eh_frame_hdr + *(.eh_frame_hdr) + +.eh_frame 0x000000000001a8fc 0x2cc8 + *(.eh_frame) + .eh_frame 0x000000000001a8fc 0x108 init/main.o + .eh_frame 0x000000000001aa04 0xd2c kernel/kernel.o + 0xe64 (size before relaxing) + .eh_frame 0x000000000001b730 0x1b0 mm/mm.o + 0x1c8 (size before relaxing) + .eh_frame 0x000000000001b8e0 0xdd8 fs/fs.o + 0xf70 (size before relaxing) + .eh_frame 0x000000000001c6b8 0x98 kernel/blk_drv/blk_drv.a(ll_rw_blk.o) + 0xb0 (size before relaxing) + .eh_frame 0x000000000001c750 0x23c kernel/blk_drv/blk_drv.a(floppy.o) + 0x254 (size before relaxing) + .eh_frame 0x000000000001c98c 0x1e8 kernel/blk_drv/blk_drv.a(hd.o) + 0x200 (size before relaxing) + .eh_frame 0x000000000001cb74 0xac kernel/blk_drv/blk_drv.a(ramdisk.o) + 0xc4 (size before relaxing) + .eh_frame 0x000000000001cc20 0x12c kernel/chr_drv/chr_drv.a(tty_io.o) + 0x144 (size before relaxing) + .eh_frame 0x000000000001cd4c 0x2c0 kernel/chr_drv/chr_drv.a(console.o) + 0x2d8 (size before relaxing) + .eh_frame 0x000000000001d00c 0x54 kernel/chr_drv/chr_drv.a(serial.o) + 0x6c (size before relaxing) + .eh_frame 0x000000000001d060 0x148 kernel/chr_drv/chr_drv.a(tty_ioctl.o) + 0x160 (size before relaxing) + .eh_frame 0x000000000001d1a8 0x5c kernel/math/math.a(math_emulate.o) + 0x74 (size before relaxing) + .eh_frame 0x000000000001d204 0x1c lib/lib.a(_exit.o) + 0x34 (size before relaxing) + .eh_frame 0x000000000001d220 0x24 lib/lib.a(open.o) + 0x3c (size before relaxing) + .eh_frame 0x000000000001d244 0x20 lib/lib.a(close.o) + 0x38 (size before relaxing) + .eh_frame 0x000000000001d264 0x20 lib/lib.a(write.o) + 0x38 (size before relaxing) + .eh_frame 0x000000000001d284 0x20 lib/lib.a(dup.o) + 0x38 (size before relaxing) + .eh_frame 0x000000000001d2a4 0x18 lib/lib.a(setsid.o) + 0x30 (size before relaxing) + .eh_frame 0x000000000001d2bc 0x20 lib/lib.a(execve.o) + 0x38 (size before relaxing) + .eh_frame 0x000000000001d2dc 0x38 lib/lib.a(wait.o) + 0x50 (size before relaxing) + .eh_frame 0x000000000001d314 0x2b0 lib/lib.a(string.o) + 0x2c8 (size before relaxing) + +.gcc_except_table + *(.gcc_except_table .gcc_except_table.*) + +.exception_ranges + *(.exception_ranges .exception_ranges*) + 0x000000000001d5c4 . = . + +.eh_frame + *(.eh_frame) + +.gcc_except_table + *(.gcc_except_table .gcc_except_table.*) + +.exception_ranges + *(.exception_ranges .exception_ranges*) + +.tdata + *(.tdata .tdata.* .gnu.linkonce.td.*) + +.tbss + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + +.preinit_array 0x000000000001d5c4 0x0 + 0x000000000001d5c4 PROVIDE (__preinit_array_start, .) + *(.preinit_array) + 0x000000000001d5c4 PROVIDE (__preinit_array_end, .) + +.init_array 0x000000000001d5c4 0x0 + 0x000000000001d5c4 PROVIDE (__init_array_start, .) + *(SORT(.init_array.*) SORT(.ctors.*)) + *(.init_array EXCLUDE_FILE(*crtend?.o *crtend.o *crtbegin?.o *crtbegin.o) .ctors) + 0x000000000001d5c4 PROVIDE (__init_array_end, .) + +.fini_array 0x000000000001d5c4 0x0 + 0x000000000001d5c4 PROVIDE (__fini_array_start, .) + *(SORT(.fini_array.*) SORT(.dtors.*)) + *(.fini_array EXCLUDE_FILE(*crtend?.o *crtend.o *crtbegin?.o *crtbegin.o) .dtors) + 0x000000000001d5c4 PROVIDE (__fini_array_end, .) + +.ctors + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + +.dtors + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + +.jcr + *(.jcr) + +.data.rel.ro + *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) + *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) + +.dynamic + *(.dynamic) + +.got + *(.got) + *(.igot) + +.got.plt 0x000000000001d5c4 0x0 + *(.got.plt) + *(.igot.plt) + .igot.plt 0x0000000000000000 0x0 boot/head.o + +.data 0x000000000001d5e0 0x3b21 + *(.data .data.* .gnu.linkonce.d.*) + .data 0x000000000001d5e0 0x0 boot/head.o + .data 0x000000000001d5e0 0x28 init/main.o + *fill* 0x000000000001d608 0x18 + .data 0x000000000001d620 0x1330 kernel/kernel.o + 0x000000000001d620 sys_call_table + 0x000000000001d790 NR_syscalls + 0x000000000001e7a0 current + 0x000000000001e7c0 task + 0x000000000001e8c0 stack_start + 0x000000000001e8c8 current_DOR + .data 0x000000000001e950 0x0 mm/mm.o + *fill* 0x000000000001e950 0x10 + .data 0x000000000001e960 0x60 fs/fs.o + 0x000000000001e964 start_buffer + .data 0x000000000001e9c0 0x0 kernel/blk_drv/blk_drv.a(ll_rw_blk.o) + .data 0x000000000001e9c0 0xcd kernel/blk_drv/blk_drv.a(floppy.o) + *fill* 0x000000000001ea8d 0x3 + .data 0x000000000001ea90 0x4 kernel/blk_drv/blk_drv.a(hd.o) + .data 0x000000000001ea94 0x0 kernel/blk_drv/blk_drv.a(ramdisk.o) + *fill* 0x000000000001ea94 0xc + .data 0x000000000001eaa0 0x2538 kernel/chr_drv/chr_drv.a(tty_io.o) + 0x000000000001eaa0 tty_table + 0x0000000000020fc0 table_list + .data 0x0000000000020fd8 0x1 kernel/chr_drv/chr_drv.a(console.o) + .data 0x0000000000020fd9 0x0 kernel/chr_drv/chr_drv.a(keyboard.2.o) + .data 0x0000000000020fd9 0x0 kernel/chr_drv/chr_drv.a(serial.o) + .data 0x0000000000020fd9 0x0 kernel/chr_drv/chr_drv.a(rs_io.o) + *fill* 0x0000000000020fd9 0x7 + .data 0x0000000000020fe0 0x20 kernel/chr_drv/chr_drv.a(tty_ioctl.o) + .data 0x0000000000021000 0x0 kernel/math/math.a(math_emulate.o) + .data 0x0000000000021000 0x101 lib/lib.a(ctype.o) + 0x0000000000021000 _ctype + .data 0x0000000000021101 0x0 lib/lib.a(_exit.o) + .data 0x0000000000021101 0x0 lib/lib.a(open.o) + .data 0x0000000000021101 0x0 lib/lib.a(close.o) + .data 0x0000000000021101 0x0 lib/lib.a(errno.o) + .data 0x0000000000021101 0x0 lib/lib.a(write.o) + .data 0x0000000000021101 0x0 lib/lib.a(dup.o) + .data 0x0000000000021101 0x0 lib/lib.a(setsid.o) + .data 0x0000000000021101 0x0 lib/lib.a(execve.o) + .data 0x0000000000021101 0x0 lib/lib.a(wait.o) + .data 0x0000000000021101 0x0 lib/lib.a(string.o) + +.data1 + *(.data1) + 0x0000000000021101 _edata = . + 0x0000000000021101 PROVIDE (edata, .) + 0x0000000000021101 . = . + 0x0000000000021101 __bss_start = . + +.bss 0x0000000000021120 0x44b0 + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + .bss 0x0000000000021120 0x0 boot/head.o + .bss 0x0000000000021120 0x40c init/main.o + *fill* 0x000000000002152c 0x14 + .bss 0x0000000000021540 0x760 kernel/kernel.o + 0x0000000000021540 jiffies + 0x0000000000021544 startup_time + 0x0000000000021548 last_task_used_math + 0x0000000000021884 last_pid + .bss 0x0000000000021ca0 0xf20 mm/mm.o + .bss 0x0000000000022bc0 0x710 fs/fs.o + 0x0000000000022bc0 inode_table + 0x00000000000232c0 nr_buffers + 0x00000000000232cc ROOT_DEV + *fill* 0x00000000000232d0 0x10 + .bss 0x00000000000232e0 0x58 kernel/blk_drv/blk_drv.a(ll_rw_blk.o) + 0x00000000000232e0 wait_for_request + 0x0000000000023300 blk_dev + .bss 0x0000000000023338 0x25 kernel/blk_drv/blk_drv.a(floppy.o) + 0x0000000000023338 do_floppy + 0x000000000002333c selected + 0x0000000000023340 wait_on_floppy_select + *fill* 0x000000000002335d 0x3 + .bss 0x0000000000023360 0xb0 kernel/blk_drv/blk_drv.a(hd.o) + 0x0000000000023360 do_hd + 0x0000000000023380 hd_info + .bss 0x0000000000023410 0x4 kernel/blk_drv/blk_drv.a(ramdisk.o) + 0x0000000000023410 rd_length + .bss 0x0000000000023414 0x4 kernel/chr_drv/chr_drv.a(tty_io.o) + *fill* 0x0000000000023418 0x8 + .bss 0x0000000000023420 0xac kernel/chr_drv/chr_drv.a(console.o) + 0x0000000000023420 beepcount + .bss 0x00000000000234cc 0x0 kernel/chr_drv/chr_drv.a(keyboard.2.o) + .bss 0x00000000000234cc 0x0 kernel/chr_drv/chr_drv.a(serial.o) + .bss 0x00000000000234cc 0x0 kernel/chr_drv/chr_drv.a(rs_io.o) + .bss 0x00000000000234cc 0x0 kernel/chr_drv/chr_drv.a(tty_ioctl.o) + .bss 0x00000000000234cc 0x0 kernel/math/math.a(math_emulate.o) + .bss 0x00000000000234cc 0x0 lib/lib.a(ctype.o) + .bss 0x00000000000234cc 0x0 lib/lib.a(_exit.o) + .bss 0x00000000000234cc 0x0 lib/lib.a(open.o) + .bss 0x00000000000234cc 0x0 lib/lib.a(close.o) + .bss 0x00000000000234cc 0x0 lib/lib.a(errno.o) + .bss 0x00000000000234cc 0x0 lib/lib.a(write.o) + .bss 0x00000000000234cc 0x0 lib/lib.a(dup.o) + .bss 0x00000000000234cc 0x0 lib/lib.a(setsid.o) + .bss 0x00000000000234cc 0x0 lib/lib.a(execve.o) + .bss 0x00000000000234cc 0x0 lib/lib.a(wait.o) + .bss 0x00000000000234cc 0x0 lib/lib.a(string.o) + *(COMMON) + *fill* 0x00000000000234cc 0x14 + COMMON 0x00000000000234e0 0x20 init/main.o + 0x00000000000234e0 drive_info + COMMON 0x0000000000023500 0x1000 kernel/kernel.o + 0x0000000000023500 user_stack + COMMON 0x0000000000024500 0xc40 fs/fs.o + 0x0000000000024500 hash_table + 0x00000000000249e0 super_block + 0x0000000000024d40 file_table + COMMON 0x0000000000025140 0x480 kernel/blk_drv/blk_drv.a(ll_rw_blk.o) + 0x0000000000025140 request + COMMON 0x00000000000255c0 0x4 kernel/blk_drv/blk_drv.a(ramdisk.o) + 0x00000000000255c0 rd_start + COMMON 0x00000000000255c4 0x1 lib/lib.a(ctype.o) + 0x00000000000255c4 _ctmp + *fill* 0x00000000000255c5 0x3 + COMMON 0x00000000000255c8 0x4 lib/lib.a(errno.o) + 0x00000000000255c8 errno + COMMON 0x00000000000255cc 0x4 lib/lib.a(string.o) + 0x00000000000255cc ___strtok + 0x00000000000255d0 . = ALIGN ((. != 0x0)?0x4:0x1) + 0x00000000000255d0 . = ALIGN (0x4) + 0x00000000000255d0 . = SEGMENT_START ("ldata-segment", .) + 0x00000000000255d0 . = ALIGN (0x4) + 0x00000000000255d0 _end = . + 0x00000000000255d0 PROVIDE (end, .) + +.stab + *(.stab) + +.stabstr + *(.stabstr) + +.stab.excl + *(.stab.excl) + +.stab.exclstr + *(.stab.exclstr) + +.stab.index + *(.stab.index) + +.stab.indexstr + *(.stab.indexstr) + +.comment 0x0000000000000000 0x29 + *(.comment) + .comment 0x0000000000000000 0x29 init/main.o + 0x2a (size before relaxing) + .comment 0x0000000000000000 0x222 kernel/kernel.o + .comment 0x0000000000000000 0x2a mm/mm.o + .comment 0x0000000000000000 0x2f4 fs/fs.o + .comment 0x0000000000000000 0x2a kernel/blk_drv/blk_drv.a(ll_rw_blk.o) + .comment 0x0000000000000000 0x2a kernel/blk_drv/blk_drv.a(floppy.o) + .comment 0x0000000000000000 0x2a kernel/blk_drv/blk_drv.a(hd.o) + .comment 0x0000000000000000 0x2a kernel/blk_drv/blk_drv.a(ramdisk.o) + .comment 0x0000000000000000 0x2a kernel/chr_drv/chr_drv.a(tty_io.o) + .comment 0x0000000000000000 0x2a kernel/chr_drv/chr_drv.a(console.o) + .comment 0x0000000000000000 0x2a kernel/chr_drv/chr_drv.a(serial.o) + .comment 0x0000000000000000 0x2a kernel/chr_drv/chr_drv.a(tty_ioctl.o) + .comment 0x0000000000000000 0x2a kernel/math/math.a(math_emulate.o) + .comment 0x0000000000000000 0x2a lib/lib.a(ctype.o) + .comment 0x0000000000000000 0x2a lib/lib.a(_exit.o) + .comment 0x0000000000000000 0x2a lib/lib.a(open.o) + .comment 0x0000000000000000 0x2a lib/lib.a(close.o) + .comment 0x0000000000000000 0x2a lib/lib.a(errno.o) + .comment 0x0000000000000000 0x2a lib/lib.a(write.o) + .comment 0x0000000000000000 0x2a lib/lib.a(dup.o) + .comment 0x0000000000000000 0x2a lib/lib.a(setsid.o) + .comment 0x0000000000000000 0x2a lib/lib.a(execve.o) + .comment 0x0000000000000000 0x2a lib/lib.a(wait.o) + .comment 0x0000000000000000 0x2a lib/lib.a(string.o) + +.debug + *(.debug) + +.line + *(.line) + +.debug_srcinfo + *(.debug_srcinfo) + +.debug_sfnames + *(.debug_sfnames) + +.debug_aranges 0x0000000000000000 0x688 + *(.debug_aranges) + .debug_aranges + 0x0000000000000000 0x20 init/main.o + .debug_aranges + 0x0000000000000020 0x1a0 kernel/kernel.o + .debug_aranges + 0x00000000000001c0 0x20 mm/mm.o + .debug_aranges + 0x00000000000001e0 0x238 fs/fs.o + .debug_aranges + 0x0000000000000418 0x20 kernel/blk_drv/blk_drv.a(ll_rw_blk.o) + .debug_aranges + 0x0000000000000438 0x20 kernel/blk_drv/blk_drv.a(floppy.o) + .debug_aranges + 0x0000000000000458 0x20 kernel/blk_drv/blk_drv.a(hd.o) + .debug_aranges + 0x0000000000000478 0x20 kernel/blk_drv/blk_drv.a(ramdisk.o) + .debug_aranges + 0x0000000000000498 0x20 kernel/chr_drv/chr_drv.a(tty_io.o) + .debug_aranges + 0x00000000000004b8 0x20 kernel/chr_drv/chr_drv.a(console.o) + .debug_aranges + 0x00000000000004d8 0x20 kernel/chr_drv/chr_drv.a(serial.o) + .debug_aranges + 0x00000000000004f8 0x20 kernel/chr_drv/chr_drv.a(tty_ioctl.o) + .debug_aranges + 0x0000000000000518 0x20 kernel/math/math.a(math_emulate.o) + .debug_aranges + 0x0000000000000538 0x18 lib/lib.a(ctype.o) + .debug_aranges + 0x0000000000000550 0x20 lib/lib.a(_exit.o) + .debug_aranges + 0x0000000000000570 0x20 lib/lib.a(open.o) + .debug_aranges + 0x0000000000000590 0x20 lib/lib.a(close.o) + .debug_aranges + 0x00000000000005b0 0x18 lib/lib.a(errno.o) + .debug_aranges + 0x00000000000005c8 0x20 lib/lib.a(write.o) + .debug_aranges + 0x00000000000005e8 0x20 lib/lib.a(dup.o) + .debug_aranges + 0x0000000000000608 0x20 lib/lib.a(setsid.o) + .debug_aranges + 0x0000000000000628 0x20 lib/lib.a(execve.o) + .debug_aranges + 0x0000000000000648 0x20 lib/lib.a(wait.o) + .debug_aranges + 0x0000000000000668 0x20 lib/lib.a(string.o) + +.debug_pubnames + *(.debug_pubnames) + +.debug_info 0x0000000000000000 0x19187 + *(.debug_info .gnu.linkonce.wi.*) + .debug_info 0x0000000000000000 0xb73 init/main.o + .debug_info 0x0000000000000b73 0x6a7d kernel/kernel.o + .debug_info 0x00000000000075f0 0xba8 mm/mm.o + .debug_info 0x0000000000008198 0xa290 fs/fs.o + .debug_info 0x0000000000012428 0x932 kernel/blk_drv/blk_drv.a(ll_rw_blk.o) + .debug_info 0x0000000000012d5a 0xc9f kernel/blk_drv/blk_drv.a(floppy.o) + .debug_info 0x00000000000139f9 0xd5f kernel/blk_drv/blk_drv.a(hd.o) + .debug_info 0x0000000000014758 0xad5 kernel/blk_drv/blk_drv.a(ramdisk.o) + .debug_info 0x000000000001522d 0xacd kernel/chr_drv/chr_drv.a(tty_io.o) + .debug_info 0x0000000000015cfa 0xdb0 kernel/chr_drv/chr_drv.a(console.o) + .debug_info 0x0000000000016aaa 0x85c kernel/chr_drv/chr_drv.a(serial.o) + .debug_info 0x0000000000017306 0xb47 kernel/chr_drv/chr_drv.a(tty_ioctl.o) + .debug_info 0x0000000000017e4d 0x7b5 kernel/math/math.a(math_emulate.o) + .debug_info 0x0000000000018602 0x66 lib/lib.a(ctype.o) + .debug_info 0x0000000000018668 0x77 lib/lib.a(_exit.o) + .debug_info 0x00000000000186df 0xd0 lib/lib.a(open.o) + .debug_info 0x00000000000187af 0x97 lib/lib.a(close.o) + .debug_info 0x0000000000018846 0x36 lib/lib.a(errno.o) + .debug_info 0x000000000001887c 0xc9 lib/lib.a(write.o) + .debug_info 0x0000000000018945 0x97 lib/lib.a(dup.o) + .debug_info 0x00000000000189dc 0x95 lib/lib.a(setsid.o) + .debug_info 0x0000000000018a71 0xcb lib/lib.a(execve.o) + .debug_info 0x0000000000018b3c 0xed lib/lib.a(wait.o) + .debug_info 0x0000000000018c29 0x55e lib/lib.a(string.o) + +.debug_abbrev 0x0000000000000000 0x4901 + *(.debug_abbrev) + .debug_abbrev 0x0000000000000000 0x237 init/main.o + .debug_abbrev 0x0000000000000237 0x1447 kernel/kernel.o + .debug_abbrev 0x000000000000167e 0x20b mm/mm.o + .debug_abbrev 0x0000000000001889 0x19f1 fs/fs.o + .debug_abbrev 0x000000000000327a 0x169 kernel/blk_drv/blk_drv.a(ll_rw_blk.o) + .debug_abbrev 0x00000000000033e3 0x27d kernel/blk_drv/blk_drv.a(floppy.o) + .debug_abbrev 0x0000000000003660 0x23c kernel/blk_drv/blk_drv.a(hd.o) + .debug_abbrev 0x000000000000389c 0x1a8 kernel/blk_drv/blk_drv.a(ramdisk.o) + .debug_abbrev 0x0000000000003a44 0x279 kernel/chr_drv/chr_drv.a(tty_io.o) + .debug_abbrev 0x0000000000003cbd 0x26b kernel/chr_drv/chr_drv.a(console.o) + .debug_abbrev 0x0000000000003f28 0x175 kernel/chr_drv/chr_drv.a(serial.o) + .debug_abbrev 0x000000000000409d 0x18d kernel/chr_drv/chr_drv.a(tty_ioctl.o) + .debug_abbrev 0x000000000000422a 0x163 kernel/math/math.a(math_emulate.o) + .debug_abbrev 0x000000000000438d 0x3e lib/lib.a(ctype.o) + .debug_abbrev 0x00000000000043cb 0x51 lib/lib.a(_exit.o) + .debug_abbrev 0x000000000000441c 0x97 lib/lib.a(open.o) + .debug_abbrev 0x00000000000044b3 0x75 lib/lib.a(close.o) + .debug_abbrev 0x0000000000004528 0x2c lib/lib.a(errno.o) + .debug_abbrev 0x0000000000004554 0xa1 lib/lib.a(write.o) + .debug_abbrev 0x00000000000045f5 0x75 lib/lib.a(dup.o) + .debug_abbrev 0x000000000000466a 0x73 lib/lib.a(setsid.o) + .debug_abbrev 0x00000000000046dd 0x85 lib/lib.a(execve.o) + .debug_abbrev 0x0000000000004762 0xb6 lib/lib.a(wait.o) + .debug_abbrev 0x0000000000004818 0xe9 lib/lib.a(string.o) + +.debug_line 0x0000000000000000 0x4bde + *(.debug_line .debug_line.* .debug_line_end) + .debug_line 0x0000000000000000 0x1e5 init/main.o + .debug_line 0x00000000000001e5 0x144d kernel/kernel.o + .debug_line 0x0000000000001632 0x2b4 mm/mm.o + .debug_line 0x00000000000018e6 0x1c50 fs/fs.o + .debug_line 0x0000000000003536 0x197 kernel/blk_drv/blk_drv.a(ll_rw_blk.o) + .debug_line 0x00000000000036cd 0x24c kernel/blk_drv/blk_drv.a(floppy.o) + .debug_line 0x0000000000003919 0x2bf kernel/blk_drv/blk_drv.a(hd.o) + .debug_line 0x0000000000003bd8 0x160 kernel/blk_drv/blk_drv.a(ramdisk.o) + .debug_line 0x0000000000003d38 0x33b kernel/chr_drv/chr_drv.a(tty_io.o) + .debug_line 0x0000000000004073 0x3ab kernel/chr_drv/chr_drv.a(console.o) + .debug_line 0x000000000000441e 0xd9 kernel/chr_drv/chr_drv.a(serial.o) + .debug_line 0x00000000000044f7 0x1db kernel/chr_drv/chr_drv.a(tty_ioctl.o) + .debug_line 0x00000000000046d2 0xe1 kernel/math/math.a(math_emulate.o) + .debug_line 0x00000000000047b3 0x28 lib/lib.a(ctype.o) + .debug_line 0x00000000000047db 0x39 lib/lib.a(_exit.o) + .debug_line 0x0000000000004814 0x62 lib/lib.a(open.o) + .debug_line 0x0000000000004876 0x5c lib/lib.a(close.o) + .debug_line 0x00000000000048d2 0x28 lib/lib.a(errno.o) + .debug_line 0x00000000000048fa 0x76 lib/lib.a(write.o) + .debug_line 0x0000000000004970 0x5a lib/lib.a(dup.o) + .debug_line 0x00000000000049ca 0x77 lib/lib.a(setsid.o) + .debug_line 0x0000000000004a41 0x5d lib/lib.a(execve.o) + .debug_line 0x0000000000004a9e 0x7a lib/lib.a(wait.o) + .debug_line 0x0000000000004b18 0xc6 lib/lib.a(string.o) + +.debug_frame + *(.debug_frame) + +.debug_str 0x0000000000000000 0x21bc + *(.debug_str) + .debug_str 0x0000000000000000 0x3bd init/main.o + 0x460 (size before relaxing) + .debug_str 0x00000000000003bd 0xb28 kernel/kernel.o + 0x30bd (size before relaxing) + .debug_str 0x0000000000000ee5 0x181 mm/mm.o + 0x4e8 (size before relaxing) + .debug_str 0x0000000000001066 0x7a3 fs/fs.o + 0x49a7 (size before relaxing) + .debug_str 0x0000000000001809 0xf0 kernel/blk_drv/blk_drv.a(ll_rw_blk.o) + 0x491 (size before relaxing) + .debug_str 0x00000000000018f9 0x1cf kernel/blk_drv/blk_drv.a(floppy.o) + 0x673 (size before relaxing) + .debug_str 0x0000000000001ac8 0x15e kernel/blk_drv/blk_drv.a(hd.o) + 0x5e8 (size before relaxing) + .debug_str 0x0000000000001c26 0x43 kernel/blk_drv/blk_drv.a(ramdisk.o) + 0x58a (size before relaxing) + .debug_str 0x0000000000001c69 0xfb kernel/chr_drv/chr_drv.a(tty_io.o) + 0x4e3 (size before relaxing) + .debug_str 0x0000000000001d64 0x1b9 kernel/chr_drv/chr_drv.a(console.o) + 0x5b7 (size before relaxing) + .debug_str 0x0000000000001f1d 0x1a kernel/chr_drv/chr_drv.a(serial.o) + 0x3fc (size before relaxing) + .debug_str 0x0000000000001f37 0x8b kernel/chr_drv/chr_drv.a(tty_ioctl.o) + 0x4a7 (size before relaxing) + .debug_str 0x0000000000001fc2 0x70 kernel/math/math.a(math_emulate.o) + 0x392 (size before relaxing) + .debug_str 0x0000000000002032 0x8d lib/lib.a(ctype.o) + 0xb6 (size before relaxing) + .debug_str 0x00000000000020bf 0x31 lib/lib.a(_exit.o) + 0xde (size before relaxing) + .debug_str 0x0000000000000000 0x31 lib/lib.a(open.o) + 0xee (size before relaxing) + .debug_str 0x00000000000020f0 0x8 lib/lib.a(close.o) + 0xe0 (size before relaxing) + .debug_str 0x00000000000020f8 0x8 lib/lib.a(errno.o) + 0x93 (size before relaxing) + .debug_str 0x0000000000000000 0x8 lib/lib.a(write.o) + 0xec (size before relaxing) + .debug_str 0x0000000000002100 0x6 lib/lib.a(dup.o) + 0xd8 (size before relaxing) + .debug_str 0x0000000000002106 0x9 lib/lib.a(setsid.o) + 0xe8 (size before relaxing) + .debug_str 0x000000000000210f 0x9 lib/lib.a(execve.o) + 0xf1 (size before relaxing) + .debug_str 0x0000000000002118 0x11 lib/lib.a(wait.o) + 0xfe (size before relaxing) + .debug_str 0x0000000000002129 0x93 lib/lib.a(string.o) + 0x147 (size before relaxing) + +.debug_loc + *(.debug_loc) + +.debug_macinfo + *(.debug_macinfo) + +.debug_weaknames + *(.debug_weaknames) + +.debug_funcnames + *(.debug_funcnames) + +.debug_typenames + *(.debug_typenames) + +.debug_varnames + *(.debug_varnames) + +.debug_pubtypes + *(.debug_pubtypes) + +.debug_ranges 0x0000000000000000 0x18 + *(.debug_ranges) + .debug_ranges 0x0000000000000000 0x18 init/main.o + +.debug_macro + *(.debug_macro) + +.gnu.attributes + *(.gnu.attributes) + +/DISCARD/ + *(.note.GNU-stack) + *(.gnu_debuglink) + *(.gnu.lto_*) +OUTPUT(tools/system elf32-i386) diff --git a/os/os/linux/boot/bootsect b/os/os/linux/boot/bootsect new file mode 100644 index 0000000000000000000000000000000000000000..4fbb8f823afe23687f1887d48deeb19fdcf83049 GIT binary patch literal 544 zcmZQ%7GP0e00JfufdrZ$>>UT#`)=%Dn9z4%Cj+DAH_iW_m%fre~uHUSwNXN9*i=ymehGJ;Ln!ff#WtiVnQ zhTZH8d+ix_Fbba)*ufysci@E)!;7N~dJF$B+A=VditBaD0d;UNHUH)>;o2bsq=ibD zUjNfu{D<)s1B1c@RhzFW-(_8 zyWs)N8wX!-zAym_G6SXbtl4ZCONDkYGHA2SVkl+#&o+l)@hk?z1B+)cfHa*h-qdq| z733tt+pm`g1P2Cni_Kx^=9|Ib*m1R6Y!*YuwM`6-j~E!Y0DW7;8WkBGaTw@dps&vg zgE+6x1nv67yn*3e)L{k&UM`>f#FWgubcN!|;*!){1wB1IUM^lPq<|j0Og84wRRH+h BgWdoD literal 0 HcmV?d00001 diff --git a/os/os/linux/boot/bootsect.o b/os/os/linux/boot/bootsect.o new file mode 100644 index 0000000000000000000000000000000000000000..e35422ec017a165928bfcbec5f9f0363b4a9e75c GIT binary patch literal 923 zcmYjPe@GKy7=FH+PB$=@gOrLGSb;@HGl?KZQ#V8qHK&qRjLn^EOg*`~_2a*bAQEj2 z`bR7R8DjO1Ax5YD;D!W64T2~X>5mFT9P~#*1c~eYW`BB3fn$y+MeVjqc)FB7D{5ZwQc zlnx;W9UDX^enV$llvLXoyfYO9Z}$=84ic;$V`O7tS=LmkPeZ`p+0`EKHzCjy2sHQl zw}lpeD-uHysXwTY5sDOw1Y=|-4_TXAn>%^rd%=iw84Yc11;O9ydW>fq~$ltjP-a7_y>584mLI>~!sq4M`D5Ly@qm@(>AWA%vwU zr%{<_+X|nde;^cvTBwf1Bxp*gFV1T;>8i$^g?NcKSG5q0@!xcE+`au;IbOSyoY+a~ z{!PR`f4ixx+SO^8CCMcNsiZj%R`aVSzcIBg=v7dW8hevmN}95U=#^i zr)no|09j{lb(WIStn(?vkzMq|I|{AlEXVU%$9xr@m*6E`j|&EKW*r6`Npr0hYp)?r zZZZ#$s1!#JP?cts3OD|gYj$Hl#R^TxZHehkwhp*b#dJ@BG4oNrJhA0o88bcbDr`}l zq`HQqR(%{jBbm%s8(UUwT8Z1NS<0;0*6J{lvGC1C@wAnkO^FJFf$S6TC5rM^{XXi` zL>k>@nq232gLmrem|4t+bg$&5+XH7iM)#1fVRRQc{Pnj!5uJed*5_GV{{}WkC!rMg z_MAVrNM}JOl67*Dd*89})A9sAdKZB*dkfv2*ih7^UQ;z`&?SnZugqR%-#z8CTDl%r F<1c(7E-?TA literal 0 HcmV?d00001 diff --git a/os/os/linux/boot/bootsect.s b/os/os/linux/boot/bootsect.s new file mode 100644 index 0000000..711f103 --- /dev/null +++ b/os/os/linux/boot/bootsect.s @@ -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: diff --git a/os/os/linux/boot/head.o b/os/os/linux/boot/head.o new file mode 100644 index 0000000000000000000000000000000000000000..a4c55649c84336692e2f017e7d3b9dc5fd3082ba GIT binary patch literal 27012 zcmeI5O=ule7>2)-rn#v$OwS%uL!8 z6a%qn7P*Sc3jRisn&iB4& z&iUrdGdG*FIOn4m54>cIk-Qk$Ah(^!ke}VzorWRlmW`=8*Nf1++Dw|)n=8(lL2X<) zq}4H0_qtn3hEHg(eMrzN@gL4WGWd|l-26`+&h}(Q)Bb+)4UucVe)-Gw{Sx<}!~D%I z+*?{aEZ2TpTI?Ts6R8Drs4QHmT#)ACbDHqHPI#fPaIkZJx%=grzZ~<#59qk$nEtaG zwGRskkN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@ zkN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg z011!)36KB@kN^pg011!)36KB@{I3YSFZx$|7#nQXbmBLjzwysojfuwek;Xv15&K~{ z6T}bn$jEE2Z|!ovS+gN%tq)^XR$HyssPk=M+o88dFJpht^U^0$N=mKOKTj>|UZ7II z4x`H(J5>#+>Q=Qw)n--0B9~TQ#eSfLn=SeK)YI5gR6e{_N}TOiv2kb*y3Aqg&{f?# zRHRiv)sBntlbK~r0wh2JBtQZrur3L-9K81NMAG<0vMw3$rAdGUNPq-LVBHWXMn|V& zZ%m3&9A>eWtI(e;#{O(9#j+QBQXGq-`^K^jJ@x#QE<0i`Vp6sSL02)fJdSHqsHM(blD3iP(3Pv78q7&_8 zM*5-k_?fI2(eEHwXv&I_5`-Qfll%P;pXV0YUx3zAW3po86$m{&CikN%^o7%6cM$*qTtc_Ysx=5yrWmz#Y0Wq@1&%*1%SXPY8K_u4qV*JPI(}(IbjC`7P zOl$R@sT#=|)qkDIv{wK99Ukv?m%n(Im&lK20=Hg{t*Sze*ZlDbcXsa{@hVv2a|5sH zyZGms^dqTP8`GihV(m}Dz>RbuF1PGQ!HL`fm@lJ4uYeu7y6z=u@~z6cI{M&Nu>=k<<%P!gh--%^>djmB1Ic# zG~x&OiAMa0zq0GKeRF1UbBAE`q28r)_-9Aob|_S NJgpJWKc}%z4Mb 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 4 +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 */ + cld /* by wyj */ + ret /* this also flushes prefetch-queue */ + +.align 4 +.word 0 +idt_descr: + .word 256*8-1 # idt contains 256 entries + .long idt +.align 4 +.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 8 +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 */ diff --git a/os/os/linux/boot/setup b/os/os/linux/boot/setup new file mode 100644 index 0000000000000000000000000000000000000000..0e70f4846819f560fb2e22a8eb1e7186c7956ab0 GIT binary patch literal 344 zcmZQ%7GP0eU|_Id1QJNVq7lN`!7!ok#ujFS|7Qg{#TXd2bet7k%*3#TAIOzsVOY$@ zutjLIz*&LC91NXuTnwFjJPbP+82WA;HDh4}X+5yNfnlcr!{;SXQ3*l_<@!izwL4T8@UUNgLAc(wpUZcuop2&OfjEda<7{%Xg;=gL$t<~Tutazx3hbYqSrLZVca%ibUp9b?$HkVw;4TnF?Rz@46w`UObliF2LrIX1l zD$%Xa$Sgt^u2&7@|GQ@O1M(N{a&->*XRca94ek$5^Qt@KbHx4WGu-r2)9WkibQgy407%ZoGynhq literal 0 HcmV?d00001 diff --git a/os/os/linux/boot/setup.s b/os/os/linux/boot/setup.s new file mode 100644 index 0000000..2329d00 --- /dev/null +++ b/os/os/linux/boot/setup.s @@ -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: diff --git a/os/os/linux/execve2.patch b/os/os/linux/execve2.patch new file mode 100644 index 0000000..7d99d4f --- /dev/null +++ b/os/os/linux/execve2.patch @@ -0,0 +1,41 @@ +diff -Naur 0/linux/init/main.c 4/linux/init/main.c +--- 0/linux/init/main.c 2016-08-08 09:40:13.000000000 +0800 ++++ 4/linux/init/main.c 2021-07-06 14:16:56.000000000 +0800 +@@ -208,3 +208,9 @@ + } + _exit(0); /* NOTE! _exit, not exit() */ + } ++ ++void print_nr(int sid) ++{ ++ if (sid > 86) ++ printk(" --syscall: sid=%d, pid=%d\n", sid, current->pid); ++} +diff -Naur 0/linux/kernel/system_call.s 4/linux/kernel/system_call.s +--- 0/linux/kernel/system_call.s 2015-09-03 20:21:09.000000000 +0800 ++++ 4/linux/kernel/system_call.s 2021-07-06 14:18:56.000000000 +0800 +@@ -91,6 +91,11 @@ + mov %dx,%es + movl $0x17,%edx # fs points to local data space + mov %dx,%fs ++ ++ pushl %eax #by wyj ++ call print_nr ++ popl %eax ++ + call sys_call_table(,%eax,4) + pushl %eax + movl current,%eax +diff -Naur 0/linux/mm/memory.c 4/linux/mm/memory.c +--- 0/linux/mm/memory.c 2015-09-04 15:24:20.000000000 +0800 ++++ 4/linux/mm/memory.c 2021-07-06 14:21:45.000000000 +0800 +@@ -370,6 +370,9 @@ + unsigned long page; + int block,i; + ++ if (current->pid > 5) ++ printk(" --do_no_page: address=%x, pid=%d\n", address, current->pid); ++ + address &= 0xfffff000; + tmp = address - current->start_code; + if (!current->executable || tmp >= current->end_data) { diff --git a/os/os/linux/fs/Makefile b/os/os/linux/fs/Makefile new file mode 100644 index 0000000..970acd4 --- /dev/null +++ b/os/os/linux/fs/Makefile @@ -0,0 +1,101 @@ +AR =ar +AS =as +LD =ld +LDFLAGS =-s -x +CC =gcc -march=i386 +CFLAGS =-w -g -fstrength-reduce -fomit-frame-pointer -mcld \ + -finline-functions -nostdinc -fno-stack-protector -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 diff --git a/os/os/linux/fs/bitmap.c b/os/os/linux/fs/bitmap.c new file mode 100644 index 0000000..73951a8 --- /dev/null +++ b/os/os/linux/fs/bitmap.c @@ -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 + +#include +#include + +#define clear_block(addr) \ +__asm__ __volatile__ ("cld\n\t" \ + "rep\n\t" \ + "stosl" \ + ::"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr))) + +#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__ __volatile__ ("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)); \ +__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; +} diff --git a/os/os/linux/fs/bitmap.o b/os/os/linux/fs/bitmap.o new file mode 100644 index 0000000000000000000000000000000000000000..501d3c5e3fb1a044792589a0bdde55cbb41cfaa2 GIT binary patch literal 10280 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 J@|j5fe*vQQ&y@fG literal 0 HcmV?d00001 diff --git a/os/os/linux/fs/block_dev.c b/os/os/linux/fs/block_dev.c new file mode 100644 index 0000000..a50ae3f --- /dev/null +++ b/os/os/linux/fs/block_dev.c @@ -0,0 +1,73 @@ +/* + * linux/fs/block_dev.c + * + * (C) 1991 Linus Torvalds + */ + +#include + +#include +#include +#include +#include + +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; +} diff --git a/os/os/linux/fs/block_dev.o b/os/os/linux/fs/block_dev.o new file mode 100644 index 0000000000000000000000000000000000000000..e5e9334ce9a4697061730271c4c9d92fcf4aa105 GIT binary patch literal 7296 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 + +#include +#include +#include +#include +#include + +extern void put_super(int dev); +extern void invalidate_inodes(int dev); + +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 ; ib_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 ; ib_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 ; ib_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 ; ib_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 ; ib_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)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) \ + ) + +/* + * 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;iQ6+~nZ1VPZCP{pdlWadpWGMO3Y4-glv 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 +#include + +#include +#include + +#include +#include + +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); +} diff --git a/os/os/linux/fs/char_dev.o b/os/os/linux/fs/char_dev.o new file mode 100644 index 0000000000000000000000000000000000000000..2977060a7c0b215e10aa16a8395ed973d52837cd GIT binary patch literal 8288 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 O%Ys)0UlIH-!T$wZ8WjQn literal 0 HcmV?d00001 diff --git a/os/os/linux/fs/exec.c b/os/os/linux/fs/exec.c new file mode 100644 index 0000000..2ff220e --- /dev/null +++ b/os/os/linux/fs/exec.c @@ -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 +#include +#include +#include + +#include +#include +#include +#include +#include + +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 ; ii_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 ; iclose_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 ; ifLjn&WLJ0DU0bbdE!WBx#8#{JUaxh_{r%qa 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 C=E>Ip literal 0 HcmV?d00001 diff --git a/os/os/linux/fs/fcntl.c b/os/os/linux/fs/fcntl.c new file mode 100644 index 0000000..c201aa8 --- /dev/null +++ b/os/os/linux/fs/fcntl.c @@ -0,0 +1,75 @@ +/* + * linux/fs/fcntl.c + * + * (C) 1991 Linus Torvalds + */ + +#include +#include +#include +#include +#include + +#include +#include + +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<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<close_on_exec &= ~(1<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; + } +} diff --git a/os/os/linux/fs/fcntl.o b/os/os/linux/fs/fcntl.o new file mode 100644 index 0000000000000000000000000000000000000000..17a6ecacd50cb07b4337da65f94d880d02b367a8 GIT binary patch literal 6748 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 literal 0 HcmV?d00001 diff --git a/os/os/linux/fs/file_dev.c b/os/os/linux/fs/file_dev.c new file mode 100644 index 0000000..0c50eaa --- /dev/null +++ b/os/os/linux/fs/file_dev.c @@ -0,0 +1,90 @@ +/* + * linux/fs/file_dev.c + * + * (C) 1991 Linus Torvalds + */ + +#include +#include + +#include +#include +#include + +#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 (ii_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); +} diff --git a/os/os/linux/fs/file_dev.o b/os/os/linux/fs/file_dev.o new file mode 100644 index 0000000000000000000000000000000000000000..e1ba8a5aa9f848cbe07cc40a116357db631d2c89 GIT binary patch literal 7828 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 SclH@D3RwcTDjZc + +struct file file_table[NR_FILE]; diff --git a/os/os/linux/fs/file_table.o b/os/os/linux/fs/file_table.o new file mode 100644 index 0000000000000000000000000000000000000000..422bcb331f1423abef699440aa5b0f0ff3a8b671 GIT binary patch literal 2644 zcma)8ONbmr7_OR`-P!Hgo!w=9BnF`a8xkecvzttkb&W;|x+aF`!4(DLY)?=3Ogq!v zV?VOl_&SK&K#0s-B=xPW^?j%FhrbeTlMCJwT9?XVawWCSbyVX|l2jSv>;r0{YaW6k_^T zz^c43M3{C3LO#m~p?wD-+vFv!O1}9tWJUXp+$5jUK4*OA9`G6MD!D~It9?Y?9e~%h zNpi;q*R@lSvd7#dtx0>I{E+r8?Jnm!to=&<9J!$#WXynkS-U~|kmDcG>f|2zQB7xz zPu|k*q&*-%ra=ffB0sKOX3X>CC&cs`U|z-_!=_!MBjE%>dy4!bc}e?}e2cuIh2)nQ zKBe73zWo5~GpHxaSY_e9qLcMJC2H@1m#062oG8PB_yu{OzE~^Q_tocb$KXq%R=Xc6 z!W5mtG`ERzeXVwH?aU$)7onWoi!GZ&EG<G-(`FDL5GCjLkzBG)c>s!O5Yd43kpIj0J zL$ni?^gGLma)}S#8gV?s>Amp;_i=x>NJiF;9-MAS< z4d33%KD)7OtgJMKW~aHF8JbRnjKu9i4g+f-0>^2`Q2fM$^wI?~uoxN5N}`rr)!X zkOgp0bB?ivVFjLNqo#(BEj4ghvMo+e;Qti+cm>cWRebh7?!!!*IMC1w&2`!#>Rb)&9ZYkHg8gkiQ-5obM!ho&zcta4TOYQ7!kK zhn{n~t|E>PMc#7XSs04*p2N$^c{neB7xH;8faf`&;yT9LBvCE*xzNe^-E4CxbDRBJaN~jlSq|VjswDS1$X0~#=Lq&ga zCz+rAOpXJ}=@*Vw_-pAt>oj4i1@Xtt-Oowk-9QNMj)Y*HB&K4`iTsa2WPK#+q${0w zg!W?!)3XcxL8Yf>6#9nJ`D4X+Q{jsW-%$9r!fOgYRQQR)FBEb=InIv?e^L0SLLMmk uXB6&HxTJ7d;Yo#$D11WUrb18Qw!+sGzNPRTh3_l;TH*IZ6fvzQ&gs8hV_9GT literal 0 HcmV?d00001 diff --git a/os/os/linux/fs/fs.o b/os/os/linux/fs/fs.o new file mode 100644 index 0000000000000000000000000000000000000000..2349695695bbbdfedaff566aca9df867504e492d GIT binary patch literal 142933 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 z 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 RcGJMzRp~C5qy&x9`#(X^mgfKf literal 0 HcmV?d00001 diff --git a/os/os/linux/fs/inode.c b/os/os/linux/fs/inode.c new file mode 100644 index 0000000..9bb10b3 --- /dev/null +++ b/os/os/linux/fs/inode.c @@ -0,0 +1,340 @@ +/* + * linux/fs/inode.c + * + * (C) 1991 Linus Torvalds + */ + +#include +#include + +#include +#include +#include +#include + +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 ; ii_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 ; ii_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 ; ii_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) { + 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"); + __asm__ volatile ("cld"); /* by wyj */ + *(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"); + __asm__ volatile ("cld"); /* by wyj */ + ((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); +} diff --git a/os/os/linux/fs/inode.o b/os/os/linux/fs/inode.o new file mode 100644 index 0000000000000000000000000000000000000000..dd67bfa4d43e1073c47e0226043fc43f5f0e9153 GIT binary patch literal 14072 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 I1a}MmH>)TywEzGB literal 0 HcmV?d00001 diff --git a/os/os/linux/fs/ioctl.c b/os/os/linux/fs/ioctl.c new file mode 100644 index 0000000..36fc976 --- /dev/null +++ b/os/os/linux/fs/ioctl.c @@ -0,0 +1,46 @@ +/* + * linux/fs/ioctl.c + * + * (C) 1991 Linus Torvalds + */ + +#include +#include +#include + +#include + +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); +} diff --git a/os/os/linux/fs/ioctl.o b/os/os/linux/fs/ioctl.o new file mode 100644 index 0000000000000000000000000000000000000000..1f1f33c5568ad7f154251149e1ecc40766da48c1 GIT binary patch literal 5828 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 +#include +#include + +#include +#include +#include +#include +#include + +#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) + ); + 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]=(ib_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= (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; +} diff --git a/os/os/linux/fs/namei.o b/os/os/linux/fs/namei.o new file mode 100644 index 0000000000000000000000000000000000000000..0514463113d5878e35d040844344865d47c7032e GIT binary patch literal 20756 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 a@7aEaV1r +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +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 *) ×->actime); + modtime = get_fs_long((unsigned long *) ×->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 ; fdfilp[fd]) + break; + if (fd>=NR_OPEN) + return -EINVAL; + current->close_on_exec &= ~(1<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<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); +} diff --git a/os/os/linux/fs/open.o b/os/os/linux/fs/open.o new file mode 100644 index 0000000000000000000000000000000000000000..aceb4b8d44365ee59ea3c9bb01413542e9cf0177 GIT binary patch literal 11184 zcmb_id6ZPunZNbA>eZ|6uBM=kP*x_jwU8%oHH)R8MV#0&gi)H{C@X+uPBI~ z@sD}uy!w6Lcfal4``!EQd);3-|Dxp{k4L$eM^&lgoKgo)by_+!%uwUiIMx3~XmD9` zePU1zENiX>S=)ak^!UC%jE;^z-v7od2-*j{&98n89t!pSH#XO+QuV%1!N0Z>ejw;j z#c9y%px&^f*GRtqpqHY%9Z_WD%)uZ7@0+}Hc~ z5n$us8r%psu(}x}#UL%h6J2vXnw6yX(YXJ}EGFBZXzuW%u`=Tb5{xk8cbV}cP=-Qe zP>uP?!D*uy932f2**Ufhh+m!5;GQnSF-Q(}8Od`Fm;8rrY;H71nsjq=aL;mS-`!O^ z=En!A;nNy$)!6@ne=3Gy0q&At=Q%RRal3-%3=2~w1O zI%nw{S}VKNh;B71xaCBQe3{{#KB>2qI#+cmRSZ)&;11Ip)SE8ha|rLYI3kSqz#fV# z#}f|z|6&$DJ0`_nIA+Nm_9d`l_hed%&C;-g4H(#yI?uTu>4ZVYw9zr>`eE7*s%h%2 z(b2$DEVkr;L77z7@nNf|F0_CCXk76H5}3mToM1~Bt#g;oW7ldfyU!1O#pV5PIQ<*k zkw*7Wx$i%vYj+BK97WYI$&p5PBJ00;_+AJGy?an##z@U5>k7*@eDl9LP`&SUu7$<$ z<=Bj;gTcFRREU!r+3@#dtuLU7^vUHc#?1Zp1~#FuH?WH?`_MPLs*X-mQEno zeFxABtegR7X>U8D?AdX2)VqfXGQH%{F0ZB{uU(E5APQBkk|qr1&fhw^A(T>G^3bbR zvi}2bDeL&$u@F7qd2r0Fk3vaAy^d($yR>sg4sL0UiNPK)a0@jY%zGgTX2#u^^W)%teN=r_NwrwsI22R+T$^-W&{oRMz9UZYx?(GJp zO579NTwQmLo>P}B%gPefBk18|h0xOI?7@vkyK0d)hqJ!_Nb}X#VejQ`-ORZ{eRyTl zY#NY+`;Rm}uB#YD(H`C`Me#Rq;q>yv`fLBp`g1hbG`E+l8_~+UAPaiLK1ruyV5ClK zk9s-cNUa?-V?L7g=RkX$JE9Cg-G9x{SIAaf;0tlkJ-M`j)K ziWtFn%1omXJOc_&OOsL8o!=x(vk@FyZkb`!UyYlHPx0I!Bg3ynH5IxFtgUo zg+_1*9bCh7E;54ana;IjR->o1(aahn_>D5N4r`wZoNh@%9a>g(inp+$gTT!Smuo2n{*H-Q#6A2F`WdNtw!)3CTer6Z#06RGHCLb zn4TR*T{=-zX75X2o3zofv7$Y(yIV?u(#PYp%erKTbMmzDRju88qw6SLr9ox@$5o zrA`lRo6VQ$vzPP?Gf({#W6d(FsK1ePt9cjcO{Ck+e$r|BpJQG`x{vf+a{>KiNOzb# zo%^$-&oV#6uRllnY;!IBUr&0T@;#4KLjEF0(&S3VQIIH6fR-pVN!kh| zQ#obMB3&Cu#xegbq(gyZHml55()FMrZzCNs{|^4mcDip=eu`Kwx;VnhcL{p*8*?s~ zzWFc}JE);d9?Z?NNP7c?Lc220CT*FkD4$2V7V_E3>?9pBS5tlt>3YcLD04pPNFbh{ ztIP$Y8v`~IUr4&i{D}JJl5P&zv8~EHkMxXy9e3$j0XyN+?E$;nr8@$40e%)yzY}uM zU8EO6o>Jyw(p|6xy@d2K$d$R2d+xoTL<-!w>oqmqnw5))nlC~ccP(soD=0S%EL~S9Od;~)3t%_Qc_iqpGp_1 zb}e8-ZFP&!f+yx)-OAo5lRJ2I8_T=d+>GDqcG5G8#f=GJWk$dnt$|&6KT`qwr33wQPjG^9R z%PQ(Uh@9C+&pms~p;k#KrwbQ5&eJOL3jJP1s|KX%SpBwab=3)0*OaXi%r`}=+hBFK zj@3}@b}My4x3pThTbs&0@OV?kHu{*3%x};>HkEyB6CV?KKycLHVC!M0r>aa^HSO4Za1qp%WClG481lohQ#C79giF8lghY_>m37MpHjx{bZrdv z)+dpKFbNeI$Byi0+xgI)syhpOK<@~P)TBYA;eTK~B$EPYGIw*WPkIqQ=HPBf z8(FB6o@LY5N&2}EA4J2cYEl7O)${HKgJtKLRu`_Rs+&|d)-%owO+*6Cs;1^Vi16r~ zpsMQT*DR=68OAmyax4yC*i%(kQ^OVyTFhWstrJfD9?!}!<<=CnGTa7901B4lhYHnN zj)z#y7=)tlTJ6y1It*4ggj!vNIoL7dJ<}WLKjedd?3d%!bga&Ctw@Rhd4u9$t%!b~aFtNBWadOS$z9-i~?oa9;!FfC%VOa3B6B32n)7sjW z%EZ&9gxwY^^r;HAu&q$RR*-G!RHn35se;|pXJ?A7y>yh#*_qZj;}y5%>;i;Hs8me# z*&tCky>=`C3i%b{y|$1^>QR*H$;8r*V$sg`rLt^*70%P5QOu_@J&uqEG6t#|>sd6s z%4=K@UO%e*X**Sg3!Gdw)pzkmIuUF#vShW1;flC^ie6}|y4Ql5ADQ&=@zT7U5( ztEXhG+P~Rqd*w42>Y3IprWJ<9@8HkT2eRfC1;;Xec zYk$dFzkk0qTzX}_VPeK&aSo=!tVBzNVyvj}lP^Z`8{ec7b|DTjUy2u%ok>I!v0_XW zV$ozehT}{zAB)@3?o_camQ$%{2J^S603xP6>Pb?izF1+CO2&%4c3zbVb|Tsb8bPwT zoSje?T(Y)lX;VjQXKP1OOJ6J>?>#p)xASb!@pPi8rKhPSne9szTax)$pWTwn;)UGK zLzrSPyCqr5ApLBn08u8}qLXgP<+DXQUd-lI4xutI)V+)M=CfIJ&yHs^iCBIc5-r&F zCO{v*7%0S@$HItSU$RTKVjtL>7X8QF|l;4Z;Mkj*$fXG~3T>w&eN>H_kl z2B!|rSR4oujdK2q*-c7z7ljvScS_?0y$mq#aeC2AD#MXrbvWJRtgE)(Y@gkhDJ6<+ z*+NUk-r{V8E$ywdXSbwd-EHlTpbak*I} zIo*rGr@Mn_i8BUHJZN$6&>Mnm>!=gVT?#dXn(vEB7-#1|)#`Ow#0KJyDIGbjaMT;i zB+|$NB#xZyLhu*|WIb_b&?*!QrOBI#g1E7Q1Qx_~7+tj>#98+=|6 z8D9-}QFjGy_s9?3cH^NsFXbC>KZ%>CHZA|XBgf;ge4^I!oFnHqb@$9%DgQp??x|SI z?{xGJLhhb)wR}sRcLrp?$L*e1)#5tqYsTWb+WsnJR`ngDu6FU`b=Kl1&>!aLMStBx zCVVtSA*T<%4Y|k26MYy*D_r3FOkrCe>K=$iqp{be@^-qlXm2g5R=wM_c4J#;&1W5k zjS0KE)Pn*^W}%|#Sa)|G`$+5Y)>uB4=|QDei1ca|1H@9T@oXOt7pgUbheRtLKh8tL zv9Wuj`ay$EeZgxo^w53hJ1mfMUU@=d8?Q;Y@nTcHLd{A&ibk9lwLQ;Q7Vc@nAT*}?JeV|<%km@D) zJ5nKV$rRcu{jG*Sjwk)G+pfQDplQQ#D(LFniwQqdbO^5AZ9=o+(nx1PkGeGw8@&6R zAfE&8J|D<$2k$-?$g_^!=K*=vt9!Ax-*y=w`3Fwohfm`F0lfRnpg-pBJ}bySbCSOM zzE^p+)DL~0!1bxjdHnO(kt!c;PI%glpednTusoadvY$ZUYN31N4lO zJp&8%0OeR4tKhAILxO)H_(Q>cf=>&+A^1OnChG}t!h$V=`U5=U3m+5A2;LyLOYjcC`vrBq z!v28p&kDXJ_=#XO>kxVq1=k9)ektd7b>cR`oq|Jx-xYjF@NWeV3I0m(Il)&1-xmBt zkRL`FXT0DP!4|=D1eXh5Cdj`Y(@w7&ApePh{4Iia2;M9Bu;4yHy}qFTl<@y0xR&b$ z^1Ps4SKxOGf4|_*1YZ~YORg8_Ju3LF;HY2?)(_h!3QiSl6I>v;PS6&-UhpQt0m1tP z9}(OycvSEi!G9AR5&S^#RIFj*Df}mbHQ19F{}jPy zBI3*y{#wDb;AUyxDf~AD?-P7P@MXb265;P-;j0mg@frlD64Aa$_)7#g3YG+S2<{R5 yo*>Fec`%1OXV8z{=YUP%`HbVc2$6rCBqjuJ6#SOp!-7WypBJ>SKhds9@P7eekoV01 literal 0 HcmV?d00001 diff --git a/os/os/linux/fs/pipe.c b/os/os/linux/fs/pipe.c new file mode 100644 index 0000000..dfc4480 --- /dev/null +++ b/os/os/linux/fs/pipe.c @@ -0,0 +1,111 @@ +/* + * linux/fs/pipe.c + * + * (C) 1991 Linus Torvalds + */ + +#include + +#include +#include /* for get_free_page */ +#include + +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 && if_count++; + if (j==1) + f[0]->f_count=0; + if (j<2) + return -1; + j=0; + for(i=0;j<2 && ifilp[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; +} diff --git a/os/os/linux/fs/pipe.o b/os/os/linux/fs/pipe.o new file mode 100644 index 0000000000000000000000000000000000000000..d5b5db26c38f6881a408d3b6291aeb9d28c67659 GIT binary patch literal 8104 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 Jg} +#include +#include + +#include +#include +#include + +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; +} diff --git a/os/os/linux/fs/read_write.o b/os/os/linux/fs/read_write.o new file mode 100644 index 0000000000000000000000000000000000000000..998aad95c9e243e4bfcae9647b34d9235f717844 GIT binary patch literal 7520 zcmbVQYiu0Xb-wf1;mmSLQCvzEBRN?cD{Ezw%cVq1v`kvGMN5?Yh^&V#Id)e2nB}gu zukOx@q+v9+7!{=nR}lg_n!NhJNvN*AKtHNnh1&}46z~!@%^Y@GbSM+Hi&+) z_;%mobMb-b+=o9$?eekszzdgui_HAQ(sVq6%82lGEQ2mj+2<~K+Z0`%8Y+DCs$GC; zV2x_=J>yLH^>=UFxN+@EjO6>iI5qb1OJ4Z(A5i~kU%zGXJdej%Du+ZXEIWMdE6BC9h62MA z*FFygV$Ps-_G5ajP3=Mn;$%Hxqn(z}dF12FaS1v7nUqezq2$`NXa9Tx3EU5_B zL$CjYX`J?3NG#KDtN2$TCPhq$*1Zh&l1x{kusqd^+NERhKFsb6Fan$gvIpkZ%{V(N zJ9h0yU~pX(?-b(gl<{Vm{vh7}iuG{ZTvFY;_QjjTnG(X=ur~Pf2%cx~W!c#o?aC5o zF|j;l-gEiPMoHx)B4Ls3mzS=f%QG^`AM27yzCH~b=81h{o|vy84vfA_LB5zxe^jjM z9J8Fe#WyB?t|@!ilpGHtFFl zG?T&>J^VrFd?BWHXB(%L5ZA*9sf2{yT`%Q@agw2j^l+UuQb_6H?=qSc#`N%HTNp>8+rvEJx4)o5!!}`*qrI4X_Fzhoh5X`%-#!?RyM(FD@9{_~zL|4j2;x%w9$JMc&t58@?@;k{*%Ok&w+_nm(x-f>wBUT}Y`5z|l zvkJAEFp}g0;LwkdZ*m?(d?Us1TSSB^E*H5tq9XJNM)WtvPHuhY01d}zA)MbPznk2& zn$46jc9Gl8%hc~Ck3c^vjB)Zl=ZnmvPvfOOI$1JyrID2V74n6o3`2_SOVcbtX1z+$7$fuzf z#y-*+i|LvseHgtI#)G7Xtvu*{(qmQu^Z@AzYZi2d^eId3xr5}VoD`nMA@aP#H>UB> zLFBV2B0s`pbC1f@en><{!TD3E?lQRpBN@0H2(-Fb|3^riHYk?`YIr1RpZPrM`wMyK zx$5)_BKi)}r44df>KDxDH>E@${enHf<*sdJOZtWR4PK=#v@L#}CpJ#PNZU=3q2H0= zLwI$`@Viy`{%orNt0fg4pnTfl@A1Qz2WHvW9_|(WLQ!n|1Byo(J`5F43+*%cApFr) z;g7BgFMZnKkFN^H=1fZEM%|d~h12YwZX1EEo#gGu) z9YG*QH0@xN!Fz5K2csjf@7D7k2pa5;4Px7%5bKlL-a$Xmw!wo@j$&%lryh`& z{h@Zp^i4uUA*v2g92i?AZh)vp!P<>Ci~Fm7+*?*W_YO{=6F38qIQ)<(`Q#(Gu8<$X z9O~jMn5O-tw+B!8iN~2uCPzxuT)CBZN6MvYYhH9HnhVViQHTaERp~iipOQI-EkaHf z1;R9QMOV>6(^q*5b(a+VYL;fJnKC$*6Q)o0)ELyJaNE%=&(af7$?T+MPhR}?Mf-MD z(RwxISM*ygdopETgyKx=k+xqvda-rUo_zIHY4t-qb^9B58Yiri_Cxx;Q9O34*oQ3p zA^U=TvenY>7_b*lu8Hz9W26}9jwrlz6S>RPTDb8wy-dSP(njZDr>XG>lsQy0i-nt2qZbQK9d-2};arHU(B^0_LwP87g;d-OyxjC=aK!2L9dm2!Y<3!}$)RmrfIcCol zrke6DakVbaq-CWDdWXrC|B6De`0AbV3 zI&vghRW21bucG^jE~U|1-O>dyJwbU2k99UU%bvLh*9F@l#|I|sR9rXghZux<(^B%33bI~Q|P$2|hd zI=WPCRRjhAP>qn_(w-a3FZ#M!xarHmwlsj9X z9E{rcG6Zg*9mQzx!l0frx>Af)nPNQ7^hz-V7E4Dl1SY$q7&4 + +int sys_select() +{ + return -ENOSYS; +} + diff --git a/os/os/linux/fs/select.o b/os/os/linux/fs/select.o new file mode 100644 index 0000000000000000000000000000000000000000..d61f73a39bf58c107d845f3825c695fe69663502 GIT binary patch literal 1776 zcma)7&ubG=5T2J!Yc*|X8^x9irr?h%?k3TorD`oLDvI>~7iJXeveV zCY}@#J&1bs?8UqPfKX4Kdi3hqL;YsoPO~}bz`U9HX5P%3>16x#`kfm}DH2j-P~Rf@ zl+m7QEas>{P2kmV>r<>uh}!akeCds_eOT8?M2Wg)X97y zXXIz{6KZmJ{3ubzqHEJeej#@`cdNkQ($w4KX(HnU<#LNTV+09~f%U6&dCo2MSm&o^ z=r~TL{^ZAS#{HoyMWNGi>XB9FIHI9A%~auDMj@)y@?EFobsJI14^7W`RO+<7ZqF=R zm5SN1Yo)RVO3jdNuC5hVidAdgsuoSx4(hF|?F;i4q1QW&qPbBto4(tQ%w}M_j=AZh zUncKQJrYawEG&Ru~0ZwnU4Z zUPM;Ij%>1OVMtcsbgYI`>u#*Ky`~RWtlPC(;57dvg*F;I@kis zL)RAOsi&aRIIZ<~a{8_RbIu@$_g4DiB@mtO%TCWGy1^hwHd9;uxYGc5+5Qz*MvUa< z9Gq{Nm4w8{zmS6hLcYY~mLMmkQ0ApQ$Ac%gz;MoiD`Am=g*R7#1j7tNTI!1mRP(~3C{b&IOkWGJ +#include + +#include +#include +#include +#include + +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= NR_OPEN || !(f=current->filp[fd]) || !(inode=f->f_inode)) + return -EBADF; + cp_stat(inode,statbuf); + return 0; +} + +int sys_readlink() +{ + return -ENOSYS; +} diff --git a/os/os/linux/fs/stat.o b/os/os/linux/fs/stat.o new file mode 100644 index 0000000000000000000000000000000000000000..fdb41d331a01a0b46c2a069b24d4be4631d5abd0 GIT binary patch literal 7212 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 +#include +#include +#include + +#include +#include + +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;is_imap[i]); + for(i=0;is_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; + } + __asm__ volatile ("cld"); /* by wyj */ + *((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;is_imap[i] = NULL; + for (i=0;is_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;is_imap[i]); + for(i=0;is_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 ; inodei_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;is_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); +} diff --git a/os/os/linux/fs/super.o b/os/os/linux/fs/super.o new file mode 100644 index 0000000000000000000000000000000000000000..b551798da16bfa699c2dc2848c061720be0e1b2a GIT binary patch literal 12284 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 + +#include + +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; +} + diff --git a/os/os/linux/fs/truncate.o b/os/os/linux/fs/truncate.o new file mode 100644 index 0000000000000000000000000000000000000000..8975b924958105c719b40601717933b390dce7b0 GIT binary patch literal 6848 zcmcgwdyHIF89(>2d#5wI)5mVhwk&i?wxz)C>}RR2risfTDql6k`Ht2u6*dO`w#bK=6S=tiRv6=WeG+qVW$; zGWYlUzVn^$ob#RUoO|xvxMKZEP18hBG+~G{k`QlC^lN%0%oeR;qB!to=Yf44y`t7| z@;0bP2ReF320Bb&V#Mrt{e#n|PeX2nO{?&>LftwlplClf(9uRWr@EnQ&y9-Q%};vM z6d(WSlOJ|+8ukZZsefu;N84$P>V{)oIdalx`sZq+&6FOSe)Fj-{&w=Ie>99d`_y~WFFJadTJ43AqqG|toJ|<@VPr7G zHGRzzLV6OWb`yc;{;AyO6kEYc` z{VE5~ko71U8LKPcVe2Su){sZ6HuAOPP1bwl>&Tm}ZSZfbPoUKVtA%Yh%*V6UT138) zyv;gJ`;U>gTbGg#lE*~Iya_(W-2>qX!`w(G*89+ygPeh|-i2@T3OO6Ag?tlv$eIO1 z^Gfn2YcKViA8ADY;mzb*sGp#R6BMpWLul2*AqrP>wrzTN$C%Krhi5|P*TnQlx;m_c z4n2$tCCt_%6(=jqt#sX~hjXlvLP8IBaWGQo)x)E7ErmWkynL)?kshhh!6z8wemxvR z5PV^o9)5{tvSvV!4AJZwnyu8sb66vV)$m5wQdp~pzfWNshqGP}Z{cvRr7)<6x3P^B zHtXSA$Aqi(@cnEfYqsg(E5>TJ>)|3DT*pqcdc^bg2y=THLS7GVXHAMV1;k(%#+LpJ z^17mjkJCYhf~SW!b3R!LyY=t|?8j!T_vzs%&2mp;dG_m(LKX>|{|$r}(2wg1bBEI) z#OpdTp%X4b<_KCfvAgwX*SrBFB=r5@ea5wm;okZ*oEvhe!g8TElC;*XKjUd^XQ!t1 zAZ=3QA?s&wYoz_O9iUCdPumP_vP{yb^;`PMG5cZ`yEKN_w!^xGZS&-_t#;Zw?5oq7 zM*AJ)aqAB9Ve*8vhrB@lbF8)GMe@1UMEWU__gW|LG|J@jtlyJY$md&pT^QGsFA)0s z=xl=FF`ibK6*YDsteNCH$#v^S@?GSn^&C6fP4kcyBHzQ~rU~(67#r8Yw9(qkX51|k z8WS(l^LJR+^9rc2hRNsL25wq$C>rOc@eEl3Hhlm>wpC%vS+=7yK8@ z*;}!cMus_Z5pz)(F8Rgers0uaLLM@5PDPlVK6%J`m-+?dP0;rU zvyXg&B`q)IvlaR|!dyt+W@M^!g?SlyyJ2(Si^yY^i+;_;%Wv?>V?_d03~Cy9i_EV0wJ}f|!C!rZ7i;4Xbk)w<+Id65U2Bw29ix zXiLP1o*SL0O=_HQ4w|=UMl=#x7`ZH>wO}7K3nN5fO-mo*WOj&1WCbi+?{vUcHAYQ{G} zgQTAYwuaLljGXbsUPWP3Jg`d zrBfH7zjNlv-m#exDuz(ql*qWNf^q^x7yI$lwD+UUc*=V}7c3s{c1oE-Eo*ldoKkJK zs8hIm+&U4jr)sT~NqKfWL&teLm5n0-g~+)+x|zJKRNkJ7O)UoDIzy#Y0URrjg_6TE zBHHD(t)X8XI`qTP=Y)IDF|=;$q0kI{R?8oxW^Lo1(5s<$ zLkAx|pwDa3O-#)7QdKXBXJ%NWliWObro5EM+HMB=YAxdlyOi~nZYr58q_DfaYARzV z(~eh6RfLl)Ar`|fNXm1Hwy4P`&YC%*R!q6WBA4>=c2(3|JDV(m*N0}+#x1esvEF!J zyf@ZWOjR@a#m?Nm`QVvCHr6#1>&lgjj@Ol|riyk~rHs3$U4_zNr*>BkG4`Bt$%U#^ z?vgXc!4# zmQGfx_D+AGSdxUmqX(_n4_ehKSZ)~%Gx%jN89l1VP)6l{)cSIXhY_LfVwOd{#u_EQK^NXeChfsDLsyDk<|;CdDW zIpfO7!obH8$CoOkszuSAFBk3ZQZ4Ism))+Cz02Q^U5R*4Pgfz8?oRlMZoHPp;*rUx zszOE_*_d;%Ks%gV&cRzQm#pBu4^;)jX23A2QmyFEMeRvZ8LC!<&FM-J<_vd; z7S}*kgHl}jb7wu@Znl$1Bu??HyYS}uD+tXjT&VQlu6G&Vua-)voTYEtUCp{F;V=)K6- z;&|n;gQD%-B(!}Y?c65QycMSw_44By$XB9R9!=<9iJH{+DqX#ve_*V~FL>9{-ssVy zc+27X>h39GhXB2*kNJRA?Lyqc))H}f4#m^BZN#a}+UeR5CYURuO7c`X&6TRFO;uB+ zAuMN|il;=-0DXvfrd%xA*zoZZ4v9F9AOFzs+t_*R6dW`h%iaj;B3Qrv%G}=B2EOs zgv>hr_9+bPeuTkY3|&wHyPKgP56THnqOJsW_d-V=EbHsA%huU(d@Oh2S3i%3Fc0o2 z&SN}&!94i4W8JXDdMF-%E+|32^?kAqcQ7#sC9Y#*{y1dzS?_N<@|55CK?(c?a)9-E zQ@nFJ&=b%8r<8Ji50p)O=J|zZh>i$hc=DVHWK}J}kQsSKV~DzhhT4!TUSBW&QyEhj zW4-w*L*PzaR}2}EGYUgA3-0rvFiza3L7|)o1R!O8>;z}uB+REDa!^>mIuL-A>+eKk z?~Jqr>pn2wGP5RoJIDEY^#{sJr@_4A3a zJECwA5|vl?O+*~_Jm)lQD6SX3zLqlP?`M^Kx5BS0JfiRi3ZGH zctqi|3Xdy%OW_9!$6-s-&jy8C71|1~SNKVVBMR?Qcv#`X3LjVaQ-!}!_&bFs75+t` zh69cLH!GZ~aHhf@g-aB!Rrqm*X@w<)dllZU@JkB6q42v3pHTR$!apk9(BO|}hr*o- zZ&LVWh2K+nT;YA#Ae_fT3Qs9~hlp55aa6H>wZe@==!cbjNa2G@|A>;GSNMuTxDy&U T&knY~U11EUL+(?^{YLp;_3Udb literal 0 HcmV?d00001 diff --git a/os/os/linux/include/a.out.h b/os/os/linux/include/a.out.h new file mode 100644 index 0000000..3e67974 --- /dev/null +++ b/os/os/linux/include/a.out.h @@ -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__ */ diff --git a/os/os/linux/include/asm/io.h b/os/os/linux/include/asm/io.h new file mode 100644 index 0000000..d5cc42a --- /dev/null +++ b/os/os/linux/include/asm/io.h @@ -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; \ +}) diff --git a/os/os/linux/include/asm/memory.h b/os/os/linux/include/asm/memory.h new file mode 100644 index 0000000..51b69e7 --- /dev/null +++ b/os/os/linux/include/asm/memory.h @@ -0,0 +1,15 @@ +/* + * 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)) \ + ); \ +_res; \ +}) + diff --git a/os/os/linux/include/asm/segment.h b/os/os/linux/include/asm/segment.h new file mode 100644 index 0000000..94dd102 --- /dev/null +++ b/os/os/linux/include/asm/segment.h @@ -0,0 +1,65 @@ +static inline unsigned char get_fs_byte(const char * addr) +{ + unsigned register char _v; + + __asm__ ("movb %%fs:%1,%0":"=r" (_v):"m" (*addr)); + return _v; +} + +static inline unsigned short get_fs_word(const unsigned short *addr) +{ + unsigned short _v; + + __asm__ ("movw %%fs:%1,%0":"=r" (_v):"m" (*addr)); + return _v; +} + +static inline unsigned long get_fs_long(const unsigned long *addr) +{ + unsigned long _v; + + __asm__ ("movl %%fs:%1,%0":"=r" (_v):"m" (*addr)); \ + return _v; +} + +static inline void put_fs_byte(char val,char *addr) +{ +__asm__ ("movb %0,%%fs:%1"::"r" (val),"m" (*addr)); +} + +static inline void put_fs_word(short val,short * addr) +{ +__asm__ ("movw %0,%%fs:%1"::"r" (val),"m" (*addr)); +} + +static 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 ] + */ + +static inline unsigned long get_fs() +{ + unsigned short _v; + __asm__("mov %%fs,%%ax":"=a" (_v):); + return _v; +} + +static inline unsigned long get_ds() +{ + unsigned short _v; + __asm__("mov %%ds,%%ax":"=a" (_v):); + return _v; +} + +static inline void set_fs(unsigned long val) +{ + __asm__("mov %0,%%fs"::"a" ((unsigned short) val)); +} + diff --git a/os/os/linux/include/asm/system.h b/os/os/linux/include/asm/system.h new file mode 100644 index 0000000..0b5a21d --- /dev/null +++ b/os/os/linux/include/asm/system.h @@ -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") diff --git a/os/os/linux/include/const.h b/os/os/linux/include/const.h new file mode 100644 index 0000000..7828e61 --- /dev/null +++ b/os/os/linux/include/const.h @@ -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 diff --git a/os/os/linux/include/ctype.h b/os/os/linux/include/ctype.h new file mode 100644 index 0000000..7acf55d --- /dev/null +++ b/os/os/linux/include/ctype.h @@ -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 diff --git a/os/os/linux/include/errno.h b/os/os/linux/include/errno.h new file mode 100644 index 0000000..c282f69 --- /dev/null +++ b/os/os/linux/include/errno.h @@ -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 diff --git a/os/os/linux/include/fcntl.h b/os/os/linux/include/fcntl.h new file mode 100644 index 0000000..a5bf9af --- /dev/null +++ b/os/os/linux/include/fcntl.h @@ -0,0 +1,55 @@ +#ifndef _FCNTL_H +#define _FCNTL_H + +#include + +/* 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 diff --git a/os/os/linux/include/linux/config.h b/os/os/linux/include/linux/config.h new file mode 100644 index 0000000..c979fb3 --- /dev/null +++ b/os/os/linux/include/linux/config.h @@ -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 diff --git a/os/os/linux/include/linux/fdreg.h b/os/os/linux/include/linux/fdreg.h new file mode 100644 index 0000000..01355af --- /dev/null +++ b/os/os/linux/include/linux/fdreg.h @@ -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 diff --git a/os/os/linux/include/linux/fs.h b/os/os/linux/include/linux/fs.h new file mode 100644 index 0000000..7a90b10 --- /dev/null +++ b/os/os/linux/include/linux/fs.h @@ -0,0 +1,202 @@ +/* + * This file has definitions for some important file table + * structures etc. + */ + +#ifndef _FS_H +#define _FS_H + +#include + +/* 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 diff --git a/os/os/linux/include/linux/hdreg.h b/os/os/linux/include/linux/hdreg.h new file mode 100644 index 0000000..e6c593f --- /dev/null +++ b/os/os/linux/include/linux/hdreg.h @@ -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 diff --git a/os/os/linux/include/linux/head.h b/os/os/linux/include/linux/head.h new file mode 100644 index 0000000..db3dda2 --- /dev/null +++ b/os/os/linux/include/linux/head.h @@ -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 diff --git a/os/os/linux/include/linux/kernel.h b/os/os/linux/include/linux/kernel.h new file mode 100644 index 0000000..cb40dd5 --- /dev/null +++ b/os/os/linux/include/linux/kernel.h @@ -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) + diff --git a/os/os/linux/include/linux/mm.h b/os/os/linux/include/linux/mm.h new file mode 100644 index 0000000..5a160f3 --- /dev/null +++ b/os/os/linux/include/linux/mm.h @@ -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 diff --git a/os/os/linux/include/linux/sched.h b/os/os/linux/include/linux/sched.h new file mode 100644 index 0000000..772646a --- /dev/null +++ b/os/os/linux/include/linux/sched.h @@ -0,0 +1,239 @@ +#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 +#include +#include +#include + +#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__ ("push %%edx\n\t" \ + "movw %%dx,%0\n\t" \ + "rorl $16,%%edx\n\t" \ + "movb %%dl,%1\n\t" \ + "movb %%dh,%2\n\t" \ + "pop %%edx" \ + ::"m" (*((addr)+2)), \ + "m" (*((addr)+4)), \ + "m" (*((addr)+7)), \ + "d" (base) \ + ) + +#define _set_limit(addr,limit) \ +__asm__ ("push %%edx\n\t" \ + "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\n\t" \ + "pop %%edx" \ + ::"m" (*(addr)), \ + "m" (*((addr)+6)), \ + "d" (limit) \ + ) + +#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , (base) ) +#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 ) + +static inline unsigned long _get_base(char * 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))); + return __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 diff --git a/os/os/linux/include/linux/sys.h b/os/os/linux/include/linux/sys.h new file mode 100644 index 0000000..d1cb5bd --- /dev/null +++ b/os/os/linux/include/linux/sys.h @@ -0,0 +1,116 @@ +/* + * 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(); +extern int sys_execve2(); +extern int sys_getdents(); +extern int sys_pipe2(); +extern int sys_sleep(); +extern int sys_getcwd(); +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, sys_execve2, sys_getdents, sys_pipe2, +sys_sleep, sys_getcwd}; + +/* So we don't have to do any more manual updating.... */ +int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr); diff --git a/os/os/linux/include/linux/tty.h b/os/os/linux/include/linux/tty.h new file mode 100644 index 0000000..ad846b3 --- /dev/null +++ b/os/os/linux/include/linux/tty.h @@ -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 + +#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 diff --git a/os/os/linux/include/new0.h b/os/os/linux/include/new0.h new file mode 100644 index 0000000..5f265eb --- /dev/null +++ b/os/os/linux/include/new0.h @@ -0,0 +1,30 @@ +#ifndef _NEW_H +#define _NEW_H + +#include + +struct linux_dirent { + long d_ino; + off_t d_off; + unsigned short d_reclen; + char d_name[14]; +}; + +/* Return value of `mmap' in case of an error. */ +#define MAP_FAILED ((void *) -1) + +#define PROT_READ 0x1 /* page can be read */ +#define PROT_WRITE 0x2 /* page can be written */ +#define PROT_EXEC 0x4 /* page can be executed */ +#define PROT_SEM 0x8 /* page may be used for atomic ops */ +#define PROT_NONE 0x0 /* page can not be accessed */ + +/* compatibility flags */ +#define MAP_FILE 0 + +#define MAP_SHARED 0x01 /* Share changes */ +#define MAP_PRIVATE 0x02 /* Changes are private */ + +#define CLONE_VM 0x00000100 /* set if VM shared between processes */ + +#endif \ No newline at end of file diff --git a/os/os/linux/include/signal.h b/os/os/linux/include/signal.h new file mode 100644 index 0000000..0eea9a3 --- /dev/null +++ b/os/os/linux/include/signal.h @@ -0,0 +1,68 @@ +#ifndef _SIGNAL_H +#define _SIGNAL_H + +#include + +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 */ diff --git a/os/os/linux/include/stdarg.h b/os/os/linux/include/stdarg.h new file mode 100644 index 0000000..fd79ec0 --- /dev/null +++ b/os/os/linux/include/stdarg.h @@ -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 */ diff --git a/os/os/linux/include/stddef.h b/os/os/linux/include/stddef.h new file mode 100644 index 0000000..97f72ff --- /dev/null +++ b/os/os/linux/include/stddef.h @@ -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 diff --git a/os/os/linux/include/string.h b/os/os/linux/include/string.h new file mode 100644 index 0000000..48b91e5 --- /dev/null +++ b/os/os/linux/include/string.h @@ -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)); +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)); +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)); +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) + ); +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)); +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)); +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)); +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)); +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) + ); +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) + ); +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) + ); +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) + ); +return __res; +} + +extern inline int strlen(const char * s) +{ +register int __res ; +__asm__("cld\n\t" + "repne\n\t" + "scasb\n\t" + "notl %0\n\t" + "decl %0" + :"=c" (__res):"D" (s),"a" (0),"0" (0xffffffff)); +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) + ); +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) + ); +return dest; +} + +extern inline void * memmove(void * dest,const void * src, int n) +{ +if (dest + +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 diff --git a/os/os/linux/include/sys/times.h b/os/os/linux/include/sys/times.h new file mode 100644 index 0000000..68d5bfb --- /dev/null +++ b/os/os/linux/include/sys/times.h @@ -0,0 +1,15 @@ +#ifndef _TIMES_H +#define _TIMES_H + +#include + +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 diff --git a/os/os/linux/include/sys/types.h b/os/os/linux/include/sys/types.h new file mode 100644 index 0000000..557aa31 --- /dev/null +++ b/os/os/linux/include/sys/types.h @@ -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 diff --git a/os/os/linux/include/sys/utsname.h b/os/os/linux/include/sys/utsname.h new file mode 100644 index 0000000..0a1c5a0 --- /dev/null +++ b/os/os/linux/include/sys/utsname.h @@ -0,0 +1,16 @@ +#ifndef _SYS_UTSNAME_H +#define _SYS_UTSNAME_H + +#include + +struct utsname { + char sysname[9]; + char nodename[9]; + char release[9]; + char version[9]; + char machine[9]; +}; + +extern int uname(struct utsname * utsbuf); + +#endif diff --git a/os/os/linux/include/sys/wait.h b/os/os/linux/include/sys/wait.h new file mode 100644 index 0000000..53190c2 --- /dev/null +++ b/os/os/linux/include/sys/wait.h @@ -0,0 +1,23 @@ +#ifndef _SYS_WAIT_H +#define _SYS_WAIT_H + +#include + +#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 diff --git a/os/os/linux/include/termios.h b/os/os/linux/include/termios.h new file mode 100644 index 0000000..2b7b913 --- /dev/null +++ b/os/os/linux/include/termios.h @@ -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 diff --git a/os/os/linux/include/time.h b/os/os/linux/include/time.h new file mode 100644 index 0000000..d0a765d --- /dev/null +++ b/os/os/linux/include/time.h @@ -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 diff --git a/os/os/linux/include/unistd.h b/os/os/linux/include/unistd.h new file mode 100644 index 0000000..d0ab29f --- /dev/null +++ b/os/os/linux/include/unistd.h @@ -0,0 +1,276 @@ +#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 +#include +#include +#include + +#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 __NR_execve2 87 +#define __NR_getdents 88 +#define __NR_pipe2 89 +#define __NR_sleep 90 +#define __NR_getcwd 91 +#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); +int sys_getdents(unsigned int fd, struct linux_dirent *d, unsigned int count); +int sys_pipe2(unsigned long * fildes,int flag); +int sys_sleep(unsigned int seconds); +#define __always_inline inline __attribute__((always_inline)) + +#endif diff --git a/os/os/linux/include/utime.h b/os/os/linux/include/utime.h new file mode 100644 index 0000000..83f07c7 --- /dev/null +++ b/os/os/linux/include/utime.h @@ -0,0 +1,13 @@ +#ifndef _UTIME_H +#define _UTIME_H + +#include /* 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 diff --git a/os/os/linux/init/main.c b/os/os/linux/init/main.c new file mode 100644 index 0000000..bd86a68 --- /dev/null +++ b/os/os/linux/init/main.c @@ -0,0 +1,216 @@ +/* + * linux/init/main.c + * + * (C) 1991 Linus Torvalds + */ + +#define __LIBRARY__ +#include +#include + +/* + * 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. + */ + +__always_inline _syscall0(int,fork) +__always_inline _syscall0(int,pause) +__always_inline _syscall1(int,setup,void *,BIOS) +__always_inline _syscall0(int,sync) + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +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; + __asm__ volatile ("cld"); /* by wyj */ + 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() */ +} + +void print_nr(int sid) +{ + if (sid > 86) + printk(" --syscall: sid=%d, pid=%d\n", sid, current->pid); +} diff --git a/os/os/linux/init/main.o b/os/os/linux/init/main.o new file mode 100644 index 0000000000000000000000000000000000000000..03263d3eb0949ce4e61a59fb169e9f5235d01092 GIT binary patch literal 12208 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 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 diff --git a/os/os/linux/kernel/asm.o b/os/os/linux/kernel/asm.o new file mode 100644 index 0000000000000000000000000000000000000000..a89ec75e6e7dea54ae5b8d9b94ba28158b48a77f GIT binary patch literal 1740 zcma)+O=uHQ5XWcRv}sSZ2!7VKN<_gLTB@F^9;`i75B*Zxid{F^*K{@67k4+Yil|sH zrv|)<7wbhmD2RBl?IjkWde90*5b+=$0#XkiyeY()eY^2xiRgpv|Nnb$W-{}d&9$S) z`xHe1e<@H4e+Zz*gMDtmZfJlym?EDGMTQ55PMti_THiEx4rWIp9YYK2@F4#&zm)${ zdN=d3q3K?@?aYKaK6ZL^#Z6j!Eo4c^qL61o9t*iIN>a0?YOGAXEIm;+mxxDna!+$#}~zPg>(|qFzDh#3ziNdZhm7_Gt$HGtt5$ zJb2(2L6$5XS6!9gLaHZMBo4WC>dM&)G@;K)yrt}^F9miX@AvkI_oDBSxC{Lei4UOf zm-sOHL5cg&k4j8uHzb}wuS$Fw{k+6C(HA7XgML}!hv?r*yy$rny5~3eqzG`)Jgcaa zE(!kRc@m2M7T_NN{u$t~^pB$a<^Z<^_)viR13VsJBf!@Kd@I0Ua+O&Yx70Y-8Aw() zvWCvYA?PfYNr0I$z%ZR|;8|u(Ciz8(@r %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 + diff --git a/os/os/linux/kernel/blk_drv/Makefile b/os/os/linux/kernel/blk_drv/Makefile new file mode 100644 index 0000000..1fb57f9 --- /dev/null +++ b/os/os/linux/kernel/blk_drv/Makefile @@ -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 =ar +AS =as +LD =ld +LDFLAGS =-s -x +CC =gcc -march=i386 +CFLAGS =-w -g -fstrength-reduce -fomit-frame-pointer -mcld \ + -finline-functions -nostdinc -fno-stack-protector -I../../include +CPP =gcc -E -nostdinc -I../../include + +.c.s: + $(CC) $(CFLAGS) \ + -S -o $*.s $< +.s.o: + $(AS) -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 diff --git a/os/os/linux/kernel/blk_drv/blk.h b/os/os/linux/kernel/blk_drv/blk.h new file mode 100644 index 0000000..7a69b71 --- /dev/null +++ b/os/os/linux/kernel/blk_drv/blk.h @@ -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 (MAJOR_NR > 3) +/* 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); + +static 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); +} + +static 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 diff --git a/os/os/linux/kernel/blk_drv/blk_drv.a b/os/os/linux/kernel/blk_drv/blk_drv.a new file mode 100644 index 0000000000000000000000000000000000000000..02751f123aa0c72fe90e820ca24599de825468be GIT binary patch literal 52212 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 +#include +#include +#include +#include +#include +#include + +#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)) \ + ) + +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; + current_drive = 1; /* by wyj, ?? */ + 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); +} diff --git a/os/os/linux/kernel/blk_drv/floppy.o b/os/os/linux/kernel/blk_drv/floppy.o new file mode 100644 index 0000000000000000000000000000000000000000..33235bcdcc660371f0cfe6077089e24f2a1c3a96 GIT binary patch literal 16612 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 literal 0 HcmV?d00001 diff --git a/os/os/linux/kernel/blk_drv/hd.c b/os/os/linux/kernel/blk_drv/hd.c new file mode 100644 index 0000000..c0e908f --- /dev/null +++ b/os/os/linux/kernel/blk_drv/hd.c @@ -0,0 +1,351 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#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 = 0; /* 1, wen */ +static int reset = 0; + +/* + * 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)) + +#define port_write(port,buf,nr) \ +__asm__("cld;rep;outsw"::"d" (port),"S" (buf),"c" (nr)) + +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 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 ; driveb_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; */ + int retries=100000; + + /* while (--retries && (inb_p(HD_STATUS)&0xc0)!=0x40); */ + while (--retries && (inb_p(HD_STATUS)&0x80)); + 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); +} diff --git a/os/os/linux/kernel/blk_drv/hd.o b/os/os/linux/kernel/blk_drv/hd.o new file mode 100644 index 0000000000000000000000000000000000000000..bf2b0d10bc58477ea1758f63f765ba3eab8d6225 GIT binary patch literal 15520 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 literal 0 HcmV?d00001 diff --git a/os/os/linux/kernel/blk_drv/ll_rw_blk.c b/os/os/linux/kernel/blk_drv/ll_rw_blk.c new file mode 100644 index 0000000..f57d998 --- /dev/null +++ b/os/os/linux/kernel/blk_drv/ll_rw_blk.c @@ -0,0 +1,165 @@ +/* + * linux/kernel/blk_dev/ll_rw.c + * + * (C) 1991 Linus Torvalds + */ + +/* + * This handles all read/write requests to block devices + */ +#include +#include +#include +#include + +#include "blk.h" + +/* + * The request-struct contains all necessary data + * to load a nr of sectors into memory + */ +struct request request[NR_REQUEST]; + +/* + * used to wait on when there are no free requests + */ +struct task_struct * wait_for_request = NULL; + +/* blk_dev_struct is: + * do_request-address + * next-request + */ +struct blk_dev_struct blk_dev[NR_BLK_DEV] = { + { NULL, NULL }, /* no_dev */ + { NULL, NULL }, /* dev mem */ + { NULL, NULL }, /* dev fd */ + { NULL, NULL }, /* dev hd */ + { NULL, NULL }, /* dev ttyx */ + { NULL, NULL }, /* dev tty */ + { NULL, NULL } /* dev lp */ +}; + +static inline void lock_buffer(struct buffer_head * bh) +{ + cli(); + while (bh->b_lock) + sleep_on(&bh->b_wait); + bh->b_lock=1; + sti(); +} + +static inline void unlock_buffer(struct buffer_head * bh) +{ + if (!bh->b_lock) + printk("ll_rw_block.c: buffer not locked\n\r"); + bh->b_lock = 0; + wake_up(&bh->b_wait); +} + +/* + * add-request adds a request to the linked list. + * It disables interrupts so that it can muck with the + * request-lists in peace. + */ +static void add_request(struct blk_dev_struct * dev, struct request * req) +{ + struct request * tmp; + + req->next = NULL; + cli(); + if (req->bh) + req->bh->b_dirt = 0; + if (!(tmp = dev->current_request)) { + dev->current_request = req; + sti(); + (dev->request_fn)(); + return; + } + for ( ; tmp->next ; tmp=tmp->next) + if ((IN_ORDER(tmp,req) || + !IN_ORDER(tmp,tmp->next)) && + IN_ORDER(req,tmp->next)) + break; + req->next=tmp->next; + tmp->next=req; + sti(); +} + +static void make_request(int major,int rw, struct buffer_head * bh) +{ + struct request * req; + int rw_ahead; + +/* WRITEA/READA is special case - it is not really needed, so if the */ +/* buffer is locked, we just forget about it, else it's a normal read */ + if (rw_ahead = (rw == READA || rw == WRITEA)) { + if (bh->b_lock) + return; + if (rw == READA) + rw = READ; + else + rw = WRITE; + } + if (rw!=READ && rw!=WRITE) + panic("Bad block dev command, must be R/W/RA/WA"); + lock_buffer(bh); + if ((rw == WRITE && !bh->b_dirt) || (rw == READ && bh->b_uptodate)) { + unlock_buffer(bh); + return; + } +repeat: +/* we don't allow the write-requests to fill up the queue completely: + * we want some room for reads: they take precedence. The last third + * of the requests are only for reads. + */ + if (rw == READ) + req = request+NR_REQUEST; + else + req = request+((NR_REQUEST*2)/3); +/* find an empty request */ + while (--req >= request) + if (req->dev<0) + break; +/* if none found, sleep on new requests: check for rw_ahead */ + if (req < request) { + if (rw_ahead) { + unlock_buffer(bh); + return; + } + sleep_on(&wait_for_request); + goto repeat; + } +/* fill up the request-info, and add it to the queue */ + req->dev = bh->b_dev; + req->cmd = rw; + req->errors=0; + req->sector = bh->b_blocknr<<1; + req->nr_sectors = 2; + req->buffer = bh->b_data; + req->waiting = NULL; + req->bh = bh; + req->next = NULL; + add_request(major+blk_dev,req); +} + +void ll_rw_block(int rw, struct buffer_head * bh) +{ + unsigned int major; + + if ((major=MAJOR(bh->b_dev)) >= NR_BLK_DEV || + !(blk_dev[major].request_fn)) { + printk("Trying to read nonexistent block-device\n\r"); + return; + } + make_request(major,rw,bh); +} + +void blk_dev_init(void) +{ + int i; + + for (i=0 ; iYkGs}N`|^F* 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 + +#include +#include +#include +#include +#include +#include +#include + +#define MAJOR_NR 1 +#include "blk.h" + +char *rd_start; +int rd_length = 0; + +void do_rd_request(void) +{ + int len; + char *addr; + + INIT_REQUEST; + addr = rd_start + (CURRENT->sector << 9); + len = CURRENT->nr_sectors << 9; + if ((MINOR(CURRENT->dev) != 1) || (addr+len > rd_start+rd_length)) { + end_request(0); + goto repeat; + } + if (CURRENT-> cmd == WRITE) { + (void ) memcpy(addr, + CURRENT->buffer, + len); + } else if (CURRENT->cmd == READ) { + (void) memcpy(CURRENT->buffer, + addr, + len); + } else + panic("unknown ramdisk-command"); + end_request(1); + goto repeat; +} + +/* + * Returns amount of memory which needs to be reserved. + */ +long rd_init(long mem_start, int length) +{ + int i; + char *cp; + + blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; + rd_start = (char *) mem_start; + rd_length = length; + cp = rd_start; + for (i=0; i < length; i++) + *cp++ = '\0'; + return(length); +} + +/* + * If the root device is the ram disk, try to load it. + * In order to do this, the root device is originally set to the + * floppy, and we later change it to be ram disk. + */ +void rd_load(void) +{ + struct buffer_head *bh; + struct super_block s; + int block = 256; /* Start at block 256 */ + int i = 1; + int nblocks; + char *cp; /* Move pointer */ + + if (!rd_length) + return; + printk("Ram disk: %d bytes, starting at 0x%x\n", rd_length, + (int) rd_start); + if (MAJOR(ROOT_DEV) != 2) + return; + bh = breada(ROOT_DEV,block+1,block,block+2,-1); + if (!bh) { + printk("Disk error while looking for ramdisk!\n"); + return; + } + __asm__ volatile ("cld"); /* by wyj */ + *((struct d_super_block *) &s) = *((struct d_super_block *) bh->b_data); + brelse(bh); + if (s.s_magic != SUPER_MAGIC) + /* No ram disk image present, assume normal floppy boot */ + return; + nblocks = s.s_nzones << s.s_log_zone_size; + if (nblocks > (rd_length >> BLOCK_SIZE_BITS)) { + printk("Ram disk image too big! (%d blocks, %d avail)\n", + nblocks, rd_length >> BLOCK_SIZE_BITS); + return; + } + printk("Loading %d bytes into ram disk... 0000k", + nblocks << BLOCK_SIZE_BITS); + cp = rd_start; + while (nblocks) { + if (nblocks > 2) + bh = breada(ROOT_DEV, block, block+1, block+2, -1); + else + bh = bread(ROOT_DEV, block); + if (!bh) { + printk("I/O error on block %d, aborting load\n", + block); + return; + } + (void) memcpy(cp, bh->b_data, BLOCK_SIZE); + brelse(bh); + printk("\010\010\010\010\010%4dk",i); + cp += BLOCK_SIZE; + block++; + nblocks--; + i++; + } + printk("\010\010\010\010\010done \n"); + ROOT_DEV=0x0101; +} diff --git a/os/os/linux/kernel/blk_drv/ramdisk.o b/os/os/linux/kernel/blk_drv/ramdisk.o new file mode 100644 index 0000000000000000000000000000000000000000..d37a922496b20c46741e78e22466958ee16e9dcd GIT binary patch literal 10664 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 azd^gt2s%I$JikGRTt|uA(-65=A^s1$?rygL literal 0 HcmV?d00001 diff --git a/os/os/linux/kernel/chr_drv/Makefile b/os/os/linux/kernel/chr_drv/Makefile new file mode 100644 index 0000000..9d4d8d1 --- /dev/null +++ b/os/os/linux/kernel/chr_drv/Makefile @@ -0,0 +1,68 @@ +# +# Makefile for the FREAX-kernel character 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 =ar +AS =as +LD =ld +LDFLAGS =-s -x +CC =gcc -march=i386 +CFLAGS =-w -g -fstrength-reduce -fomit-frame-pointer -mcld \ + -finline-functions -nostdinc -fno-stack-protector -I../../include +CPP =gcc -E -nostdinc -I../../include + +.c.s: + $(CC) $(CFLAGS) \ + -S -o $*.s $< +.s.o: + $(AS) -o $*.o $< +.c.o: + $(CC) $(CFLAGS) \ + -c -o $*.o $< + +OBJS = tty_io.o console.o keyboard.2.o serial.o rs_io.o \ + tty_ioctl.o + +chr_drv.a: $(OBJS) + $(AR) rcs chr_drv.a $(OBJS) + sync + +keyboard.2.s: keyboard.S ../../include/linux/config.h + $(CPP) -traditional keyboard.S -o keyboard.2.s + +clean: + rm -f core *.o *.a tmp_make keyboard.2.s + 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: +console.s console.o : console.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/tty.h ../../include/termios.h ../../include/asm/io.h \ + ../../include/asm/system.h +serial.s serial.o : serial.c ../../include/linux/tty.h ../../include/termios.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/asm/system.h ../../include/asm/io.h +tty_io.s tty_io.o : tty_io.c ../../include/ctype.h ../../include/errno.h \ + ../../include/signal.h ../../include/sys/types.h \ + ../../include/linux/sched.h ../../include/linux/head.h \ + ../../include/linux/fs.h ../../include/linux/mm.h ../../include/linux/tty.h \ + ../../include/termios.h ../../include/asm/segment.h \ + ../../include/asm/system.h +tty_ioctl.s tty_ioctl.o : tty_ioctl.c ../../include/errno.h ../../include/termios.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/tty.h ../../include/asm/io.h \ + ../../include/asm/segment.h ../../include/asm/system.h diff --git a/os/os/linux/kernel/chr_drv/chr_drv.a b/os/os/linux/kernel/chr_drv/chr_drv.a new file mode 100644 index 0000000000000000000000000000000000000000..d2f3869a9d5cd226117476be64275b50d1cf4aa7 GIT binary patch literal 68902 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ਞ(_ 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 E8yu$yWB>pF literal 0 HcmV?d00001 diff --git a/os/os/linux/kernel/chr_drv/console.c b/os/os/linux/kernel/chr_drv/console.c new file mode 100644 index 0000000..a12ffbf --- /dev/null +++ b/os/os/linux/kernel/chr_drv/console.c @@ -0,0 +1,710 @@ +/* + * linux/kernel/console.c + * + * (C) 1991 Linus Torvalds + */ + +/* + * console.c + * + * This module implements the console io functions + * 'void con_init(void)' + * 'void con_write(struct tty_queue * queue)' + * Hopefully this will be a rather complete VT102 implementation. + * + * Beeping thanks to John T Kohl. + */ + +/* + * NOTE!!! We sometimes disable and enable interrupts for a short while + * (to put a word in video IO), but this will work even for keyboard + * interrupts. We know interrupts aren't enabled when getting a keyboard + * interrupt, as we use trap-gates. Hopefully all is well. + */ + +/* + * Code to check for different video-cards mostly by Galen Hunt, + * + */ + +#include +#include +#include +#include + +/* + * These are set up by the setup-routine at boot-time: + */ + +#define ORIG_X (*(unsigned char *)0x90000) +#define ORIG_Y (*(unsigned char *)0x90001) +#define ORIG_VIDEO_PAGE (*(unsigned short *)0x90004) +#define ORIG_VIDEO_MODE ((*(unsigned short *)0x90006) & 0xff) +#define ORIG_VIDEO_COLS (((*(unsigned short *)0x90006) & 0xff00) >> 8) +#define ORIG_VIDEO_LINES (25) +#define ORIG_VIDEO_EGA_AX (*(unsigned short *)0x90008) +#define ORIG_VIDEO_EGA_BX (*(unsigned short *)0x9000a) +#define ORIG_VIDEO_EGA_CX (*(unsigned short *)0x9000c) + +#define VIDEO_TYPE_MDA 0x10 /* Monochrome Text Display */ +#define VIDEO_TYPE_CGA 0x11 /* CGA Display */ +#define VIDEO_TYPE_EGAM 0x20 /* EGA/VGA in Monochrome Mode */ +#define VIDEO_TYPE_EGAC 0x21 /* EGA/VGA in Color Mode */ + +#define NPAR 16 + +extern void keyboard_interrupt(void); + +static unsigned char video_type; /* Type of display being used */ +static unsigned long video_num_columns; /* Number of text columns */ +static unsigned long video_size_row; /* Bytes per row */ +static unsigned long video_num_lines; /* Number of test lines */ +static unsigned char video_page; /* Initial video page */ +static unsigned long video_mem_start; /* Start of video RAM */ +static unsigned long video_mem_end; /* End of video RAM (sort of) */ +static unsigned short video_port_reg; /* Video register select port */ +static unsigned short video_port_val; /* Video register value port */ +static unsigned short video_erase_char; /* Char+Attrib to erase with */ + +static unsigned long origin; /* Used for EGA/VGA fast scroll */ +static unsigned long scr_end; /* Used for EGA/VGA fast scroll */ +static unsigned long pos; +static unsigned long x,y; +static unsigned long top,bottom; +static unsigned long state=0; +static unsigned long npar,par[NPAR]; +static unsigned long ques=0; +static unsigned char attr=0x07; + +static void sysbeep(void); + +/* + * this is what the terminal answers to a ESC-Z or csi0c + * query (= vt100 response). + */ +#define RESPONSE "\033[?1;2c" + +/* NOTE! gotoxy thinks x==video_num_columns is ok */ +static inline void gotoxy(unsigned int new_x,unsigned int new_y) +{ + if (new_x > video_num_columns || new_y >= video_num_lines) + return; + x=new_x; + y=new_y; + pos=origin + y*video_size_row + (x<<1); +} + +static inline void set_origin(void) +{ + cli(); + outb_p(12, video_port_reg); + outb_p(0xff&((origin-video_mem_start)>>9), video_port_val); + outb_p(13, video_port_reg); + outb_p(0xff&((origin-video_mem_start)>>1), video_port_val); + sti(); +} + +static void scrup(void) +{ + if (video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_EGAM) + { + if (!top && bottom == video_num_lines) { + origin += video_size_row; + pos += video_size_row; + scr_end += video_size_row; + if (scr_end > video_mem_end) { + __asm__("cld\n\t" + "rep\n\t" + "movsl\n\t" + "movl video_num_columns,%1\n\t" + "rep\n\t" + "stosw" + ::"a" (video_erase_char), + "c" ((video_num_lines-1)*video_num_columns>>1), + "D" (video_mem_start), + "S" (origin) + ); + scr_end -= origin-video_mem_start; + pos -= origin-video_mem_start; + origin = video_mem_start; + } else { + __asm__("cld\n\t" + "rep\n\t" + "stosw" + ::"a" (video_erase_char), + "c" (video_num_columns), + "D" (scr_end-video_size_row) + ); + } + set_origin(); + } else { + __asm__("cld\n\t" + "rep\n\t" + "movsl\n\t" + "movl video_num_columns,%%ecx\n\t" + "rep\n\t" + "stosw" + ::"a" (video_erase_char), + "c" ((bottom-top-1)*video_num_columns>>1), + "D" (origin+video_size_row*top), + "S" (origin+video_size_row*(top+1)) + ); + } + } + else /* Not EGA/VGA */ + { + __asm__("cld\n\t" + "rep\n\t" + "movsl\n\t" + "movl video_num_columns,%%ecx\n\t" + "rep\n\t" + "stosw" + ::"a" (video_erase_char), + "c" ((bottom-top-1)*video_num_columns>>1), + "D" (origin+video_size_row*top), + "S" (origin+video_size_row*(top+1)) + ); + } +} + +static void scrdown(void) +{ + if (video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_EGAM) + { + __asm__("std\n\t" + "rep\n\t" + "movsl\n\t" + "addl $2,%%edi\n\t" /* %edi has been decremented by 4 */ + "movl video_num_columns,%%ecx\n\t" + "rep\n\t" + "stosw" + ::"a" (video_erase_char), + "c" ((bottom-top-1)*video_num_columns>>1), + "D" (origin+video_size_row*bottom-4), + "S" (origin+video_size_row*(bottom-1)-4) + ); + } + else /* Not EGA/VGA */ + { + __asm__("std\n\t" + "rep\n\t" + "movsl\n\t" + "addl $2,%%edi\n\t" /* %edi has been decremented by 4 */ + "movl video_num_columns,%%ecx\n\t" + "rep\n\t" + "stosw" + ::"a" (video_erase_char), + "c" ((bottom-top-1)*video_num_columns>>1), + "D" (origin+video_size_row*bottom-4), + "S" (origin+video_size_row*(bottom-1)-4) + ); + } +} + +static void lf(void) +{ + if (y+1top) { + y--; + pos -= video_size_row; + return; + } + scrdown(); +} + +static void cr(void) +{ + pos -= x<<1; + x=0; +} + +static void del(void) +{ + if (x) { + pos -= 2; + x--; + *(unsigned short *)pos = video_erase_char; + } +} + +static void csi_J(int par) +{ + long count __asm__("cx"); + long start __asm__("di"); + + switch (par) { + case 0: /* erase from cursor to end of display */ + count = (scr_end-pos)>>1; + start = pos; + break; + case 1: /* erase from start to cursor */ + count = (pos-origin)>>1; + start = origin; + break; + case 2: /* erase whole display */ + count = video_num_columns * video_num_lines; + start = origin; + break; + default: + return; + } + __asm__("cld\n\t" + "rep\n\t" + "stosw\n\t" + ::"c" (count), + "D" (start),"a" (video_erase_char) + ); +} + +static void csi_K(int par) +{ + long count __asm__("cx"); + long start __asm__("di"); + + switch (par) { + case 0: /* erase from cursor to end of line */ + if (x>=video_num_columns) + return; + count = video_num_columns-x; + start = pos; + break; + case 1: /* erase from start of line to cursor */ + start = pos - (x<<1); + count = (x>9), video_port_val); + outb_p(15, video_port_reg); + outb_p(0xff&((pos-video_mem_start)>>1), video_port_val); + sti(); +} + +static void respond(struct tty_struct * tty) +{ + char * p = RESPONSE; + + cli(); + while (*p) { + PUTCH(*p,tty->read_q); + p++; + } + sti(); + copy_to_cooked(tty); +} + +static void insert_char(void) +{ + int i=x; + unsigned short tmp, old = video_erase_char; + unsigned short * p = (unsigned short *) pos; + + while (i++=video_num_columns) + return; + i = x; + while (++i < video_num_columns) { + *p = *(p+1); + p++; + } + *p = video_erase_char; +} + +static void delete_line(void) +{ + int oldtop,oldbottom; + + oldtop=top; + oldbottom=bottom; + top=y; + bottom = video_num_lines; + scrup(); + top=oldtop; + bottom=oldbottom; +} + +static void csi_at(unsigned int nr) +{ + if (nr > video_num_columns) + nr = video_num_columns; + else if (!nr) + nr = 1; + while (nr--) + insert_char(); +} + +static void csi_L(unsigned int nr) +{ + if (nr > video_num_lines) + nr = video_num_lines; + else if (!nr) + nr = 1; + while (nr--) + insert_line(); +} + +static void csi_P(unsigned int nr) +{ + if (nr > video_num_columns) + nr = video_num_columns; + else if (!nr) + nr = 1; + while (nr--) + delete_char(); +} + +static void csi_M(unsigned int nr) +{ + if (nr > video_num_lines) + nr = video_num_lines; + else if (!nr) + nr=1; + while (nr--) + delete_line(); +} + +static int saved_x=0; +static int saved_y=0; + +static void save_cur(void) +{ + saved_x=x; + saved_y=y; +} + +static void restore_cur(void) +{ + gotoxy(saved_x, saved_y); +} + +void con_write(struct tty_struct * tty) +{ + int nr; + char c; + + nr = CHARS(tty->write_q); + while (nr--) { + GETCH(tty->write_q,c); + switch(state) { + case 0: + if (c>31 && c<127) { + if (x>=video_num_columns) { + x -= video_num_columns; + pos -= video_size_row; + lf(); + } + __asm__("movb attr,%%ah\n\t" + "movw %%ax,%1\n\t" + ::"a" (c),"m" (*(short *)pos) + ); + pos += 2; + x++; + } else if (c==27) + state=1; + else if (c==10 || c==11 || c==12) + lf(); + else if (c==13) + cr(); + else if (c==ERASE_CHAR(tty)) + del(); + else if (c==8) { + if (x) { + x--; + pos -= 2; + } + } else if (c==9) { + c=8-(x&7); + x += c; + pos += c<<1; + if (x>video_num_columns) { + x -= video_num_columns; + pos -= video_size_row; + lf(); + } + c=9; + } else if (c==7) + sysbeep(); + break; + case 1: + state=0; + if (c=='[') + state=2; + else if (c=='E') + gotoxy(0,y+1); + else if (c=='M') + ri(); + else if (c=='D') + lf(); + else if (c=='Z') + respond(tty); + else if (x=='7') + save_cur(); + else if (x=='8') + restore_cur(); + break; + case 2: + for(npar=0;npar='0' && c<='9') { + par[npar]=10*par[npar]+c-'0'; + break; + } else state=4; + case 4: + state=0; + switch(c) { + case 'G': case '`': + if (par[0]) par[0]--; + gotoxy(par[0],y); + break; + case 'A': + if (!par[0]) par[0]++; + gotoxy(x,y-par[0]); + break; + case 'B': case 'e': + if (!par[0]) par[0]++; + gotoxy(x,y+par[0]); + break; + case 'C': case 'a': + if (!par[0]) par[0]++; + gotoxy(x+par[0],y); + break; + case 'D': + if (!par[0]) par[0]++; + gotoxy(x-par[0],y); + break; + case 'E': + if (!par[0]) par[0]++; + gotoxy(0,y+par[0]); + break; + case 'F': + if (!par[0]) par[0]++; + gotoxy(0,y-par[0]); + break; + case 'd': + if (par[0]) par[0]--; + gotoxy(x,par[0]); + break; + case 'H': case 'f': + if (par[0]) par[0]--; + if (par[1]) par[1]--; + gotoxy(par[1],par[0]); + break; + case 'J': + csi_J(par[0]); + break; + case 'K': + csi_K(par[0]); + break; + case 'L': + csi_L(par[0]); + break; + case 'M': + csi_M(par[0]); + break; + case 'P': + csi_P(par[0]); + break; + case '@': + csi_at(par[0]); + break; + case 'm': + csi_m(); + break; + case 'r': + if (par[0]) par[0]--; + if (!par[1]) par[1] = video_num_lines; + if (par[0] < par[1] && + par[1] <= video_num_lines) { + top=par[0]; + bottom=par[1]; + } + break; + case 's': + save_cur(); + break; + case 'u': + restore_cur(); + break; + } + } + } + set_cursor(); +} + +/* + * void con_init(void); + * + * This routine initalizes console interrupts, and does nothing + * else. If you want the screen to clear, call tty_write with + * the appropriate escape-sequece. + * + * Reads the information preserved by setup.s to determine the current display + * type and sets everything accordingly. + */ +void con_init(void) +{ + register unsigned char a; + char *display_desc = "????"; + char *display_ptr; + + video_num_columns = ORIG_VIDEO_COLS; + video_size_row = video_num_columns * 2; + video_num_lines = ORIG_VIDEO_LINES; + video_page = ORIG_VIDEO_PAGE; + video_erase_char = 0x0720; + + if (ORIG_VIDEO_MODE == 7) /* Is this a monochrome display? */ + { + video_mem_start = 0xb0000; + video_port_reg = 0x3b4; + video_port_val = 0x3b5; + if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) + { + video_type = VIDEO_TYPE_EGAM; + video_mem_end = 0xb8000; + display_desc = "EGAm"; + } + else + { + video_type = VIDEO_TYPE_MDA; + video_mem_end = 0xb2000; + display_desc = "*MDA"; + } + } + else /* If not, it is color. */ + { + video_mem_start = 0xb8000; + video_port_reg = 0x3d4; + video_port_val = 0x3d5; + if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) + { + video_type = VIDEO_TYPE_EGAC; + video_mem_end = 0xbc000; + display_desc = "EGAc"; + } + else + { + video_type = VIDEO_TYPE_CGA; + video_mem_end = 0xba000; + display_desc = "*CGA"; + } + } + + /* Let the user known what kind of display driver we are using */ + + display_ptr = ((char *)video_mem_start) + video_size_row - 8; + while (*display_desc) + { + *display_ptr++ = *display_desc++; + display_ptr++; + } + + /* Initialize the variables used for scrolling (mostly EGA/VGA) */ + + origin = video_mem_start; + scr_end = video_mem_start + video_num_lines * video_size_row; + top = 0; + bottom = video_num_lines; + + gotoxy(ORIG_X,ORIG_Y); + set_trap_gate(0x21,&keyboard_interrupt); + outb_p(inb_p(0x21)&0xfd,0x21); + a=inb_p(0x61); + outb_p(a|0x80,0x61); + outb(a,0x61); +} +/* from bsd-net-2: */ + +void sysbeepstop(void) +{ + /* disable counter 2 */ + outb(inb_p(0x61)&0xFC, 0x61); +} + +int beepcount = 0; + +static void sysbeep(void) +{ + /* enable counter 2 */ + outb_p(inb_p(0x61)|3, 0x61); + /* set command for counter 2, 2 byte write */ + outb_p(0xB6, 0x43); + /* send 0x637 for 750 HZ */ + outb_p(0x37, 0x42); + outb(0x06, 0x42); + /* 1/8 second */ + beepcount = HZ/8; +} diff --git a/os/os/linux/kernel/chr_drv/console.o b/os/os/linux/kernel/chr_drv/console.o new file mode 100644 index 0000000000000000000000000000000000000000..cdb09cf249a683c556a1bd6a57bcc3dbe96270a4 GIT binary patch literal 20896 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" +# 1 "" +# 1 "keyboard.S" + + + + + + + + + + + + + +# 1 "../../include/linux/config.h" 1 + + + + + + + + + + + + + + + + + + + + + +# 36 "../../include/linux/config.h" + +# 47 "../../include/linux/config.h" + +# 14 "keyboard.S" 2 + +.text +.globl keyboard_interrupt + + + + +size = 1024 + +head = 4 +tail = 8 +proc_list = 12 +buf = 16 + +mode: .byte 0 +leds: .byte 2 +e0: .byte 0 + + + + + + +keyboard_interrupt: + pushl %eax + pushl %ebx + pushl %ecx + pushl %edx + push %ds + push %es + movl $0x10,%eax + mov %ax,%ds + mov %ax,%es + xor %al,%al + inb $0x60,%al + cmpb $0xe0,%al + je set_e0 + cmpb $0xe1,%al + je set_e1 + call key_table(,%eax,4) + movb $0,e0 +e0_e1: inb $0x61,%al + jmp 1f +1: jmp 1f +1: orb $0x80,%al + jmp 1f +1: jmp 1f +1: outb %al,$0x61 + jmp 1f +1: jmp 1f +1: andb $0x7F,%al + outb %al,$0x61 + movb $0x20,%al + outb %al,$0x20 + pushl $0 + call do_tty_interrupt + addl $4,%esp + pop %es + pop %ds + popl %edx + popl %ecx + popl %ebx + popl %eax + iret +set_e0: movb $1,e0 + jmp e0_e1 +set_e1: movb $2,e0 + jmp e0_e1 + + + + + + +put_queue: + pushl %ecx + pushl %edx + movl table_list,%edx # read-queue for console + movl head(%edx),%ecx +1: movb %al,buf(%edx,%ecx) + incl %ecx + andl $size-1,%ecx + cmpl tail(%edx),%ecx # buffer full - discard everything + je 3f + shrdl $8,%ebx,%eax + je 2f + shrl $8,%ebx + jmp 1b +2: movl %ecx,head(%edx) + movl proc_list(%edx),%ecx + testl %ecx,%ecx + je 3f + movl $0,(%ecx) +3: popl %edx + popl %ecx + ret + +ctrl: movb $0x04,%al + jmp 1f +alt: movb $0x10,%al +1: cmpb $0,e0 + je 2f + addb %al,%al +2: orb %al,mode + ret +unctrl: movb $0x04,%al + jmp 1f +unalt: movb $0x10,%al +1: cmpb $0,e0 + je 2f + addb %al,%al +2: notb %al + andb %al,mode + ret + +lshift: + orb $0x01,mode + ret +unlshift: + andb $0xfe,mode + ret +rshift: + orb $0x02,mode + ret +unrshift: + andb $0xfd,mode + ret + +caps: testb $0x80,mode + jne 1f + xorb $4,leds + xorb $0x40,mode + orb $0x80,mode +set_leds: + call kb_wait + movb $0xed,%al + outb %al,$0x60 + call kb_wait + movb leds,%al + outb %al,$0x60 + ret +uncaps: andb $0x7f,mode + ret +scroll: + xorb $1,leds + jmp set_leds +num: xorb $2,leds + jmp set_leds + + + + + +cursor: + subb $0x47,%al + jb 1f + cmpb $12,%al + ja 1f + jne cur2 + testb $0x0c,mode + je cur2 + testb $0x30,mode + jne reboot +cur2: cmpb $0x01,e0 + je cur + testb $0x02,leds + je cur + testb $0x03,mode + jne cur + xorl %ebx,%ebx + movb num_table(%eax),%al + jmp put_queue +1: ret + +cur: movb cur_table(%eax),%al + cmpb $'9,%al + ja ok_cur + movb $'~,%ah +ok_cur: shll $16,%eax + movw $0x5b1b,%ax + xorl %ebx,%ebx + jmp put_queue + + + + + +num_table: + .ascii "789 456 1230," + +cur_table: + .ascii "HA5 DGC YB623" + + + + +func: + pushl %eax + pushl %ecx + pushl %edx + call show_stat + popl %edx + popl %ecx + popl %eax + subb $0x3B,%al + jb end_func + cmpb $9,%al + jbe ok_func + subb $18,%al + cmpb $10,%al + jb end_func + cmpb $11,%al + ja end_func +ok_func: + cmpl $4,%ecx + jl end_func + movl func_table(,%eax,4),%eax + xorl %ebx,%ebx + jmp put_queue +end_func: + ret + + + + +func_table: + .long 0x415b5b1b,0x425b5b1b,0x435b5b1b,0x445b5b1b + .long 0x455b5b1b,0x465b5b1b,0x475b5b1b,0x485b5b1b + .long 0x495b5b1b,0x4a5b5b1b,0x4b5b5b1b,0x4c5b5b1b + +# 294 "keyboard.S" + +key_map: + .byte 0,27 + .ascii "1234567890-=" + .byte 127,9 + .ascii "qwertyuiop[]" + .byte 13,0 + .ascii "asdfghjkl;'" + .byte '`,0 + .ascii "\\zxcvbnm,./" + .byte 0,'*,0,32 /* 36-39 */ + .fill 16,1,0 + .byte '-,0,0,0,'+ + .byte 0,0,0,0,0,0,0 + .byte '< + .fill 10,1,0 + + +shift_map: + .byte 0,27 + .ascii "!@#$%^&*()_+" + .byte 127,9 + .ascii "QWERTYUIOP{}" + .byte 13,0 + .ascii "ASDFGHJKL:\"" + .byte '~,0 + .ascii "|ZXCVBNM<>?" + .byte 0,'*,0,32 /* 36-39 */ + .fill 16,1,0 + .byte '-,0,0,0,'+ + .byte 0,0,0,0,0,0,0 + .byte '> + .fill 10,1,0 + +alt_map: + .byte 0,0 + .ascii "\0@\0$\0\0{[]}\\\0" + .byte 0,0 + .byte 0,0,0,0,0,0,0,0,0,0,0 + .byte '~,13,0 + .byte 0,0,0,0,0,0,0,0,0,0,0 + .byte 0,0 + .byte 0,0,0,0,0,0,0,0,0,0,0 + .byte 0,0,0,0 + .fill 16,1,0 + .byte 0,0,0,0,0 + .byte 0,0,0,0,0,0,0 + .byte '| + .fill 10,1,0 + +# 449 "keyboard.S" + + + + +do_self: + lea alt_map,%ebx + testb $0x20,mode + jne 1f + lea shift_map,%ebx + testb $0x03,mode + jne 1f + lea key_map,%ebx +1: movb (%ebx,%eax),%al + orb %al,%al + je none + testb $0x4c,mode + je 2f + cmpb $'a,%al + jb 2f + cmpb $'},%al + ja 2f + subb $32,%al +2: testb $0x0c,mode + je 3f + cmpb $64,%al + jb 3f + cmpb $64+32,%al + jae 3f + subb $64,%al +3: testb $0x10,mode + je 4f + orb $0x80,%al +4: andl $0xff,%eax + xorl %ebx,%ebx + call put_queue +none: ret + + + + + + +minus: cmpb $1,e0 + jne do_self + movl $'/,%eax + xorl %ebx,%ebx + jmp put_queue + + + + + + +key_table: + .long none,do_self,do_self,do_self + .long do_self,do_self,do_self,do_self + .long do_self,do_self,do_self,do_self + .long do_self,do_self,do_self,do_self + .long do_self,do_self,do_self,do_self + .long do_self,do_self,do_self,do_self + .long do_self,do_self,do_self,do_self + .long do_self,ctrl,do_self,do_self + .long do_self,do_self,do_self,do_self + .long do_self,do_self,do_self,do_self + .long do_self,do_self,lshift,do_self + .long do_self,do_self,do_self,do_self + .long do_self,do_self,do_self,do_self + .long do_self,minus,rshift,do_self + .long alt,do_self,caps,func + .long func,func,func,func + .long func,func,func,func + .long func,num,scroll,cursor + .long cursor,cursor,do_self,cursor + .long cursor,cursor,do_self,cursor + .long cursor,cursor,cursor,cursor + .long none,none,do_self,func + .long func,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,unctrl,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,unlshift,none + .long none,none,none,none + .long none,none,none,none + .long none,none,unrshift,none + .long unalt,none,uncaps,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + .long none,none,none,none + + + + + +kb_wait: + pushl %eax +1: inb $0x64,%al + testb $0x02,%al + jne 1b + popl %eax + ret + + + + +reboot: + call kb_wait + movw $0x1234,0x472 + movb $0xfc,%al + outb %al,$0x64 +die: jmp die diff --git a/os/os/linux/kernel/chr_drv/keyboard.S b/os/os/linux/kernel/chr_drv/keyboard.S new file mode 100644 index 0000000..25210b4 --- /dev/null +++ b/os/os/linux/kernel/chr_drv/keyboard.S @@ -0,0 +1,588 @@ +/* + * linux/kernel/keyboard.S + * + * (C) 1991 Linus Torvalds + */ + +/* + * Thanks to Alfred Leung for US keyboard patches + * Wolfgang Thiel for German keyboard patches + * Marc Corsini for the French keyboard + */ + +#include + +.text +.globl keyboard_interrupt + +/* + * these are for the keyboard read functions + */ +size = 1024 /* must be a power of two ! And MUST be the same + as in tty_io.c !!!! */ +head = 4 +tail = 8 +proc_list = 12 +buf = 16 + +mode: .byte 0 /* caps, alt, ctrl and shift mode */ +leds: .byte 2 /* num-lock, caps, scroll-lock mode (nom-lock on) */ +e0: .byte 0 + +/* + * con_int is the real interrupt routine that reads the + * keyboard scan-code and converts it into the appropriate + * ascii character(s). + */ +keyboard_interrupt: + pushl %eax + pushl %ebx + pushl %ecx + pushl %edx + push %ds + push %es + movl $0x10,%eax + mov %ax,%ds + mov %ax,%es + xor %al,%al /* %eax is scan code */ + inb $0x60,%al + cmpb $0xe0,%al + je set_e0 + cmpb $0xe1,%al + je set_e1 + call key_table(,%eax,4) + movb $0,e0 +e0_e1: inb $0x61,%al + jmp 1f +1: jmp 1f +1: orb $0x80,%al + jmp 1f +1: jmp 1f +1: outb %al,$0x61 + jmp 1f +1: jmp 1f +1: andb $0x7F,%al + outb %al,$0x61 + movb $0x20,%al + outb %al,$0x20 + pushl $0 + call do_tty_interrupt + addl $4,%esp + pop %es + pop %ds + popl %edx + popl %ecx + popl %ebx + popl %eax + iret +set_e0: movb $1,e0 + jmp e0_e1 +set_e1: movb $2,e0 + jmp e0_e1 + +/* + * This routine fills the buffer with max 8 bytes, taken from + * %ebx:%eax. (%edx is high). The bytes are written in the + * order %al,%ah,%eal,%eah,%bl,%bh ... until %eax is zero. + */ +put_queue: + pushl %ecx + pushl %edx + movl table_list,%edx # read-queue for console + movl head(%edx),%ecx +1: movb %al,buf(%edx,%ecx) + incl %ecx + andl $size-1,%ecx + cmpl tail(%edx),%ecx # buffer full - discard everything + je 3f + shrdl $8,%ebx,%eax + je 2f + shrl $8,%ebx + jmp 1b +2: movl %ecx,head(%edx) + movl proc_list(%edx),%ecx + testl %ecx,%ecx + je 3f + movl $0,(%ecx) +3: popl %edx + popl %ecx + ret + +ctrl: movb $0x04,%al + jmp 1f +alt: movb $0x10,%al +1: cmpb $0,e0 + je 2f + addb %al,%al +2: orb %al,mode + ret +unctrl: movb $0x04,%al + jmp 1f +unalt: movb $0x10,%al +1: cmpb $0,e0 + je 2f + addb %al,%al +2: notb %al + andb %al,mode + ret + +lshift: + orb $0x01,mode + ret +unlshift: + andb $0xfe,mode + ret +rshift: + orb $0x02,mode + ret +unrshift: + andb $0xfd,mode + ret + +caps: testb $0x80,mode + jne 1f + xorb $4,leds + xorb $0x40,mode + orb $0x80,mode +set_leds: + call kb_wait + movb $0xed,%al /* set leds command */ + outb %al,$0x60 + call kb_wait + movb leds,%al + outb %al,$0x60 + ret +uncaps: andb $0x7f,mode + ret +scroll: + xorb $1,leds + jmp set_leds +num: xorb $2,leds + jmp set_leds + +/* + * curosr-key/numeric keypad cursor keys are handled here. + * checking for numeric keypad etc. + */ +cursor: + subb $0x47,%al + jb 1f + cmpb $12,%al + ja 1f + jne cur2 /* check for ctrl-alt-del */ + testb $0x0c,mode + je cur2 + testb $0x30,mode + jne reboot +cur2: cmpb $0x01,e0 /* e0 forces cursor movement */ + je cur + testb $0x02,leds /* not num-lock forces cursor */ + je cur + testb $0x03,mode /* shift forces cursor */ + jne cur + xorl %ebx,%ebx + movb num_table(%eax),%al + jmp put_queue +1: ret + +cur: movb cur_table(%eax),%al + cmpb $'9,%al + ja ok_cur + movb $'~,%ah +ok_cur: shll $16,%eax + movw $0x5b1b,%ax + xorl %ebx,%ebx + jmp put_queue + +#if defined(KBD_FR) +num_table: + .ascii "789 456 1230." +#else +num_table: + .ascii "789 456 1230," +#endif +cur_table: + .ascii "HA5 DGC YB623" + +/* + * this routine handles function keys + */ +func: + pushl %eax + pushl %ecx + pushl %edx + call show_stat + popl %edx + popl %ecx + popl %eax + subb $0x3B,%al + jb end_func + cmpb $9,%al + jbe ok_func + subb $18,%al + cmpb $10,%al + jb end_func + cmpb $11,%al + ja end_func +ok_func: + cmpl $4,%ecx /* check that there is enough room */ + jl end_func + movl func_table(,%eax,4),%eax + xorl %ebx,%ebx + jmp put_queue +end_func: + ret + +/* + * function keys send F1:'esc [ [ A' F2:'esc [ [ B' etc. + */ +func_table: + .long 0x415b5b1b,0x425b5b1b,0x435b5b1b,0x445b5b1b + .long 0x455b5b1b,0x465b5b1b,0x475b5b1b,0x485b5b1b + .long 0x495b5b1b,0x4a5b5b1b,0x4b5b5b1b,0x4c5b5b1b + +#if defined(KBD_FINNISH) +key_map: + .byte 0,27 + .ascii "1234567890+'" + .byte 127,9 + .ascii "qwertyuiop}" + .byte 0,13,0 + .ascii "asdfghjkl|{" + .byte 0,0 + .ascii "'zxcvbnm,.-" + .byte 0,'*,0,32 /* 36-39 */ + .fill 16,1,0 /* 3A-49 */ + .byte '-,0,0,0,'+ /* 4A-4E */ + .byte 0,0,0,0,0,0,0 /* 4F-55 */ + .byte '< + .fill 10,1,0 + +shift_map: + .byte 0,27 + .ascii "!\"#$%&/()=?`" + .byte 127,9 + .ascii "QWERTYUIOP]^" + .byte 13,0 + .ascii "ASDFGHJKL\\[" + .byte 0,0 + .ascii "*ZXCVBNM;:_" + .byte 0,'*,0,32 /* 36-39 */ + .fill 16,1,0 /* 3A-49 */ + .byte '-,0,0,0,'+ /* 4A-4E */ + .byte 0,0,0,0,0,0,0 /* 4F-55 */ + .byte '> + .fill 10,1,0 + +alt_map: + .byte 0,0 + .ascii "\0@\0$\0\0{[]}\\\0" + .byte 0,0 + .byte 0,0,0,0,0,0,0,0,0,0,0 + .byte '~,13,0 + .byte 0,0,0,0,0,0,0,0,0,0,0 + .byte 0,0 + .byte 0,0,0,0,0,0,0,0,0,0,0 + .byte 0,0,0,0 /* 36-39 */ + .fill 16,1,0 /* 3A-49 */ + .byte 0,0,0,0,0 /* 4A-4E */ + .byte 0,0,0,0,0,0,0 /* 4F-55 */ + .byte '| + .fill 10,1,0 + +#elif defined(KBD_US) + +key_map: + .byte 0,27 + .ascii "1234567890-=" + .byte 127,9 + .ascii "qwertyuiop[]" + .byte 13,0 + .ascii "asdfghjkl;'" + .byte '`,0 + .ascii "\\zxcvbnm,./" + .byte 0,'*,0,32 /* 36-39 */ + .fill 16,1,0 /* 3A-49 */ + .byte '-,0,0,0,'+ /* 4A-4E */ + .byte 0,0,0,0,0,0,0 /* 4F-55 */ + .byte '< + .fill 10,1,0 + + +shift_map: + .byte 0,27 + .ascii "!@#$%^&*()_+" + .byte 127,9 + .ascii "QWERTYUIOP{}" + .byte 13,0 + .ascii "ASDFGHJKL:\"" + .byte '~,0 + .ascii "|ZXCVBNM<>?" + .byte 0,'*,0,32 /* 36-39 */ + .fill 16,1,0 /* 3A-49 */ + .byte '-,0,0,0,'+ /* 4A-4E */ + .byte 0,0,0,0,0,0,0 /* 4F-55 */ + .byte '> + .fill 10,1,0 + +alt_map: + .byte 0,0 + .ascii "\0@\0$\0\0{[]}\\\0" + .byte 0,0 + .byte 0,0,0,0,0,0,0,0,0,0,0 + .byte '~,13,0 + .byte 0,0,0,0,0,0,0,0,0,0,0 + .byte 0,0 + .byte 0,0,0,0,0,0,0,0,0,0,0 + .byte 0,0,0,0 /* 36-39 */ + .fill 16,1,0 /* 3A-49 */ + .byte 0,0,0,0,0 /* 4A-4E */ + .byte 0,0,0,0,0,0,0 /* 4F-55 */ + .byte '| + .fill 10,1,0 + +#elif defined(KBD_GR) + +key_map: + .byte 0,27 + .ascii "1234567890\\'" + .byte 127,9 + .ascii "qwertzuiop@+" + .byte 13,0 + .ascii "asdfghjkl[]^" + .byte 0,'# + .ascii "yxcvbnm,.-" + .byte 0,'*,0,32 /* 36-39 */ + .fill 16,1,0 /* 3A-49 */ + .byte '-,0,0,0,'+ /* 4A-4E */ + .byte 0,0,0,0,0,0,0 /* 4F-55 */ + .byte '< + .fill 10,1,0 + + +shift_map: + .byte 0,27 + .ascii "!\"#$%&/()=?`" + .byte 127,9 + .ascii "QWERTZUIOP\\*" + .byte 13,0 + .ascii "ASDFGHJKL{}~" + .byte 0,'' + .ascii "YXCVBNM;:_" + .byte 0,'*,0,32 /* 36-39 */ + .fill 16,1,0 /* 3A-49 */ + .byte '-,0,0,0,'+ /* 4A-4E */ + .byte 0,0,0,0,0,0,0 /* 4F-55 */ + .byte '> + .fill 10,1,0 + +alt_map: + .byte 0,0 + .ascii "\0@\0$\0\0{[]}\\\0" + .byte 0,0 + .byte '@,0,0,0,0,0,0,0,0,0,0 + .byte '~,13,0 + .byte 0,0,0,0,0,0,0,0,0,0,0 + .byte 0,0 + .byte 0,0,0,0,0,0,0,0,0,0,0 + .byte 0,0,0,0 /* 36-39 */ + .fill 16,1,0 /* 3A-49 */ + .byte 0,0,0,0,0 /* 4A-4E */ + .byte 0,0,0,0,0,0,0 /* 4F-55 */ + .byte '| + .fill 10,1,0 + + +#elif defined(KBD_FR) + +key_map: + .byte 0,27 + .ascii "&{\"'(-}_/@)=" + .byte 127,9 + .ascii "azertyuiop^$" + .byte 13,0 + .ascii "qsdfghjklm|" + .byte '`,0,42 /* coin sup gauche, don't know, [*|mu] */ + .ascii "wxcvbn,;:!" + .byte 0,'*,0,32 /* 36-39 */ + .fill 16,1,0 /* 3A-49 */ + .byte '-,0,0,0,'+ /* 4A-4E */ + .byte 0,0,0,0,0,0,0 /* 4F-55 */ + .byte '< + .fill 10,1,0 + +shift_map: + .byte 0,27 + .ascii "1234567890]+" + .byte 127,9 + .ascii "AZERTYUIOP<>" + .byte 13,0 + .ascii "QSDFGHJKLM%" + .byte '~,0,'# + .ascii "WXCVBN?./\\" + .byte 0,'*,0,32 /* 36-39 */ + .fill 16,1,0 /* 3A-49 */ + .byte '-,0,0,0,'+ /* 4A-4E */ + .byte 0,0,0,0,0,0,0 /* 4F-55 */ + .byte '> + .fill 10,1,0 + +alt_map: + .byte 0,0 + .ascii "\0~#{[|`\\^@]}" + .byte 0,0 + .byte '@,0,0,0,0,0,0,0,0,0,0 + .byte '~,13,0 + .byte 0,0,0,0,0,0,0,0,0,0,0 + .byte 0,0 + .byte 0,0,0,0,0,0,0,0,0,0,0 + .byte 0,0,0,0 /* 36-39 */ + .fill 16,1,0 /* 3A-49 */ + .byte 0,0,0,0,0 /* 4A-4E */ + .byte 0,0,0,0,0,0,0 /* 4F-55 */ + .byte '| + .fill 10,1,0 + +#else +#error "KBD-type not defined" +#endif +/* + * do_self handles "normal" keys, ie keys that don't change meaning + * and which have just one character returns. + */ +do_self: + lea alt_map,%ebx + testb $0x20,mode /* alt-gr */ + jne 1f + lea shift_map,%ebx + testb $0x03,mode + jne 1f + lea key_map,%ebx +1: movb (%ebx,%eax),%al + orb %al,%al + je none + testb $0x4c,mode /* ctrl or caps */ + je 2f + cmpb $'a,%al + jb 2f + cmpb $'},%al + ja 2f + subb $32,%al +2: testb $0x0c,mode /* ctrl */ + je 3f + cmpb $64,%al + jb 3f + cmpb $64+32,%al + jae 3f + subb $64,%al +3: testb $0x10,mode /* left alt */ + je 4f + orb $0x80,%al +4: andl $0xff,%eax + xorl %ebx,%ebx + call put_queue +none: ret + +/* + * minus has a routine of it's own, as a 'E0h' before + * the scan code for minus means that the numeric keypad + * slash was pushed. + */ +minus: cmpb $1,e0 + jne do_self + movl $'/,%eax + xorl %ebx,%ebx + jmp put_queue + +/* + * This table decides which routine to call when a scan-code has been + * gotten. Most routines just call do_self, or none, depending if + * they are make or break. + */ +key_table: + .long none,do_self,do_self,do_self /* 00-03 s0 esc 1 2 */ + .long do_self,do_self,do_self,do_self /* 04-07 3 4 5 6 */ + .long do_self,do_self,do_self,do_self /* 08-0B 7 8 9 0 */ + .long do_self,do_self,do_self,do_self /* 0C-0F + ' bs tab */ + .long do_self,do_self,do_self,do_self /* 10-13 q w e r */ + .long do_self,do_self,do_self,do_self /* 14-17 t y u i */ + .long do_self,do_self,do_self,do_self /* 18-1B o p } ^ */ + .long do_self,ctrl,do_self,do_self /* 1C-1F enter ctrl a s */ + .long do_self,do_self,do_self,do_self /* 20-23 d f g h */ + .long do_self,do_self,do_self,do_self /* 24-27 j k l | */ + .long do_self,do_self,lshift,do_self /* 28-2B { para lshift , */ + .long do_self,do_self,do_self,do_self /* 2C-2F z x c v */ + .long do_self,do_self,do_self,do_self /* 30-33 b n m , */ + .long do_self,minus,rshift,do_self /* 34-37 . - rshift * */ + .long alt,do_self,caps,func /* 38-3B alt sp caps f1 */ + .long func,func,func,func /* 3C-3F f2 f3 f4 f5 */ + .long func,func,func,func /* 40-43 f6 f7 f8 f9 */ + .long func,num,scroll,cursor /* 44-47 f10 num scr home */ + .long cursor,cursor,do_self,cursor /* 48-4B up pgup - left */ + .long cursor,cursor,do_self,cursor /* 4C-4F n5 right + end */ + .long cursor,cursor,cursor,cursor /* 50-53 dn pgdn ins del */ + .long none,none,do_self,func /* 54-57 sysreq ? < f11 */ + .long func,none,none,none /* 58-5B f12 ? ? ? */ + .long none,none,none,none /* 5C-5F ? ? ? ? */ + .long none,none,none,none /* 60-63 ? ? ? ? */ + .long none,none,none,none /* 64-67 ? ? ? ? */ + .long none,none,none,none /* 68-6B ? ? ? ? */ + .long none,none,none,none /* 6C-6F ? ? ? ? */ + .long none,none,none,none /* 70-73 ? ? ? ? */ + .long none,none,none,none /* 74-77 ? ? ? ? */ + .long none,none,none,none /* 78-7B ? ? ? ? */ + .long none,none,none,none /* 7C-7F ? ? ? ? */ + .long none,none,none,none /* 80-83 ? br br br */ + .long none,none,none,none /* 84-87 br br br br */ + .long none,none,none,none /* 88-8B br br br br */ + .long none,none,none,none /* 8C-8F br br br br */ + .long none,none,none,none /* 90-93 br br br br */ + .long none,none,none,none /* 94-97 br br br br */ + .long none,none,none,none /* 98-9B br br br br */ + .long none,unctrl,none,none /* 9C-9F br unctrl br br */ + .long none,none,none,none /* A0-A3 br br br br */ + .long none,none,none,none /* A4-A7 br br br br */ + .long none,none,unlshift,none /* A8-AB br br unlshift br */ + .long none,none,none,none /* AC-AF br br br br */ + .long none,none,none,none /* B0-B3 br br br br */ + .long none,none,unrshift,none /* B4-B7 br br unrshift br */ + .long unalt,none,uncaps,none /* B8-BB unalt br uncaps br */ + .long none,none,none,none /* BC-BF br br br br */ + .long none,none,none,none /* C0-C3 br br br br */ + .long none,none,none,none /* C4-C7 br br br br */ + .long none,none,none,none /* C8-CB br br br br */ + .long none,none,none,none /* CC-CF br br br br */ + .long none,none,none,none /* D0-D3 br br br br */ + .long none,none,none,none /* D4-D7 br br br br */ + .long none,none,none,none /* D8-DB br ? ? ? */ + .long none,none,none,none /* DC-DF ? ? ? ? */ + .long none,none,none,none /* E0-E3 e0 e1 ? ? */ + .long none,none,none,none /* E4-E7 ? ? ? ? */ + .long none,none,none,none /* E8-EB ? ? ? ? */ + .long none,none,none,none /* EC-EF ? ? ? ? */ + .long none,none,none,none /* F0-F3 ? ? ? ? */ + .long none,none,none,none /* F4-F7 ? ? ? ? */ + .long none,none,none,none /* F8-FB ? ? ? ? */ + .long none,none,none,none /* FC-FF ? ? ? ? */ + +/* + * kb_wait waits for the keyboard controller buffer to empty. + * there is no timeout - if the buffer doesn't empty, we hang. + */ +kb_wait: + pushl %eax +1: inb $0x64,%al + testb $0x02,%al + jne 1b + popl %eax + ret +/* + * This routine reboots the machine by asking the keyboard + * controller to pulse the reset-line low. + */ +reboot: + call kb_wait + movw $0x1234,0x472 /* don't do memory check */ + movb $0xfc,%al /* pulse reset and A20 low */ + outb %al,$0x64 +die: jmp die diff --git a/os/os/linux/kernel/chr_drv/rs_io.o b/os/os/linux/kernel/chr_drv/rs_io.o new file mode 100644 index 0000000000000000000000000000000000000000..9d7d5b3a22aa1a7d33dea95b723af176ee68e951 GIT binary patch literal 1320 zcma)5O=}ZT6upy7lN1_>vDAuUi$oC$(TZ-YF8rt{7SvR*(+bl`=7mYg$1w9^jTe}J1pL8J+VS-DUc@11#5ry}TuH|L!9&O7g8W*$#YU6UjU z!jd2kzZJlJAu zYUu}^X)*0615dy3#7CS5;3%o*n6o2-mX*|mBJ()SkJ>Kxy3mDOdS@N-cB{sLjja`nuw?{k1!T?BECWK1Ur++2eHxq=#!x{gli&& zBRH@@L{yj;>c8RMuaxqliKJ!!PW(mv0M`reH^_6neMo3eLAl-mBy=A^x!y36flz|$ z9Yaq056bmU5ZT?V>*Z0VgF%1b96oaqeG&Pkh$c>dL{JjkL^3ZF1^Vqn>-rt20MOw)mDl`5E4qoh_V zHiu%f3^vy+-ZaTqsdKQH=_9M_uuwBq{86e5Y7L#$RJ8J@4U1NVGqq%B7P>V(VAV>U z?KNO{nOQ2UnY@MR;}pv*t7+mQ_L+$Cmk2hbH&o7BkuiEb(opct5uPWFopkSn(*o}a PoD +#include +#include +#include + +#define WAKEUP_CHARS (TTY_BUF_SIZE/4) + +extern void rs1_interrupt(void); +extern void rs2_interrupt(void); + +static void init(int port) +{ + outb_p(0x80,port+3); /* set DLAB of line control reg */ + outb_p(0x30,port); /* LS of divisor (48 -> 2400 bps */ + outb_p(0x00,port+1); /* MS of divisor */ + outb_p(0x03,port+3); /* reset DLAB */ + outb_p(0x0b,port+4); /* set DTR,RTS, OUT_2 */ + outb_p(0x0d,port+1); /* enable all intrs but writes */ + (void)inb(port); /* read data port to reset things (?) */ +} + +void rs_init(void) +{ + set_intr_gate(0x24,rs1_interrupt); + set_intr_gate(0x23,rs2_interrupt); + init(tty_table[1].read_q.data); + init(tty_table[2].read_q.data); + outb(inb_p(0x21)&0xE7,0x21); +} + +/* + * This routine gets called when tty_write has put something into + * the write_queue. It must check wheter the queue is empty, and + * set the interrupt register accordingly + * + * void _rs_write(struct tty_struct * tty); + */ +void rs_write(struct tty_struct * tty) +{ + cli(); + if (!EMPTY(tty->write_q)) + outb(inb_p(tty->write_q.data+1)|0x02,tty->write_q.data+1); + sti(); +} diff --git a/os/os/linux/kernel/chr_drv/serial.o b/os/os/linux/kernel/chr_drv/serial.o new file mode 100644 index 0000000000000000000000000000000000000000..bf80e08be94a19c3982f10989e20a6e929a1d240 GIT binary patch literal 6752 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 +#include +#include + +#define ALRMMASK (1<<(SIGALRM-1)) +#define KILLMASK (1<<(SIGKILL-1)) +#define INTMASK (1<<(SIGINT-1)) +#define QUITMASK (1<<(SIGQUIT-1)) +#define TSTPMASK (1<<(SIGTSTP-1)) + +#include +#include +#include +#include + +#define _L_FLAG(tty,f) ((tty)->termios.c_lflag & f) +#define _I_FLAG(tty,f) ((tty)->termios.c_iflag & f) +#define _O_FLAG(tty,f) ((tty)->termios.c_oflag & f) + +#define L_CANON(tty) _L_FLAG((tty),ICANON) +#define L_ISIG(tty) _L_FLAG((tty),ISIG) +#define L_ECHO(tty) _L_FLAG((tty),ECHO) +#define L_ECHOE(tty) _L_FLAG((tty),ECHOE) +#define L_ECHOK(tty) _L_FLAG((tty),ECHOK) +#define L_ECHOCTL(tty) _L_FLAG((tty),ECHOCTL) +#define L_ECHOKE(tty) _L_FLAG((tty),ECHOKE) + +#define I_UCLC(tty) _I_FLAG((tty),IUCLC) +#define I_NLCR(tty) _I_FLAG((tty),INLCR) +#define I_CRNL(tty) _I_FLAG((tty),ICRNL) +#define I_NOCR(tty) _I_FLAG((tty),IGNCR) + +#define O_POST(tty) _O_FLAG((tty),OPOST) +#define O_NLCR(tty) _O_FLAG((tty),ONLCR) +#define O_CRNL(tty) _O_FLAG((tty),OCRNL) +#define O_NLRET(tty) _O_FLAG((tty),ONLRET) +#define O_LCUC(tty) _O_FLAG((tty),OLCUC) + +struct tty_struct tty_table[] = { + { + {ICRNL, /* change incoming CR to NL */ + OPOST|ONLCR, /* change outgoing NL to CRNL */ + 0, + ISIG | ICANON | ECHO | ECHOCTL | ECHOKE, + 0, /* console termio */ + INIT_C_CC}, + 0, /* initial pgrp */ + 0, /* initial stopped */ + con_write, + {0,0,0,0,""}, /* console read-queue */ + {0,0,0,0,""}, /* console write-queue */ + {0,0,0,0,""} /* console secondary queue */ + },{ + {0, /* no translation */ + 0, /* no translation */ + B2400 | CS8, + 0, + 0, + INIT_C_CC}, + 0, + 0, + rs_write, + {0x3f8,0,0,0,""}, /* rs 1 */ + {0x3f8,0,0,0,""}, + {0,0,0,0,""} + },{ + {0, /* no translation */ + 0, /* no translation */ + B2400 | CS8, + 0, + 0, + INIT_C_CC}, + 0, + 0, + rs_write, + {0x2f8,0,0,0,""}, /* rs 2 */ + {0x2f8,0,0,0,""}, + {0,0,0,0,""} + } +}; + +/* + * these are the tables used by the machine code handlers. + * you can implement pseudo-tty's or something by changing + * them. Currently not done. + */ +struct tty_queue * table_list[]={ + &tty_table[0].read_q, &tty_table[0].write_q, + &tty_table[1].read_q, &tty_table[1].write_q, + &tty_table[2].read_q, &tty_table[2].write_q + }; + +void tty_init(void) +{ + rs_init(); + con_init(); +} + +void tty_intr(struct tty_struct * tty, int mask) +{ + int i; + + if (tty->pgrp <= 0) + return; + for (i=0;ipgrp==tty->pgrp) + task[i]->signal |= mask; +} + +static void sleep_if_empty(struct tty_queue * queue) +{ + cli(); + while (!current->signal && EMPTY(*queue)) + interruptible_sleep_on(&queue->proc_list); + sti(); +} + +static void sleep_if_full(struct tty_queue * queue) +{ + if (!FULL(*queue)) + return; + cli(); + while (!current->signal && LEFT(*queue)<128) + interruptible_sleep_on(&queue->proc_list); + sti(); +} + +void wait_for_keypress(void) +{ + sleep_if_empty(&tty_table[0].secondary); +} + +void copy_to_cooked(struct tty_struct * tty) +{ + signed char c; + + while (!EMPTY(tty->read_q) && !FULL(tty->secondary)) { + GETCH(tty->read_q,c); + if (c==13) + if (I_CRNL(tty)) + c=10; + else if (I_NOCR(tty)) + continue; + else ; + else if (c==10 && I_NLCR(tty)) + c=13; + if (I_UCLC(tty)) + c=tolower(c); + if (L_CANON(tty)) { + if (c==KILL_CHAR(tty)) { + /* deal with killing the input line */ + while(!(EMPTY(tty->secondary) || + (c=LAST(tty->secondary))==10 || + c==EOF_CHAR(tty))) { + if (L_ECHO(tty)) { + if (c<32) + PUTCH(127,tty->write_q); + PUTCH(127,tty->write_q); + tty->write(tty); + } + DEC(tty->secondary.head); + } + continue; + } + if (c==ERASE_CHAR(tty)) { + if (EMPTY(tty->secondary) || + (c=LAST(tty->secondary))==10 || + c==EOF_CHAR(tty)) + continue; + if (L_ECHO(tty)) { + if (c<32) + PUTCH(127,tty->write_q); + PUTCH(127,tty->write_q); + tty->write(tty); + } + DEC(tty->secondary.head); + continue; + } + if (c==STOP_CHAR(tty)) { + tty->stopped=1; + continue; + } + if (c==START_CHAR(tty)) { + tty->stopped=0; + continue; + } + } + if (L_ISIG(tty)) { + if (c==INTR_CHAR(tty)) { + tty_intr(tty,INTMASK); + continue; + } + if (c==QUIT_CHAR(tty)) { + tty_intr(tty,QUITMASK); + continue; + } + } + if (c==10 || c==EOF_CHAR(tty)) + tty->secondary.data++; + if (L_ECHO(tty)) { + if (c==10) { + PUTCH(10,tty->write_q); + PUTCH(13,tty->write_q); + } else if (c<32) { + if (L_ECHOCTL(tty)) { + PUTCH('^',tty->write_q); + PUTCH(c+64,tty->write_q); + } + } else + PUTCH(c,tty->write_q); + tty->write(tty); + } + PUTCH(c,tty->secondary); + } + wake_up(&tty->secondary.proc_list); +} + +int tty_read(unsigned channel, char * buf, int nr) +{ + struct tty_struct * tty; + char c, * b=buf; + int minimum,time,flag=0; + long oldalarm; + + if (channel>2 || nr<0) return -1; + tty = &tty_table[channel]; + oldalarm = current->alarm; + time = 10L*tty->termios.c_cc[VTIME]; + minimum = tty->termios.c_cc[VMIN]; + if (time && !minimum) { + minimum=1; + if (flag=(!oldalarm || time+jiffiesalarm = time+jiffies; + } + if (minimum>nr) + minimum=nr; + while (nr>0) { + if (flag && (current->signal & ALRMMASK)) { + current->signal &= ~ALRMMASK; + break; + } + if (current->signal) + break; + if (EMPTY(tty->secondary) || (L_CANON(tty) && + !tty->secondary.data && LEFT(tty->secondary)>20)) { + sleep_if_empty(&tty->secondary); + continue; + } + do { + GETCH(tty->secondary,c); + if (c==EOF_CHAR(tty) || c==10) + tty->secondary.data--; + if (c==EOF_CHAR(tty) && L_CANON(tty)) + return (b-buf); + else { + put_fs_byte(c,b++); + if (!--nr) + break; + } + } while (nr>0 && !EMPTY(tty->secondary)); + if (time && !L_CANON(tty)) + if (flag=(!oldalarm || time+jiffiesalarm = time+jiffies; + else + current->alarm = oldalarm; + if (L_CANON(tty)) { + if (b-buf) + break; + } else if (b-buf >= minimum) + break; + } + current->alarm = oldalarm; + if (current->signal && !(b-buf)) + return -EINTR; + return (b-buf); +} + +int tty_write(unsigned channel, char * buf, int nr) +{ + static cr_flag=0; + struct tty_struct * tty; + char c, *b=buf; + + if (channel>2 || nr<0) return -1; + tty = channel + tty_table; + while (nr>0) { + sleep_if_full(&tty->write_q); + if (current->signal) + break; + while (nr>0 && !FULL(tty->write_q)) { + c=get_fs_byte(b); + if (O_POST(tty)) { + if (c=='\r' && O_CRNL(tty)) + c='\n'; + else if (c=='\n' && O_NLRET(tty)) + c='\r'; + if (c=='\n' && !cr_flag && O_NLCR(tty)) { + cr_flag = 1; + PUTCH(13,tty->write_q); + continue; + } + if (O_LCUC(tty)) + c=toupper(c); + } + b++; nr--; + cr_flag = 0; + PUTCH(c,tty->write_q); + } + tty->write(tty); + if (nr>0) + schedule(); + } + return (b-buf); +} + +/* + * Jeh, sometimes I really like the 386. + * This routine is called from an interrupt, + * and there should be absolutely no problem + * with sleeping even in an interrupt (I hope). + * Of course, if somebody proves me wrong, I'll + * hate intel for all time :-). We'll have to + * be careful and see to reinstating the interrupt + * chips before calling this, though. + * + * I don't think we sleep here under normal circumstances + * anyway, which is good, as the task sleeping might be + * totally innocent. + */ +void do_tty_interrupt(int tty) +{ + copy_to_cooked(tty_table+tty); +} + +void chr_dev_init(void) +{ +} diff --git a/os/os/linux/kernel/chr_drv/tty_io.o b/os/os/linux/kernel/chr_drv/tty_io.o new file mode 100644 index 0000000000000000000000000000000000000000..37e2b15961ebc5713d826d6c25e53571ac6fbb83 GIT binary patch literal 22504 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 O^kQA0pRj`M3jQCx0hyNo literal 0 HcmV?d00001 diff --git a/os/os/linux/kernel/chr_drv/tty_ioctl.c b/os/os/linux/kernel/chr_drv/tty_ioctl.c new file mode 100644 index 0000000..e4e3745 --- /dev/null +++ b/os/os/linux/kernel/chr_drv/tty_ioctl.c @@ -0,0 +1,204 @@ +/* + * linux/kernel/chr_drv/tty_ioctl.c + * + * (C) 1991 Linus Torvalds + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +static unsigned short quotient[] = { + 0, 2304, 1536, 1047, 857, + 768, 576, 384, 192, 96, + 64, 48, 24, 12, 6, 3 +}; + +static void change_speed(struct tty_struct * tty) +{ + unsigned short port,quot; + + if (!(port = tty->read_q.data)) + return; + quot = quotient[tty->termios.c_cflag & CBAUD]; + cli(); + outb_p(0x80,port+3); /* set DLAB */ + outb_p(quot & 0xff,port); /* LS of divisor */ + outb_p(quot >> 8,port+1); /* MS of divisor */ + outb(0x03,port+3); /* reset DLAB */ + sti(); +} + +static void flush(struct tty_queue * queue) +{ + cli(); + queue->head = queue->tail; + sti(); +} + +static void wait_until_sent(struct tty_struct * tty) +{ + /* do nothing - not implemented */ +} + +static void send_break(struct tty_struct * tty) +{ + /* do nothing - not implemented */ +} + +static int get_termios(struct tty_struct * tty, struct termios * termios) +{ + int i; + + verify_area(termios, sizeof (*termios)); + for (i=0 ; i< (sizeof (*termios)) ; i++) + put_fs_byte( ((char *)&tty->termios)[i] , i+(char *)termios ); + return 0; +} + +static int set_termios(struct tty_struct * tty, struct termios * termios) +{ + int i; + + for (i=0 ; i< (sizeof (*termios)) ; i++) + ((char *)&tty->termios)[i]=get_fs_byte(i+(char *)termios); + change_speed(tty); + return 0; +} + +static int get_termio(struct tty_struct * tty, struct termio * termio) +{ + int i; + struct termio tmp_termio; + + verify_area(termio, sizeof (*termio)); + tmp_termio.c_iflag = tty->termios.c_iflag; + tmp_termio.c_oflag = tty->termios.c_oflag; + tmp_termio.c_cflag = tty->termios.c_cflag; + tmp_termio.c_lflag = tty->termios.c_lflag; + tmp_termio.c_line = tty->termios.c_line; + for(i=0 ; i < NCC ; i++) + tmp_termio.c_cc[i] = tty->termios.c_cc[i]; + for (i=0 ; i< (sizeof (*termio)) ; i++) + put_fs_byte( ((char *)&tmp_termio)[i] , i+(char *)termio ); + return 0; +} + +/* + * This only works as the 386 is low-byt-first + */ +static int set_termio(struct tty_struct * tty, struct termio * termio) +{ + int i; + struct termio tmp_termio; + + for (i=0 ; i< (sizeof (*termio)) ; i++) + ((char *)&tmp_termio)[i]=get_fs_byte(i+(char *)termio); + *(unsigned short *)&tty->termios.c_iflag = tmp_termio.c_iflag; + *(unsigned short *)&tty->termios.c_oflag = tmp_termio.c_oflag; + *(unsigned short *)&tty->termios.c_cflag = tmp_termio.c_cflag; + *(unsigned short *)&tty->termios.c_lflag = tmp_termio.c_lflag; + tty->termios.c_line = tmp_termio.c_line; + for(i=0 ; i < NCC ; i++) + tty->termios.c_cc[i] = tmp_termio.c_cc[i]; + change_speed(tty); + return 0; +} + +int tty_ioctl(int dev, int cmd, int arg) +{ + struct tty_struct * tty; + if (MAJOR(dev) == 5) { + dev=current->tty; + if (dev<0) + panic("tty_ioctl: dev<0"); + } else + dev=MINOR(dev); + tty = dev + tty_table; + switch (cmd) { + case TCGETS: + return get_termios(tty,(struct termios *) arg); + case TCSETSF: + flush(&tty->read_q); /* fallthrough */ + case TCSETSW: + wait_until_sent(tty); /* fallthrough */ + case TCSETS: + return set_termios(tty,(struct termios *) arg); + case TCGETA: + return get_termio(tty,(struct termio *) arg); + case TCSETAF: + flush(&tty->read_q); /* fallthrough */ + case TCSETAW: + wait_until_sent(tty); /* fallthrough */ + case TCSETA: + return set_termio(tty,(struct termio *) arg); + case TCSBRK: + if (!arg) { + wait_until_sent(tty); + send_break(tty); + } + return 0; + case TCXONC: + return -EINVAL; /* not implemented */ + case TCFLSH: + if (arg==0) + flush(&tty->read_q); + else if (arg==1) + flush(&tty->write_q); + else if (arg==2) { + flush(&tty->read_q); + flush(&tty->write_q); + } else + return -EINVAL; + return 0; + case TIOCEXCL: + return -EINVAL; /* not implemented */ + case TIOCNXCL: + return -EINVAL; /* not implemented */ + case TIOCSCTTY: + return -EINVAL; /* set controlling term NI */ + case TIOCGPGRP: + verify_area((void *) arg,4); + put_fs_long(tty->pgrp,(unsigned long *) arg); + return 0; + case TIOCSPGRP: + tty->pgrp=get_fs_long((unsigned long *) arg); + return 0; + case TIOCOUTQ: + verify_area((void *) arg,4); + put_fs_long(CHARS(tty->write_q),(unsigned long *) arg); + return 0; + case TIOCINQ: + verify_area((void *) arg,4); + put_fs_long(CHARS(tty->secondary), + (unsigned long *) arg); + return 0; + case TIOCSTI: + return -EINVAL; /* not implemented */ + case TIOCGWINSZ: + return -EINVAL; /* not implemented */ + case TIOCSWINSZ: + return -EINVAL; /* not implemented */ + case TIOCMGET: + return -EINVAL; /* not implemented */ + case TIOCMBIS: + return -EINVAL; /* not implemented */ + case TIOCMBIC: + return -EINVAL; /* not implemented */ + case TIOCMSET: + return -EINVAL; /* not implemented */ + case TIOCGSOFTCAR: + return -EINVAL; /* not implemented */ + case TIOCSSOFTCAR: + return -EINVAL; /* not implemented */ + default: + return -EINVAL; + } +} diff --git a/os/os/linux/kernel/chr_drv/tty_ioctl.o b/os/os/linux/kernel/chr_drv/tty_ioctl.o new file mode 100644 index 0000000000000000000000000000000000000000..6fcf766d95e129c53038533553e2124de8516b4b GIT binary patch literal 10648 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 literal 0 HcmV?d00001 diff --git a/os/os/linux/kernel/exec2.o b/os/os/linux/kernel/exec2.o new file mode 100644 index 0000000000000000000000000000000000000000..8c4add44fe837910ad6661ad07b87365c26ffc38 GIT binary patch literal 15272 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 brvwiOo)&ydkmor1sS%th*dxgOm-_z?t#1c? literal 0 HcmV?d00001 diff --git a/os/os/linux/kernel/execve2.c b/os/os/linux/kernel/execve2.c new file mode 100644 index 0000000..03c522f --- /dev/null +++ b/os/os/linux/kernel/execve2.c @@ -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 +#include +#include +#include + +#include +#include +#include +#include +#include + +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 + +/* + * 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 * mq; + + mq = (unsigned long *) (0xfffffffc & (unsigned long) p); + mq -= envc+1; + envp = mq; + mq -= argc+1; + argv = mq; + put_fs_long((unsigned long)envp,--mq); + put_fs_long((unsigned long)argv,--mq); + put_fs_long((unsigned long)argc,--mq); + 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 mq; +} + +/* + * 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 mqecifies + * whether the string and the string array are from user or kernel segments: + * + * from_kmem argv * argv ** + * 0 user mqace user mqace + * 1 kernel mqace user mqace + * 2 kernel mqace kernel mqace + * + * 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_execve2(unsigned long * eip,long tmp,char * filename, + char ** argv, char ** envp) +{ + struct m_inode * inode; + struct buffer_head * sp; + struct exec ex; + unsigned long page[MAX_ARG_PAGES]; + int i,argc,envc; + int e_uid, e_gid; + int retval; + unsigned long currentaddr; + 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 ; ii_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 (!(sp = bread(inode->i_dev,inode->i_zone[0]))) { + retval = -EACCES; + goto exec_error2; + } + ex = *((struct exec *) sp->b_data); /* read exec-header */ + if ((sp->b_data[0] == '#') && (sp->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, sp->b_data+2, 1022); + brelse(sp); + 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); + } + /* + * mqlice 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(sp); + 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 ; iclose_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; + + //add brk 用于指明进程当前数据段(包括未初始化数据部分)末端位置,供内核为进程分配内存时指定分配开始位置。 + for (currentaddr=0; currentaddrbrk; currentaddr+=0x1000) + do_no_pagex(6, currentaddr+current->start_code);//error code=6表示执行一般代码,由写操作引起。 + + 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 ; iU+r=6ZZRV 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 T7W}Coj*Hq)t>A3IUcvtWAfDs5 literal 0 HcmV?d00001 diff --git a/os/os/linux/kernel/exit.c b/os/os/linux/kernel/exit.c new file mode 100644 index 0000000..2406ebe --- /dev/null +++ b/os/os/linux/kernel/exit.c @@ -0,0 +1,197 @@ +/* + * linux/kernel/exit.c + * + * (C) 1991 Linus Torvalds + */ + +#include +#include +#include + +#include +#include +#include +#include + +int sys_pause(void); +int sys_close(int fd); + +void release(struct task_struct * p) +{ + int i; + + if (!p) + return; + for (i=1 ; i32) + return -EINVAL; + if (priv || (current->euid==p->euid) || suser()) + p->signal |= (1<<(sig-1)); + else + return -EPERM; + return 0; +} + +static void kill_session(void) +{ + struct task_struct **p = NR_TASKS + task; + + while (--p > &FIRST_TASK) { + if (*p && (*p)->session == current->session) + (*p)->signal |= 1<<(SIGHUP-1); + } +} + +/* + * XXX need to check permissions needed to send signals to process + * groups, etc. etc. kill() permissions semantics are tricky! + */ +int sys_kill(int pid,int sig) +{ + struct task_struct **p = NR_TASKS + task; + int err, retval = 0; + + if (!pid) while (--p > &FIRST_TASK) { + if (*p && (*p)->pgrp == current->pid) + if (err=send_sig(sig,*p,1)) + retval = err; + } else if (pid>0) while (--p > &FIRST_TASK) { + if (*p && (*p)->pid == pid) + if (err=send_sig(sig,*p,0)) + retval = err; + } else if (pid == -1) while (--p > &FIRST_TASK) + if (err = send_sig(sig,*p,0)) + retval = err; + else while (--p > &FIRST_TASK) + if (*p && (*p)->pgrp == -pid) + if (err = send_sig(sig,*p,0)) + retval = err; + return retval; +} + +static void tell_father(int pid) +{ + int i; + + if (pid) + for (i=0;ipid != pid) + continue; + task[i]->signal |= (1<<(SIGCHLD-1)); + return; + } +/* if we don't find any fathers, we just release ourselves */ +/* This is not really OK. Must change it to make father 1 */ + printk("BAD BAD - no father found\n\r"); + release(current); +} + +int do_exit(long code) +{ + int i; + + free_page_tables(get_base(current->ldt[1]),get_limit(0x0f)); + free_page_tables(get_base(current->ldt[2]),get_limit(0x17)); + for (i=0 ; ifather == current->pid) { + task[i]->father = 1; + if (task[i]->state == TASK_ZOMBIE) + /* assumption task[1] is always init */ + (void) send_sig(SIGCHLD, task[1], 1); + } + for (i=0 ; ifilp[i]) + sys_close(i); + iput(current->pwd); + current->pwd=NULL; + iput(current->root); + current->root=NULL; + iput(current->executable); + current->executable=NULL; + if (current->leader && current->tty >= 0) + tty_table[current->tty].pgrp = 0; + if (last_task_used_math == current) + last_task_used_math = NULL; + if (current->leader) + kill_session(); + current->state = TASK_ZOMBIE; + current->exit_code = code; + tell_father(current->father); + schedule(); + return (-1); /* just to suppress warnings */ +} + +int sys_exit(int error_code) +{ + return do_exit((error_code&0xff)<<8); +} + +int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options) +{ + int flag, code; + struct task_struct ** p; + + verify_area(stat_addr,4); +repeat: + flag=0; + for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) { + if (!*p || *p == current) + continue; + if ((*p)->father != current->pid) + continue; + if (pid>0) { + if ((*p)->pid != pid) + continue; + } else if (!pid) { + if ((*p)->pgrp != current->pgrp) + continue; + } else if (pid != -1) { + if ((*p)->pgrp != -pid) + continue; + } + switch ((*p)->state) { + case TASK_STOPPED: + if (!(options & WUNTRACED)) + continue; + put_fs_long(0x7f,stat_addr); + return (*p)->pid; + case TASK_ZOMBIE: + current->cutime += (*p)->utime; + current->cstime += (*p)->stime; + flag = (*p)->pid; + code = (*p)->exit_code; + release(*p); + put_fs_long(code,stat_addr); + return flag; + default: + flag=1; + continue; + } + } + if (flag) { + if (options & WNOHANG) + return 0; + current->state=TASK_INTERRUPTIBLE; + schedule(); + if (!(current->signal &= ~(1<<(SIGCHLD-1)))) + goto repeat; + else + return -EINTR; + } + return -ECHILD; +} + + diff --git a/os/os/linux/kernel/exit.o b/os/os/linux/kernel/exit.o new file mode 100644 index 0000000000000000000000000000000000000000..97c5057fd4da000378b2c23ca0dba2b274e9b855 GIT binary patch literal 11164 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 + +#include +#include +#include +#include + +extern void write_verify(unsigned long address); + +long last_pid=0; + +void verify_area(void * addr,int size) +{ + unsigned long start; + + start = (unsigned long) addr; + size += start & 0xfff; + start &= 0xfffff000; + start += get_base(current->ldt[2]); + while (size>0) { + size -= 4096; + write_verify(start); + start += 4096; + } +} + +int copy_mem(int nr,struct task_struct * p) +{ + unsigned long old_data_base,new_data_base,data_limit; + unsigned long old_code_base,new_code_base,code_limit; + + code_limit=get_limit(0x0f); + data_limit=get_limit(0x17); + old_code_base = get_base(current->ldt[1]); + old_data_base = get_base(current->ldt[2]); + if (old_data_base != old_code_base) + panic("We don't support separate I&D"); + if (data_limit < code_limit) + panic("Bad data_limit"); + new_data_base = new_code_base = nr * 0x4000000; + p->start_code = new_code_base; + set_base(p->ldt[1],new_code_base); + set_base(p->ldt[2],new_data_base); + if (copy_page_tables(old_data_base,new_data_base,data_limit)) { + free_page_tables(new_data_base,data_limit); + return -ENOMEM; + } + return 0; +} + +/* + * Ok, this is the main fork-routine. It copies the system process + * information (task[nr]) and sets up the necessary registers. It + * also copies the data segment in it's entirety. + */ +int copy_process(int nr,long ebp,long edi,long esi,long gs,long none, + long ebx,long ecx,long edx, + long fs,long es,long ds, + long eip,long cs,long eflags,long esp,long ss) +{ + struct task_struct *p; + int i; + struct file *f; + + p = (struct task_struct *) get_free_page(); + if (!p) + return -EAGAIN; + task[nr] = p; + __asm__ volatile ("cld"); /* by wyj */ + *p = *current; /* NOTE! this doesn't copy the supervisor stack */ + p->state = TASK_UNINTERRUPTIBLE; + p->pid = last_pid; + p->father = current->pid; + p->counter = p->priority; + p->signal = 0; + p->alarm = 0; + p->leader = 0; /* process leadership doesn't inherit */ + p->utime = p->stime = 0; + p->cutime = p->cstime = 0; + p->start_time = jiffies; + p->tss.back_link = 0; + p->tss.esp0 = PAGE_SIZE + (long) p; + p->tss.ss0 = 0x10; + p->tss.eip = eip; + p->tss.eflags = eflags; + p->tss.eax = 0; + p->tss.ecx = ecx; + p->tss.edx = edx; + p->tss.ebx = ebx; + p->tss.esp = esp; + p->tss.ebp = ebp; + p->tss.esi = esi; + p->tss.edi = edi; + p->tss.es = es & 0xffff; + p->tss.cs = cs & 0xffff; + p->tss.ss = ss & 0xffff; + p->tss.ds = ds & 0xffff; + p->tss.fs = fs & 0xffff; + p->tss.gs = gs & 0xffff; + p->tss.ldt = _LDT(nr); + p->tss.trace_bitmap = 0x80000000; + if (last_task_used_math == current) + __asm__("clts ; fnsave %0"::"m" (p->tss.i387)); + if (copy_mem(nr,p)) { + task[nr] = NULL; + free_page((long) p); + return -EAGAIN; + } + for (i=0; ifilp[i]) + f->f_count++; + if (current->pwd) + current->pwd->i_count++; + if (current->root) + current->root->i_count++; + if (current->executable) + current->executable->i_count++; + set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss)); + set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&(p->ldt)); + p->state = TASK_RUNNING; /* do this last, just in case */ + return last_pid; +} + +int find_empty_process(void) +{ + int i; + + repeat: + if ((++last_pid)<0) last_pid=1; + for(i=0 ; ipid == last_pid) goto repeat; + for(i=1 ; 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 iRJf6deFDP}8v5Y +#include +#include +#include + +#include +#include +#include +#include +#include + +struct linux_dirent { + long d_ino; + off_t d_off; + unsigned short d_reclen; + char d_name[14]; +}; + +int sys_getdents(unsigned int fd, struct linux_dirent *d, unsigned int count) +{ + struct file *f; + struct m_inode * m; + struct buffer_head * b; + struct dir_entry * dir; + int i,j,k,res; + struct linux_dirent usrd; + i=0; + res=0; + f=current->filp[fd]; + m=f->f_inode; + b=bread(m->i_dev,m->i_zone[0]); + dir=(struct dir_entry*)b->b_data; + while(dir[i].inode>0) + { + if(res+sizeof(struct linux_dirent)>count) + break; + usrd.d_ino=dir[i].inode; + usrd.d_off=0; + usrd.d_reclen=sizeof(struct linux_dirent); + for(j=0;j<14;j++) + usrd.d_name[j]=dir[i].name[j]; + for(k=0;kroot->i_dev; + inode=current->pwd; + inum=inode->i_num; + b=bread(dev,inode->i_zone[0]); + d=(struct dir_entry*) b->b_data; + i=0; + l=0; + while(inum!=1) + { + inode=iget(dev, d[1].inode); + b=bread(dev,inode->i_zone[0]); + d=(struct dir_entry*) b->b_data; + j=0; + while(d[j].inode!=inum) j++; + inum=inode->i_num; + path[i]=d[j].name; + i++; + } + while(i>0) + { + i--; + put_fs_byte('/',buf+l); + l++; + k=0; + while(path[i][k]!='\0') + { + put_fs_byte(path[i][k],buf+l); + l++; + if(l>=size) break; + k++; + } + if(l>=size) break; + } + return buf; +} + + + diff --git a/os/os/linux/kernel/getdents.o b/os/os/linux/kernel/getdents.o new file mode 100644 index 0000000000000000000000000000000000000000..8c229382a25f1271e059251c4723ef8bbad4cc77 GIT binary patch literal 7672 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 PP1RR4m`jAML+Aeit}rS> literal 0 HcmV?d00001 diff --git a/os/os/linux/kernel/math/Makefile b/os/os/linux/kernel/math/Makefile new file mode 100644 index 0000000..b35d488 --- /dev/null +++ b/os/os/linux/kernel/math/Makefile @@ -0,0 +1,43 @@ +# +# Makefile for the FREAX-kernel character 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 =ar +AS =as +LD =ld +LDFLAGS =-s -x +CC =gcc -march=i386 +CFLAGS =-w -g -fstrength-reduce -fomit-frame-pointer -mcld \ + -nostdinc -fno-stack-protector -I../../include +CPP =gcc -E -nostdinc -I../../include + +.c.s: + $(CC) $(CFLAGS) \ + -S -o $*.s $< +.s.o: + $(AS) -o $*.o $< +.c.o: + $(CC) $(CFLAGS) \ + -c -o $*.o $< + +OBJS = math_emulate.o + +math.a: $(OBJS) + $(AR) rcs math.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: diff --git a/os/os/linux/kernel/math/math.a b/os/os/linux/kernel/math/math.a new file mode 100644 index 0000000000000000000000000000000000000000..f92fb43a9c019f8e75bf744c65f88b59c8d4ba88 GIT binary patch literal 6628 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 + +#include +#include +#include + +void math_emulate(long edi, long esi, long ebp, long sys_call_ret, + long eax,long ebx,long ecx,long edx, + unsigned short fs,unsigned short es,unsigned short ds, + unsigned long eip,unsigned short cs,unsigned long eflags, + unsigned short ss, unsigned long esp) +{ + unsigned char first, second; + +/* 0x0007 means user code space */ + if (cs != 0x000F) { + printk("math_emulate: %04x:%08x\n\r",cs,eip); + panic("Math emulation needed in kernel"); + } + first = get_fs_byte((char *)((*&eip)++)); + second = get_fs_byte((char *)((*&eip)++)); + printk("%04x:%08x %02x %02x\n\r",cs,eip-2,first,second); + current->signal |= 1<<(SIGFPE-1); +} + +void math_error(void) +{ + __asm__("fnclex"); + if (last_task_used_math) + last_task_used_math->signal |= 1<<(SIGFPE-1); +} diff --git a/os/os/linux/kernel/math/math_emulate.o b/os/os/linux/kernel/math/math_emulate.o new file mode 100644 index 0000000000000000000000000000000000000000..8a98b22720edd26bc9b196e2d1b86549665ddef0 GIT binary patch literal 6464 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 + +/* + * This isn't the library routine, it is only used in the kernel. + * as such, we don't care about years<1970 etc, but assume everything + * is ok. Similarly, TZ etc is happily ignored. We just do everything + * as easily as possible. Let's find something public for the library + * routines (although I think minix times is public). + */ +/* + * PS. I hate whoever though up the year 1970 - couldn't they have gotten + * a leap-year instead? I also hate Gregorius, pope or no. I'm grumpy. + */ +#define MINUTE 60 +#define HOUR (60*MINUTE) +#define DAY (24*HOUR) +#define YEAR (365*DAY) + +/* interestingly, we assume leap-years */ +static int month[12] = { + 0, + DAY*(31), + DAY*(31+29), + DAY*(31+29+31), + DAY*(31+29+31+30), + DAY*(31+29+31+30+31), + DAY*(31+29+31+30+31+30), + DAY*(31+29+31+30+31+30+31), + DAY*(31+29+31+30+31+30+31+31), + DAY*(31+29+31+30+31+30+31+31+30), + DAY*(31+29+31+30+31+30+31+31+30+31), + DAY*(31+29+31+30+31+30+31+31+30+31+30) +}; + +long kernel_mktime(struct tm * tm) +{ + long res; + int year; + if (tm->tm_year < 70 ) tm->tm_year += 100; /* gohigh */ + year = tm->tm_year - 70; +/* magic offsets (y+1) needed to get leapyears right.*/ + res = YEAR*year + DAY*((year+1)/4); + res += month[tm->tm_mon]; +/* and (y+2) here. If it wasn't a leap-year, we have to adjust */ + if (tm->tm_mon>1 && ((year+2)%4)) + res -= DAY; + res += DAY*(tm->tm_mday-1); + res += HOUR*tm->tm_hour; + res += MINUTE*tm->tm_min; + res += tm->tm_sec; + return res; +} diff --git a/os/os/linux/kernel/mktime.o b/os/os/linux/kernel/mktime.o new file mode 100644 index 0000000000000000000000000000000000000000..6694bf8258168567f68b2aba8bfc5ed630e30698 GIT binary patch literal 2872 zcma)8U1%It6h3!mHraGH+f8=c=BL9R=z+QC zJLlZh2X+aMEv_t>trhe7 zs=+FMvsh7H_c`1WH#v6H&lF#_7Ezv9*R)o}g{=tMS}|I;&BYZj{7N|;Z9Xl?_laJb zy7!+sbi64(04lkZ^z#JEw@~X^<|*sGoj9@%qYI3-zKwt5w^gpqUj~T!PEd383^f<8 z5*2O|-T9N6-}eamWL(gJl4$n6A(|h2E>b)kOL|%2Nt}5PFW*T8(P1??!wQYF%COpD zFue+;jqZ;aTKk|*0Ft#II4RZEhrnBa!&WCpF}4Cntxo8-0mrQn^gX~ys}K5K;2vui za3An?3&%40fm0N+LM7Luwrebj!QH%qP@{PFZ$|B0mly;xE>pPX)Jg2cF5~jqj<1=E zhY-iO?9nD!cLZXD-J@6{INm?3=}2O4-(6lqCNC^>iQTb8#EkXFxcneQzY^j ztGFErVTL1-{gDF^k>ECTk{N?AnHY_52(>Xx)Mkr=y}s?i-pK?)jrF|qcrU!#Lu7`1 zFQbQ>HnKtNU{S?{b<<`}KFMAYAtn=WkM5+&M3&Rhc76;Lt)>d3#|T{J#~|E3A@0UH zd6kzHO|T+#TCCnYx$DpU%wJs-Bbgsx@RQRvR@s?bKYSJna`l3rj$BF>73&&%scXkDpCbUrK1xQ`%?p_ zW*V;7@Q;*vxFMzC3&SJ!(8!>#<*R`SFo|;~Nt_Rh{-|ZW&eP)8K+YOAIp2v`(i|5t zd6(__LdDC?kX`p`J}+uibIP{oob|{qJbHHN9lg{A-$Y1?s@gL!-S zBN1mE^5T3tFW>nM@!sQj^Q_aP`$J4UrLA^zH?rA;v#(!9l zgBc)OgxP>F5Bw(!k}2Q7b&W~#cYaM_$_cND?5(5uI+LR7MnXh#w zG`P#%nAqCq-~V;k_#GyCi}wmH8{YxJ+xEdL7= CPoF&i literal 0 HcmV?d00001 diff --git a/os/os/linux/kernel/panic.c b/os/os/linux/kernel/panic.c new file mode 100644 index 0000000..7d8a06b --- /dev/null +++ b/os/os/linux/kernel/panic.c @@ -0,0 +1,24 @@ +/* + * linux/kernel/panic.c + * + * (C) 1991 Linus Torvalds + */ + +/* + * This function is used through-out the kernel (includeinh mm and fs) + * to indicate a major problem. + */ +#include +#include + +void sys_sync(void); /* it's really int */ + +volatile void panic(const char * s) +{ + printk("Kernel panic: %s\n\r",s); + if (current == task[0]) + printk("In swapper task - not syncing\n\r"); + else + sys_sync(); + for(;;); +} diff --git a/os/os/linux/kernel/panic.o b/os/os/linux/kernel/panic.o new file mode 100644 index 0000000000000000000000000000000000000000..da42b57864ffc04172b2020b3f3f9096af53eb86 GIT binary patch literal 5424 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 D&gTd! literal 0 HcmV?d00001 diff --git a/os/os/linux/kernel/pipe2.c b/os/os/linux/kernel/pipe2.c new file mode 100644 index 0000000..8ee1c43 --- /dev/null +++ b/os/os/linux/kernel/pipe2.c @@ -0,0 +1,55 @@ +/* + * linux/fs/pipe.c + * + * (C) 1991 Linus Torvalds + */ + +#include + +#include +#include /* for get_free_page */ +#include + + +int sys_pipe2(unsigned long * fildes,int flag) +{ + struct m_inode * inode; + struct file * f[2]; + int fd[2]; + int i,j; + if(flag==0){ + j=0; + for(i=0;j<2 && if_count++; + if (j==1) + f[0]->f_count=0; + if (j<2) + return -1; + j=0; + for(i=0;j<2 && ifilp[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; +} diff --git a/os/os/linux/kernel/pipe2.o b/os/os/linux/kernel/pipe2.o new file mode 100644 index 0000000000000000000000000000000000000000..1b0316d42205c62f784943d6b258ed5cf8d40171 GIT binary patch literal 6280 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 T4KMCf#`~ed7*L1IJCpct-OJBB literal 0 HcmV?d00001 diff --git a/os/os/linux/kernel/printk.c b/os/os/linux/kernel/printk.c new file mode 100644 index 0000000..0daa097 --- /dev/null +++ b/os/os/linux/kernel/printk.c @@ -0,0 +1,41 @@ +/* + * linux/kernel/printk.c + * + * (C) 1991 Linus Torvalds + */ + +/* + * When in kernel-mode, we cannot use printf, as fs is liable to + * point to 'interesting' things. Make a printf with fs-saving, and + * all is well. + */ +#include +#include + +#include + +static char buf[1024]; + +extern int vsprintf(char * buf, const char * fmt, va_list args); + +int printk(const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i=vsprintf(buf,fmt,args); + va_end(args); + __asm__("push %%fs\n\t" + "push %%ds\n\t" + "pop %%fs\n\t" + "pushl %0\n\t" + "pushl $buf\n\t" + "pushl $0\n\t" + "call tty_write\n\t" + "addl $8,%%esp\n\t" + "popl %0\n\t" + "pop %%fs" + ::"r" (i):"ax","cx","dx"); + return i; +} diff --git a/os/os/linux/kernel/printk.o b/os/os/linux/kernel/printk.o new file mode 100644 index 0000000000000000000000000000000000000000..93ce6e40ca451b8b2b024367e2fd7f575b694368 GIT binary patch literal 2424 zcma)7&2Jk;6o2DgCr+F=bwa44L}e?vC4jtkz$&FcNl74zT1BEwQKbUW+Fsk+*lV-9 zPLry@Ap#ObAoTzO!66j~E?kfhSCAS$gv5Ou_hxtEEfNw>nt8wXJ@aOE z_N^B#y(okrMS?WyOGHgQw3H>Ar3WZWSGNC{eQz;e-d)Vk>@DU?d#m}G-PL>wvi^gf zXV2gNK0G{xoZEXPpBvjhF?RP#ll3=3%l1L)`q*8>=C%)Juisi90ly z>aykdDJiyw91=P9O5ADEu%2|>07X85BF&XXc={4!l&3=tH3#1S8mjc_B(nQ}NevS+ zX2q$@L|V&CXR=~^;Mj4be2}!vx%AWNhz0-DrLfy04cA?ur zdfS82aa)dS7wSE?8aN%-hsx~~{J^TN7rI_2u&Y7GqgKal7(Lf_8m?V4_zbZkpEj(u zmg5KHJGbm$t7}uS*=gHFw^s{_9lzk(H;c&L+bopKxw%5isuWA1qPT8*uH6dra=N4a zR-2X=NkmHv3+Ig4tCgM`^uoOr9`8wM?#;QfSt>sgY6;&}NaEII61P)gdPLWE&{P9z zJ`yH*3>Pw~?ZiT+l(?8lUAUK#--hXLwF9d{rXP4AZz|;3Eiec z$O^M5i?7IF5RtO2K#teF2H_ZVT$lH!>e|3629V~E?;3-Ml+A)1&)0;&c{txNhRXLk zFvsw|nRb!ymk`RCZ9HyAT=~6`G|KE@(H-d7eQUg`kCXV589b>lVJwlj!6Ly5PP@Nmnz+;^@S&-W3E%tEI~ z@kn{1j;@ME+C(083(}ch`{!E#R3zOA&vW cIpTsy{wm_%F-Lt_7ZcwB_FIU!0iJ;T4?BzyrvLx| literal 0 HcmV?d00001 diff --git a/os/os/linux/kernel/sched.c b/os/os/linux/kernel/sched.c new file mode 100644 index 0000000..15d839b --- /dev/null +++ b/os/os/linux/kernel/sched.c @@ -0,0 +1,412 @@ +/* + * linux/kernel/sched.c + * + * (C) 1991 Linus Torvalds + */ + +/* + * 'sched.c' is the main kernel file. It contains scheduling primitives + * (sleep_on, wakeup, schedule etc) as well as a number of simple system + * call functions (type getpid(), which just extracts a field from + * current-task + */ +#include +#include +#include +#include +#include +#include +#include + +#include + +#define _S(nr) (1<<((nr)-1)) +#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) + +void show_task(int nr,struct task_struct * p) +{ + int i,j = 4096-sizeof(struct task_struct); + + printk("%d: pid=%d, state=%d, ",nr,p->pid,p->state); + i=0; + while (i>2 ] ; + +struct { + long * a; + short b; + } stack_start = { & user_stack [PAGE_SIZE>>2] , 0x10 }; +/* + * 'math_state_restore()' saves the current math information in the + * old math state array, and gets the new ones from the current task + */ +void math_state_restore() +{ + if (last_task_used_math == current) + return; + __asm__("fwait"); + if (last_task_used_math) { + __asm__("fnsave %0"::"m" (last_task_used_math->tss.i387)); + } + last_task_used_math=current; + if (current->used_math) { + __asm__("frstor %0"::"m" (current->tss.i387)); + } else { + __asm__("fninit"::); + current->used_math=1; + } +} + +/* + * 'schedule()' is the scheduler function. This is GOOD CODE! There + * probably won't be any reason to change this, as it should work well + * in all circumstances (ie gives IO-bound processes good response etc). + * The one thing you might take a look at is the signal-handler code here. + * + * NOTE!! Task 0 is the 'idle' task, which gets called when no other + * tasks can run. It can not be killed, and it cannot sleep. The 'state' + * information in task[0] is never used. + */ +void schedule(void) +{ + int i,next,c; + struct task_struct ** p; + +/* check alarm, wake up any interruptible tasks that have got a signal */ + + for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) + if (*p) { + if ((*p)->alarm && (*p)->alarm < jiffies) { + (*p)->signal |= (1<<(SIGALRM-1)); + (*p)->alarm = 0; + } + if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) && + (*p)->state==TASK_INTERRUPTIBLE) + (*p)->state=TASK_RUNNING; + } + +/* this is the scheduler proper: */ + + while (1) { + c = -1; + next = 0; + i = NR_TASKS; + p = &task[NR_TASKS]; + while (--i) { + if (!*--p) + continue; + if ((*p)->state == TASK_RUNNING && (*p)->counter > c) + c = (*p)->counter, next = i; + } + if (c) break; + for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) + if (*p) + (*p)->counter = ((*p)->counter >> 1) + + (*p)->priority; + } + switch_to(next); +} + +int sys_pause(void) +{ + current->state = TASK_INTERRUPTIBLE; + schedule(); + return 0; +} + +void sleep_on(struct task_struct **p) +{ + struct task_struct *tmp; + + if (!p) + return; + if (current == &(init_task.task)) + panic("task[0] trying to sleep"); + tmp = *p; + *p = current; + current->state = TASK_UNINTERRUPTIBLE; + schedule(); + if (tmp) + tmp->state=0; +} + +void interruptible_sleep_on(struct task_struct **p) +{ + struct task_struct *tmp; + + if (!p) + return; + if (current == &(init_task.task)) + panic("task[0] trying to sleep"); + tmp=*p; + *p=current; +repeat: current->state = TASK_INTERRUPTIBLE; + schedule(); + if (*p && *p != current) { + (**p).state=0; + goto repeat; + } + *p=NULL; + if (tmp) + tmp->state=0; +} + +void wake_up(struct task_struct **p) +{ + if (p && *p) { + (**p).state=0; + *p=NULL; + } +} + +/* + * OK, here are some floppy things that shouldn't be in the kernel + * proper. They are here because the floppy needs a timer, and this + * was the easiest way of doing it. + */ +static struct task_struct * wait_motor[4] = {NULL,NULL,NULL,NULL}; +static int mon_timer[4]={0,0,0,0}; +static int moff_timer[4]={0,0,0,0}; +unsigned char current_DOR = 0x0C; + +int ticks_to_floppy_on(unsigned int nr) +{ + extern unsigned char selected; + unsigned char mask = 0x10 << nr; + + if (nr>3) + panic("floppy_on: nr>3"); + moff_timer[nr]=10000; /* 100 s = very big :-) */ + cli(); /* use floppy_off to turn it off */ + mask |= current_DOR; + if (!selected) { + mask &= 0xFC; + mask |= nr; + } + if (mask != current_DOR) { + outb(mask,FD_DOR); + if ((mask ^ current_DOR) & 0xf0) + mon_timer[nr] = HZ/2; + else if (mon_timer[nr] < 2) + mon_timer[nr] = 2; + current_DOR = mask; + } + sti(); + return mon_timer[nr]; +} + +void floppy_on(unsigned int nr) +{ + cli(); + while (ticks_to_floppy_on(nr)) + sleep_on(nr+wait_motor); + sti(); +} + +void floppy_off(unsigned int nr) +{ + moff_timer[nr]=3*HZ; +} + +void do_floppy_timer(void) +{ + int i; + unsigned char mask = 0x10; + + for (i=0 ; i<4 ; i++,mask <<= 1) { + if (!(mask & current_DOR)) + continue; + if (mon_timer[i]) { + if (!--mon_timer[i]) + wake_up(i+wait_motor); + } else if (!moff_timer[i]) { + current_DOR &= ~mask; + outb(current_DOR,FD_DOR); + } else + moff_timer[i]--; + } +} + +#define TIME_REQUESTS 64 + +static struct timer_list { + long jiffies; + void (*fn)(); + struct timer_list * next; +} timer_list[TIME_REQUESTS], * next_timer = NULL; + +void add_timer(long jiffies, void (*fn)(void)) +{ + struct timer_list * p; + + if (!fn) + return; + cli(); + if (jiffies <= 0) + (fn)(); + else { + for (p = timer_list ; p < timer_list + TIME_REQUESTS ; p++) + if (!p->fn) + break; + if (p >= timer_list + TIME_REQUESTS) + panic("No more time requests free"); + p->fn = fn; + p->jiffies = jiffies; + p->next = next_timer; + next_timer = p; + while (p->next && p->next->jiffies < p->jiffies) { + p->jiffies -= p->next->jiffies; + fn = p->fn; + p->fn = p->next->fn; + p->next->fn = fn; + jiffies = p->jiffies; + p->jiffies = p->next->jiffies; + p->next->jiffies = jiffies; + p = p->next; + } + } + sti(); +} + +void do_timer(long cpl) +{ + extern int beepcount; + extern void sysbeepstop(void); + + if (beepcount) + if (!--beepcount) + sysbeepstop(); + + if (cpl) + current->utime++; + else + current->stime++; + + if (next_timer) { + next_timer->jiffies--; + while (next_timer && next_timer->jiffies <= 0) { + void (*fn)(void); + + fn = next_timer->fn; + next_timer->fn = NULL; + next_timer = next_timer->next; + (fn)(); + } + } + if (current_DOR & 0xf0) + do_floppy_timer(); + if ((--current->counter)>0) return; + current->counter=0; + if (!cpl) return; + schedule(); +} + +int sys_alarm(long seconds) +{ + int old = current->alarm; + + if (old) + old = (old - jiffies) / HZ; + current->alarm = (seconds>0)?(jiffies+HZ*seconds):0; + return (old); +} + +int sys_getpid(void) +{ + return current->pid; +} + +int sys_getppid(void) +{ + return current->father; +} + +int sys_getuid(void) +{ + return current->uid; +} + +int sys_geteuid(void) +{ + return current->euid; +} + +int sys_getgid(void) +{ + return current->gid; +} + +int sys_getegid(void) +{ + return current->egid; +} + +int sys_nice(long increment) +{ + if (current->priority-increment>0) + current->priority -= increment; + return 0; +} + +void sched_init(void) +{ + int i; + struct desc_struct * p; + + if (sizeof(struct sigaction) != 16) + panic("Struct sigaction MUST be 16 bytes"); + set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss)); + set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt)); + p = gdt+2+FIRST_TSS_ENTRY; + for(i=1;ia=p->b=0; + p++; + p->a=p->b=0; + p++; + } +/* Clear NT, so that we won't have troubles with that later on */ + __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl"); + ltr(0); + lldt(0); + outb_p(0x36,0x43); /* binary, mode 3, LSB/MSB, ch 0 */ + outb_p(LATCH & 0xff , 0x40); /* LSB */ + outb(LATCH >> 8 , 0x40); /* MSB */ + set_intr_gate(0x20,&timer_interrupt); + outb(inb_p(0x21)&~0x01,0x21); + set_system_gate(0x80,&system_call); +} diff --git a/os/os/linux/kernel/sched.o b/os/os/linux/kernel/sched.o new file mode 100644 index 0000000000000000000000000000000000000000..11112c0c588cd0587908cb992ab9c69f343c68e4 GIT binary patch literal 22936 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 literal 0 HcmV?d00001 diff --git a/os/os/linux/kernel/signal.c b/os/os/linux/kernel/signal.c new file mode 100644 index 0000000..8d5a65f --- /dev/null +++ b/os/os/linux/kernel/signal.c @@ -0,0 +1,129 @@ +/* + * linux/kernel/signal.c + * + * (C) 1991 Linus Torvalds + */ + +#include +#include +#include +#include +#include + +volatile void do_exit(int error_code); + +int sys_sgetmask() +{ + return current->blocked; +} + +int sys_ssetmask(int newmask) +{ + int old=current->blocked; + + current->blocked = newmask & ~(1<<(SIGKILL-1)); + return old; +} + +int sys_sigpending() +{ + return -ENOSYS; +} + +int sys_sigsuspend() +{ + return -ENOSYS; +} + +static inline void save_old(char * from,char * to) +{ + int i; + + verify_area(to, sizeof(struct sigaction)); + for (i=0 ; i< sizeof(struct sigaction) ; i++) { + put_fs_byte(*from,to); + from++; + to++; + } +} + +static inline void get_new(char * from,char * to) +{ + int i; + + for (i=0 ; i< sizeof(struct sigaction) ; i++) + *(to++) = get_fs_byte(from++); +} + +int sys_signal(int signum, long handler, long restorer) +{ + struct sigaction tmp; + + if (signum<1 || signum>32 || signum==SIGKILL) + return -1; + tmp.sa_handler = (void (*)(int)) handler; + tmp.sa_mask = 0; + tmp.sa_flags = SA_ONESHOT | SA_NOMASK; + tmp.sa_restorer = (void (*)(void)) restorer; + handler = (long) current->sigaction[signum-1].sa_handler; + current->sigaction[signum-1] = tmp; + return handler; +} + +int sys_sigaction(int signum, const struct sigaction * action, + struct sigaction * oldaction) +{ + struct sigaction tmp; + + if (signum<1 || signum>32 || signum==SIGKILL) + return -1; + tmp = current->sigaction[signum-1]; + get_new((char *) action, + (char *) (signum-1+current->sigaction)); + if (oldaction) + save_old((char *) &tmp,(char *) oldaction); + if (current->sigaction[signum-1].sa_flags & SA_NOMASK) + current->sigaction[signum-1].sa_mask = 0; + else + current->sigaction[signum-1].sa_mask |= (1<<(signum-1)); + return 0; +} + +void do_signal(long signr,long eax, long ebx, long ecx, long edx, + long fs, long es, long ds, + long eip, long cs, long eflags, + unsigned long * esp, long ss) +{ + unsigned long sa_handler; + long old_eip=eip; + struct sigaction * sa = current->sigaction + signr - 1; + int longs; + unsigned long * tmp_esp; + + sa_handler = (unsigned long) sa->sa_handler; + if (sa_handler==1) + return; + if (!sa_handler) { + if (signr==SIGCHLD) + return; + else + do_exit(1<<(signr-1)); + } + if (sa->sa_flags & SA_ONESHOT) + sa->sa_handler = NULL; + *(&eip) = sa_handler; + longs = (sa->sa_flags & SA_NOMASK)?7:8; + *(&esp) -= longs; + verify_area(esp,longs*4); + tmp_esp=esp; + put_fs_long((long) sa->sa_restorer,tmp_esp++); + put_fs_long(signr,tmp_esp++); + if (!(sa->sa_flags & SA_NOMASK)) + put_fs_long(current->blocked,tmp_esp++); + put_fs_long(eax,tmp_esp++); + put_fs_long(ecx,tmp_esp++); + put_fs_long(edx,tmp_esp++); + put_fs_long(eflags,tmp_esp++); + put_fs_long(old_eip,tmp_esp++); + current->blocked |= sa->sa_mask; +} diff --git a/os/os/linux/kernel/signal.o b/os/os/linux/kernel/signal.o new file mode 100644 index 0000000000000000000000000000000000000000..1970f39f72c6b0c63a277c6955a88089975ca4d3 GIT binary patch literal 8960 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 literal 0 HcmV?d00001 diff --git a/os/os/linux/kernel/sys.c b/os/os/linux/kernel/sys.c new file mode 100644 index 0000000..3069d63 --- /dev/null +++ b/os/os/linux/kernel/sys.c @@ -0,0 +1,299 @@ +/* + * linux/kernel/sys.c + * + * (C) 1991 Linus Torvalds + */ +#define SIGALRM 14 +#include +#include +#include +#include +#include +#include +#include + +int sys_ftime() +{ + return -ENOSYS; +} + +int sys_break() +{ + return -ENOSYS; +} + +int sys_ptrace() +{ + return -ENOSYS; +} + +int sys_stty() +{ + return -ENOSYS; +} + +int sys_gtty() +{ + return -ENOSYS; +} + +int sys_rename() +{ + return -ENOSYS; +} + +int sys_prof() +{ + return -ENOSYS; +} + +int sys_setregid(int rgid, int egid) +{ + if (rgid>0) { + if ((current->gid == rgid) || + suser()) + current->gid = rgid; + else + return(-EPERM); + } + if (egid>0) { + if ((current->gid == egid) || + (current->egid == egid) || + suser()) { + current->egid = egid; + current->sgid = egid; + } else + return(-EPERM); + } + return 0; +} + +int sys_setgid(int gid) +{ +/* return(sys_setregid(gid, gid)); */ + if (suser()) + current->gid = current->egid = current->sgid = gid; + else if ((gid == current->gid) || (gid == current->sgid)) + current->egid = gid; + else + return -EPERM; + return 0; +} + +int sys_acct() +{ + return -ENOSYS; +} + +int sys_phys() +{ + return -ENOSYS; +} + +int sys_lock() +{ + return -ENOSYS; +} + +int sys_mpx() +{ + return -ENOSYS; +} + +int sys_ulimit() +{ + return -ENOSYS; +} + +int sys_time(long * tloc) +{ + int i; + + i = CURRENT_TIME; + if (tloc) { + verify_area(tloc,4); + put_fs_long(i,(unsigned long *)tloc); + } + return i; +} + +/* + * Unprivileged users may change the real user id to the effective uid + * or vice versa. + */ +int sys_setreuid(int ruid, int euid) +{ + int old_ruid = current->uid; + + if (ruid>0) { + if ((current->euid==ruid) || + (old_ruid == ruid) || + suser()) + current->uid = ruid; + else + return(-EPERM); + } + if (euid>0) { + if ((old_ruid == euid) || + (current->euid == euid) || + suser()) { + current->euid = euid; + current->suid = euid; + } else { + current->uid = old_ruid; + return(-EPERM); + } + } + return 0; +} + +int sys_setuid(int uid) +{ +/* return(sys_setreuid(uid, uid)); */ + if (suser()) + current->uid = current->euid = current->suid = uid; + else if ((uid == current->uid) || (uid == current->suid)) + current->euid = uid; + else + return -EPERM; + return(0); +} + +int sys_stime(long * tptr) +{ + if (!suser()) + return -EPERM; + startup_time = get_fs_long((unsigned long *)tptr) - jiffies/HZ; + return 0; +} + +int sys_times(struct tms * tbuf) +{ + if (tbuf) { + verify_area(tbuf,sizeof *tbuf); + put_fs_long(current->utime,(unsigned long *)&tbuf->tms_utime); + put_fs_long(current->stime,(unsigned long *)&tbuf->tms_stime); + put_fs_long(current->cutime,(unsigned long *)&tbuf->tms_cutime); + put_fs_long(current->cstime,(unsigned long *)&tbuf->tms_cstime); + } + return jiffies; +} + +int sys_brk(unsigned long end_data_seg) +{ + if (end_data_seg >= current->end_code && + end_data_seg < current->start_stack - 16384) + current->brk = end_data_seg; + return current->brk; +} + +/* + * This needs some heave checking ... + * I just haven't get the stomach for it. I also don't fully + * understand sessions/pgrp etc. Let somebody who does explain it. + */ +int sys_setpgid(int pid, int pgid) +{ + int i; + + if (!pid) + pid = current->pid; + if (!pgid) + pgid = current->pid; + for (i=0 ; ipid==pid) { + if (task[i]->leader) + return -EPERM; + if (task[i]->session != current->session) + return -EPERM; + task[i]->pgrp = pgid; + return 0; + } + return -ESRCH; +} + +int sys_getpgrp(void) +{ + return current->pgrp; +} + +int sys_setsid(void) +{ + if (current->leader && !suser()) + return -EPERM; + current->leader = 1; + current->session = current->pgrp = current->pid; + current->tty = -1; + return current->pgrp; +} + +int sys_getgroups() +{ + return -ENOSYS; +} + +int sys_setgroups() +{ + return -ENOSYS; +} + +int sys_uname(struct utsname * name) +{ + static struct utsname thisname = { + "linux .0","nodename","release ","version ","machine " + }; + int i; + + if (!name) return -ERROR; + verify_area(name,sizeof *name); + for(i=0;iumask; + + current->umask = mask & 0777; + return (old); +} + +int sys_sleep(unsigned int seconds) +{ + sys_signal(SIGALRM,SIG_IGN,NULL); + sys_alarm(seconds); + sys_pause(); + return 0; +} diff --git a/os/os/linux/kernel/sys.o b/os/os/linux/kernel/sys.o new file mode 100644 index 0000000000000000000000000000000000000000..dfa95feba02b68d81a619cb10b80b86298586b60 GIT binary patch literal 13576 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 G{Qm&3UrH7L literal 0 HcmV?d00001 diff --git a/os/os/linux/kernel/system_call.o b/os/os/linux/kernel/system_call.o new file mode 100644 index 0000000000000000000000000000000000000000..7f18738326d585dc583de8d6575122ff94f92c89 GIT binary patch literal 2640 zcma)8U1%It6h523R*BhEqxGlS6(hzr#w1#;R>d@%)WS+PS(0vBb(rkTcGv9gEHigw z76g$rL=6eS2kC5D&aNT z&pG$pvp0A0(ok$T6bg}VA!?+$B8oP+GY>k@Mcb*FR&3aMdMR@RgIE57NH5L&dE$ki z?`R1xkB%f(+cCcQ-Qp*!JDFUH|H3{=yJMD<#Lw`1W6Ho|LPHL2}dgLHld90DK2HgfO3kZGE=TMQ?!)n8$@Q&cBYl-Qr{LL2sdMGZl`CdHi|6hJPBp*;GUoR8S{8Aa^rA{Gn1fBmgq;6nXgU9D&~pAapm`0~s`gtxbudI{f%W(heGJW4 zrE4KN590T;9lzf9&@t~Yu>J}9H`f{a2+{B0-O@aU=rKvRf@_k#1$p zrGdPhe-!$(w4R@fhq#Yj8Zspf3gVuK_Lp z@$&wztDOyZzc&Q*-hkd0(3CiQNEv)87NwzqBn=(JGl(aeq~Qb&B`Avb;W!NfhGPSV z5_BXM9ZJL*5(%<|Ds)O2rGn5+Dwn|$DpP})+o?K&PYw_8d<86Q43lQ z&Y*eKnq*Ap)RPtyQ@4a+VzOW=R@oAIUP-CBoJA9=#siKbc%?GBR?6w1LP?uOzCJ01 z5l5sAbCN_hubWDii!@6`;Y{e$dTL6SXg_5%$tRsNip8=tP*hFSqUWR`O`po9bfsVj zMV(T!IduXxrHrC!q;$(NOa<#1*s5PH8dMNU0VCdC6nvyOq-2_UL6G2vXolkTFRzM> zm%^b=xBVuOJDV@%_$PQin@(qSi-VobGVyj;WBruQ7BofA7e!g|YUFC`0c^nsR8^%INwj0>+0P-^81ALHiAJNl{58+;8d>HwFAzaK$jE@kVV?+_3Gaf)b R&U-J>2aNX<{m9r$^f#OT6iNU9 literal 0 HcmV?d00001 diff --git a/os/os/linux/kernel/system_call.s b/os/os/linux/kernel/system_call.s new file mode 100644 index 0000000..7872a77 --- /dev/null +++ b/os/os/linux/kernel/system_call.s @@ -0,0 +1,298 @@ +/* + * linux/kernel/system_call.s + * + * (C) 1991 Linus Torvalds + */ + +/* + * system_call.s contains the system-call low-level handling routines. + * This also contains the timer-interrupt handler, as some of the code is + * the same. The hd- and flopppy-interrupts are also here. + * + * NOTE: This code handles signal-recognition, which happens every time + * after a timer-interrupt and after each system call. Ordinary interrupts + * don't handle signal-recognition, as that would clutter them up totally + * unnecessarily. + * + * Stack layout in 'ret_from_system_call': + * + * 0(%esp) - %eax + * 4(%esp) - %ebx + * 8(%esp) - %ecx + * C(%esp) - %edx + * 10(%esp) - %fs + * 14(%esp) - %es + * 18(%esp) - %ds + * 1C(%esp) - %eip + * 20(%esp) - %cs + * 24(%esp) - %eflags + * 28(%esp) - %oldesp + * 2C(%esp) - %oldss + */ + +SIG_CHLD = 17 + +EAX = 0x00 +EBX = 0x04 +ECX = 0x08 +EDX = 0x0C +FS = 0x10 +ES = 0x14 +DS = 0x18 +EIP = 0x1C +CS = 0x20 +EFLAGS = 0x24 +OLDESP = 0x28 +OLDSS = 0x2C + +state = 0 # these are offsets into the task-struct. +counter = 4 +priority = 8 +signal = 12 +sigaction = 16 # MUST be 16 (=len of sigaction) +blocked = (33*16) + +# offsets within sigaction +sa_handler = 0 +sa_mask = 4 +sa_flags = 8 +sa_restorer = 12 + +nr_system_calls = 92 /* 72 */ + +/* + * Ok, I get parallel printer interrupts while using the floppy for some + * strange reason. Urgel. Now I just ignore them. + */ +.globl system_call,sys_fork,timer_interrupt,sys_execve,sys_execve2 +.globl hd_interrupt,floppy_interrupt,parallel_interrupt +.globl device_not_available, coprocessor_error + +.align 4 +bad_sys_call: + movl $-1,%eax + iret +.align 4 +reschedule: + pushl $ret_from_sys_call + jmp schedule +.align 4 +system_call: + cmpl $nr_system_calls-1,%eax + ja bad_sys_call + push %ds + push %es + push %fs + pushl %edx + pushl %ecx # push %ebx,%ecx,%edx as parameters + pushl %ebx # to the system call + movl $0x10,%edx # set up ds,es to kernel space + mov %dx,%ds + mov %dx,%es + movl $0x17,%edx # fs points to local data space + mov %dx,%fs + + pushl %eax #by wyj + call print_nr + popl %eax + + call sys_call_table(,%eax,4) + pushl %eax + movl current,%eax + cmpl $0,state(%eax) # state + jne reschedule + cmpl $0,counter(%eax) # counter + je reschedule +ret_from_sys_call: + movl current,%eax # task[0] cannot have signals + cmpl task,%eax + je 3f + cmpw $0x0f,CS(%esp) # was old code segment supervisor ? + jne 3f + cmpw $0x17,OLDSS(%esp) # was stack segment = 0x17 ? + jne 3f + movl signal(%eax),%ebx + movl blocked(%eax),%ecx + notl %ecx + andl %ebx,%ecx + bsfl %ecx,%ecx + je 3f + btrl %ecx,%ebx + movl %ebx,signal(%eax) + incl %ecx + pushl %ecx + call do_signal + popl %eax +3: popl %eax + popl %ebx + popl %ecx + popl %edx + pop %fs + pop %es + pop %ds + iret + +.align 4 +coprocessor_error: + push %ds + push %es + push %fs + pushl %edx + pushl %ecx + pushl %ebx + pushl %eax + movl $0x10,%eax + mov %ax,%ds + mov %ax,%es + movl $0x17,%eax + mov %ax,%fs + pushl $ret_from_sys_call + jmp math_error + +.align 2 +device_not_available: + push %ds + push %es + push %fs + pushl %edx + pushl %ecx + pushl %ebx + pushl %eax + movl $0x10,%eax + mov %ax,%ds + mov %ax,%es + movl $0x17,%eax + mov %ax,%fs + pushl $ret_from_sys_call + clts # clear TS so that we can use math + movl %cr0,%eax + testl $0x4,%eax # EM (math emulation bit) + je math_state_restore + pushl %ebp + pushl %esi + pushl %edi + call math_emulate + popl %edi + popl %esi + popl %ebp + ret + +.align 4 +timer_interrupt: + push %ds # save ds,es and put kernel data space + push %es # into them. %fs is used by _system_call + push %fs + pushl %edx # we save %eax,%ecx,%edx as gcc doesn't + pushl %ecx # save those across function calls. %ebx + pushl %ebx # is saved as we use that in ret_sys_call + pushl %eax + movl $0x10,%eax + mov %ax,%ds + mov %ax,%es + movl $0x17,%eax + mov %ax,%fs + incl jiffies + movb $0x20,%al # EOI to interrupt controller #1 + outb %al,$0x20 + movl CS(%esp),%eax + andl $3,%eax # %eax is CPL (0 or 3, 0=supervisor) + pushl %eax + call do_timer # 'do_timer(long CPL)' does everything from + addl $4,%esp # task switching to accounting ... + jmp ret_from_sys_call + +.align 4 +sys_execve: + lea EIP(%esp),%eax + pushl %eax + call do_execve + addl $4,%esp + ret + +.align 4 +sys_execve2: + lea EIP(%esp),%eax + pushl %eax + call do_execve2 + addl $4,%esp + ret + +.align 4 +sys_fork: + call find_empty_process + testl %eax,%eax + js 1f + push %gs + pushl %esi + pushl %edi + pushl %ebp + pushl %eax + call copy_process + addl $20,%esp +1: ret + +hd_interrupt: + pushl %eax + pushl %ecx + pushl %edx + push %ds + push %es + push %fs + movl $0x10,%eax + mov %ax,%ds + mov %ax,%es + movl $0x17,%eax + mov %ax,%fs + movb $0x20,%al + outb %al,$0xA0 # EOI to interrupt controller #1 + jmp 1f # give port chance to breathe +1: jmp 1f +1: xorl %edx,%edx + xchgl do_hd,%edx + testl %edx,%edx + jne 1f + movl $unexpected_hd_interrupt,%edx +1: outb %al,$0x20 + call *%edx # "interesting" way of handling intr. + pop %fs + pop %es + pop %ds + popl %edx + popl %ecx + popl %eax + iret + +floppy_interrupt: + pushl %eax + pushl %ecx + pushl %edx + push %ds + push %es + push %fs + movl $0x10,%eax + mov %ax,%ds + mov %ax,%es + movl $0x17,%eax + mov %ax,%fs + movb $0x20,%al + outb %al,$0x20 # EOI to interrupt controller #1 + xorl %eax,%eax + xchgl do_floppy,%eax + testl %eax,%eax + jne 1f + movl $unexpected_floppy_interrupt,%eax +1: call *%eax # "interesting" way of handling intr. + pop %fs + pop %es + pop %ds + popl %edx + popl %ecx + popl %eax + iret + +parallel_interrupt: + pushl %eax + movb $0x20,%al + outb %al,$0x20 + popl %eax + iret diff --git a/os/os/linux/kernel/traps.c b/os/os/linux/kernel/traps.c new file mode 100644 index 0000000..f9bd8f1 --- /dev/null +++ b/os/os/linux/kernel/traps.c @@ -0,0 +1,208 @@ +/* + * linux/kernel/traps.c + * + * (C) 1991 Linus Torvalds + */ + +/* + * 'Traps.c' handles hardware traps and faults after we have saved some + * state in 'asm.s'. Currently mostly a debugging-aid, will be extended + * to mainly kill the offending process (probably by giving it a signal, + * but possibly by killing it outright if necessary). + */ +#include + +#include +#include +#include +#include +#include +#include + +#define get_seg_byte(seg,addr) ({ \ +register char __res; \ +__asm__("push %%fs;mov %%ax,%%fs;movb %%fs:%2,%%al;pop %%fs" \ + :"=a" (__res):"0" (seg),"m" (*(addr))); \ +__res;}) + +#define get_seg_long(seg,addr) ({ \ +register unsigned long __res; \ +__asm__("push %%fs;mov %%ax,%%fs;movl %%fs:%2,%%eax;pop %%fs" \ + :"=a" (__res):"0" (seg),"m" (*(addr))); \ +__res;}) + +#define _fs() ({ \ +register unsigned short __res; \ +__asm__("mov %%fs,%%ax":"=a" (__res):); \ +__res;}) + +int do_exit(long code); + +void page_exception(void); + +void divide_error(void); +void debug(void); +void nmi(void); +void int3(void); +void overflow(void); +void bounds(void); +void invalid_op(void); +void device_not_available(void); +void double_fault(void); +void coprocessor_segment_overrun(void); +void invalid_TSS(void); +void segment_not_present(void); +void stack_segment(void); +void general_protection(void); +void page_fault(void); +void coprocessor_error(void); +void reserved(void); +void parallel_interrupt(void); +void irq13(void); + +static void die(char * str,long esp_ptr,long nr) +{ + long * esp = (long *) esp_ptr; + int i; + + printk("%s: %04x\n\r",str,nr&0xffff); + printk("EIP:\t%04x:%p\nEFLAGS:\t%p\nESP:\t%04x:%p\n", + esp[1],esp[0],esp[2],esp[4],esp[3]); + printk("fs: %04x\n",_fs()); + printk("base: %p, limit: %p\n",get_base(current->ldt[1]),get_limit(0x17)); + if (esp[4] == 0x17) { + printk("Stack: "); + for (i=0;i<4;i++) + printk("%p ",get_seg_long(0x17,i+(long *)esp[3])); + printk("\n"); + } + str(i); + printk("Pid: %d, process nr: %d\n\r",current->pid,0xffff & i); + for(i=0;i<10;i++) + printk("%02x ",0xff & get_seg_byte(esp[1],(i+(char *)esp[0]))); + printk("\n\r"); + do_exit(11); /* play segment exception */ +} + +void do_double_fault(long esp, long error_code) +{ + die("double fault",esp,error_code); +} + +void do_general_protection(long esp, long error_code) +{ + die("general protection",esp,error_code); +} + +void do_divide_error(long esp, long error_code) +{ + die("divide error",esp,error_code); +} + +void do_int3(long * esp, long error_code, + long fs,long es,long ds, + long ebp,long esi,long edi, + long edx,long ecx,long ebx,long eax) +{ + int tr; + + __asm__("str %%ax":"=a" (tr):"0" (0)); + printk("eax\t\tebx\t\tecx\t\tedx\n\r%8x\t%8x\t%8x\t%8x\n\r", + eax,ebx,ecx,edx); + printk("esi\t\tedi\t\tebp\t\tesp\n\r%8x\t%8x\t%8x\t%8x\n\r", + esi,edi,ebp,(long) esp); + printk("\n\rds\tes\tfs\ttr\n\r%4x\t%4x\t%4x\t%4x\n\r", + ds,es,fs,tr); + printk("EIP: %8x CS: %4x EFLAGS: %8x\n\r",esp[0],esp[1],esp[2]); +} + +void do_nmi(long esp, long error_code) +{ + die("nmi",esp,error_code); +} + +void do_debug(long esp, long error_code) +{ + die("debug",esp,error_code); +} + +void do_overflow(long esp, long error_code) +{ + die("overflow",esp,error_code); +} + +void do_bounds(long esp, long error_code) +{ + die("bounds",esp,error_code); +} + +void do_invalid_op(long esp, long error_code) +{ + die("invalid operand",esp,error_code); +} + +void do_device_not_available(long esp, long error_code) +{ + die("device not available",esp,error_code); +} + +void do_coprocessor_segment_overrun(long esp, long error_code) +{ + die("coprocessor segment overrun",esp,error_code); +} + +void do_invalid_TSS(long esp,long error_code) +{ + die("invalid TSS",esp,error_code); +} + +void do_segment_not_present(long esp,long error_code) +{ + die("segment not present",esp,error_code); +} + +void do_stack_segment(long esp,long error_code) +{ + die("stack segment",esp,error_code); +} + +void do_coprocessor_error(long esp, long error_code) +{ + if (last_task_used_math != current) + return; + die("coprocessor error",esp,error_code); +} + +void do_reserved(long esp, long error_code) +{ + die("reserved (15,17-47) error",esp,error_code); +} + +void trap_init(void) +{ + int i; + + set_trap_gate(0,÷_error); + set_trap_gate(1,&debug); + set_trap_gate(2,&nmi); + set_system_gate(3,&int3); /* int3-5 can be called from all */ + set_system_gate(4,&overflow); + set_system_gate(5,&bounds); + set_trap_gate(6,&invalid_op); + set_trap_gate(7,&device_not_available); + set_trap_gate(8,&double_fault); + set_trap_gate(9,&coprocessor_segment_overrun); + set_trap_gate(10,&invalid_TSS); + set_trap_gate(11,&segment_not_present); + set_trap_gate(12,&stack_segment); + set_trap_gate(13,&general_protection); + set_trap_gate(14,&page_fault); + set_trap_gate(15,&reserved); + set_trap_gate(16,&coprocessor_error); + for (i=17;i<48;i++) + set_trap_gate(i,&reserved); + set_trap_gate(45,&irq13); + outb_p(inb_p(0x21)&0xfb,0x21); + outb(inb_p(0xA1)&0xdf,0xA1); + set_trap_gate(39,¶llel_interrupt); +} diff --git a/os/os/linux/kernel/traps.o b/os/os/linux/kernel/traps.o new file mode 100644 index 0000000000000000000000000000000000000000..51de46fe88ac98ea479385c2c283bf030d1f46cd GIT binary patch literal 12972 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 +#include + +/* we use this so that we can do without the ctype library */ +#define is_digit(c) ((c) >= '0' && (c) <= '9') + +static int skip_atoi(const char **s) +{ + int i=0; + + while (is_digit(**s)) + i = i*10 + *((*s)++) - '0'; + return i; +} + +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIAL 32 /* 0x */ +#define SMALL 64 /* use 'abcdef' instead of 'ABCDEF' */ + +#define do_div(n,base) ({ \ +int __res; \ +__asm__("divl %4":"=a" (n),"=d" (__res):"0" (n),"1" (0),"r" (base)); \ +__res; }) + +static char * number(char * str, int num, int base, int size, int precision + ,int type) +{ + char c,sign,tmp[36]; + const char *digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + int i; + + if (type&SMALL) digits="0123456789abcdefghijklmnopqrstuvwxyz"; + if (type&LEFT) type &= ~ZEROPAD; + if (base<2 || base>36) + return 0; + c = (type & ZEROPAD) ? '0' : ' ' ; + if (type&SIGN && num<0) { + sign='-'; + num = -num; + } else + sign=(type&PLUS) ? '+' : ((type&SPACE) ? ' ' : 0); + if (sign) size--; + if (type&SPECIAL) + if (base==16) size -= 2; + else if (base==8) size--; + i=0; + if (num==0) + tmp[i++]='0'; + else while (num!=0) + tmp[i++]=digits[do_div(num,base)]; + if (i>precision) precision=i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + *str++ = ' '; + if (sign) + *str++ = sign; + if (type&SPECIAL) + if (base==8) + *str++ = '0'; + else if (base==16) { + *str++ = '0'; + *str++ = digits[33]; + } + if (!(type&LEFT)) + while(size-->0) + *str++ = c; + while(i0) + *str++ = tmp[i]; + while(size-->0) + *str++ = ' '; + return str; +} + +int vsprintf(char *buf, const char *fmt, va_list args) +{ + int len; + int i; + char * str; + char *s; + int *ip; + + int flags; /* flags to number() */ + + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier; /* 'h', 'l', or 'L' for integer fields */ + + for (str=buf ; *fmt ; ++fmt) { + if (*fmt != '%') { + *str++ = *fmt; + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case '-': flags |= LEFT; goto repeat; + case '+': flags |= PLUS; goto repeat; + case ' ': flags |= SPACE; goto repeat; + case '#': flags |= SPECIAL; goto repeat; + case '0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if (is_digit(*fmt)) + field_width = skip_atoi(&fmt); + else if (*fmt == '*') { + /* it's the next argument */ + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == '.') { + ++fmt; + if (is_digit(*fmt)) + precision = skip_atoi(&fmt); + else if (*fmt == '*') { + /* it's the next argument */ + precision = va_arg(args, int); + } + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { + qualifier = *fmt; + ++fmt; + } + + switch (*fmt) { + case 'c': + if (!(flags & LEFT)) + while (--field_width > 0) + *str++ = ' '; + *str++ = (unsigned char) va_arg(args, int); + while (--field_width > 0) + *str++ = ' '; + break; + + case 's': + s = va_arg(args, char *); + len = strlen(s); + if (precision < 0) + precision = len; + else if (len > precision) + len = precision; + + if (!(flags & LEFT)) + while (len < field_width--) + *str++ = ' '; + for (i = 0; i < len; ++i) + *str++ = *s++; + while (len < field_width--) + *str++ = ' '; + break; + + case 'o': + str = number(str, va_arg(args, unsigned long), 8, + field_width, precision, flags); + break; + + case 'p': + if (field_width == -1) { + field_width = 8; + flags |= ZEROPAD; + } + str = number(str, + (unsigned long) va_arg(args, void *), 16, + field_width, precision, flags); + break; + + case 'x': + flags |= SMALL; + case 'X': + str = number(str, va_arg(args, unsigned long), 16, + field_width, precision, flags); + break; + + case 'd': + case 'i': + flags |= SIGN; + case 'u': + str = number(str, va_arg(args, unsigned long), 10, + field_width, precision, flags); + break; + + case 'n': + ip = va_arg(args, int *); + *ip = (str - buf); + break; + + default: + if (*fmt != '%') + *str++ = '%'; + if (*fmt) + *str++ = *fmt; + else + --fmt; + break; + } + } + *str = '\0'; + return str-buf; +} diff --git a/os/os/linux/kernel/vsprintf.o b/os/os/linux/kernel/vsprintf.o new file mode 100644 index 0000000000000000000000000000000000000000..5acfe6576413e77d5a31e400e048fdd1e4ad4bf8 GIT binary patch literal 6156 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 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: +_exit.s _exit.o : _exit.c ../include/unistd.h ../include/sys/stat.h \ + ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \ + ../include/utime.h +close.s close.o : close.c ../include/unistd.h ../include/sys/stat.h \ + ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \ + ../include/utime.h +ctype.s ctype.o : ctype.c ../include/ctype.h +dup.s dup.o : dup.c ../include/unistd.h ../include/sys/stat.h \ + ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \ + ../include/utime.h +errno.s errno.o : errno.c +execve.s execve.o : execve.c ../include/unistd.h ../include/sys/stat.h \ + ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \ + ../include/utime.h +malloc.s malloc.o : malloc.c ../include/linux/kernel.h ../include/linux/mm.h \ + ../include/asm/system.h +open.s open.o : open.c ../include/unistd.h ../include/sys/stat.h \ + ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \ + ../include/utime.h ../include/stdarg.h +setsid.s setsid.o : setsid.c ../include/unistd.h ../include/sys/stat.h \ + ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \ + ../include/utime.h +string.s string.o : string.c ../include/string.h +wait.s wait.o : wait.c ../include/unistd.h ../include/sys/stat.h \ + ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \ + ../include/utime.h ../include/sys/wait.h +write.s write.o : write.c ../include/unistd.h ../include/sys/stat.h \ + ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \ + ../include/utime.h diff --git a/os/os/linux/lib/_exit.c b/os/os/linux/lib/_exit.c new file mode 100644 index 0000000..c0c9d69 --- /dev/null +++ b/os/os/linux/lib/_exit.c @@ -0,0 +1,13 @@ +/* + * linux/lib/_exit.c + * + * (C) 1991 Linus Torvalds + */ + +#define __LIBRARY__ +#include + +volatile void _exit(int exit_code) +{ + __asm__("int $0x80"::"a" (__NR_exit),"b" (exit_code)); +} diff --git a/os/os/linux/lib/_exit.o b/os/os/linux/lib/_exit.o new file mode 100644 index 0000000000000000000000000000000000000000..3941812ad719da7d5634486aad433784a57edec3 GIT binary patch literal 1988 zcma)7&2QX96n|syCQCNmHVKGEsgNTTHI&$!&;^y!@|8dZRFNoDJ)kP}?oM_sVmq?E zkXDEfaRG7a0dYa%(m#PiCAd{W;($1C;)3`WICFsCZ|vDPCwS7#`@N5O@6Gef_>%M($X_*O_t=8yz_t_U%h*__2qBBeEQzQ98$yB8|pT=TEY|HgW{fgP@@SOk zp~szD|9qTgg?G%<9jCGGCX->&P4n)4luQo&jbL-r-w*rUUa7#`mprX^MhW6-e{YfuiYQHTsFKvr zi*WG1e~_hx9u#SIRPkUOX0o3qBU3xKx;sdRT8v(R4?8>tL4GGL!ajJBm3(Yb zp$`iQhG7v((9d%TGQA%Rb$>G2jgq|-CWFI%Khq!7tzi}>BYkWETVfX=z666bjx|13 zkf0+0x?Fas45P=prmL*@{}GQmZw~JPiFc}gzGx$@Vh~qXPqwM7k@Y(V9gg>Z`fb3+ zu3;F)`;ed_Yg>o>h*g5G&x#y^FJSO9a4_Fx47&zUe!zH}pdxGAfow5N^AJ3OimdHT z$o0JUk(Yg8UchPI5ZJB(lywNt6I5hvw;mBuSRaYp=A?WX2k}qvMT`>|%*(zrXFc8- + +_syscall1(int,close,int,fd) diff --git a/os/os/linux/lib/close.o b/os/os/linux/lib/close.o new file mode 100644 index 0000000000000000000000000000000000000000..4c8ffdcb6a0e11b2f875544cd6eeed6da4ac0498 GIT binary patch literal 2220 zcma)7&2Jl35TCcZ{%D*UCn*psNEj&LRZn__k zRskwSNL1;iLMTG&t^5tB2X5tr1P6LSfbZlOU5Oi0BtH^R%Q`q60KTZ*JeO-73Pc^VZ`0)jQu`xq51GdV6benl_6& zQ18{4|M}BR9&_sfX#3mRySG0Fve-nHcpqGR2i9Z^dLa{JSS8jBtFRx!vKSn3dP1dlSouK?5;Njp zb*^Go7pgO2wpe=K9C55}R*zI(tUOsiGsnTl=XX!m#T<$i$Skwx z%$zY#RBTZen8DHn9;?4pM{T(rNZk?EbPHIQ^P}gW3Gr8TKe*f@?2K@nrXO^MY1bp_ z48z!SIy@o`{5a`4gKYN-2HVVi;x)8V6wBzLW%PbG3docOvEL88Zi8Dp41>N@WGadW zVU#rXL^KEC$ZG~^H))1(bLa=@roHT}tk^@h-E3tB@HTl-6ohp8?D@u8qvfnRt%f~v zqt4){e|YuzhTU)2y>R3wb}w>Ap1l#Gycfaf2T1DKy)@_~ei+0s1)&`$Zs&r%5rv7@ zNy3QM*CQ{+D%IRO12-BkKlU$s$)ydCq?JyutsQABoo}Z>l4dippG_rN`FN$}EVmA2 zR&LP&W*~9-9Eq*6SeUk~&(LPxApV%-#+;~@w~e*x{Kabd#On1Ka?Kmcfja{#u_SgNO7s4fVx807s5At3&a)Ulrnj66F(F0I}oK83z zdDuKBKzAH;JnL3A#v8254rg=!Km2h7@tNl%&BSLt|7X8$@tga5a0GubC?`ar0{=edQK6(u2;e5NSDAK-V;Qaiik^Bm5Jih`yJ-_47^%$tQ zS8#k-QKWt6fVIx94*?piDAK;O!1=n@P`3sf*X8x;x;U_V^6etQd$4KJ`CJ(C`EDQy z=iz))_;kLD(0L56o9PdLyHd*-`}o^ZQperFE5PW(aGtl*a04l8l++;-&&yR`axF+?TChhfvC^J%PQ-fq!v544@--dB-vz5-*eJ|R>7 + +char _ctmp; +unsigned char _ctype[] = {0x00, /* EOF */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ +_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ +_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ +_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ +_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ +_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ +_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ +_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ +_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ +_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ +_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ +_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ +_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ +_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 160-175 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 176-191 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 192-207 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 208-223 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 224-239 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* 240-255 */ + diff --git a/os/os/linux/lib/ctype.o b/os/os/linux/lib/ctype.o new file mode 100644 index 0000000000000000000000000000000000000000..acd65e6a3869dcf4ecb16245dcd9f21e6856c20c GIT binary patch literal 1908 zcmcgtOK;Oa5Z;Yl`bZlRr97$%luE4#2s;S`RJF8FBB+9@9*}xLf?_*PViDVs<3Ni9 z`~q(L0B%U!xbSDVaN!4lxFJ-&+4Ux_=z$X>&CcuFnf2_$Z|?2f=bSS|oM~)qG4@WA zk-89NmS=McD&>@-GLbUI@_qg|=_5+~TY|8Lzeob^3d)>76rVc2n*VRvD5;CGI)4bs z*HdfA+<;+%H5$-ZU7u_~(fO1CG4YX{GZ#n|eV*7M$MlntL+7VH!C<_=S8~OymRro_ z&oP$ayjkQ$?>nnU-72u4kLY+Y6cVm^}~9P?}_=LdCEQ&ajIZ zIscWL!zfMy_MbB+KJ2@uBcPRT=)09**orIRzzEzIm7W(24~(i=s~J7Zu2iK1qs@lF z!0QBVtK@X8Xq0B)y>uxf+jnBW&$f5>N{v$8Ts7+@!?z-*yWw45y;(9kC8HhsUTm}@ z%Xf`_=moJG!RZC4=^E`};KW`S4B!evV-Q=;Gov4cvFpTPMA@l`D9yGTjkQvF&mIQx zP}VZ84TV*EU8|eb`eo_G77Y&l*s>wxNXo9#V)r0sX3L5#X4-=RGb6WWwp@GI+4q8W zh>*}N+m77l>8KT1LC3`e382+09l4q5gud?v$Q@wuCK@6?Ml}52hDF*q@TmkY@9220 zy2nciF1gC=4%sRQy#yw@1g86>a9b%1#g$o2>EtI|o0NnU?kenQ<%FD_Wb7#<&Zszu zbZw~KEwGvcm3@G*NlHR0whLS76#52(j<+HedjLneZVz>-4%LM!YLopKtmZ&vzhRU~ zNl3*!*rd~U6RqGbeU_>iDMlP8QsKS;cSRuNpm47eoC?XiudMN!3UH~tpeW(qj$xy< zQ(k$!WpEw`;w#kC;8`&BIS;0ur1Sj*?ks$YD9=fh_Ur8XQ5tjnZ$bIfD + +_syscall1(int,dup,int,fd) diff --git a/os/os/linux/lib/dup.o b/os/os/linux/lib/dup.o new file mode 100644 index 0000000000000000000000000000000000000000..a354c34721c94522d7e1f903b03506ad1aee4c85 GIT binary patch literal 2196 zcma)7O>7%g5T3WY{%M>VCkBxyNEj)F1iI^lS`ZaVQ&Ol3s7QryfJ3yl*Y>LRZn{5^ zR^dkqNL1;iLMTGw)-xwAy`pjf353*3kG+>e3zay4RK9upUc5QMNbk*jGxKKV&D;0( z)7Rd5T?j#%1er8OM8BDtr6t({JxWvb&d%?(8;elvzB@m2<<>8sT{%5JxwAb#Nn6ET zh<9r||8@I1uetFMwDV)_gPUIgS*#*UtYa33F+I%~^kT-yuu3c$R^bOQ(<=BuLWWVQ zvr?45m$uT+5*2TOS>1G##KbX(OdLmiyNkKd>ngo*jf&r~e&Q%*<61(cw^{gAE)rAX zNVQ%ut8>*UF%+1&Wh7&*dsUU3{LpR zR$ge>{f6BOM}A`WB6sB3n<27#5tM#_pq|}JgHGayK@3$8+HvA`F4&ttjFN=@;%U*J6(<7;-Giz(d8w>00G)U5{6#My9qUBGPTh3BzG1C&h z;f%!P^CY&*Vs6s1zC>&JPijCc+Ww}{{Q92_2@MmhvV(Bph(-6fb;eJgZj3hI}_#1HXhrGYrmiHBs?oUvPt`Wq5QPz&+JvwaKH9%l%F;~fUvUf zmDR`aYmEFpuIBdf2yA*EQ;_vH0FjOYTxUTM*T=+M=VW{jAM8DFyt%~x501xu=bZU? zckmr>4oy0q#+v8#7TtfS^~?|c2^r@zFy`!IGUXSS$MRpcuQ26_?nA8SlO2;ulVbqM zB>aGKWD<99OeQ*@Gw|J=Mz<A6zzyJk0W040f&c&j literal 0 HcmV?d00001 diff --git a/os/os/linux/lib/errno.c b/os/os/linux/lib/errno.c new file mode 100644 index 0000000..50aca2e --- /dev/null +++ b/os/os/linux/lib/errno.c @@ -0,0 +1,7 @@ +/* + * linux/lib/errno.c + * + * (C) 1991 Linus Torvalds + */ + +int errno; diff --git a/os/os/linux/lib/errno.o b/os/os/linux/lib/errno.o new file mode 100644 index 0000000000000000000000000000000000000000..2b68237de5d516e34b24195231b0aca298879d71 GIT binary patch literal 1472 zcma)6OK;Oa5T1=w3Ydmg1wmB_8L5aA;Z4#;RaIVx3Mvrltw)6HWYZdIyK>f04m|FN zQzg#)0?zylPW%tJawy;IdK)8wV5HfZ`R3c5eT@C~{^JKi2y!CGqe(;*G;F4COq*tD zhF0J=P23c#u;RT5?9d1qnU)x*JchjHRFY|6bK+WS-uGIIt=UUNjXrs;4gZ$^aQ@yx z<1%g4zI(q1Z~h2j6(cu&0sWJ$A$%|qR4VNU>bGy@>F%Qa;Q7` zILy?`&VG`WhhbOtdf|Q)ce)n97~6@owY?K;27S3M`$3pS#bEDFvbw$&gu6jF%F{%L zqasRGc#z{XssNZ|SX70hG8^b5&&GhVJRIw2@H{*ya;*kBFDBdC+T7d-+BC)B- zS4tE0-t_vi+h4XQksQBDbri$u!rDFOX?3Vc4kI0rjK^b=h1!=x6_>kDlWdeDW&9|P z3-zL&jfyDSRhVE2ymRMcZIXjLO%oAA%n@OM*0>xf%W?lD%bcN^;Fz@=wUp6kTr zwgEVwb048-;uCSXM?mUzzo0JH;kwgMSN92gHwP|#hPK(M#N`si?DM%dHD^0`P{Vn9=cGS3H+G;zUhcI0wwV1*e(!;SW6KSHBFC{e%O4g?Ao$4$9}9h4P)$ z*E_(yFvp3j>tbi?c$2;#JDlzBe=d&eJK?xqkz?M?M7)#kwU}pKsGhICB+oxPNy78Y z2`7+8zBwmXVV$EN$0z>-^SiR&i@-<2cO$So-!t2bm0e(qhB5y<;QWRHWd6 + +_syscall3(int,execve,const char *,file,char **,argv,char **,envp) diff --git a/os/os/linux/lib/execve.o b/os/os/linux/lib/execve.o new file mode 100644 index 0000000000000000000000000000000000000000..00b88ef1b942c5e6836f7ddd415189ecc5a043c3 GIT binary patch literal 2336 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 literal 0 HcmV?d00001 diff --git a/os/os/linux/lib/malloc.c b/os/os/linux/lib/malloc.c new file mode 100644 index 0000000..d7c95d5 --- /dev/null +++ b/os/os/linux/lib/malloc.c @@ -0,0 +1,232 @@ +/* + * malloc.c --- a general purpose kernel memory allocator for Linux. + * + * Written by Theodore Ts'o (tytso@mit.edu), 11/29/91 + * + * This routine is written to be as fast as possible, so that it + * can be called from the interrupt level. + * + * Limitations: maximum size of memory we can allocate using this routine + * is 4k, the size of a page in Linux. + * + * The general game plan is that each page (called a bucket) will only hold + * objects of a given size. When all of the object on a page are released, + * the page can be returned to the general free pool. When malloc() is + * called, it looks for the smallest bucket size which will fulfill its + * request, and allocate a piece of memory from that bucket pool. + * + * Each bucket has as its control block a bucket descriptor which keeps + * track of how many objects are in use on that page, and the free list + * for that page. Like the buckets themselves, bucket descriptors are + * stored on pages requested from get_free_page(). However, unlike buckets, + * pages devoted to bucket descriptor pages are never released back to the + * system. Fortunately, a system should probably only need 1 or 2 bucket + * descriptor pages, since a page can hold 256 bucket descriptors (which + * corresponds to 1 megabyte worth of bucket pages.) If the kernel is using + * that much allocated memory, it's probably doing something wrong. :-) + * + * Note: malloc() and free() both call get_free_page() and free_page() + * in sections of code where interrupts are turned off, to allow + * malloc() and free() to be safely called from an interrupt routine. + * (We will probably need this functionality when networking code, + * particularily things like NFS, is added to Linux.) However, this + * presumes that get_free_page() and free_page() are interrupt-level + * safe, which they may not be once paging is added. If this is the + * case, we will need to modify malloc() to keep a few unused pages + * "pre-allocated" so that it can safely draw upon those pages if + * it is called from an interrupt routine. + * + * Another concern is that get_free_page() should not sleep; if it + * does, the code is carefully ordered so as to avoid any race + * conditions. The catch is that if malloc() is called re-entrantly, + * there is a chance that unecessary pages will be grabbed from the + * system. Except for the pages for the bucket descriptor page, the + * extra pages will eventually get released back to the system, though, + * so it isn't all that bad. + */ + +#include +#include +#include + +struct bucket_desc { /* 16 bytes */ + void *page; + struct bucket_desc *next; + void *freeptr; + unsigned short refcnt; + unsigned short bucket_size; +}; + +struct _bucket_dir { /* 8 bytes */ + int size; + struct bucket_desc *chain; +}; + +/* + * The following is the where we store a pointer to the first bucket + * descriptor for a given size. + * + * If it turns out that the Linux kernel allocates a lot of objects of a + * specific size, then we may want to add that specific size to this list, + * since that will allow the memory to be allocated more efficiently. + * However, since an entire page must be dedicated to each specific size + * on this list, some amount of temperance must be exercised here. + * + * Note that this list *must* be kept in order. + */ +struct _bucket_dir bucket_dir[] = { + { 16, (struct bucket_desc *) 0}, + { 32, (struct bucket_desc *) 0}, + { 64, (struct bucket_desc *) 0}, + { 128, (struct bucket_desc *) 0}, + { 256, (struct bucket_desc *) 0}, + { 512, (struct bucket_desc *) 0}, + { 1024, (struct bucket_desc *) 0}, + { 2048, (struct bucket_desc *) 0}, + { 4096, (struct bucket_desc *) 0}, + { 0, (struct bucket_desc *) 0}}; /* End of list marker */ + +/* + * This contains a linked list of free bucket descriptor blocks + */ +struct bucket_desc *free_bucket_desc = (struct bucket_desc *) 0; + +/* + * This routine initializes a bucket description page. + */ +static inline void init_bucket_desc() +{ + struct bucket_desc *bdesc, *first; + int i; + + first = bdesc = (struct bucket_desc *) get_free_page(); + if (!bdesc) + panic("Out of memory in init_bucket_desc()"); + for (i = PAGE_SIZE/sizeof(struct bucket_desc); i > 1; i--) { + bdesc->next = bdesc+1; + bdesc++; + } + /* + * This is done last, to avoid race conditions in case + * get_free_page() sleeps and this routine gets called again.... + */ + bdesc->next = free_bucket_desc; + free_bucket_desc = first; +} + +void *malloc(unsigned int len) +{ + struct _bucket_dir *bdir; + struct bucket_desc *bdesc; + void *retval; + + /* + * First we search the bucket_dir to find the right bucket change + * for this request. + */ + for (bdir = bucket_dir; bdir->size; bdir++) + if (bdir->size >= len) + break; + if (!bdir->size) { + printk("malloc called with impossibly large argument (%d)\n", + len); + panic("malloc: bad arg"); + } + /* + * Now we search for a bucket descriptor which has free space + */ + cli(); /* Avoid race conditions */ + for (bdesc = bdir->chain; bdesc; bdesc = bdesc->next) + if (bdesc->freeptr) + break; + /* + * If we didn't find a bucket with free space, then we'll + * allocate a new one. + */ + if (!bdesc) { + char *cp; + int i; + + if (!free_bucket_desc) + init_bucket_desc(); + bdesc = free_bucket_desc; + free_bucket_desc = bdesc->next; + bdesc->refcnt = 0; + bdesc->bucket_size = bdir->size; + bdesc->page = bdesc->freeptr = (void *) (cp = get_free_page()); + if (!cp) + panic("Out of memory in kernel malloc()"); + /* Set up the chain of free objects */ + for (i=PAGE_SIZE/bdir->size; i > 1; i--) { + *((char **) cp) = cp + bdir->size; + cp += bdir->size; + } + *((char **) cp) = 0; + bdesc->next = bdir->chain; /* OK, link it in! */ + bdir->chain = bdesc; + } + retval = (void *) bdesc->freeptr; + bdesc->freeptr = *((void **) retval); + bdesc->refcnt++; + sti(); /* OK, we're safe again */ + return(retval); +} + +/* + * Here is the free routine. If you know the size of the object that you + * are freeing, then free_s() will use that information to speed up the + * search for the bucket descriptor. + * + * We will #define a macro so that "free(x)" is becomes "free_s(x, 0)" + */ +void free_s(void *obj, int size) +{ + void *page; + struct _bucket_dir *bdir; + struct bucket_desc *bdesc, *prev; + + /* Calculate what page this object lives in */ + page = (void *) ((unsigned long) obj & 0xfffff000); + /* Now search the buckets looking for that page */ + for (bdir = bucket_dir; bdir->size; bdir++) { + prev = 0; + /* If size is zero then this conditional is always false */ + if (bdir->size < size) + continue; + for (bdesc = bdir->chain; bdesc; bdesc = bdesc->next) { + if (bdesc->page == page) + goto found; + prev = bdesc; + } + } + panic("Bad address passed to kernel free_s()"); +found: + cli(); /* To avoid race conditions */ + *((void **)obj) = bdesc->freeptr; + bdesc->freeptr = obj; + bdesc->refcnt--; + if (bdesc->refcnt == 0) { + /* + * We need to make sure that prev is still accurate. It + * may not be, if someone rudely interrupted us.... + */ + if ((prev && (prev->next != bdesc)) || + (!prev && (bdir->chain != bdesc))) + for (prev = bdir->chain; prev; prev = prev->next) + if (prev->next == bdesc) + break; + if (prev) + prev->next = bdesc->next; + else { + if (bdir->chain != bdesc) + panic("malloc bucket chains corrupted"); + bdir->chain = bdesc->next; + } + free_page((unsigned long) bdesc->page); + bdesc->next = free_bucket_desc; + free_bucket_desc = bdesc; + } + sti(); + return; +} + diff --git a/os/os/linux/lib/malloc.o b/os/os/linux/lib/malloc.o new file mode 100644 index 0000000000000000000000000000000000000000..83667757057ff0915c7c4ad6ae9f4d0c0160ea5d GIT binary patch literal 4880 zcma)AS!`Ta89sOBdNTId@?Fn#g3%ipE_#~_of1bL9E?Nob`ab!I zi+!(7T-}TyePri5q3N3vn|36JywH3rg7ig|=;VdqFN>4|Y6uD0$b_k=Ozh-m4gGIv zI%LD9cRm58cWNkl@`4|l?@)}?Ahli*ydk0WLLZY-Bqxr*atWsx2y&Iz zQ1g(^z4->@t0pdP##;1&99S)`$%Svb1UW~T9|qN>$66&9Xz+Mw{to(0$ucMAd%z^5 zsx45e1P1PsQe}d~6C!wxTZ1Ve4odw4tl?9LEbGU0OQ?zs$Z02#;(*FHF*VeDKiCAS z-K?TEkDk2Hdh$HH5xPtGEf9AhAMBq*z}?ygU-|`*FUMK ztQwMHeY;T9`P+36j^gt$ylB#2GF+vqk9thnNjbH}1CY=vxtnf0Gl3(3^_R`jIHd8* z8W#_1NDFL@QH>^mWin7}?XuCyX7W@C@xE~mx?b5WIx02> zLEA>-eBN_wHK&@X)i9V}akSy6=ei>`X{hs2NjkalOrczJauv@Ds=k{SJ(#+hwQa3M zSSyK3=UF}9VptKO1z?*sSO$bsFtF|*DZ*bMeP}EFgIxg~u_Au} z6Mq+-b?$9Q4&$><&7*IwWFLi44Io-&J8t<=Zfh zuznSU0PRfU2DBaQ8kyeDA?b9`Sr0OU2D#py6BO)cJS7lTyR|yr84Jf(#@nrqNZYL_ zL8ldt$6^~}n_^ZcR;)#Y<79SrZouN(ts(|!Anb%Xk_5380fbngNgT0g8Zqd^phJo0 zwskX9Cju zNweIX?UuE(lL>Y7h@GANm`>+XX7_Z{UhooUY0ViTWeyGLH}QqUZRjoQM!W^R{I!7S zmOl0A9PLml87BOOu!f?Y!K?_`p&53U+3iDTMRrAw%}qZTZrnUG+b0DNM^4W~x4zOd zcUJLdB42u8`jP3`nak1Z!OL`vZdvM2=^#gDF8}!K-1VLZ!cDuj{c`4s+5WlN{u5Gp zCQ_03a3mc2&dZ2<{T<2s=tIAV1aot9W~9TxTXVCoU7q`DPfy6kyhbZQIWKC3$6VpL zqd6SdEH6aCo2cr0!d#LCPu%yZhn(%sV0uG(&`FgtUT%C#;S(F~bW&qZYP3=+_^DAZ zQ*u+)3eLUjL0Bjk3uQMo8kBQ>p@RD>HCnEuYJMhnFje&`zMJzao*b(FG8X;gm6F?E z4)T6~rIsqYhx-vGIFcGjuUnTYX0rVQN`O9#bdehK_m5UN2mer}C~#eR;^s?UEDiz> zb<-|Rk5iU+tf-AwJl_e*wZd2#cQdarbroa9tC=y^xX6-KJ@=4UW;)r#jsR(Dn0prXBggk@H{;7>{|~kFP%76)3yw1cv>#(bDMt54>`qijVOamt&f}2U75-!=og0Gw}>>uwHJ9zw?*k zVq5;#Fyq&cK;Fz+xr9Z7Fy$*i6k1kU+M82p?76~AExfF9wCBn%wXkSeVnBsu1(rl% zS&4c+F3&k7!}!|a@iDDt=IzM;F3l5I$9r$$9{|s}@Luh}eD>U=e+0a_Td6;AlYZ&d zc;7oz_om8c$nboG#_$)36w0@znkg4@I+Cb*c#IC3mutyL?S&9F)`yXU)gZ)2fg$X_ z&ydIDG8(HyY@X+dusaJ3VMD#B`IpGU@1Nx1XJhWfE{*Ge9Ov`o;eUWU>>IIB8MjD; z{EI-!*J9g{9{`fyP5gimdniZTtVZq*-Z%J91Yu$6c}9r*KN4a$5ixs+*l1i!%GYb$ zs&SV_-ci(NHOjjK{NtMcipJ+O{!rr!M2z!_=6|j6ipGCveJkgWcpuWZR^#17_>XAb z( +#include + +int open(const char * filename, int flag, ...) +{ + register int res; + va_list arg; + + va_start(arg,flag); + __asm__("int $0x80" + :"=a" (res) + :"0" (__NR_open),"b" (filename),"c" (flag), + "d" (va_arg(arg,int))); + if (res>=0) + return res; + errno = -res; + return -1; +} diff --git a/os/os/linux/lib/open.o b/os/os/linux/lib/open.o new file mode 100644 index 0000000000000000000000000000000000000000..8d78c9dd4a63d212cd5944be48fef65ab261893d GIT binary patch literal 2364 zcma)7U1%It6h3!mHoM6t+x%2bNWc+NjXyJ+*hNc!Qxh#AO@!7eq8Mj)XLkp8XX4Ck zNlUGfSTID)XiHh2Esxxpwm?|?SG8hmN{HoOGi5c9CblMpV~E$MNYcGW2KhHgY+fL(F6*9n^>O3%w&4BRhZ^)YzyIE4PK1Q$c%Kxw3? zm&Qv&Vz_7UJ|Im}v3MLI6s2YXOT3r#(&6Hf;=%|Pxeq05^w{FWSQ39|Y+-~UW=F3* zH71bD=XOVEqeKNT^;SqPBq$u~dyp8Vh-iv^V(jP`>L$P%ST&n1)m^q<0c$i1Da1de z0Z4fva1DfQmp#AM?$%wRVAb{Q8mcIY>*$Bw;+xX-J-CUDy~ug=qFDZ9>HFJ@i&tON za=_!ERBi_BBgNL3lt)^);f{qtkjSz#Z)c_a74H5KwOyXLNu3wA2z>g5}11pN1 z+H2No7{qQZ4njKbthBKOY$WoUzFRkIEhnU?6@;<58{<3IXgkflDvl(T-bFXQuD1iZVRPzSwd=>-WX0CwUFpqSo~hW=m4}lkTDhP52@)62khoM3vI?C3%#cB*7YahT|qvO>3Q$L?B8cHM~`va3-J3w4G`-bkAqAPU!ee-2Th}?xY%kImoUBosNsm+CCa-<8YG3CS%;ziad;D z{r^Yak0NY4d8^R;f0MnVoMRdX_ev`fZ{s!LN5f#Q;l8kcAoX=5@51hROK!C@T6>jNvi*J1M*-ZxVNcz-0O zl$>L}lxkJ?92)+JtVo2ayOP$a)Ma%rX@KjPJ_55X|8JnzQFjzt5wDNwLvVHex?5kZTqx9Wxsq(Sd4C(Sj_X4^+*{t8c=fKhlU$G47#2wrt9Ub61!n6P$ z#tCsx6mehFf4cl4B!BF51YrSa{!R-Bo>icMd?u{#Ni~1V1P=TG)|hB2jh9n>EY + +_syscall0(pid_t,setsid) diff --git a/os/os/linux/lib/setsid.o b/os/os/linux/lib/setsid.o new file mode 100644 index 0000000000000000000000000000000000000000..7326d9cd51e2bc48d357c3c7806290fb07f04be0 GIT binary patch literal 2240 zcma)7&2QX96rZu3O`1)Y%?E9wfG{W(;ltj9u25AH#4n4oLk6IOf8sTtVW7xN@n018|`dhw}T4XLen2fG5xUp7&3A=W>`cn1sJXWCfQ^@4Yb4!Kg>7~o_oOyon^9xH7Zk6U}jhP5yhSUup2hAy-bWn%nI`? z>iQi<$oF=_%QUX}-) zZEq({^01R9sc5y*FvDi`7COBk75yaMDmD{c4_OkS)Z)^{#%Xu;T6-Ah!(u7k3qvKX zf4JWC*P721TAc9$(?hY75&n9Bn__8{|P7G*1iKGh7<> z{XE>wh2IVGK=|zp?W3|Awuf7-DBet9Qhd;Er{Q~LYmf%<7WP+~z@nH5$RYerG8lyD zoFAhmKI&Z5sF)M>TB@$an*R@e0#3aD746J>Up}O?5tcEID6T+t+zxzV4ud|t@RUzz z*#;%3b6T(pn|RMbqW^#SaXn@Z12EoaWHcBX-f)V*#8k@QW&e zEm*-Z*rPBs&9tj|pe|&d@qYk(%KV7{ literal 0 HcmV?d00001 diff --git a/os/os/linux/lib/string.c b/os/os/linux/lib/string.c new file mode 100644 index 0000000..1182e63 --- /dev/null +++ b/os/os/linux/lib/string.c @@ -0,0 +1,14 @@ +/* + * linux/lib/string.c + * + * (C) 1991 Linus Torvalds + */ + +#ifndef __GNUC__ +#error I want gcc! +#endif + +#define extern +#define inline +#define __LIBRARY__ +#include diff --git a/os/os/linux/lib/string.o b/os/os/linux/lib/string.o new file mode 100644 index 0000000000000000000000000000000000000000..840f038b2beb337cf418b004cd61fe5f8badc3b6 GIT binary patch literal 6380 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 b$T5+-MNW%6E;57|# +#include + +_syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options) + +pid_t wait(int * wait_stat) +{ + return waitpid(-1,wait_stat,0); +} diff --git a/os/os/linux/lib/wait.o b/os/os/linux/lib/wait.o new file mode 100644 index 0000000000000000000000000000000000000000..69f2ed6dfe014cec8c0f238dd83b4e502c1fb143 GIT binary patch literal 2580 zcma)8U5Hdw96$GCX2+e~an?26MWKmC(sJ&&IhB~7t!BnzVOfF2cxUGB&ZV7uw|npS zh4jG^BufuMC4q0^qYwlkJp~%}ViCPWFHuiM2HA^5lKp#>5MYH_A&h)wP#~U|f2&IIn1;&^@u;;&`$Ti>5&=A}EJ#Vh5*mlto0T-{SG&R`b8>Nq_HAtF)#xW~|7USEGDY6pK4xLeMHC4+)z~ss)fcq>ayjSi^Yfkt>Q;% z#o{1m=j66Yta>em$>pnqqI85z(NUl&4uBiRU!_rSdBu;(YW*~smAwS^E@%Zp(21C;h^v;Cl*_+b#k6oj=naoexg7NRim+DRD6 z4K-m*u#4EA3%pLH-E|`oF32Picf%;D-1YI^vImm!D&FIfnX!M;V{^oO7|d0e&}>Ft ze7AM`rl+@7)*ov1gQTBssP<@IYEy4cHJnY24XKq)UP%TrP97A-se-X)#J1l<$9cFM zB;I4OyHr>-r%MyZN`>8*OE&YiDIf2+m@bu@C48|?e4>}QEnpI**ws?x%{z&AJP}UE zObpWB88ov0JBf3rPAP zg}YqWdjuB7|5qH>qjOk<^?swENc%QH&#rG9luuye`f?b0eY+s*9Ejo_D4$VKq3KcKI)^1*M!l016ltFeJzMWK6xQKBhB0)#Hy|^I z`zC#hdVi;)Gg@2WWM`cof_GBA$xF$QJ%JOOVb?s=dlu8;H~ zMs^=I7GH*q`&f>l_b~=JJJk#v=V8;N=grPZUztsT5ihzJ#b7U!5{mL+f8pn@g%2Vy{$JkhMqlO2#HMg|HbOW+qWLze8| zz+j;RYzK+&*a|d;z0gE?6^8z;re8m#e1`b~r@s>NQ5O7 + +_syscall3(int,write,int,fd,const char *,buf,off_t,count) diff --git a/os/os/linux/lib/write.o b/os/os/linux/lib/write.o new file mode 100644 index 0000000000000000000000000000000000000000..0d4504785067360dab5e22df170e3bc4a698f092 GIT binary patch literal 2372 zcma)7&2QXP5T9pzKax$i`QRf_Dq*B8q`-O;x}Yd+X-f(vs47ySJwU6-yX(zb?AodA zZIdbjq<|<22O_?N#HA{K0pbvGKu84v5^zI8LgK`Y9tsx@J(S-(zn67SFxodWznOV6 z@6FiW*Pl7{tPp}U2{LJbh+0r`dm4*RywS0=Y!s@Olh@y?0L z$mT|6gx2y~Q2!id{?D)1dFRd@(B?OzuiW?+D9ve!L(s(^>{oO|Ny9393DvN2zd)E) z&JPkYjKVcGisJha)&bV-$Cz7%AEhJz9YpR6Ffn`(oQYG4Pd^9Gw_D0?Y*W6`Zv(O2 z*tQBajv9VWqGIuPiDc^Sgodmg;Nh3SN>6~9Kg--=OzbaDl+5yUc}$GwNAE|b3YAJv z!Gs{C7ID)1$Sg0E4waTBa5_gEol4=uQ%e)P^VsCaPfrQ>@;Ne#X`nGlQ~*@_7#8by z!J)mV#TkbmA{M2A`{>l+DV%d3mVu@F&6;j7>k*bgFMtbiySxWnJ_ne-aGaVSG`szl zSBuwU8bG4Uk)L=@lM^KCt6uDM_<89Eew?(R%Yr${%^~qTW+U>&?;(u#-$o8KYMrp> z)q;L2sfBT^>j(X{>Z~(2SM9ouT0J#@Hz;hkmlJA+eT?3Vq9CM`r_b7pcHNnG>UOo~ zM$OI<|KR+Sc6G(Bw!@yERNIl;^Qx;M9v3fy(GO6-tG4?=Gx5V9hA9ZEapE>#t*%C4 z;x&^n!r^0oCGc8yv*Sh-cfu&KcWwOS$vY3i*p!C)S3GV4b;DrAX7loLaAnG?VE*Q0 zA6WJ=O=As7EoJZGCBu)#u{ef5FO2sqY(g?!OvNtO`5uLZmSnW~brkJpBhI_?4*{)mi7 znT~r)#c9{udN9hsaZI0Jv7Ub9h^``To*jz#d`ur=W$$q~bC137>3fVp&zAZc;5uxY zblq%C_Ptpkx&?`^FzvzOeB5`gna!7=dH2GmN$1m8%dFj^zwT%|%e()b8D}dn*0)Y~ znevGnWH1Sb&5$W4Ixv`WvROPb0MJarpIe4Z;tmeTL@;rEP`Rp8bUP&9$0R9)xBoVOy literal 0 HcmV?d00001 diff --git a/os/os/linux/mm/Makefile b/os/os/linux/mm/Makefile new file mode 100644 index 0000000..e0bcd73 --- /dev/null +++ b/os/os/linux/mm/Makefile @@ -0,0 +1,38 @@ +AR =ar +AS =as +LD =ld +LDFLAGS =-m elf_i386 -Ttext 0 -e startup_32 +CC =gcc -march=i386 +CFLAGS =-w -g -fstrength-reduce -fomit-frame-pointer -mcld \ + -finline-functions -nostdinc -fno-stack-protector -I../include +CPP =gcc -E -nostdinc -I../include + +.c.o: + $(CC) $(CFLAGS) \ + -c -o $*.o $< +.s.o: + $(AS) -o $*.o $< +.c.s: + $(CC) $(CFLAGS) \ + -S -o $*.s $< + +OBJS = memory.o page.o + +all: mm.o + +mm.o: $(OBJS) + $(LD) -r -o mm.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: +memory.o : memory.c ../include/signal.h ../include/sys/types.h \ + ../include/asm/system.h ../include/linux/sched.h ../include/linux/head.h \ + ../include/linux/fs.h ../include/linux/mm.h ../include/linux/kernel.h diff --git a/os/os/linux/mm/memory.c b/os/os/linux/mm/memory.c new file mode 100644 index 0000000..7cf53a4 --- /dev/null +++ b/os/os/linux/mm/memory.c @@ -0,0 +1,468 @@ +/* + * linux/mm/memory.c + * + * (C) 1991 Linus Torvalds + */ + +/* + * demand-loading started 01.12.91 - seems it is high on the list of + * things wanted, and it should be easy to implement. - Linus + */ + +/* + * Ok, demand-loading was easy, shared pages a little bit tricker. Shared + * pages started 02.12.91, seems to work. - Linus. + * + * Tested sharing by executing about 30 /bin/sh: under the old kernel it + * would have taken more than the 6M I have free, but it worked well as + * far as I could see. + * + * Also corrected some "invalidate()"s - I wasn't doing enough of them. + */ + +#include + +#include + +#include +#include +#include + +volatile void do_exit(long code); + +static inline volatile void oom(void) +{ + printk("out of memory\n\r"); + do_exit(SIGSEGV); +} + +#define invalidate() \ +__asm__("movl %%eax,%%cr3"::"a" (0)) + +/* these are not to be changed without changing head.s etc */ +#define LOW_MEM 0x100000 +#define PAGING_MEMORY (15*1024*1024) +#define PAGING_PAGES (PAGING_MEMORY>>12) +#define MAP_NR(addr) (((addr)-LOW_MEM)>>12) +#define USED 100 + +#define CODE_SPACE(addr) ((((addr)+4095)&~4095) < \ +current->start_code + current->end_code) + +static long HIGH_MEMORY = 0; + +#define copy_page(from,to) \ +__asm__("cld ; rep ; movsl"::"S" (from),"D" (to),"c" (1024)) + +static unsigned char mem_map [ PAGING_PAGES ] = {0,}; + +/* + * Get physical address of first (actually last :-) free page, and mark it + * used. If no free pages left, return 0. + */ +unsigned long get_free_page(void) +{ +register unsigned long __res asm("ax"); + +__asm__("std ; repne ; scasb\n\t" + "jne 1f\n\t" + "movb $1,1(%%edi)\n\t" + "sall $12,%%ecx\n\t" + "addl %2,%%ecx\n\t" + "movl %%ecx,%%edx\n\t" + "movl $1024,%%ecx\n\t" + "leal 4092(%%edx),%%edi\n\t" + "rep ; stosl\n\t" + "movl %%edx,%%eax\n\t" + "1:" + "cld\n\t" /* by wyj */ + :"=a" (__res) + :"0" (0),"i" (LOW_MEM),"c" (PAGING_PAGES), + "D" (mem_map+PAGING_PAGES-1) + ); +return __res; +} + +/* + * Free a page of memory at physical address 'addr'. Used by + * 'free_page_tables()' + */ +void free_page(unsigned long addr) +{ + if (addr < LOW_MEM) return; + if (addr >= HIGH_MEMORY) + panic("trying to free nonexistent page"); + addr -= LOW_MEM; + addr >>= 12; + if (mem_map[addr]--) return; + mem_map[addr]=0; + panic("trying to free free page"); +} + +/* + * This function frees a continuos block of page tables, as needed + * by 'exit()'. As does copy_page_tables(), this handles only 4Mb blocks. + */ +int free_page_tables(unsigned long from,unsigned long size) +{ + unsigned long *pg_table; + unsigned long * dir, nr; + + if (from & 0x3fffff) + panic("free_page_tables called with wrong alignment"); + if (!from) + panic("Trying to free up swapper memory space"); + size = (size + 0x3fffff) >> 22; + dir = (unsigned long *) ((from>>20) & 0xffc); /* _pg_dir = 0 */ + for ( ; size-->0 ; dir++) { + if (!(1 & *dir)) + continue; + pg_table = (unsigned long *) (0xfffff000 & *dir); + for (nr=0 ; nr<1024 ; nr++) { + if (1 & *pg_table) + free_page(0xfffff000 & *pg_table); + *pg_table = 0; + pg_table++; + } + free_page(0xfffff000 & *dir); + *dir = 0; + } + invalidate(); + return 0; +} + +/* + * Well, here is one of the most complicated functions in mm. It + * copies a range of linerar addresses by copying only the pages. + * Let's hope this is bug-free, 'cause this one I don't want to debug :-) + * + * Note! We don't copy just any chunks of memory - addresses have to + * be divisible by 4Mb (one page-directory entry), as this makes the + * function easier. It's used only by fork anyway. + * + * NOTE 2!! When from==0 we are copying kernel space for the first + * fork(). Then we DONT want to copy a full page-directory entry, as + * that would lead to some serious memory waste - we just copy the + * first 160 pages - 640kB. Even that is more than we need, but it + * doesn't take any more memory - we don't copy-on-write in the low + * 1 Mb-range, so the pages can be shared with the kernel. Thus the + * special case for nr=xxxx. + */ +int copy_page_tables(unsigned long from,unsigned long to,long size) +{ + unsigned long * from_page_table; + unsigned long * to_page_table; + unsigned long this_page; + unsigned long * from_dir, * to_dir; + unsigned long nr; + + if ((from&0x3fffff) || (to&0x3fffff)) + panic("copy_page_tables called with wrong alignment"); + from_dir = (unsigned long *) ((from>>20) & 0xffc); /* _pg_dir = 0 */ + to_dir = (unsigned long *) ((to>>20) & 0xffc); + size = ((unsigned) (size+0x3fffff)) >> 22; + for( ; size-->0 ; from_dir++,to_dir++) { + if (1 & *to_dir) + panic("copy_page_tables: already exist"); + if (!(1 & *from_dir)) + continue; + from_page_table = (unsigned long *) (0xfffff000 & *from_dir); + if (!(to_page_table = (unsigned long *) get_free_page())) + return -1; /* Out of memory, see freeing */ + *to_dir = ((unsigned long) to_page_table) | 7; + nr = (from==0)?0xA0:1024; + for ( ; nr-- > 0 ; from_page_table++,to_page_table++) { + this_page = *from_page_table; + if (!(1 & this_page)) + continue; + this_page &= ~2; + *to_page_table = this_page; + if (this_page > LOW_MEM) { + *from_page_table = this_page; + this_page -= LOW_MEM; + this_page >>= 12; + mem_map[this_page]++; + } + } + } + invalidate(); + return 0; +} + +/* + * This function puts a page in memory at the wanted address. + * It returns the physical address of the page gotten, 0 if + * out of memory (either when trying to access page-table or + * page.) + */ +unsigned long put_page(unsigned long page,unsigned long address) +{ + unsigned long tmp, *page_table; + +/* NOTE !!! This uses the fact that _pg_dir=0 */ + + if (page < LOW_MEM || page >= HIGH_MEMORY) + printk("Trying to put page %p at %p\n",page,address); + if (mem_map[(page-LOW_MEM)>>12] != 1) + printk("mem_map disagrees with %p at %p\n",page,address); + page_table = (unsigned long *) ((address>>20) & 0xffc); + if ((*page_table)&1) + page_table = (unsigned long *) (0xfffff000 & *page_table); + else { + if (!(tmp=get_free_page())) + return 0; + *page_table = tmp|7; + page_table = (unsigned long *) tmp; + } + page_table[(address>>12) & 0x3ff] = page | 7; +/* no need for invalidate */ + return page; +} + +void un_wp_page(unsigned long * table_entry) +{ + unsigned long old_page,new_page; + + old_page = 0xfffff000 & *table_entry; + if (old_page >= LOW_MEM && mem_map[MAP_NR(old_page)]==1) { + *table_entry |= 2; + invalidate(); + return; + } + if (!(new_page=get_free_page())) + oom(); + if (old_page >= LOW_MEM) + mem_map[MAP_NR(old_page)]--; + *table_entry = new_page | 7; + invalidate(); + copy_page(old_page,new_page); +} + +/* + * This routine handles present pages, when users try to write + * to a shared page. It is done by copying the page to a new address + * and decrementing the shared-page counter for the old page. + * + * If it's in code space we exit with a segment error. + */ +void do_wp_page(unsigned long error_code,unsigned long address) +{ +#if 0 +/* we cannot do this yet: the estdio library writes to code space */ +/* stupid, stupid. I really want the libc.a from GNU */ + if (CODE_SPACE(address)) + do_exit(SIGSEGV); +#endif + un_wp_page((unsigned long *) + (((address>>10) & 0xffc) + (0xfffff000 & + *((unsigned long *) ((address>>20) &0xffc))))); + +} + +void write_verify(unsigned long address) +{ + unsigned long page; + + if (!( (page = *((unsigned long *) ((address>>20) & 0xffc)) )&1)) + return; + page &= 0xfffff000; + page += ((address>>10) & 0xffc); + if ((3 & *(unsigned long *) page) == 1) /* non-writeable, present */ + un_wp_page((unsigned long *) page); + return; +} + +void get_empty_page(unsigned long address) +{ + unsigned long tmp; + + if (!(tmp=get_free_page()) || !put_page(tmp,address)) { + free_page(tmp); /* 0 is ok - ignored */ + oom(); + } +} + +/* + * try_to_share() checks the page at address "address" in the task "p", + * to see if it exists, and if it is clean. If so, share it with the current + * task. + * + * NOTE! This assumes we have checked that p != current, and that they + * share the same executable. + */ +static int try_to_share(unsigned long address, struct task_struct * p) +{ + unsigned long from; + unsigned long to; + unsigned long from_page; + unsigned long to_page; + unsigned long phys_addr; + + from_page = to_page = ((address>>20) & 0xffc); + from_page += ((p->start_code>>20) & 0xffc); + to_page += ((current->start_code>>20) & 0xffc); +/* is there a page-directory at from? */ + from = *(unsigned long *) from_page; + if (!(from & 1)) + return 0; + from &= 0xfffff000; + from_page = from + ((address>>10) & 0xffc); + phys_addr = *(unsigned long *) from_page; +/* is the page clean and present? */ + if ((phys_addr & 0x41) != 0x01) + return 0; + phys_addr &= 0xfffff000; + if (phys_addr >= HIGH_MEMORY || phys_addr < LOW_MEM) + return 0; + to = *(unsigned long *) to_page; + if (!(to & 1)) + if (to = get_free_page()) + *(unsigned long *) to_page = to | 7; + else + oom(); + to &= 0xfffff000; + to_page = to + ((address>>10) & 0xffc); + if (1 & *(unsigned long *) to_page) + panic("try_to_share: to_page already exists"); +/* share them: write-protect */ + *(unsigned long *) from_page &= ~2; + *(unsigned long *) to_page = *(unsigned long *) from_page; + invalidate(); + phys_addr -= LOW_MEM; + phys_addr >>= 12; + mem_map[phys_addr]++; + return 1; +} + +/* + * share_page() tries to find a process that could share a page with + * the current one. Address is the address of the wanted page relative + * to the current data space. + * + * We first check if it is at all feasible by checking executable->i_count. + * It should be >1 if there are other tasks sharing this inode. + */ +static int share_page(unsigned long address) +{ + struct task_struct ** p; + + if (!current->executable) + return 0; + if (current->executable->i_count < 2) + return 0; + for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) { + if (!*p) + continue; + if (current == *p) + continue; + if ((*p)->executable != current->executable) + continue; + if (try_to_share(address,*p)) + return 1; + } + return 0; +} + +void do_no_page(unsigned long error_code,unsigned long address) +{ + int nr[4]; + unsigned long tmp; + unsigned long page; + int block,i; + + if (current->pid > 5) + printk(" --do_no_page: address=%x, pid=%d\n", address, current->pid); + + address &= 0xfffff000; + tmp = address - current->start_code; + if (!current->executable || tmp >= current->end_data) { + get_empty_page(address); + return; + } + if (share_page(tmp)) + return; + if (!(page = get_free_page())) + oom(); +/* remember that 1 block is used for header */ + block = 1 + tmp/BLOCK_SIZE; + for (i=0 ; i<4 ; block++,i++) + nr[i] = bmap(current->executable,block); + bread_page(page,current->executable->i_dev,nr); + i = tmp + 4096 - current->end_data; + tmp = page + 4096; + while (i-- > 0) { + tmp--; + *(char *)tmp = 0; + } + if (put_page(page,address)) + return; + free_page(page); + oom(); +} + +void do_no_pagex(unsigned long error_code,unsigned long address) +{ + int nr[4]; + unsigned long tmp; + unsigned long page; + int block,i; + + address &= 0xfffff000; + tmp = address - current->start_code; + if (!current->executable || tmp >= current->end_data) { + get_empty_page(address); + return; + } + if (share_page(tmp)) + return; + if (!(page = get_free_page())) + oom(); +/* remember that 1 block is used for header */ + block = 1 + tmp/BLOCK_SIZE; + for (i=0 ; i<4 ; block++,i++) + nr[i] = bmap(current->executable,block); + bread_page(page,current->executable->i_dev,nr); + i = tmp + 4096 - current->end_data; + tmp = page + 4096; + while (i-- > 0) { + tmp--; + *(char *)tmp = 0; + } + if (put_page(page,address)) + return; + free_page(page); + oom(); +} + +void mem_init(long start_mem, long end_mem) +{ + int i; + + HIGH_MEMORY = end_mem; + for (i=0 ; i>= 12; + while (end_mem-->0) + mem_map[i++]=0; +} + +void calc_mem(void) +{ + int i,j,k,free=0; + long * pg_tbl; + + for(i=0 ; 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 T!PSDjg1ZDC7v%qTv)+FKQ=t$V literal 0 HcmV?d00001 diff --git a/os/os/linux/mm/mm.o b/os/os/linux/mm/mm.o new file mode 100644 index 0000000000000000000000000000000000000000..549d06c1dc3c93101ef2aeffa85a31b5def277d2 GIT binary patch literal 13936 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 M(++mG>`3K50pD0JzW@LL literal 0 HcmV?d00001 diff --git a/os/os/linux/mm/page.o b/os/os/linux/mm/page.o new file mode 100644 index 0000000000000000000000000000000000000000..da4852668a6d8b88d91c428ae8572bb3d4d2090d GIT binary patch literal 640 zcmb<-^>JflWMqH=Mh0dE1doAX4phPfOlvT3Ft9STv#10H$+7V-*d+iI?Yq@?sP7TK z!lj^ql^~s^>@WWO|Ns9rE0}6N!ok0gT|O!@;yi<1ab<2vViJ%pDT2@$Fji4&j$TP> zMG1pmN@7VOgI-c`G1OurD0!e7kj-pRwIH{eL)jn-<{xPwn-fXAfQf+ts z<^W< +#include + +#define NAME_MAX 80 +#include + +int main(int argc, char *argv[]) +{ + DIR *dir ; + struct dirent *de; + + if (argc != 1) + exit(1); + + if ((dir = opendir(".")) == NULL) + exit(1); + + while ((de = readdir(dir)) != NULL) + printf("%s\t", de->d_name); + + printf("\n"); + closedir(dir); + exit(0); +} diff --git a/os/os/linux/tools/build b/os/os/linux/tools/build new file mode 100644 index 0000000000000000000000000000000000000000..0fa6ae7f877d2483ad12f6df98491878b0f38b14 GIT binary patch literal 15144 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 N^|Cbi(V*L${{d;jp)>#h literal 0 HcmV?d00001 diff --git a/os/os/linux/tools/build.c b/os/os/linux/tools/build.c new file mode 100644 index 0000000..8b8c7ab --- /dev/null +++ b/os/os/linux/tools/build.c @@ -0,0 +1,171 @@ +/* + * linux/tools/build.c + * + * (C) 1991 Linus Torvalds + */ + +/* + * This file builds a disk-image from three different files: + * + * - bootsect: max 510 bytes of 8086 machine code, loads the rest + * - setup: max 4 sectors of 8086 machine code, sets up system parm + * - system: 80386 code for actual system + * + * It does some checking that all files are of the correct type, and + * just writes the result to stdout, removing headers and padding to + * the right amount. It also writes some system data to stderr. + */ + +/* + * Changes by tytso to allow root device specification + */ + +#include /* fprintf */ +#include +#include /* contains exit */ +#include /* unistd.h needs this */ +#include +#include +#include /* contains read/write */ +#include + +#define MAJOR(a) (((unsigned)(a))>>8) +#define MINOR(a) ((a)&0xff) + +#define MINIX_HEADER 32 +#define GCC_HEADER 0x80 /* 0x1000 */ /* by wyj */ + +#define SYS_SIZE 0x3000 + +#define DEFAULT_MAJOR_ROOT 0x03 //0x02 /* by wyj */ +#define DEFAULT_MINOR_ROOT 0x00 //0x1d + +/* max nr of sectors of setup: don't change unless you also change + * bootsect etc */ +#define SETUP_SECTS 4 + +#define STRINGIFY(x) #x + +void die(char * str) +{ + fprintf(stderr,"%s\n",str); + exit(1); +} + +void usage(void) +{ + die("Usage: build bootsect setup system [rootdev] [> image]"); +} + +int main(int argc, char ** argv) +{ + int i,c,id; + char buf[1024*4]; /* by wyj */ + char major_root, minor_root; + struct stat sb; + + if ((argc != 4) && (argc != 5)) + usage(); + if (argc == 5) { + if (strcmp(argv[4], "FLOPPY")) { + if (stat(argv[4], &sb)) { + perror(argv[4]); + die("Couldn't stat root device."); + } + major_root = MAJOR(sb.st_rdev); + minor_root = MINOR(sb.st_rdev); + } else { + major_root = 0; + minor_root = 0; + } + } else { + major_root = DEFAULT_MAJOR_ROOT; + minor_root = DEFAULT_MINOR_ROOT; + } + fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root); + if ((major_root != 2) && (major_root != 3) && + (major_root != 0)) { + fprintf(stderr, "Illegal root device (major = %d)\n", + major_root); + die("Bad root device --- major #"); + } + for (i=0;i0 ; i+=c ) + if (write(1,buf,c)!=c) + die("Write call failed"); + close (id); + if (i > SETUP_SECTS*512) + die("Setup exceeds " STRINGIFY(SETUP_SECTS) + " sectors - rewrite build/boot/setup"); + fprintf(stderr,"Setup is %d bytes.\n",i); + for (c=0 ; c sizeof(buf)) + c = sizeof(buf); + if (write(1,buf,c) != c) + die("Write call failed"); + i += c; + } + + if ((id=open(argv[3],O_RDONLY,0))<0) + die("Unable to open 'system'"); + if (read(id,buf,GCC_HEADER) != GCC_HEADER) + die("Unable to read header of 'system'"); +// if (((long *) buf)[5] != 0) +// die("Non-GCC header of 'system'"); + for (i=0 ; (c=read(id,buf,sizeof buf))>0 ; i+=c ) + if (write(1,buf,c)!=c) + die("Write call failed"); + close(id); + fprintf(stderr,"System is %d bytes.\n",i); + if (i > SYS_SIZE*16) + die("System is too big"); + return(0); +} diff --git a/os/os/linux/tools/system b/os/os/linux/tools/system new file mode 100644 index 0000000000000000000000000000000000000000..f61bee765ca166b1564cdc94650cf3f220f28eed GIT binary patch literal 306090 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�b&Xfwa62;M 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�@?)L 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 t{&|{e*<55HtTR{-why#uvf|8mX0epaId_#6