added patched kernel compilable on ubuntu 64

Esse commit está contido em:
Popa Adrian Marius
2013-09-18 10:18:30 +03:00
commit 7a53075306
97 arquivos alterados com 13864 adições e 0 exclusões
+98
Ver Arquivo
@@ -0,0 +1,98 @@
#
# Makefile for linux.
# If you don't have '-mstring-insns' in your gcc (and nobody but me has :-)
# remove them from the CFLAGS defines.
#
AS86 =as86 -0
CC86 =cc86 -0
LD86 =ld86 -0
AS =as --32
LD =ld -m elf_i386
LDFLAGS =-M -Ttext 0 -e startup_32
#LDFLAGS =-s -x -M -Ttext 0 -e startup_32
CC =gcc
CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer -fno-stack-protector -fno-builtin -g -m32
CPP =gcc -E -nostdinc -Iinclude
ARCHIVES=kernel/kernel.o mm/mm.o fs/fs.o
LIBS =lib/lib.a
.c.s:
$(CC) $(CFLAGS) \
-nostdinc -Iinclude -S -o $*.s $<
.s.o:
$(AS) --32 -o $*.o $<
.c.o:
$(CC) $(CFLAGS) \
-nostdinc -Iinclude -c -o $*.o $<
all: Image
Image: boot/boot tools/system tools/build
objcopy -O binary -R .note -R .comment tools/system tools/system.bin
tools/build boot/boot tools/system.bin > Image
# sync
tools/build: tools/build.c
$(CC) $(CFLAGS) \
-o tools/build tools/build.c
#chmem +65000 tools/build
boot/head.o: boot/head.s
tools/system: boot/head.o init/main.o \
$(ARCHIVES) $(LIBS)
$(LD) $(LDFLAGS) boot/head.o init/main.o \
$(ARCHIVES) \
$(LIBS) \
-o tools/system > System.map
kernel/kernel.o:
(cd kernel; make)
mm/mm.o:
(cd mm; make)
fs/fs.o:
(cd fs; make)
lib/lib.a:
(cd lib; make)
boot/boot: boot/boot.s tools/system
(echo -n "SYSSIZE = (";stat -c%s tools/system \
| tr '\012' ' '; echo "+ 15 ) / 16") > tmp.s
cat boot/boot.s >> tmp.s
$(AS86) -o boot/boot.o tmp.s
rm -f tmp.s
$(LD86) -s -o boot/boot boot/boot.o
clean:
rm -f Image System.map tmp_make boot/boot core
rm -f init/*.o boot/*.o tools/system tools/build tools/system.bin
(cd mm;make clean)
(cd fs;make clean)
(cd kernel;make clean)
(cd lib;make clean)
backup: clean
(cd .. ; tar cf - linux | compress16 - > backup.Z)
# sync
dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
(for i in init/*.c;do echo -n "init/";$(CPP) -M $$i;done) >> tmp_make
cp tmp_make Makefile
(cd fs; make dep)
(cd kernel; make dep)
(cd mm; make dep)
### Dependencies:
init/main.o : init/main.c include/unistd.h include/sys/stat.h \
include/sys/types.h include/sys/times.h include/sys/utsname.h \
include/utime.h include/time.h include/linux/tty.h include/termios.h \
include/linux/sched.h include/linux/head.h include/linux/fs.h \
include/linux/mm.h include/asm/system.h include/asm/io.h include/stddef.h \
include/stdarg.h include/fcntl.h
Ver Arquivo
+329
Ver Arquivo
@@ -0,0 +1,329 @@
;
; boot.s
;
; boot.s is loaded at 0x7c00 by the bios-startup routines, and moves itself
; out of the way to address 0x90000, and jumps there.
;
; It then loads the system at 0x10000, using BIOS interrupts. Thereafter
; it disables all interrupts, moves the system down to 0x0000, changes
; to protected mode, and calls the start of system. System then must
; RE-initialize the protected mode in it's own tables, and enable
; interrupts as needed.
;
; 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 - in fact more would mean we'd have to move
; not just these start-up routines, but also do something about the cache-
; memory (block IO devices). The area left over in the lower 640 kB is meant
; for these. No other memory is assumed to be "physical", ie all memory
; over 1Mb is demand-paging. All addresses under 1Mb are guaranteed to match
; their physical addresses.
;
; NOTE1 abouve is no longer valid in it's entirety. cache-memory is allocated
; above the 1Mb mark as well as below. Otherwise it is mainly correct.
;
; NOTE 2! The boot disk type must be set at compile-time, by setting
; the following equ. Having the boot-up procedure hunt for the right
; disk type is severe brain-damage.
; The loader has been made as simple as possible (had to, to get it
; in 512 bytes with the code to move to protected mode), 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.
; 1.44Mb disks:
sectors = 18
; 1.2Mb disks:
; sectors = 15
; 720kB disks:
; sectors = 9
.globl begtext, begdata, begbss, endtext, enddata, endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text
BOOTSEG = 0x07c0
INITSEG = 0x9000
SYSSEG = 0x1000 ; system loaded at 0x10000 (65536).
ENDSEG = SYSSEG + SYSSIZE
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
mov ss,ax
mov sp,#0x400 ; arbitrary value >>512
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
; if the read went well we get current cursor position ans save it for
; posterity.
mov ah,#0x03 ; read cursor pos
xor bh,bh
int 0x10 ; save it in known place, con_init fetches
mov [510],dx ; it from 0x90510.
; 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
j do_move
; then we load the segment descriptors
end_move:
mov ax,cs ; 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
; 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)
;
; This routine has to be recompiled to fit another drive type,
; just change the "sectors" variable at the start of the file
; (originally 18, for a 1.44Mb drive)
;
sread: .word 1 ; 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:
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
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
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 gdt,0x9 ; gdt base = 0X9xxxx
msg1:
.byte 13,10
.ascii "Loading system ..."
.byte 13,10,13,10
.text
endtext:
.data
enddata:
.bss
endbss:
+176
Ver Arquivo
@@ -0,0 +1,176 @@
/*
* head.s contains the 32-bit startup code.
*
* NOTE!!! Startup happens at absolute address 0x00000000, which is also where
* the page directory will exist. The startup code will be overwritten by
* the page directory.
*/
.code32
.text
.globl idt,gdt,pg_dir,startup_32
pg_dir:
startup_32:
movl $0x10,%eax
mov %ax,%ds
mov %ax,%es
mov %ax,%fs
mov %ax,%gs
lss stack_start,%esp
call setup_idt
call setup_gdt
movl $0x10,%eax # reload all the segment registers
mov %ax,%ds # after changing gdt. CS was already
mov %ax,%es # reloaded in 'setup_gdt'
mov %ax,%fs
mov %ax,%gs
lss stack_start,%esp
xorl %eax,%eax
1: incl %eax # check that A20 really IS enabled
movl %eax,0x000000
cmpl %eax,0x100000
je 1b
movl %cr0,%eax # check math chip
andl $0x80000011,%eax # Save PG,ET,PE
testl $0x10,%eax
jne 1f # ET is set - 387 is present
orl $4,%eax # else set emulate bit
1: movl %eax,%cr0
jmp after_page_tables
/*
* setup_idt
*
* sets up a idt with 256 entries pointing to
* ignore_int, interrupt gates. It then loads
* idt. Everything that wants to install itself
* in the idt-table may do so themselves. Interrupts
* are enabled elsewhere, when we can be relatively
* sure everything is ok. This routine will be over-
* written by the page tables.
*/
setup_idt:
lea ignore_int,%edx
movl $0x00080000,%eax
movw %dx,%ax /* selector = 0x0008 = cs */
movw $0x8E00,%dx /* interrupt gate - dpl=0, present */
lea idt,%edi
mov $256,%ecx
rp_sidt:
movl %eax,(%edi)
movl %edx,4(%edi)
addl $8,%edi
dec %ecx
jne rp_sidt
lidt idt_descr
ret
/*
* setup_gdt
*
* This routines sets up a new gdt and loads it.
* Only two entries are currently built, the same
* ones that were built in init.s. The routine
* is VERY complicated at two whole lines, so this
* rather long comment is certainly needed :-).
* This routine will beoverwritten by the page tables.
*/
setup_gdt:
lgdt gdt_descr
ret
.org 0x1000
pg0:
.org 0x2000
pg1:
.org 0x3000
pg2: # This is not used yet, but if you
# want to expand past 8 Mb, you'll have
# to use it.
.org 0x4000
after_page_tables:
pushl $0 # These are the parameters to main :-)
pushl $0
pushl $0
pushl $L6 # return address for main, if it decides to.
pushl $main
jmp setup_paging
L6:
jmp L6 # main should never return here, but
# just in case, we know what happens.
/* This is the default interrupt "handler" :-) */
.align 2
ignore_int:
incb 0xb8000+160 # put something on the screen
movb $2,0xb8000+161 # so that we know something
iret # happened
/*
* Setup_paging
*
* This routine sets up paging by setting the page bit
* in cr0. The page tables are set up, identity-mapping
* the first 8MB. The pager assumes that no illegal
* addresses are produced (ie >4Mb on a 4Mb machine).
*
* NOTE! Although all physical memory should be identity
* mapped by this routine, only the kernel page functions
* use the >1Mb addresses directly. All "normal" functions
* use just the lower 1Mb, or the local data space, which
* will be mapped to some other place - mm keeps track of
* that.
*
* For those with more memory than 8 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 8Mb, 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 "8Mb"), but I
* won't guarantee that's all :-( )
*/
.align 2
setup_paging:
movl $1024*3,%ecx
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 $pg1+4092,%edi
movl $0x7ff007,%eax /* 8Mb - 4096 + 7 (r/w user,p) */
std
1: stosl /* fill pages backwards - more efficient :-) */
subl $0x1000,%eax
jge 1b
xorl %eax,%eax /* pg_dir is at 0x0000 */
movl %eax,%cr3 /* cr3 - page directory start */
movl %cr0,%eax
orl $0x80000000,%eax
movl %eax,%cr0 /* set paging (PG) bit */
ret /* this also flushes prefetch-queue */
.align 2
.word 0
idt_descr:
.word 256*8-1 # idt contains 256 entries
.long idt
.align 2
.word 0
gdt_descr:
.word 256*8-1 # so does gdt (not that that's any
.long gdt # magic number, but it works for me :^)
.align 8
idt: .fill 256,8,0 # idt is uninitialized
gdt: .quad 0x0000000000000000 /* NULL descriptor */
.quad 0x00c09a00000007ff /* 8Mb */
.quad 0x00c09200000007ff /* 8Mb */
.quad 0x0000000000000000 /* TEMPORARY - don't use */
.fill 252,8,0 /* space for LDT's and TSS's etc */
+95
Ver Arquivo
@@ -0,0 +1,95 @@
AR =ar
AS =as --32
CC =gcc
LD =ld -m elf_i386
CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer -m32 \
-fno-stack-protector -nostdinc -fno-builtin -g -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 tty_ioctl.o truncate.o sys_getdents.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/linux/kernel.h
block_dev.o : block_dev.c ../include/errno.h ../include/linux/fs.h \
../include/sys/types.h ../include/linux/kernel.h ../include/asm/segment.h
buffer.o : buffer.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/linux/kernel.h ../include/asm/system.h
char_dev.o : char_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/linux/kernel.h
exec.o : exec.c ../include/errno.h ../include/sys/stat.h \
../include/sys/types.h ../include/elf.h ../include/linux/fs.h \
../include/linux/sched.h ../include/linux/head.h ../include/linux/mm.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/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/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/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
../include/linux/mm.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
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/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/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/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/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/linux/kernel.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/sys/stat.h
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/linux/kernel.h \
../include/linux/tty.h ../include/asm/segment.h ../include/asm/system.h
+158
Ver Arquivo
@@ -0,0 +1,158 @@
/* bitmap.c contains the code that handles the inode and block bitmaps */
#include <string.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#define clear_block(addr) \
__asm__("cld\n\t" \
"rep\n\t" \
"stosl" \
::"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr))/*:"cx","di"*/)
#define set_bit(nr,addr) ({\
register int res;/* __asm__("ax");*/ \
__asm__("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__("btrl %2,%3\n\tsetnb %%al":"=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \
res;})
#define find_first_zero(addr) ({ \
int __res; \
__asm__("cld\n" \
"1:\tlodsl\n\t" \
"notl %%eax\n\t" \
"bsfl %%eax,%%edx\n\t" \
"je 2f\n\t" \
"addl %%edx,%%ecx\n\t" \
"jmp 3f\n" \
"2:\taddl $32,%%ecx\n\t" \
"cmpl $8192,%%ecx\n\t" \
"jl 1b\n" \
"3:" \
:"=c" (__res):"c" (0),"S" (addr):"ax","dx"/*,"si"*/); \
__res;})
void free_block(int dev, int block)
{
struct super_block * sb;
struct buffer_head * bh;
if (!(sb = get_super(dev)))
panic("trying to free block on nonexistent device");
if (block < sb->s_firstdatazone || block >= sb->s_nzones)
panic("trying to free block not in datazone");
bh = get_hash_table(dev,block);
if (bh) {
if (bh->b_count != 1) {
printk("trying to free block (%04x:%d), count=%d\n",
dev,block,bh->b_count);
return;
}
bh->b_dirt=0;
bh->b_uptodate=0;
brelse(bh);
}
block -= sb->s_firstdatazone - 1 ;
if (clear_bit(block&8191,sb->s_zmap[block/8192]->b_data)) {
printk("block (%04x:%d) ",dev,block+sb->s_firstdatazone-1);
panic("free_block: bit already cleared");
}
sb->s_zmap[block/8192]->b_dirt = 1;
}
int new_block(int dev)
{
struct buffer_head * bh;
struct super_block * sb;
int i,j;
if (!(sb = get_super(dev)))
panic("trying to get new block from nonexistant device");
j = 8192;
for (i=0 ; i<8 ; i++)
if ((bh=sb->s_zmap[i]))
if ((j=find_first_zero(bh->b_data))<8192)
break;
if (i>=8 || !bh || j>=8192)
return 0;
if (set_bit(j,bh->b_data))
panic("new_block: bit already set");
bh->b_dirt = 1;
j += i*8192 + sb->s_firstdatazone-1;
if (j >= sb->s_nzones)
return 0;
if (!(bh=getblk(dev,j)))
panic("new_block: cannot get block");
if (bh->b_count != 1)
panic("new block: count is != 1");
clear_block(bh->b_data);
bh->b_uptodate = 1;
bh->b_dirt = 1;
brelse(bh);
return j;
}
void free_inode(struct m_inode * inode)
{
struct super_block * sb;
struct buffer_head * bh;
if (!inode)
return;
if (!inode->i_dev) {
memset(inode,0,sizeof(*inode));
return;
}
if (inode->i_count>1) {
printk("trying to free inode with count=%d\n",inode->i_count);
panic("free_inode");
}
if (inode->i_nlinks)
panic("trying to free inode with links");
if (!(sb = get_super(inode->i_dev)))
panic("trying to free inode on nonexistent device");
if (inode->i_num < 1 || inode->i_num > sb->s_ninodes)
panic("trying to free inode 0 or nonexistant inode");
if (!(bh=sb->s_imap[inode->i_num>>13]))
panic("nonexistent imap in superblock");
if (clear_bit(inode->i_num&8191,bh->b_data))
panic("free_inode: bit already cleared");
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_dirt=1;
inode->i_num = j + i*8192;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
return inode;
}
+86
Ver Arquivo
@@ -0,0 +1,86 @@
#include <errno.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <asm/segment.h>
#define NR_BLK_DEV ((sizeof (rd_blk))/(sizeof (rd_blk[0])))
int block_write(int dev, long * pos, char * buf, int count)
{
int block = *pos / BLOCK_SIZE;
int offset = *pos % BLOCK_SIZE;
int chars;
int written = 0;
struct buffer_head * bh;
register char * p;
while (count>0) {
bh = bread(dev,block);
if (!bh)
return written?written:-EIO;
chars = (count<BLOCK_SIZE) ? count : BLOCK_SIZE;
p = offset + bh->b_data;
offset = 0;
block++;
*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;
int offset = *pos % BLOCK_SIZE;
int chars;
int read = 0;
struct buffer_head * bh;
register char * p;
while (count>0) {
bh = bread(dev,block);
if (!bh)
return read?read:-EIO;
chars = (count<BLOCK_SIZE) ? count : BLOCK_SIZE;
p = offset + bh->b_data;
offset = 0;
block++;
*pos += chars;
read += chars;
count -= chars;
while (chars-->0)
put_fs_byte(*(p++),buf++);
bh->b_dirt = 1;
brelse(bh);
}
return read;
}
extern void rw_hd(int rw, struct buffer_head * bh);
typedef void (*blk_fn)(int rw, struct buffer_head * bh);
static blk_fn rd_blk[]={
NULL, /* nodev */
NULL, /* dev mem */
NULL, /* dev fd */
rw_hd, /* dev hd */
NULL, /* dev ttyx */
NULL, /* dev tty */
NULL}; /* dev lp */
void ll_rw_block(int rw, struct buffer_head * bh)
{
blk_fn blk_addr=NULL;
unsigned int major;
if ((major=MAJOR(bh->b_dev)) >= NR_BLK_DEV || !(blk_addr=rd_blk[major]))
panic("Trying to read nonexistent block-device");
blk_addr(rw, bh);
}
+254
Ver Arquivo
@@ -0,0 +1,254 @@
/*
* 'buffer.c' implements the buffer-cache functions. Race-conditions have
* been avoided by NEVER letting a interrupt change a buffer (except for the
* data, of course), but instead letting the caller do it. NOTE! As interrupts
* can wake up a caller, some cli-sti sequences are needed to check for
* sleep-on-calls. These should be extremely quick, though (I hope).
*/
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/system.h>
#if (BUFFER_END & 0xfff)
#error "Bad BUFFER_END value"
#endif
#if (BUFFER_END > 0xA0000 && BUFFER_END <= 0x100000)
#error "Bad BUFFER_END value"
#endif
extern int end;
struct buffer_head * start_buffer = (struct buffer_head *) &end;
struct buffer_head * hash_table[NR_HASH];
static struct buffer_head * free_list;
static struct task_struct * buffer_wait = NULL;
int NR_BUFFERS = 0;
static inline void wait_on_buffer(struct buffer_head * bh)
{
cli();
while (bh->b_lock)
sleep_on(&bh->b_wait);
sti();
}
int sys_sync(void)
{
int i;
struct buffer_head * bh;
sync_inodes(); /* write out inodes into buffers */
bh = start_buffer;
for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
wait_on_buffer(bh);
if (bh->b_dirt)
ll_rw_block(WRITE,bh);
}
return 0;
}
static int sync_dev(int dev)
{
int i;
struct buffer_head * bh;
bh = start_buffer;
for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
if (bh->b_dev != dev)
continue;
wait_on_buffer(bh);
if (bh->b_dirt)
ll_rw_block(WRITE,bh);
}
return 0;
}
#define _hashfn(dev,block) (((unsigned)(dev^block))%NR_HASH)
#define hash(dev,block) hash_table[_hashfn(dev,block)]
static inline void remove_from_queues(struct buffer_head * bh)
{
/* remove from hash-queue */
if (bh->b_next)
bh->b_next->b_prev = bh->b_prev;
if (bh->b_prev)
bh->b_prev->b_next = bh->b_next;
if (hash(bh->b_dev,bh->b_blocknr) == bh)
hash(bh->b_dev,bh->b_blocknr) = bh->b_next;
/* remove from free list */
if (!(bh->b_prev_free) || !(bh->b_next_free))
panic("Free block list corrupted");
bh->b_prev_free->b_next_free = bh->b_next_free;
bh->b_next_free->b_prev_free = bh->b_prev_free;
if (free_list == bh)
free_list = bh->b_next_free;
}
static inline void insert_into_queues(struct buffer_head * bh)
{
/* put at end of free list */
bh->b_next_free = free_list;
bh->b_prev_free = free_list->b_prev_free;
free_list->b_prev_free->b_next_free = bh;
free_list->b_prev_free = bh;
/* put the buffer in new hash-queue if it has a device */
bh->b_prev = NULL;
bh->b_next = NULL;
if (!bh->b_dev)
return;
bh->b_next = hash(bh->b_dev,bh->b_blocknr);
hash(bh->b_dev,bh->b_blocknr) = bh;
bh->b_next->b_prev = bh;
}
static struct buffer_head * find_buffer(int dev, int block)
{
struct buffer_head * tmp;
for (tmp = hash(dev,block) ; tmp != NULL ; tmp = tmp->b_next)
if (tmp->b_dev==dev && tmp->b_blocknr==block)
return tmp;
return NULL;
}
/*
* Why like this, I hear you say... The reason is race-conditions.
* As we don't lock buffers (unless we are readint them, that is),
* something might happen to it while we sleep (ie a read-error
* will force it bad). This shouldn't really happen currently, but
* the code is ready.
*/
struct buffer_head * get_hash_table(int dev, int block)
{
struct buffer_head * bh;
repeat:
if (!(bh=find_buffer(dev,block)))
return NULL;
bh->b_count++;
wait_on_buffer(bh);
if (bh->b_dev != dev || bh->b_blocknr != block) {
brelse(bh);
goto repeat;
}
return bh;
}
/*
* 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.
*/
struct buffer_head * getblk(int dev,int block)
{
struct buffer_head * tmp;
repeat:
if ((tmp=get_hash_table(dev,block)))
return tmp;
tmp = free_list;
do {
if (!tmp->b_count) {
wait_on_buffer(tmp); /* we still have to wait */
if (!tmp->b_count) /* on it, it might be dirty */
break;
}
tmp = tmp->b_next_free;
} while (tmp != free_list || (tmp=NULL));
/* Kids, don't try THIS at home ^^^^^. Magic */
if (!tmp) {
printk("Sleeping on free buffer ..");
sleep_on(&buffer_wait);
printk("ok\n");
goto repeat;
}
tmp->b_count++;
remove_from_queues(tmp);
/*
* Now, when we know nobody can get to this node (as it's removed from the
* free list), we write it out. We can sleep here without fear of race-
* conditions.
*/
if (tmp->b_dirt)
sync_dev(tmp->b_dev);
/* update buffer contents */
tmp->b_dev=dev;
tmp->b_blocknr=block;
tmp->b_dirt=0;
tmp->b_uptodate=0;
/* NOTE!! While we possibly slept in sync_dev(), somebody else might have
* added "this" block already, so check for that. Thank God for goto's.
*/
if (find_buffer(dev,block)) {
tmp->b_dev=0; /* ok, someone else has beaten us */
tmp->b_blocknr=0; /* to it - free this block and */
tmp->b_count=0; /* try again */
insert_into_queues(tmp);
goto repeat;
}
/* and then insert into correct position */
insert_into_queues(tmp);
return tmp;
}
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);
if (bh->b_uptodate)
return bh;
brelse(bh);
return (NULL);
}
void buffer_init(void)
{
struct buffer_head * h = start_buffer;
void * b = (void *) BUFFER_END;
int i;
while ( (b -= BLOCK_SIZE) >= ((void *) (h+1)) ) {
h->b_dev = 0;
h->b_dirt = 0;
h->b_count = 0;
h->b_lock = 0;
h->b_uptodate = 0;
h->b_wait = NULL;
h->b_next = NULL;
h->b_prev = NULL;
h->b_data = (char *) b;
h->b_prev_free = h-1;
h->b_next_free = h+1;
h++;
NR_BUFFERS++;
if (b == (void *) 0x100000)
b = (void *) 0xA0000;
}
h--;
free_list = start_buffer;
free_list->b_prev_free = h;
h->b_next_free = free_list;
for (i=0;i<NR_HASH;i++)
hash_table[i]=NULL;
}
+50
Ver Arquivo
@@ -0,0 +1,50 @@
#include <errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
extern int tty_read(unsigned minor,char * buf,int count);
extern int tty_write(unsigned minor,char * buf,int count);
static int rw_ttyx(int rw,unsigned minor,char * buf,int count);
static int rw_tty(int rw,unsigned minor,char * buf,int count);
typedef int (*crw_ptr)(int rw,unsigned minor,char * buf,int count);
#define NRDEVS ((sizeof (crw_table))/(sizeof (crw_ptr)))
static crw_ptr crw_table[]={
NULL, /* nodev */
NULL, /* /dev/mem */
NULL, /* /dev/fd */
NULL, /* /dev/hd */
rw_ttyx, /* /dev/ttyx */
rw_tty, /* /dev/tty */
NULL, /* /dev/lp */
NULL}; /* unnamed pipes */
static int rw_ttyx(int rw,unsigned minor,char * buf,int count)
{
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)
{
if (current->tty<0)
return -EPERM;
return rw_ttyx(rw,current->tty,buf,count);
}
int rw_char(int rw,int dev, char * buf, int count)
{
crw_ptr call_addr;
if (MAJOR(dev)>=NRDEVS)
panic("rw_char: dev>NRDEV");
if (!(call_addr=crw_table[MAJOR(dev)])) {
printk("dev: %04x\n",dev);
panic("Trying to r/w from/to nonexistent character device");
}
return call_addr(rw,MINOR(dev),buf,count);
}
+466
Ver Arquivo
@@ -0,0 +1,466 @@
/*
* linux/fs/exec.c
*
* (C) 1991 Linus Torvalds
* (C) 2007 Abdel Benamrouche : use elf binary instead of a.out
*
*/
#include <errno.h>
#include <sys/stat.h>
#include <elf.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <asm/segment.h>
extern int sys_exit(int exit_code);
extern int sys_close(int fd);
/*
* MAX_ARG_PAGES defines the number of pages allocated for arguments
* and envelope for the new program. 32 should suffice, this gives
* a maximum env+arg of 128kB !
*/
#define MAX_ARG_PAGES 32
inline void cp_block(const void * from,void * to, int size)
{
int d0,d1,d2;
__asm__ __volatile("pushl $0x10\n\t"
"pushl $0x17\n\t"
"pop %%es\n\t"
"cld\n\t"
"rep\n\t"
"movsl\n\t"
"pop %%es"
:"=&c" (d0), "=&S" (d1), "=&D" (d2)
:"0" (size/4),"1" (from),"2" (to)
:"memory");
}
typedef struct
{
unsigned long b_entry;
unsigned long b_size; //file size
}bin_section;
#include <string.h>
/*
* 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.
*/
static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
unsigned long p)
{
int len,i;
char *tmp;
while (argc-- > 0) {
if (!(tmp = (char *)get_fs_long(((unsigned long *) argv)+argc)))
panic("argc is wrong");
len=0; /* remember zero-padding */
do {
len++;
} while (get_fs_byte(tmp++));
if (p-len < 0) /* this shouldn't happen - 128kB */
return 0;
i = ((unsigned) (p-len)) >> 12;
while (i<MAX_ARG_PAGES && !page[i]) {
if (!(page[i]=get_free_page()))
return 0;
i++;
}
do {
--p;
if (!page[p/PAGE_SIZE])
panic("nonexistent page in exec.c");
((char *) page[p/PAGE_SIZE])[p%PAGE_SIZE] =
get_fs_byte(--tmp);
} while (--len);
}
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;
}
/*
* return 1 if ex if a valid elf executable
* */
int is_valid_elf(Elf32_Ehdr* ex)
{
if (ex->e_ident[EI_MAG0]!=ELFMAG0 || ex->e_ident[EI_MAG1]!=ELFMAG1 ||
ex->e_ident[EI_MAG2]!=ELFMAG2 || ex->e_ident[EI_MAG3]!=ELFMAG3){
printk("not elf format\n");
return 0; /*not elf format */
}
if (ex->e_type != ET_EXEC || ex->e_machine != EM_386){
printk("bad elf binary\n");
return 0;
}
return 1;
}
/*
* bread(dev,ind) is an array of block index
* So we have to get from this array our wanted index ( variable block)
* */
struct buffer_head* read_file_block_ind(int dev,int ind,int block_num)
{
struct buffer_head * bh=NULL,*ih;
unsigned short block;
if (!(ih=bread(dev,ind)))
{
printk("bad block tab\n");
return NULL;
}
if ((block = *((unsigned short *) (ih->b_data) + block_num))){
if (!(bh=bread(dev,block))) {
brelse(ih);
printk("bad block file\n");
return NULL;
}
}
brelse(ih);
return bh;
}
/*
* if block_num=5, read file at position 5*1024.
* this work only for minix 1 fs
*/
struct buffer_head* read_file_block(struct m_inode * inode,int block_num)
{
struct buffer_head * dind;
int i;
unsigned short table;
/* 7 1st block can be read directly */
if (block_num<=6)
{
return bread(inode->i_dev,inode->i_zone[block_num]);
}
block_num-=7;
if (block_num<512)
{
/* read block at i_zone[7] is an array of block index */
return read_file_block_ind(inode->i_dev,inode->i_zone[7],block_num);
}
block_num-=512;
if (block_num>512*512)
{
panic("Impossibly long executable");
return NULL; //just to avoid warning compilation
}
/* i_zone[8] => array of array block index */
if (!(i=inode->i_zone[8]))
return NULL;
if (!(dind = bread(inode->i_dev,i)))
return NULL;
table = *((unsigned short *) dind->b_data+(block_num/512));
brelse(dind);
if (block_num>=512)
block_num-=(block_num-1)*512;
return read_file_block_ind(inode->i_dev,table,block_num);
}
/*
* read an area into %fs:mem.
*/
int copy_section(struct m_inode * inode,Elf32_Off from, Elf32_Addr dest,Elf32_Word size)
{
struct buffer_head * bh;
int block_num=from/BLOCK_SIZE;
int block_offset; //only for 1st block
int cp_size;
//read fist block
block_offset=from%BLOCK_SIZE;
bh=read_file_block(inode,block_num);
if (!bh) return -1;
cp_size=(size<BLOCK_SIZE-block_offset)?size:BLOCK_SIZE-block_offset;
//note we add 3 to size to get it aligned to word boundary
cp_block(bh->b_data+block_offset,(void*)dest,cp_size+3);
brelse(bh);
dest+=cp_size;
size-=cp_size;
block_num++;
//read others blocks
while(size)
{
bh=read_file_block(inode,block_num);
if (!bh) return -1;
cp_size=(size<BLOCK_SIZE)?size:BLOCK_SIZE;
cp_block(bh->b_data,(void*)dest,cp_size+3);
block_num++;
size-=cp_size;
dest+=cp_size;
brelse(bh);
};
return 0;
}
inline int create_bss_section(Elf32_Addr dest,Elf32_Word size)
{
while (size--)
put_fs_byte(0,(char *)dest++);
return 0;
}
/*
* in linux 0.01 only a.out binary format was supported
* Today it's hard to compile some programs (like bach) in a.out format
* So this version of linux 0.01 support elf binary.
* nb : there is no support of shared library !
*/
int load_elf_binary(struct m_inode *inode, struct buffer_head* bh,
bin_section* bs)
{
Elf32_Ehdr ex;
Elf32_Shdr sect;
long nsect;
int lb=0;
struct buffer_head* bht=NULL;
ex = *((Elf32_Ehdr *) bh->b_data); /* read exec-header */
/* check header */
if (!is_valid_elf(&ex)) {
return -1;
}
bs->b_entry=ex.e_entry;
nsect=ex.e_shnum;
bs->b_size=ex.e_ehsize+nsect*ex.e_shentsize;
if (nsect<=1){
printk("bad nb of sections %d\n",nsect);
return -1;
}
while(nsect--){
/* load block where is our table section*/
if ((ex.e_shoff + nsect * ex.e_shentsize)/BLOCK_SIZE != lb)
{
printk(""); // gcc bug : removing this line = gcc not happy !!!
lb = (ex.e_shoff + nsect * ex.e_shentsize)/BLOCK_SIZE;
if (bht) brelse(bht);
bht=read_file_block(inode,lb);
if (!bht) return -1;
}
/* copy this section fo %fs:mem */
sect=*((Elf32_Shdr *)(bht->b_data + (ex.e_shoff +
nsect * ex.e_shentsize)%BLOCK_SIZE ));
if (!sect.sh_size || !sect.sh_addr) continue;
switch(sect.sh_type)
{
case SHT_PROGBITS:
if (copy_section(inode,sect.sh_offset,sect.sh_addr,
sect.sh_size))
{
if (bht) brelse(bht);
return -1;
}
break;
case SHT_NOBITS:
create_bss_section(sect.sh_addr,sect.sh_size);
break;
default:
continue;
}
/* find binary size */
if (bs->b_size<sect.sh_addr + sect.sh_size)
bs->b_size=sect.sh_addr + sect.sh_size;
};
if (bht) brelse(bht);
return 0;
}
/*
* '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;
unsigned long page[MAX_ARG_PAGES];
int i,argc,envc;
unsigned long p;
bin_section bs;
if ((0xffff & eip[1]) != 0x000f)
panic("execve called from supervisor mode");
for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
page[i]=0;
if (!(inode=namei(filename))) /* get executables inode */
return -ENOENT;
if (!S_ISREG(inode->i_mode)) { /* must be regular file */
iput(inode);
return -EACCES;
}
i = inode->i_mode;
if (current->uid && current->euid) {
if (current->euid == inode->i_uid)
i >>= 6;
else if (current->egid == inode->i_gid)
i >>= 3;
} else if (i & 0111)
i=1;
if (!(i & 1)) {
iput(inode);
return -ENOEXEC;
}
if (!(bh = bread(inode->i_dev,inode->i_zone[0]))) {
iput(inode);
return -EACCES;
}
argc = count(argv);
envc = count(envp);
p = copy_strings(envc,envp,page,PAGE_SIZE*MAX_ARG_PAGES);
p = copy_strings(argc,argv,page,p);
if (!p) {
for (i=0 ; i<MAX_ARG_PAGES ; i++)
free_page(page[i]);
iput(inode);
return -1;
}
/* OK, This is the point of no return */
for (i=0 ; i<32 ; i++)
current->sig_fn[i] = NULL;
for (i=0 ; i<NR_OPEN ; i++)
if ((current->close_on_exec>>i)&1)
sys_close(i);
current->close_on_exec = 0;
free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
if (load_elf_binary(inode,bh,&bs)){
brelse(bh);
iput(inode);
return -EACCES;
}
brelse(bh);
if (last_task_used_math == current)
last_task_used_math = NULL;
current->used_math = 0;
p += change_ldt(bs.b_size,page)-MAX_ARG_PAGES*PAGE_SIZE;
p = (unsigned long) create_tables((char *)p,argc,envc);
current->brk = bs.b_size;
current->end_data = bs.b_size;
current->end_code = bs.b_size;
current->start_stack = p & 0xfffff000;
iput(inode);
i = bs.b_size;
while (i&0xfff)
put_fs_byte(0,(char *) (i++));
eip[0] = bs.b_entry; /* eip, magic happens :-) */
eip[3] = p; /* stack pointer */
return 0;
}
+91
Ver Arquivo
@@ -0,0 +1,91 @@
#include <string.h>
#include <errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/segment.h>
#include <fcntl.h>
#include <sys/stat.h>
extern int sys_close(int fd);
static int dupfd(unsigned int fd, unsigned int arg)
{
if (fd >= NR_OPEN || !current->filp[fd])
return -EBADF;
if (arg >= NR_OPEN)
return -EINVAL;
while (arg < NR_OPEN)
if (current->filp[arg])
arg++;
else
break;
if (arg >= NR_OPEN)
return -EMFILE;
current->close_on_exec &= ~(1<<arg);
(current->filp[arg] = current->filp[fd])->f_count++;
return arg;
}
int sys_dup2(unsigned int oldfd, unsigned int newfd)
{
sys_close(newfd);
return dupfd(oldfd,newfd);
}
int sys_dup(unsigned int fildes)
{
return dupfd(fildes,0);
}
int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
{
struct file * filp;
if (fd >= NR_OPEN || !(filp = current->filp[fd]))
return -EBADF;
switch (cmd) {
case F_DUPFD:
return dupfd(fd,arg);
case F_GETFD:
return (current->close_on_exec>>fd)&1;
case F_SETFD:
if (arg&1)
current->close_on_exec |= (1<<fd);
else
current->close_on_exec &= ~(1<<fd);
return 0;
case F_GETFL:
return filp->f_flags;
case F_SETFL:
filp->f_flags &= ~(O_APPEND | O_NONBLOCK);
filp->f_flags |= arg & (O_APPEND | O_NONBLOCK);
return 0;
case F_GETLK: case F_SETLK: case F_SETLKW:
return -1;
default:
return -1;
}
}
int sys_fcntl64(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_GETLK64:
case F_SETLK64:
case F_SETLKW64:
return -ENOSYS;
default:
return sys_fcntl(fd,cmd,arg);
}
}
+84
Ver Arquivo
@@ -0,0 +1,84 @@
#include <errno.h>
#include <fcntl.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/segment.h>
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
int file_read(struct m_inode * inode, struct file * filp, char * buf, int count)
{
int left,chars,nr;
struct buffer_head * bh;
if ((left=count)<=0)
return 0;
while (left) {
if ((nr = bmap(inode,(filp->f_pos)/BLOCK_SIZE))) {
if (!(bh=bread(inode->i_dev,nr)))
break;
} else
bh = NULL;
nr = filp->f_pos % BLOCK_SIZE;
chars = MIN( BLOCK_SIZE-nr , left );
filp->f_pos += chars;
left -= chars;
if (bh) {
char * p = nr + bh->b_data;
while (chars-->0)
put_fs_byte(*(p++),buf++);
brelse(bh);
} else {
while (chars-->0)
put_fs_byte(0,buf++);
}
}
inode->i_atime = CURRENT_TIME;
return (count-left)?(count-left):-ERROR;
}
int file_write(struct m_inode * inode, struct file * filp, char * buf, int count)
{
off_t pos;
int block,c;
struct buffer_head * bh;
char * p;
int i=0;
/*
* ok, append may not work when many processes are writing at the same time
* but so what. That way leads to madness anyway.
*/
if (filp->f_flags & O_APPEND)
pos = inode->i_size;
else
pos = filp->f_pos;
while (i<count) {
if (!(block = create_block(inode,pos/BLOCK_SIZE)))
break;
if (!(bh=bread(inode->i_dev,block)))
break;
c = pos % BLOCK_SIZE;
p = c + bh->b_data;
bh->b_dirt = 1;
c = BLOCK_SIZE-c;
if (c > count-i) c = count-i;
pos += c;
if (pos > inode->i_size) {
inode->i_size = pos;
inode->i_dirt = 1;
}
i += c;
while (c-->0)
*(p++) = get_fs_byte(buf++);
brelse(bh);
}
inode->i_mtime = CURRENT_TIME;
if (!(filp->f_flags & O_APPEND)) {
filp->f_pos = pos;
inode->i_ctime = CURRENT_TIME;
}
return (i?i:-1);
}
+3
Ver Arquivo
@@ -0,0 +1,3 @@
#include <linux/fs.h>
struct file file_table[NR_FILE];
+288
Ver Arquivo
@@ -0,0 +1,288 @@
#include <string.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <asm/system.h>
struct m_inode inode_table[NR_INODE]={{0,},};
static void read_inode(struct m_inode * inode);
static void write_inode(struct m_inode * inode);
static inline void wait_on_inode(struct m_inode * inode)
{
cli();
while (inode->i_lock)
sleep_on(&inode->i_wait);
sti();
}
static inline void lock_inode(struct m_inode * inode)
{
cli();
while (inode->i_lock)
sleep_on(&inode->i_wait);
inode->i_lock=1;
sti();
}
static inline void unlock_inode(struct m_inode * inode)
{
inode->i_lock=0;
wake_up(&inode->i_wait);
}
void sync_inodes(void)
{
int i;
struct m_inode * inode;
inode = 0+inode_table;
for(i=0 ; i<NR_INODE ; i++,inode++) {
wait_on_inode(inode);
if (inode->i_dirt && !inode->i_pipe)
write_inode(inode);
}
}
static int _bmap(struct m_inode * inode,int block,int create)
{
struct buffer_head * bh;
int i;
if (block<0)
panic("_bmap: block<0");
if (block >= 7+512+512*512)
panic("_bmap: block>big");
if (block<7) {
if (create && !inode->i_zone[block])
if ((inode->i_zone[block]=new_block(inode->i_dev))) {
inode->i_ctime=CURRENT_TIME;
inode->i_dirt=1;
}
return inode->i_zone[block];
}
block -= 7;
if (block<512) {
if (create && !inode->i_zone[7])
if ((inode->i_zone[7]=new_block(inode->i_dev))) {
inode->i_dirt=1;
inode->i_ctime=CURRENT_TIME;
}
if (!inode->i_zone[7])
return 0;
if (!(bh = bread(inode->i_dev,inode->i_zone[7])))
return 0;
i = ((unsigned short *) (bh->b_data))[block];
if (create && !i)
if ((i=new_block(inode->i_dev))) {
((unsigned short *) (bh->b_data))[block]=i;
bh->b_dirt=1;
}
brelse(bh);
return i;
}
block -= 512;
if (create && !inode->i_zone[8])
if ((inode->i_zone[8]=new_block(inode->i_dev))) {
inode->i_dirt=1;
inode->i_ctime=CURRENT_TIME;
}
if (!inode->i_zone[8])
return 0;
if (!(bh=bread(inode->i_dev,inode->i_zone[8])))
return 0;
i = ((unsigned short *)bh->b_data)[block>>9];
if (create && !i)
if ((i=new_block(inode->i_dev))) {
((unsigned short *) (bh->b_data))[block>>9]=i;
bh->b_dirt=1;
}
brelse(bh);
if (!i)
return 0;
if (!(bh=bread(inode->i_dev,i)))
return 0;
i = ((unsigned short *)bh->b_data)[block&511];
if (create && !i)
if ((i=new_block(inode->i_dev))) {
((unsigned short *) (bh->b_data))[block&511]=i;
bh->b_dirt=1;
}
brelse(bh);
return i;
}
int bmap(struct m_inode * inode,int block)
{
return _bmap(inode,block,0);
}
int create_block(struct m_inode * inode, int block)
{
return _bmap(inode,block,1);
}
void iput(struct m_inode * inode)
{
if (!inode)
return;
wait_on_inode(inode);
if (!inode->i_count)
panic("iput: trying to free free inode");
if (inode->i_pipe) {
wake_up(&inode->i_wait);
if (--inode->i_count)
return;
free_page(inode->i_size);
inode->i_count=0;
inode->i_dirt=0;
inode->i_pipe=0;
return;
}
if (!inode->i_dev || inode->i_count>1) {
inode->i_count--;
return;
}
repeat:
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;
}
static volatile int last_allocated_inode = 0;
struct m_inode * get_empty_inode(void)
{
struct m_inode * inode;
int inr;
while (1) {
inode = NULL;
inr = last_allocated_inode;
do {
if (!inode_table[inr].i_count) {
inode = inr + inode_table;
break;
}
inr++;
if (inr>=NR_INODE)
inr=0;
} while (inr != last_allocated_inode);
if (!inode) {
for (inr=0 ; inr<NR_INODE ; inr++)
printk("%04x: %6d\t",inode_table[inr].i_dev,
inode_table[inr].i_num);
panic("No free inodes in mem");
}
last_allocated_inode = inr;
wait_on_inode(inode);
while (inode->i_dirt) {
write_inode(inode);
wait_on_inode(inode);
}
if (!inode->i_count)
break;
}
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 (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);
sb=get_super(inode->i_dev);
block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks +
(inode->i_num-1)/INODES_PER_BLOCK;
if (!(bh=bread(inode->i_dev,block)))
panic("unable to read i-node block");
*(struct d_inode *)inode =
((struct d_inode *)bh->b_data)
[(inode->i_num-1)%INODES_PER_BLOCK];
brelse(bh);
unlock_inode(inode);
}
static void write_inode(struct m_inode * inode)
{
struct super_block * sb;
struct buffer_head * bh;
int block;
lock_inode(inode);
sb=get_super(inode->i_dev);
block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks +
(inode->i_num-1)/INODES_PER_BLOCK;
if (!(bh=bread(inode->i_dev,block)))
panic("unable to read i-node block");
((struct d_inode *)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);
}
+40
Ver Arquivo
@@ -0,0 +1,40 @@
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <linux/sched.h>
extern int tty_ioctl(int dev, int cmd, int arg);
typedef int (*ioctl_ptr)(int dev,int cmd,int arg);
#define NRDEVS ((sizeof (ioctl_table))/(sizeof (ioctl_ptr)))
static ioctl_ptr ioctl_table[]={
NULL, /* nodev */
NULL, /* /dev/mem */
NULL, /* /dev/fd */
NULL, /* /dev/hd */
tty_ioctl, /* /dev/ttyx */
tty_ioctl, /* /dev/tty */
NULL, /* /dev/lp */
NULL}; /* named pipes */
int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
{
struct file * filp;
int dev,mode;
if (fd >= NR_OPEN || !(filp = current->filp[fd]))
return -EBADF;
mode=filp->f_inode->i_mode;
if (!S_ISCHR(mode) && !S_ISBLK(mode))
return -EINVAL;
dev = filp->f_inode->i_zone[0];
if (MAJOR(dev) >= NRDEVS)
panic("unknown device for ioctl");
if (!ioctl_table[MAJOR(dev)])
return -ENOTTY;
return ioctl_table[MAJOR(dev)](dev,cmd,arg);
}
+678
Ver Arquivo
@@ -0,0 +1,678 @@
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/segment.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <const.h>
#include <sys/stat.h>
#define ACC_MODE(x) ("\004\002\006\377"[(x)&O_ACCMODE])
/*
* comment out this line if you want names > NAME_LEN chars to be
* truncated. Else they will be disallowed.
*/
/* #define NO_TRUNCATE */
#define MAY_EXEC 1
#define MAY_WRITE 2
#define MAY_READ 4
/*
* permission()
*
* is used to check for read/write/execute permissions on a file.
* I don't know if we should look at just the euid or both euid and
* uid, but that should be easily changed.
*/
static int permission(struct m_inode * inode,int mask)
{
int mode = inode->i_mode;
/* special case: not even root can read/write a deleted file */
if (inode->i_dev && !inode->i_nlinks)
return 0;
if (!(current->uid && current->euid))
mode=0777;
else if (current->uid==inode->i_uid || current->euid==inode->i_uid)
mode >>= 6;
else if (current->gid==inode->i_gid || current->egid==inode->i_gid)
mode >>= 3;
return mode & mask & 0007;
}
/*
* ok, we cannot use strncmp, as the name is not in our data space.
* Thus we'll have to use match. No big problem. Match also makes
* some sanity tests.
*
* NOTE! unlike strncmp, match returns 1 for success, 0 for failure.
*/
static int match(int len,const char * name,struct dir_entry * de)
{
register int same __asm__("ax");
if (!de || !de->inode || len > NAME_LEN)
return 0;
if (len < NAME_LEN && de->name[len])
return 0;
__asm__("cld\n\t"
"fs ; repe ; cmpsb\n\t"
"setz %%al"
:"=a" (same)
:"0" (0),"S" ((long) name),"D" ((long) de->name),"c" (len)
/*:"cx","di","si"*/);
return same;
}
/*
* find_entry()
*
* finds and 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.
*/
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;
#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;
if (!(block = dir->i_zone[0]))
return NULL;
if (!(bh = bread(dir->i_dev,block)))
return NULL;
i = 0;
de = (struct dir_entry *) bh->b_data;
while (i < entries) {
if ((char *)de >= BLOCK_SIZE+bh->b_data) {
brelse(bh);
bh = NULL;
if (!(block = bmap(dir,i/DIR_ENTRIES_PER_BLOCK)) ||
!(bh = bread(dir->i_dev,block))) {
i += DIR_ENTRIES_PER_BLOCK;
continue;
}
de = (struct dir_entry *) bh->b_data;
}
if (match(namelen,name,de)) {
*res_dir = de;
return bh;
}
de++;
i++;
}
brelse(bh);
return NULL;
}
/*
* add_entry()
*
* adds a file entry to the specified directory, using the same
* semantics as find_entry(). It returns NULL if it failed.
*
* NOTE!! The inode part of 'de' is left at 0 - which means you
* may not sleep between calling this and putting something into
* the entry, as someone else might have used it while you slept.
*/
static struct buffer_head * add_entry(struct m_inode * dir,
const char * name, int namelen, struct dir_entry ** res_dir)
{
int block,i;
struct buffer_head * bh;
struct dir_entry * de;
*res_dir = NULL;
#ifdef NO_TRUNCATE
if (namelen > NAME_LEN)
return NULL;
#else
if (namelen > NAME_LEN)
namelen = NAME_LEN;
#endif
if (!namelen)
return NULL;
if (!(block = dir->i_zone[0]))
return NULL;
if (!(bh = bread(dir->i_dev,block)))
return NULL;
i = 0;
de = (struct dir_entry *) bh->b_data;
while (1) {
if ((char *)de >= BLOCK_SIZE+bh->b_data) {
brelse(bh);
bh = NULL;
block = create_block(dir,i/DIR_ENTRIES_PER_BLOCK);
if (!block)
return NULL;
if (!(bh = bread(dir->i_dev,block))) {
i += DIR_ENTRIES_PER_BLOCK;
continue;
}
de = (struct dir_entry *) bh->b_data;
}
if (i*sizeof(struct dir_entry) >= dir->i_size) {
de->inode=0;
dir->i_size = (i+1)*sizeof(struct dir_entry);
dir->i_dirt = 1;
dir->i_ctime = CURRENT_TIME;
}
if (!de->inode) {
dir->i_mtime = CURRENT_TIME;
for (i=0; i < NAME_LEN ; i++)
de->name[i]=(i<namelen)?get_fs_byte(name+i):0;
bh->b_dirt = 1;
*res_dir = de;
return bh;
}
de++;
i++;
}
brelse(bh);
return NULL;
}
/*
* get_dir()
*
* Getdir traverses the pathname until it hits the topmost directory.
* It returns NULL on failure.
*/
static struct m_inode * get_dir(const char * pathname)
{
char c;
const char * thisname;
struct m_inode * inode;
struct buffer_head * bh;
int namelen,inr,idev;
struct dir_entry * de;
if (!current->root || !current->root->i_count)
panic("No root inode");
if (!current->pwd || !current->pwd->i_count)
panic("No cwd inode");
if ((c=get_fs_byte(pathname))=='/') {
inode = current->root;
pathname++;
} else if (c)
inode = current->pwd;
else
return NULL; /* empty name is bad */
inode->i_count++;
while (1) {
thisname = pathname;
if (!S_ISDIR(inode->i_mode) || !permission(inode,MAY_EXEC)) {
iput(inode);
return NULL;
}
for(namelen=0;(c=get_fs_byte(pathname++))&&(c!='/');namelen++)
/* nothing */ ;
if (!c)
return inode;
if (!(bh = find_entry(inode,thisname,namelen,&de))) {
iput(inode);
return NULL;
}
inr = de->inode;
idev = inode->i_dev;
brelse(bh);
iput(inode);
if (!(inode = iget(idev,inr)))
return NULL;
}
}
/*
* dir_namei()
*
* dir_namei() returns the inode of the directory of the
* specified name, and the name within that directory.
*/
static struct m_inode * dir_namei(const char * pathname,
int * namelen, const char ** name)
{
char c;
const char * basename;
struct m_inode * dir;
if (!(dir = get_dir(pathname)))
return NULL;
basename = pathname;
while ((c=get_fs_byte(pathname++)))
if (c=='/')
basename=pathname;
*namelen = pathname-basename-1;
*name = basename;
return dir;
}
/*
* namei()
*
* is used by most simple commands to get the inode of a specified name.
* Open, link etc use their own routines, but this is enough for things
* like 'chmod' etc.
*/
struct m_inode * namei(const char * pathname)
{
const char * basename;
int inr,dev,namelen;
struct m_inode * dir;
struct buffer_head * bh;
struct dir_entry * de;
if (!(dir = dir_namei(pathname,&namelen,&basename)))
return NULL;
if (!namelen) /* special case: '/usr/' etc */
return dir;
bh = find_entry(dir,basename,namelen,&de);
if (!bh) {
iput(dir);
return NULL;
}
inr = de->inode;
dev = dir->i_dev;
brelse(bh);
iput(dir);
dir=iget(dev,inr);
if (dir) {
dir->i_atime=CURRENT_TIME;
dir->i_dirt=1;
}
return dir;
}
/*
* open_namei()
*
* namei for open - this is in fact almost the whole open-routine.
*/
int open_namei(const char * pathname, int flag, int mode,
struct m_inode ** res_inode)
{
const char * basename;
int inr,dev,namelen;
struct m_inode * dir, *inode;
struct buffer_head * bh;
struct dir_entry * de;
if ((flag & O_TRUNC) && !(flag & O_ACCMODE))
flag |= O_WRONLY;
mode &= 0777 & ~current->umask;
mode |= I_REGULAR;
if (!(dir = dir_namei(pathname,&namelen,&basename)))
return -ENOENT;
if (!namelen) { /* special case: '/usr/' etc */
if (!(flag & (O_ACCMODE|O_CREAT|O_TRUNC))) {
*res_inode=dir;
return 0;
}
iput(dir);
return -EISDIR;
}
bh = find_entry(dir,basename,namelen,&de);
if (!bh) {
if (!(flag & O_CREAT)) {
iput(dir);
return -ENOENT;
}
if (!permission(dir,MAY_WRITE)) {
iput(dir);
return -EACCES;
}
inode = new_inode(dir->i_dev);
if (!inode) {
iput(dir);
return -ENOSPC;
}
inode->i_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))!=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_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 (current->euid && current->uid)
return -EPERM;
if (!(dir = dir_namei(pathname,&namelen,&basename)))
return -ENOENT;
if (!namelen) {
iput(dir);
return -ENOENT;
}
if (!permission(dir,MAY_WRITE)) {
iput(dir);
return -EPERM;
}
bh = find_entry(dir,basename,namelen,&de);
if (bh) {
brelse(bh);
iput(dir);
return -EEXIST;
}
inode = new_inode(dir->i_dev);
if (!inode) {
iput(dir);
return -ENOSPC;
}
inode->i_size = 32;
inode->i_dirt = 1;
inode->i_mtime = inode->i_atime = CURRENT_TIME;
if (!(inode->i_zone[0]=new_block(inode->i_dev))) {
iput(dir);
inode->i_nlinks--;
iput(inode);
return -ENOSPC;
}
inode->i_dirt = 1;
if (!(dir_block=bread(inode->i_dev,inode->i_zone[0]))) {
iput(dir);
free_block(inode->i_dev,inode->i_zone[0]);
inode->i_nlinks--;
iput(inode);
return -ERROR;
}
de = (struct dir_entry *) dir_block->b_data;
de->inode=inode->i_num;
strcpy(de->name,".");
de++;
de->inode = dir->i_num;
strcpy(de->name,"..");
inode->i_nlinks = 2;
dir_block->b_dirt = 1;
brelse(dir_block);
inode->i_mode = I_DIRECTORY | (mode & 0777 & ~current->umask);
inode->i_dirt = 1;
bh = add_entry(dir,basename,namelen,&de);
if (!bh) {
iput(dir);
free_block(inode->i_dev,inode->i_zone[0]);
inode->i_nlinks=0;
iput(inode);
return -ENOSPC;
}
de->inode = inode->i_num;
bh->b_dirt = 1;
dir->i_nlinks++;
dir->i_dirt = 1;
iput(dir);
iput(inode);
brelse(bh);
return 0;
}
/*
* routine to check that the specified directory is empty (for rmdir)
*/
static int empty_dir(struct m_inode * inode)
{
int nr,block;
int len;
struct buffer_head * bh;
struct dir_entry * de;
len = inode->i_size / sizeof (struct dir_entry);
if (len<2 || !inode->i_zone[0] ||
!(bh=bread(inode->i_dev,inode->i_zone[0]))) {
printk("warning - bad directory on dev %04x\n",inode->i_dev);
return 0;
}
de = (struct dir_entry *) bh->b_data;
if (de[0].inode != inode->i_num || !de[1].inode ||
strcmp(".",de[0].name) || strcmp("..",de[1].name)) {
printk("warning - bad directory on dev %04x\n",inode->i_dev);
return 0;
}
nr = 2;
de += 2;
while (nr<len) {
if ((void *) de >= (void *) (bh->b_data+BLOCK_SIZE)) {
brelse(bh);
block=bmap(inode,nr/DIR_ENTRIES_PER_BLOCK);
if (!block) {
nr += DIR_ENTRIES_PER_BLOCK;
continue;
}
if (!(bh=bread(inode->i_dev,block)))
return 0;
de = (struct dir_entry *) bh->b_data;
}
if (de->inode) {
brelse(bh);
return 0;
}
de++;
nr++;
}
brelse(bh);
return 1;
}
int sys_rmdir(const char * name)
{
const char * basename;
int namelen;
struct m_inode * dir, * inode;
struct buffer_head * bh;
struct dir_entry * de;
if (current->euid && current->uid)
return -EPERM;
if (!(dir = dir_namei(name,&namelen,&basename)))
return -ENOENT;
if (!namelen) {
iput(dir);
return -ENOENT;
}
bh = find_entry(dir,basename,namelen,&de);
if (!bh) {
iput(dir);
return -ENOENT;
}
if (!permission(dir,MAY_WRITE)) {
iput(dir);
brelse(bh);
return -EPERM;
}
if (!(inode = iget(dir->i_dev, de->inode))) {
iput(dir);
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;
}
inode = iget(dir->i_dev, de->inode);
if (!inode) {
printk("iget failed in delete (%04x:%d)",dir->i_dev,de->inode);
iput(dir);
brelse(bh);
return -ENOENT;
}
if (!S_ISREG(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_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_ISREG(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;
}
+191
Ver Arquivo
@@ -0,0 +1,191 @@
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <utime.h>
#include <sys/stat.h>
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/kernel.h>
#include <asm/segment.h>
int sys_utime(char * filename, struct utimbuf * times)
{
struct m_inode * inode;
long actime,modtime;
if (!(inode=namei(filename)))
return -ENOENT;
if (times) {
actime = get_fs_long((unsigned long *) &times->actime);
modtime = get_fs_long((unsigned long *) &times->modtime);
} else
actime = modtime = CURRENT_TIME;
inode->i_atime = actime;
inode->i_mtime = modtime;
inode->i_dirt = 1;
iput(inode);
return 0;
}
int sys_access(const char * filename,int mode)
{
struct m_inode * inode;
int res;
mode &= 0007;
if (!(inode=namei(filename)))
return -EACCES;
res = inode->i_mode & 0777;
iput(inode);
if (!(current->euid && current->uid)) {
if (res & 0111)
res = 0777;
else
res = 0666;
}
if (current->euid == inode->i_uid)
res >>= 6;
else if (current->egid == inode->i_gid)
res >>= 6;
if ((res & 0007 & mode) == mode)
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->uid && current->euid) {
if (current->uid!=inode->i_uid && current->euid!=inode->i_uid) {
iput(inode);
return -EACCES;
} else
mode = (mode & 0777) | (inode->i_mode & 07000);
}
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 (current->uid && current->euid) {
iput(inode);
return -EACCES;
}
inode->i_uid=uid;
inode->i_gid=gid;
inode->i_dirt=1;
iput(inode);
return 0;
}
int sys_open(const char * filename,int flag,int mode)
{
struct m_inode * inode;
struct file * f;
int i,fd;
mode &= 0777 & ~current->umask;
for(fd=0 ; fd<NR_OPEN ; fd++)
if (!current->filp[fd])
break;
if (fd>=NR_OPEN)
return -EINVAL;
current->close_on_exec &= ~(1<<fd);
f=0+file_table;
for (i=0 ; i<NR_FILE ; i++,f++)
if (!f->f_count) break;
if (i>=NR_FILE)
return -EINVAL;
(current->filp[fd]=f)->f_count++;
if ((i=open_namei(filename,flag,mode,&inode))<0) {
current->filp[fd]=NULL;
f->f_count=0;
return i;
}
/* ttys are somewhat special (ttyxx major==4, tty major==5) */
if (S_ISCHR(inode->i_mode)) {
if (MAJOR(inode->i_zone[0])==4) {
if (current->leader && current->tty<0) {
current->tty = MINOR(inode->i_zone[0]);
tty_table[current->tty].pgrp = current->pgrp;
}
} else if (MAJOR(inode->i_zone[0])==5)
if (current->tty<0) {
iput(inode);
current->filp[fd]=NULL;
f->f_count=0;
return -EPERM;
}
}
f->f_mode = inode->i_mode;
f->f_flags = flag;
f->f_count = 1;
f->f_inode = inode;
f->f_pos = 0;
return (fd);
}
int sys_creat(const char * pathname, int mode)
{
return sys_open(pathname, O_CREAT | O_TRUNC, mode);
}
int sys_close(unsigned int fd)
{
struct file * filp;
if (fd >= NR_OPEN)
return -EINVAL;
current->close_on_exec &= ~(1<<fd);
if (!(filp = current->filp[fd]))
return -EINVAL;
current->filp[fd] = NULL;
if (filp->f_count == 0)
panic("Close: file count is 0");
if (--filp->f_count)
return (0);
iput(filp->f_inode);
return (0);
}
+92
Ver Arquivo
@@ -0,0 +1,92 @@
#include <signal.h>
#include <linux/sched.h>
#include <linux/mm.h> /* for get_free_page */
#include <asm/segment.h>
int read_pipe(struct m_inode * inode, char * buf, int count)
{
char * b=buf;
while (PIPE_EMPTY(*inode)) {
wake_up(&inode->i_wait);
if (inode->i_count != 2) /* are there any writers left? */
return 0;
sleep_on(&inode->i_wait);
}
while (count>0 && !(PIPE_EMPTY(*inode))) {
count --;
put_fs_byte(((char *)inode->i_size)[PIPE_TAIL(*inode)],b++);
INC_PIPE( PIPE_TAIL(*inode) );
}
wake_up(&inode->i_wait);
return b-buf;
}
int write_pipe(struct m_inode * inode, char * buf, int count)
{
char * b=buf;
wake_up(&inode->i_wait);
if (inode->i_count != 2) { /* no readers */
current->signal |= (1<<(SIGPIPE-1));
return -1;
}
while (count-->0) {
while (PIPE_FULL(*inode)) {
wake_up(&inode->i_wait);
if (inode->i_count != 2) {
current->signal |= (1<<(SIGPIPE-1));
return b-buf;
}
sleep_on(&inode->i_wait);
}
((char *)inode->i_size)[PIPE_HEAD(*inode)] = get_fs_byte(b++);
INC_PIPE( PIPE_HEAD(*inode) );
wake_up(&inode->i_wait);
}
wake_up(&inode->i_wait);
return b-buf;
}
int sys_pipe(unsigned long * fildes)
{
struct m_inode * inode;
struct file * f[2];
int fd[2];
int i,j;
j=0;
for(i=0;j<2 && i<NR_FILE;i++)
if (!file_table[i].f_count)
(f[j++]=i+file_table)->f_count++;
if (j==1)
f[0]->f_count=0;
if (j<2)
return -1;
j=0;
for(i=0;j<2 && i<NR_OPEN;i++)
if (!current->filp[i]) {
current->filp[ fd[j]=i ] = f[j];
j++;
}
if (j==1)
current->filp[fd[0]]=NULL;
if (j<2) {
f[0]->f_count=f[1]->f_count=0;
return -1;
}
if (!(inode=get_pipe_inode())) {
current->filp[fd[0]] =
current->filp[fd[1]] = NULL;
f[0]->f_count = f[1]->f_count = 0;
return -1;
}
f[0]->f_inode = f[1]->f_inode = inode;
f[0]->f_pos = f[1]->f_pos = 0;
f[0]->f_mode = 1; /* read */
f[1]->f_mode = 2; /* write */
put_fs_long(fd[0],0+fildes);
put_fs_long(fd[1],1+fildes);
return 0;
}
+97
Ver Arquivo
@@ -0,0 +1,97 @@
#include <sys/stat.h>
#include <errno.h>
#include <sys/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <asm/segment.h>
extern int rw_char(int rw,int dev, char * buf, int count);
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_BLOCKDEV(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):-1;
if (S_ISCHR(inode->i_mode))
return rw_char(READ,inode->i_zone[0],buf,count);
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):-1;
if (S_ISCHR(inode->i_mode))
return rw_char(WRITE,inode->i_zone[0],buf,count);
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;
}
+119
Ver Arquivo
@@ -0,0 +1,119 @@
#include <errno.h>
#include <sys/stat.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/segment.h>
static int cp_stat(struct m_inode * inode, struct stat * statbuf)
{
struct stat tmp;
int i;
verify_area(statbuf,sizeof (* statbuf));
tmp.st_dev = inode->i_dev;
tmp.st_ino = inode->i_num;
tmp.st_mode = inode->i_mode;
tmp.st_nlink = inode->i_nlinks;
tmp.st_uid = inode->i_uid;
tmp.st_gid = inode->i_gid;
tmp.st_rdev = inode->i_zone[0];
tmp.st_size = inode->i_size;
tmp.st_atime = inode->i_atime;
tmp.st_mtime = inode->i_mtime;
tmp.st_ctime = inode->i_ctime;
for (i=0 ; i<sizeof (tmp) ; i++)
put_fs_byte(((char *) &tmp)[i],&((char *) statbuf)[i]);
return (0);
}
int sys_stat(char * filename, struct stat * statbuf)
{
int i;
struct m_inode * inode;
if (!(inode=namei(filename)))
return -ENOENT;
i=cp_stat(inode,statbuf);
iput(inode);
return i;
}
int sys_lstat(char* filename, struct stat * statbuf)
{
return sys_stat(filename,statbuf);
}
int sys_fstat(unsigned int fd, struct stat * statbuf)
{
struct file * f;
struct m_inode * inode;
if (fd >= NR_OPEN || !(f=current->filp[fd]) || !(inode=f->f_inode))
return -ENOENT;
return cp_stat(inode,statbuf);
}
static int cp_stat64(struct m_inode * inode, struct stat64 * statbuf)
{
struct stat64 tmp;
int i;
verify_area(statbuf,sizeof (* statbuf));
tmp.st_dev = inode->i_dev;
tmp.st_ino = inode->i_num;
tmp.st_mode = inode->i_mode;
tmp.st_nlink = inode->i_nlinks;
tmp.st_uid = inode->i_uid;
tmp.st_gid = inode->i_gid;
tmp.st_rdev = inode->i_zone[0];
tmp.st_size = inode->i_size;
tmp.st_atime = inode->i_atime;
tmp.st_mtime = inode->i_mtime;
tmp.st_ctime = inode->i_ctime;
for (i=0 ; i<sizeof (tmp) ; i++)
put_fs_byte(((char *) &tmp)[i],&((char *) statbuf)[i]);
return (0);
}
int sys_stat64(char * filename, struct stat64 * statbuf)
{
int i;
struct m_inode * inode;
if (!(inode=namei(filename)))
return -ENOENT;
i=cp_stat64(inode,statbuf);
iput(inode);
return i;
}
int sys_fstat64(unsigned int fd, struct stat64 * statbuf)
{
struct file * f;
struct m_inode * inode;
if (fd >= NR_OPEN || !(f=current->filp[fd]) || !(inode=f->f_inode))
return -ENOENT;
return cp_stat64(inode,statbuf);
}
int sys_lstat64(char* filename, struct stat * statbuf)
{
return sys_stat64(filename, (struct stat64 *)statbuf);
}
int sys_oldstat()
{
printk("calling obsolete system call oldstat\n");
return 0;
}
int sys_oldfstat()
{
printk("calling obsolete system call oldfstat\n");
return 0;
}
+102
Ver Arquivo
@@ -0,0 +1,102 @@
/*
* super.c contains code to handle the super-block tables.
*/
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/kernel.h>
/* 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];
struct super_block * do_mount(int dev)
{
struct super_block * p;
struct buffer_head * bh;
int i,block;
for(p = &super_block[0] ; p < &super_block[NR_SUPER] ; p++ )
if (!(p->s_dev))
break;
p->s_dev = -1; /* mark it in use */
if (p >= &super_block[NR_SUPER])
return NULL;
if (!(bh = bread(dev,1)))
return NULL;
*p = *((struct super_block *) bh->b_data);
brelse(bh);
if (p->s_magic != SUPER_MAGIC) {
p->s_dev = 0;
return NULL;
}
for (i=0;i<I_MAP_SLOTS;i++)
p->s_imap[i] = NULL;
for (i=0;i<Z_MAP_SLOTS;i++)
p->s_zmap[i] = NULL;
block=2;
for (i=0 ; i < p->s_imap_blocks ; i++)
if ((p->s_imap[i]=bread(dev,block)))
block++;
else
break;
for (i=0 ; i < p->s_zmap_blocks ; i++)
if ((p->s_zmap[i]=bread(dev,block)))
block++;
else
break;
if (block != 2+p->s_imap_blocks+p->s_zmap_blocks) {
for(i=0;i<I_MAP_SLOTS;i++)
brelse(p->s_imap[i]);
for(i=0;i<Z_MAP_SLOTS;i++)
brelse(p->s_zmap[i]);
p->s_dev=0;
return NULL;
}
p->s_imap[0]->b_data[0] |= 1;
p->s_zmap[0]->b_data[0] |= 1;
p->s_dev = dev;
p->s_isup = NULL;
p->s_imount = NULL;
p->s_time = 0;
p->s_rd_only = 0;
p->s_dirt = 0;
return p;
}
void mount_root(void)
{
int i,free;
struct super_block * p;
struct m_inode * mi;
if (32 != sizeof (struct d_inode))
panic("bad i-node size");
for(i=0;i<NR_FILE;i++)
file_table[i].f_count=0;
for(p = &super_block[0] ; p < &super_block[NR_SUPER] ; p++)
p->s_dev = 0;
if (!(p=do_mount(ROOT_DEV)))
panic("Unable to mount root");
if (!(mi=iget(ROOT_DEV,1)))
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);
}
Arquivo executável
+124
Ver Arquivo
@@ -0,0 +1,124 @@
#include <dirent.h>
#include <errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <asm/segment.h>
#include <sys/stat.h>
struct buffer_head* read_file_block(struct m_inode * inode,int block_num);
static int minix_getdents(struct m_inode * inode, struct file * filp,
struct dirent * dirent, int count)
{
unsigned int offset,i;
char c;
struct buffer_head * bh;
struct dir_entry * de;
if (!inode ||/* !inode->i_sb ||*/ !S_ISDIR(inode->i_mode))
return -EBADF;/*
info = &inode->i_sb->u.minix_sb;
if (filp->f_pos & (info->s_dirsize - 1))
return -EBADF;*/
while (filp->f_pos < inode->i_size) {
offset = filp->f_pos & 1023;
bh = read_file_block(inode,(filp->f_pos)/BLOCK_SIZE);
if (!bh) {
filp->f_pos += 1024-offset;
continue;
}
while (offset < 1024 && filp->f_pos < inode->i_size) {
de = (struct dir_entry *) (offset + bh->b_data);
offset += sizeof(struct dir_entry);//info->s_dirsize;
filp->f_pos += sizeof(struct dir_entry);
if (de->inode) {
for (i = 0; i < NAME_LEN; i++)
if ((c = de->name[i]) != 0)
put_fs_byte(c,i+dirent->d_name);
else
break;
if (i) {
put_fs_long(de->inode,&dirent->d_ino);
put_fs_byte(0,i+dirent->d_name);
put_fs_word(i,&dirent->d_reclen);
brelse(bh);
return i;
}
}
}
brelse(bh);
}
return 0;
}
static int minix_getdents64(struct m_inode * inode, struct file * filp,
struct dirent64 * dirent, int count)
{
unsigned int offset,i;
char c;
struct buffer_head * bh;
struct dir_entry * de;
if (!inode ||/* !inode->i_sb ||*/ !S_ISDIR(inode->i_mode))
return -EBADF;/*
info = &inode->i_sb->u.minix_sb;
if (filp->f_pos & (info->s_dirsize - 1))
return -EBADF;*/
while (filp->f_pos < inode->i_size) {
offset = filp->f_pos & 1023;
bh = read_file_block(inode,(filp->f_pos)/BLOCK_SIZE);
if (!bh) {
filp->f_pos += 1024-offset;
continue;
}
while (offset < 1024 && filp->f_pos < inode->i_size) {
de = (struct dir_entry *) (offset + bh->b_data);
offset += sizeof(struct dir_entry);//info->s_dirsize;
filp->f_pos += sizeof(struct dir_entry);
if (de->inode) {
for (i = 0; i < NAME_LEN; i++)
if ((c = de->name[i]) != 0)
put_fs_byte(c,i+dirent->d_name);
else
break;
if (i) {
put_fs_long(de->inode,&dirent->d_ino);
put_fs_byte(0,i+dirent->d_name);
put_fs_word(i,&dirent->d_reclen);
brelse(bh);
return i;
}
}
}
brelse(bh);
}
return 0;
}
int sys_getdents(unsigned int fd, struct dirent *dirp, unsigned int count)
{
struct file * file;
struct m_inode * inode;
if (fd >= NR_OPEN || !(file = current->filp[fd]) ||
!(inode = file->f_inode))
return -EBADF;
verify_area(dirp, sizeof (*dirp));
return minix_getdents(inode,file,dirp,count);
}
int sys_getdents64(unsigned int fd, struct dirent64 *dirp, unsigned int count)
{
struct file * file;
struct m_inode * inode;
if (fd >= NR_OPEN || !(file = current->filp[fd]) ||
!(inode = file->f_inode))
return -EBADF;
verify_area(dirp, sizeof (*dirp));
return minix_getdents64(inode,file,dirp,count);
}
+59
Ver Arquivo
@@ -0,0 +1,59 @@
#include <linux/sched.h>
#include <sys/stat.h>
static void free_ind(int dev,int block)
{
struct buffer_head * bh;
unsigned short * p;
int i;
if (!block)
return;
if ((bh=bread(dev,block))) {
p = (unsigned short *) bh->b_data;
for (i=0;i<512;i++,p++)
if (*p)
free_block(dev,*p);
brelse(bh);
}
free_block(dev,block);
}
static void free_dind(int dev,int block)
{
struct buffer_head * bh;
unsigned short * p;
int i;
if (!block)
return;
if ((bh=bread(dev,block))) {
p = (unsigned short *) bh->b_data;
for (i=0;i<512;i++,p++)
if (*p)
free_ind(dev,*p);
brelse(bh);
}
free_block(dev,block);
}
void truncate(struct m_inode * inode)
{
int i;
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)))
return;
for (i=0;i<7;i++)
if (inode->i_zone[i]) {
free_block(inode->i_dev,inode->i_zone[i]);
inode->i_zone[i]=0;
}
free_ind(inode->i_dev,inode->i_zone[7]);
free_dind(inode->i_dev,inode->i_zone[8]);
inode->i_zone[7] = inode->i_zone[8] = 0;
inode->i_size = 0;
inode->i_dirt = 1;
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
}
+166
Ver Arquivo
@@ -0,0 +1,166 @@
#include <errno.h>
#include <termios.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/tty.h>
#include <asm/segment.h>
#include <asm/system.h>
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);
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;
}
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];
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 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;
}
}
Arquivo binário não exibido.
+24
Ver Arquivo
@@ -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; \
})
+14
Ver Arquivo
@@ -0,0 +1,14 @@
/*
* NOTE!!! memcpy(dest,src,n) assumes ds=es=normal data segment. This
* goes for all kernel functions (ds=es=kernel space, fs=local data,
* gs=null), as well as for all well-behaving user programs (ds=es=
* user data space). This is NOT a bug, as any user program that changes
* es deserves to die if it isn't careful.
*/
#define memcpy(dest,src,n) ({ \
void * _res = dest; \
__asm__ ("cld;rep;movsb" \
::"D" ((long)(_res)),"S" ((long)(src)),"c" ((long) (n)) \
:"di","si","cx"); \
_res; \
})
+38
Ver Arquivo
@@ -0,0 +1,38 @@
extern inline unsigned char get_fs_byte(const char * addr)
{
unsigned register char _v;
__asm__ ("movb %%fs:%1,%0":"=r" (_v):"m" (*addr));
return _v;
}
extern inline unsigned short get_fs_word(const unsigned short *addr)
{
unsigned short _v;
__asm__ ("movw %%fs:%1,%0":"=r" (_v):"m" (*addr));
return _v;
}
extern inline unsigned long get_fs_long(const unsigned long *addr)
{
unsigned long _v;
__asm__ ("movl %%fs:%1,%0":"=r" (_v):"m" (*addr)); \
return _v;
}
extern inline void put_fs_byte(char val,char *addr)
{
__asm__ ("movb %0,%%fs:%1"::"q" (val),"m" (*addr));
}
extern inline void put_fs_word(short val,short * addr)
{
__asm__ ("movw %0,%%fs:%1"::"r" (val),"m" (*addr));
}
extern inline void put_fs_long(unsigned long val,unsigned long * addr)
{
__asm__ ("movl %0,%%fs:%1"::"r" (val),"m" (*addr));
}
+66
Ver Arquivo
@@ -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")
Arquivo executável
+26
Ver Arquivo
@@ -0,0 +1,26 @@
/* wchar_t type related definitions.
Copyright (C) 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _BITS_WCHAR_H
#define _BITS_WCHAR_H 1
#define __WCHAR_MIN (-2147483647l - 1l)
#define __WCHAR_MAX (2147483647l)
#endif /* bits/wchar.h */
Arquivo executável
+19
Ver Arquivo
@@ -0,0 +1,19 @@
/* Copyright (C) 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#define __WORDSIZE 32
+15
Ver Arquivo
@@ -0,0 +1,15 @@
#ifndef _CONST_H
#define _CONST_H
#define BUFFER_END 0x200000
#define I_TYPE 0170000
#define I_DIRECTORY 0040000
#define I_REGULAR 0100000
#define I_BLOCK_SPECIAL 0060000
#define I_CHAR_SPECIAL 0020000
#define I_NAMED_PIPE 0010000
#define I_SET_UID_BIT 0004000
#define I_SET_GID_BIT 0002000
#endif
+34
Ver Arquivo
@@ -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 signed 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
Arquivo executável
+39
Ver Arquivo
@@ -0,0 +1,39 @@
#ifndef __DIRENT_H
#define __DIRENT_H
#include <linux/fs.h>
#include <stdint.h>
#define NAME_MAX NAME_LEN
struct dirent{
long d_ino;
off_t d_off;
unsigned short d_reclen;
char d_name[256];
};
struct dirent64 {
uint64_t d_ino;
int64_t d_off;
uint16_t d_reclen;
unsigned char d_type;
char d_name[256];
};
struct __DIR{
struct dirent64 d_dent;
int d_pos;
int d_fd;
};
#define DIR struct __DIR
DIR *opendir (const char *name);
int closedir (DIR *dir);
struct dirent *readdir (DIR *dir);
#endif
Arquivo executável
+2561
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+60
Ver Arquivo
@@ -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
+58
Ver Arquivo
@@ -0,0 +1,58 @@
#ifndef _FCNTL_H
#define _FCNTL_H
#include <sys/types.h>
/* open/fcntl - NOCTTY, NDELAY isn't implemented yet */
#define O_ACCMODE 00003
#define O_RDONLY 00
#define O_WRONLY 01
#define O_RDWR 02
#define O_CREAT 00100 /* not fcntl */
#define O_EXCL 00200 /* not fcntl */
#define O_NOCTTY 00400 /* not fcntl */
#define O_TRUNC 01000 /* not fcntl */
#define O_APPEND 02000
#define O_NONBLOCK 04000 /* not fcntl */
#define O_NDELAY O_NONBLOCK
/* Defines for fcntl-commands. Note that currently
* locking isn't supported, and other things aren't really
* tested.
*/
#define F_DUPFD 0 /* dup */
#define F_GETFD 1 /* get f_flags */
#define F_SETFD 2 /* set f_flags */
#define F_GETFL 3 /* more flags (cloexec) */
#define F_SETFL 4
#define F_GETLK 5 /* not implemented */
#define F_SETLK 6
#define F_SETLKW 7
#define F_GETLK64 12
#define F_SETLK64 13
#define F_SETLKW64 14
/* 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
+36
Ver Arquivo
@@ -0,0 +1,36 @@
#ifndef _CONFIG_H
#define _CONFIG_H
/* #define LASU_HD */
#define LINUS_HD
/*
* Amount of ram memory (in bytes, 640k-1M not discounted). Currently 8Mb.
* Don't make this bigger without making sure that there are enough page
* directory entries (boot/head.s)
*/
#define HIGH_MEMORY (0x800000)
/* End of buffer memory. Must be 0xA0000, or > 0x100000, 4096-byte aligned */
#if (HIGH_MEMORY>=0x600000)
#define BUFFER_END 0x200000
#else
#define BUFFER_END 0xA0000
#endif
/* Root device at bootup. */
#define ROOT_DEV 0x301
/*
* HD type. If 2, put 2 structures with a comma. If just 1, put
* only 1 struct. The structs are { HEAD, SECTOR, TRACKS, WPCOM, LZONE, CTL }
*
* NOTE. CTL is supposed to be 0 for drives with less than 8 heads, and
* 8 if heads >= 8. Don't know why, and I haven't tested it on a drive with
* more than 8 heads, but that is what the bios-listings seem to imply. I
* just love not having a manual.
*/
#define HD_TYPE { 4,20,1024,0,4,0 }
#endif
+185
Ver Arquivo
@@ -0,0 +1,185 @@
/*
* This file has definitions for some important file table
* structures etc.
*/
#ifndef _FS_H
#define _FS_H
#include <sys/types.h>
/* devices are as follows: (same as minix, so we can use the minix
* file system. These are major numbers.)
*
* 0 - unused (nodev)
* 1 - /dev/mem
* 2 - /dev/fd
* 3 - /dev/hd
* 4 - /dev/ttyx
* 5 - /dev/tty
* 6 - /dev/lp
* 7 - unnamed pipes
*/
#define IS_BLOCKDEV(x) ((x)==2 || (x)==3)
#define READ 0
#define WRITE 1
void buffer_init(void);
#define MAJOR(a) (((unsigned)(a))>>8)
#define MINOR(a) ((a)&0xff)
#define NAME_LEN 14
#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
#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)))
typedef char buffer_block[BLOCK_SIZE];
struct buffer_head {
char * b_data; /* pointer to data block (1024 bytes) */
unsigned short b_dev; /* device (0 = free) */
unsigned short b_blocknr; /* block number */
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;
};
#define PIPE_HEAD(inode) (((long *)((inode).i_zone))[0])
#define PIPE_TAIL(inode) (((long *)((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))
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;
unsigned char s_rd_only;
unsigned char s_dirt;
};
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 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 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 void mount_root(void);
extern inline struct super_block * get_super(int dev)
{
struct super_block * s;
for(s = 0+super_block;s < NR_SUPER+super_block; s++)
if (s->s_dev == dev)
return s;
return NULL;
}
#endif
+87
Ver Arquivo
@@ -0,0 +1,87 @@
/*
* 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
/* currently supports only 1 hd, put type here */
#define HARD_DISK_TYPE 17
/*
* Ok, hard-disk-type is currently hardcoded. Not beatiful,
* but easier. We don't use BIOS for anything else, why should
* we get HD-type from it? Get these values from Reference Guide.
*/
#define _CYL 1024
#define _HEAD 4
#define __WPCOM (-1) /*not used ?*/
#define _LZONE 1024 /*same as _CYL ?*/
#define _SECT 20
#define _CTL 0
/* Controller wants just wp-com/4 */
#if __WPCOM >= 0
#define _WPCOM ((__WPCOM)>>2)
#else
#define _WPCOM __WPCOM
#endif
/* 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 /*0 => no error */
#define INDEX_STAT 0x02 /*not used in new controller*/
#define ECC_STAT 0x04 /*1 => Corrected error */
#define DRQ_STAT 0x08 /*0=> controller not waiting for data. 1 => waiting*/
#define SEEK_STAT 0x10 /*0=> searching. 1=> end of search. waiting for read or write*/
#define WRERR_STAT 0x20 /*1=> write error.*/
#define READY_STAT 0x40 /*1=> ready*/
#define BUSY_STAT 0x80 /*1 => busy*/
/* 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 /* command stopped */
#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
+20
Ver Arquivo
@@ -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
+8
Ver Arquivo
@@ -0,0 +1,8 @@
/*
* 'kernel.h' contains some often-used function prototypes etc
*/
void verify_area(void * addr,int count);
void panic(const char * str);
int printf(const char * fmt, ...);
int printk(const char * fmt, ...);
int tty_write(unsigned ch,char * buf,int count);
+10
Ver Arquivo
@@ -0,0 +1,10 @@
#ifndef _MM_H
#define _MM_H
#define PAGE_SIZE 4096
extern unsigned long get_free_page(void);
extern unsigned long put_page(unsigned long page,unsigned long address);
extern void free_page(unsigned long addr);
#endif
+233
Ver Arquivo
@@ -0,0 +1,233 @@
#ifndef _SCHED_H
#define _SCHED_H
#define NR_TASKS 64
#define HZ 100
#define FIRST_TASK task[0]
#define LAST_TASK task[NR_TASKS-1]
#include <linux/head.h>
#include <linux/fs.h>
#include <linux/mm.h>
#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, 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;
fn_ptr sig_restorer;
fn_ptr sig_fn[32];
/* various fields */
int exit_code;
unsigned long 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;
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,NULL,{(fn_ptr) 0,}, \
/* ec,brk... */ 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,0133,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 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__ __volatile__("cmpl %%ecx,current\n\t" \
"je 1f\n\t" \
"xchgl %%ecx,current\n\t" \
"movw %%dx,%1\n\t" \
"ljmp *%0\n\t" \
"cmpl %%ecx,%2\n\t" \
"jne 1f\n\t" \
"clts\n" \
"1:\n\t" \
::"m" (*&__tmp.a),"m" (*&__tmp.b), \
"m" (last_task_used_math),"d" _TSS(n),"c" ((long) task[n])); \
}
#define PAGE_ALIGN(n) (((n)+0xfff)&0xfffff000)
#define _set_base(addr,base) do { unsigned long __pr; \
__asm__ __volatile__ ("movw %%dx,%1\n\t" \
"rorl $16,%%edx\n\t" \
"movb %%dl,%2\n\t" \
"movb %%dh,%3" \
:"=&d" (__pr) \
:"m" (*((addr)+2)), \
"m" (*((addr)+4)), \
"m" (*((addr)+7)), \
"0" (base) \
); } while(0)
#define _set_limit(addr,limit) do { unsigned long __lr; \
__asm__ __volatile__ ("movw %%dx,%1\n\t" \
"rorl $16,%%edx\n\t" \
"movb %2,%%dh\n\t" \
"andb $0xf0,%%dh\n\t" \
"orb %%dh,%%dl\n\t" \
"movb %%dl,%2" \
:"=&d" (__lr) \
:"m" (*(addr)), \
"m" (*((addr)+6)), \
"0" (limit) \
); } while(0)
#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__ __volatile__("lsll %1,%0\n\tincl %0":"=r" (__limit):"r" (segment)); \
__limit;})
#endif
+144
Ver Arquivo
@@ -0,0 +1,144 @@
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_oldstat();
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_oldfstat();
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_oldolduname();
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_stat();
extern int sys_lstat();
extern int sys_fstat();
extern int sys_uname();
extern int sys_getdents();
extern int sys_stat64();
extern int sys_lstat64();
extern int sys_fstat64();
extern int sys_getdents64();
extern int sys_fcntl64();
extern int sys_null(); /* not implemented sys_call */
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_oldstat, sys_lseek, sys_getpid, sys_mount,
sys_umount, sys_setuid, sys_getuid, sys_stime, sys_ptrace, sys_alarm,
sys_oldfstat, 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_oldolduname, sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid,
sys_getpgrp,sys_setsid, sys_null /*67*/,sys_null,sys_null,
/* 70 */sys_null,sys_null,sys_null,sys_null,sys_null,
sys_null,sys_null,sys_null,sys_null,sys_null,
/* 80 */sys_null,sys_null,sys_null,sys_null,sys_null,
sys_null,sys_null,sys_null,sys_null,sys_null,
/* 90 */sys_null,sys_null,sys_null,sys_null,sys_null,
sys_null,sys_null,sys_null,sys_null,sys_null,
/* 100 */sys_null,sys_null,sys_null,sys_null,sys_null,
sys_null,sys_stat,sys_lstat,sys_fstat,sys_null,
/* 110 */sys_null,sys_null,sys_null,sys_null,sys_null,
sys_null,sys_null,sys_null,sys_null,sys_null,
/* 120 */sys_null,sys_null,sys_uname,sys_null,sys_null,
sys_null,sys_null,sys_null,sys_null,sys_null,
/* 130 */sys_null,sys_null,sys_null,sys_null,sys_null,
sys_null,sys_null,sys_null,sys_null,sys_null,
/* 140 */sys_null,sys_getdents,sys_null,sys_null,sys_null,
sys_null,sys_null,sys_null,sys_null,sys_null,
/* 150 */sys_null,sys_null,sys_null,sys_null,sys_null,
sys_null,sys_null,sys_null,sys_null,sys_null,
/* 160 */sys_null,sys_null,sys_null,sys_null,sys_null,
sys_null,sys_null,sys_null,sys_null,sys_null,
/* 170 */sys_null,sys_null,sys_null,sys_null,sys_null,
sys_null,sys_null,sys_null,sys_null,sys_null,
/* 180 */sys_null,sys_null,sys_null,sys_null,sys_null,
sys_null,sys_null,sys_null,sys_null,sys_null,
/* 190 */sys_null,sys_null,sys_null,sys_null,sys_null,
sys_stat64,sys_lstat64,sys_fstat64,sys_null,sys_null,
/* 200 */sys_null,sys_null,sys_null,sys_null,sys_null,
sys_null,sys_null,sys_null,sys_null,sys_null,
/* 210 */sys_null,sys_null,sys_null,sys_null,sys_null,
sys_null,sys_null,sys_null,sys_null,sys_null,
/* 220 */sys_getdents64,sys_fcntl64,sys_null,sys_null,sys_null,
sys_null,sys_null,sys_null,sys_null,sys_null,
/* 230 */sys_null,sys_null,sys_null,sys_null,sys_null,
sys_null,sys_null,sys_null,sys_null,sys_null,
/* 240 */sys_null,sys_null,sys_null,sys_null,sys_null,
sys_null,sys_null,sys_null,sys_null,sys_null,
/* 250 */sys_null,sys_null,sys_null,sys_null,sys_null,
sys_null,sys_null,sys_null,sys_null,sys_null,
/* 260 */sys_null,sys_null,sys_null,sys_null,sys_null,
sys_null,sys_null,sys_null,sys_null,sys_null,
/* 270 */sys_null,sys_null,sys_null,sys_null,sys_null,
sys_null,sys_null,sys_null,sys_null,sys_null,
/* 280 */sys_null,sys_null,sys_null,sys_null,sys_null,
sys_null,sys_null,sys_null,sys_null,sys_null,
/* 290 */sys_null,sys_null,sys_null,sys_null,sys_null,
sys_null,sys_null,sys_null,sys_null,sys_null,
/* 300 */sys_null,sys_null,sys_null,sys_null,sys_null,
sys_null,sys_null,sys_null,sys_null,sys_null,
/* 310 */sys_null,sys_null,sys_null,sys_null,sys_null,
sys_null,sys_null,sys_null,sys_null,sys_null
};
+74
Ver Arquivo
@@ -0,0 +1,74 @@
/*
* 'tty.h' defines some structures used by tty_io.c and some defines.
*
* NOTE! Don't touch this without checking that nothing in rs_io.s or
* con_io.s breaks. Some constants are hardwired into the system (mainly
* offsets into 'tty_queue'
*/
#ifndef _TTY_H
#define _TTY_H
#include <termios.h>
#define TTY_BUF_SIZE 1024
struct tty_queue {
unsigned long data;
unsigned long head;
unsigned long tail;
struct task_struct * proc_list;
char buf[TTY_BUF_SIZE];
};
#define INC(a) ((a) = ((a)+1) & (TTY_BUF_SIZE-1))
#define DEC(a) ((a) = ((a)-1) & (TTY_BUF_SIZE-1))
#define EMPTY(a) ((a).head == (a).tail)
#define LEFT(a) (((a).tail-(a).head-1)&(TTY_BUF_SIZE-1))
#define LAST(a) ((a).buf[(TTY_BUF_SIZE-1)&((a).head-1)])
#define FULL(a) (!LEFT(a))
#define CHARS(a) (((a).head-(a).tail)&(TTY_BUF_SIZE-1))
#define GETCH(queue,c) \
(void)({c=(queue).buf[(queue).tail];INC((queue).tail);})
#define PUTCH(c,queue) \
(void)({(queue).buf[(queue).head]=(c);INC((queue).head);})
#define EOF_CHAR(tty) ((tty)->termios.c_cc[VEOF])
#define INTR_CHAR(tty) ((tty)->termios.c_cc[VINTR])
#define STOP_CHAR(tty) ((tty)->termios.c_cc[VSTOP])
#define START_CHAR(tty) ((tty)->termios.c_cc[VSTART])
#define ERASE_CHAR(tty) ((tty)->termios.c_cc[VERASE])
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=^Y 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\031\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
+65
Ver Arquivo
@@ -0,0 +1,65 @@
#ifndef _SIGNAL_H
#define _SIGNAL_H
#include <sys/types.h>
typedef int sig_atomic_t;
typedef unsigned int sigset_t; /* 32 bits */
#define _NSIG 32
#define NSIG _NSIG
#define SIGHUP 1
#define SIGINT 2
#define SIGQUIT 3
#define SIGILL 4
#define SIGTRAP 5
#define SIGABRT 6
#define SIGIOT 6
#define SIGUNUSED 7
#define SIGFPE 8
#define SIGKILL 9
#define SIGUSR1 10
#define SIGSEGV 11
#define SIGUSR2 12
#define SIGPIPE 13
#define SIGALRM 14
#define SIGTERM 15
#define SIGSTKFLT 16
#define SIGCHLD 17
#define SIGCONT 18
#define SIGSTOP 19
#define SIGTSTP 20
#define SIGTTIN 21
#define SIGTTOU 22
/* Ok, I haven't implemented sigactions, but trying to keep headers POSIX */
#define SA_NOCLDSTOP 1
#define 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 (*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 */
Arquivo executável
+28
Ver Arquivo
@@ -0,0 +1,28 @@
#ifndef _STDARG_H
#define _STDARG_H
typedef char *va_list;
/* Amount of space required in an argument list for an arg of type TYPE.
TYPE may alternatively be an expression whose type is used. */
#define __va_rounded_size(TYPE) \
(((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
#ifndef __sparc__
#define va_start(AP, LASTARG) \
(AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
#else
#define va_start(AP, LASTARG) \
(__builtin_saveregs (), \
AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
#endif
void va_end (va_list); /* Defined in gnulib */
#define va_end(AP)
#define va_arg(AP, TYPE) \
(AP += __va_rounded_size (TYPE), \
*((TYPE *) (AP - __va_rounded_size (TYPE))))
#endif /* _STDARG_H */
+19
Ver Arquivo
@@ -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
Arquivo executável
+320
Ver Arquivo
@@ -0,0 +1,320 @@
/* Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
/*
* ISO C99: 7.18 Integer types <stdint.h>
*/
#ifndef _STDINT_H
#define _STDINT_H 1
//#include <features.h>
#include <bits/wchar.h>
#include <bits/wordsize.h>
/* Exact integral types. */
/* Signed. */
/* There is some amount of overlap with <sys/types.h> as known by inet code */
#ifndef __int8_t_defined
# define __int8_t_defined
typedef signed char int8_t;
typedef short int int16_t;
typedef int int32_t;
# if __WORDSIZE == 64
typedef long int int64_t;
# else
__extension__
typedef long long int int64_t;
# endif
#endif
/* Unsigned. */
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
#ifndef __uint32_t_defined
typedef unsigned int uint32_t;
# define __uint32_t_defined
#endif
#if __WORDSIZE == 64
typedef unsigned long int uint64_t;
#else
__extension__
typedef unsigned long long int uint64_t;
#endif
/* Small types. */
/* Signed. */
typedef signed char int_least8_t;
typedef short int int_least16_t;
typedef int int_least32_t;
#if __WORDSIZE == 64
typedef long int int_least64_t;
#else
__extension__
typedef long long int int_least64_t;
#endif
/* Unsigned. */
typedef unsigned char uint_least8_t;
typedef unsigned short int uint_least16_t;
typedef unsigned int uint_least32_t;
#if __WORDSIZE == 64
typedef unsigned long int uint_least64_t;
#else
__extension__
typedef unsigned long long int uint_least64_t;
#endif
/* Fast types. */
/* Signed. */
typedef signed char int_fast8_t;
#if __WORDSIZE == 64
typedef long int int_fast16_t;
typedef long int int_fast32_t;
typedef long int int_fast64_t;
#else
typedef int int_fast16_t;
typedef int int_fast32_t;
__extension__
typedef long long int int_fast64_t;
#endif
/* Unsigned. */
typedef unsigned char uint_fast8_t;
#if __WORDSIZE == 64
typedef unsigned long int uint_fast16_t;
typedef unsigned long int uint_fast32_t;
typedef unsigned long int uint_fast64_t;
#else
typedef unsigned int uint_fast16_t;
typedef unsigned int uint_fast32_t;
__extension__
typedef unsigned long long int uint_fast64_t;
#endif
/* Types for `void *' pointers. */
#if __WORDSIZE == 64
# ifndef __intptr_t_defined
typedef long int intptr_t;
# define __intptr_t_defined
# endif
typedef unsigned long int uintptr_t;
#else
# ifndef __intptr_t_defined
typedef int intptr_t;
# define __intptr_t_defined
# endif
typedef unsigned int uintptr_t;
#endif
/* Largest integral types. */
#if __WORDSIZE == 64
typedef long int intmax_t;
typedef unsigned long int uintmax_t;
#else
__extension__
typedef long long int intmax_t;
__extension__
typedef unsigned long long int uintmax_t;
#endif
/* The ISO C99 standard specifies that in C++ implementations these
macros should only be defined if explicitly requested. */
#if !defined __cplusplus || defined __STDC_LIMIT_MACROS
# if __WORDSIZE == 64
# define __INT64_C(c) c ## L
# define __UINT64_C(c) c ## UL
# else
# define __INT64_C(c) c ## LL
# define __UINT64_C(c) c ## ULL
# endif
/* Limits of integral types. */
/* Minimum of signed integral types. */
# define INT8_MIN (-128)
# define INT16_MIN (-32767-1)
# define INT32_MIN (-2147483647-1)
# define INT64_MIN (-__INT64_C(9223372036854775807)-1)
/* Maximum of signed integral types. */
# define INT8_MAX (127)
# define INT16_MAX (32767)
# define INT32_MAX (2147483647)
# define INT64_MAX (__INT64_C(9223372036854775807))
/* Maximum of unsigned integral types. */
# define UINT8_MAX (255)
# define UINT16_MAX (65535)
# define UINT32_MAX (4294967295U)
# define UINT64_MAX (__UINT64_C(18446744073709551615))
/* Minimum of signed integral types having a minimum size. */
# define INT_LEAST8_MIN (-128)
# define INT_LEAST16_MIN (-32767-1)
# define INT_LEAST32_MIN (-2147483647-1)
# define INT_LEAST64_MIN (-__INT64_C(9223372036854775807)-1)
/* Maximum of signed integral types having a minimum size. */
# define INT_LEAST8_MAX (127)
# define INT_LEAST16_MAX (32767)
# define INT_LEAST32_MAX (2147483647)
# define INT_LEAST64_MAX (__INT64_C(9223372036854775807))
/* Maximum of unsigned integral types having a minimum size. */
# define UINT_LEAST8_MAX (255)
# define UINT_LEAST16_MAX (65535)
# define UINT_LEAST32_MAX (4294967295U)
# define UINT_LEAST64_MAX (__UINT64_C(18446744073709551615))
/* Minimum of fast signed integral types having a minimum size. */
# define INT_FAST8_MIN (-128)
# if __WORDSIZE == 64
# define INT_FAST16_MIN (-9223372036854775807L-1)
# define INT_FAST32_MIN (-9223372036854775807L-1)
# else
# define INT_FAST16_MIN (-2147483647-1)
# define INT_FAST32_MIN (-2147483647-1)
# endif
# define INT_FAST64_MIN (-__INT64_C(9223372036854775807)-1)
/* Maximum of fast signed integral types having a minimum size. */
# define INT_FAST8_MAX (127)
# if __WORDSIZE == 64
# define INT_FAST16_MAX (9223372036854775807L)
# define INT_FAST32_MAX (9223372036854775807L)
# else
# define INT_FAST16_MAX (2147483647)
# define INT_FAST32_MAX (2147483647)
# endif
# define INT_FAST64_MAX (__INT64_C(9223372036854775807))
/* Maximum of fast unsigned integral types having a minimum size. */
# define UINT_FAST8_MAX (255)
# if __WORDSIZE == 64
# define UINT_FAST16_MAX (18446744073709551615UL)
# define UINT_FAST32_MAX (18446744073709551615UL)
# else
# define UINT_FAST16_MAX (4294967295U)
# define UINT_FAST32_MAX (4294967295U)
# endif
# define UINT_FAST64_MAX (__UINT64_C(18446744073709551615))
/* Values to test for integral types holding `void *' pointer. */
# if __WORDSIZE == 64
# define INTPTR_MIN (-9223372036854775807L-1)
# define INTPTR_MAX (9223372036854775807L)
# define UINTPTR_MAX (18446744073709551615UL)
# else
# define INTPTR_MIN (-2147483647-1)
# define INTPTR_MAX (2147483647)
# define UINTPTR_MAX (4294967295U)
# endif
/* Minimum for largest signed integral type. */
# define INTMAX_MIN (-__INT64_C(9223372036854775807)-1)
/* Maximum for largest signed integral type. */
# define INTMAX_MAX (__INT64_C(9223372036854775807))
/* Maximum for largest unsigned integral type. */
# define UINTMAX_MAX (__UINT64_C(18446744073709551615))
/* Limits of other integer types. */
/* Limits of `ptrdiff_t' type. */
# if __WORDSIZE == 64
# define PTRDIFF_MIN (-9223372036854775807L-1)
# define PTRDIFF_MAX (9223372036854775807L)
# else
# define PTRDIFF_MIN (-2147483647-1)
# define PTRDIFF_MAX (2147483647)
# endif
/* Limits of `sig_atomic_t'. */
# define SIG_ATOMIC_MIN (-2147483647-1)
# define SIG_ATOMIC_MAX (2147483647)
/* Limit of `size_t' type. */
# if __WORDSIZE == 64
# define SIZE_MAX (18446744073709551615UL)
# else
# define SIZE_MAX (4294967295U)
# endif
/* Limits of `wchar_t'. */
# ifndef WCHAR_MIN
/* These constants might also be defined in <wchar.h>. */
# define WCHAR_MIN __WCHAR_MIN
# define WCHAR_MAX __WCHAR_MAX
# endif
/* Limits of `wint_t'. */
# define WINT_MIN (0u)
# define WINT_MAX (4294967295u)
#endif /* C++ && limit macros */
/* The ISO C99 standard specifies that in C++ implementations these
should only be defined if explicitly requested. */
#if !defined __cplusplus || defined __STDC_CONSTANT_MACROS
/* Signed. */
# define INT8_C(c) c
# define INT16_C(c) c
# define INT32_C(c) c
# if __WORDSIZE == 64
# define INT64_C(c) c ## L
# else
# define INT64_C(c) c ## LL
# endif
/* Unsigned. */
# define UINT8_C(c) c ## U
# define UINT16_C(c) c ## U
# define UINT32_C(c) c ## U
# if __WORDSIZE == 64
# define UINT64_C(c) c ## UL
# else
# define UINT64_C(c) c ## ULL
# endif
/* Maximal type. */
# if __WORDSIZE == 64
# define INTMAX_C(c) c ## L
# define UINTMAX_C(c) c ## UL
# else
# define INTMAX_C(c) c ## LL
# define UINTMAX_C(c) c ## ULL
# endif
#endif /* C++ && constant macros */
#endif /* stdint.h */
+435
Ver Arquivo
@@ -0,0 +1,435 @@
#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)
{
int d0, d1, d2;
__asm__ __volatile__("cld\n\t"
"1:\tlodsb\n\t"
"stosb\n\t"
"testb %%al,%%al\n\t"
"jne 1b"
: "=&S" (d0), "=&D" (d1), "=&a" (d2)
:"0" (src),"1" (dest) : "memory");
return dest;
}
extern inline char * strncpy(char * dest,const char *src,int count)
{
int d0, d1, d2, d3;
__asm__ __volatile__("cld\n\t"
"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" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3)
:"0" (src),"1" (dest),"2" (count) : "memory");
return dest;
}
extern inline char * strcat(char * dest,const char * src)
{
int d0, d1, d2, d3;
__asm__ __volatile__("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" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
: "0" (src), "1" (dest), "2" (0), "3" (0xffffffffu):"memory");
return dest;
}
extern inline char * strncat(char * dest,const char * src,int count)
{
int d0, d1, d2, d3;
__asm__ __volatile__("cld\n\t"
"repne\n\t"
"scasb\n\t"
"decl %1\n\t"
"movl %8,%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" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
: "0" (src),"1" (dest),"2" (0),"3" (0xffffffffu), "g" (count)
: "memory");
return dest;
}
extern inline int strcmp(const char * cs,const char * ct)
{
int d0, d1;
register int __res;
__asm__ __volatile__("cld\n\t"
"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:\tsbbl %%eax,%%eax\n\t"
"orb $1,%%al\n"
"3:"
:"=a" (__res), "=&S" (d0), "=&D" (d1)
:"1" (cs),"2" (ct)
:"memory");
return __res;
}
extern inline int strncmp(const char * cs,const char * ct,int count)
{
register int __res;
int d0, d1, d2;
__asm__ __volatile__("cld\n\t"
"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:\tsbbl %%eax,%%eax\n\t"
"orb $1,%%al\n"
"4:"
:"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
:"1" (cs),"2" (ct),"3" (count)
:"memory");
return __res;
}
extern inline char * strchr(const char * s,int c)
{
int d0;
register char * __res;
__asm__ __volatile__(
"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" (d0)
:"1" (s),"0" (c)
:"memory");
return __res;
}
extern inline char * strrchr(const char * s,int c)
{
int d0, d1;
register char * __res;
__asm__ __volatile__("cld\n\t"
"movb %%al,%%ah\n"
"1:\tlodsb\n\t"
"cmpb %%ah,%%al\n\t"
"jne 2f\n\t"
"leal -1(%%esi),%0\n"
"2:\ttestb %%al,%%al\n\t"
"jne 1b"
:"=g" (__res), "=&S" (d0), "=&a" (d1)
:"0" (0),"1" (s),"2" (c)
:"memory");
return __res;
}
extern inline int strspn(const char * cs, const char * ct)
{
register char * __res;// __asm__("si");
__asm__("cld\n\t"
"movl %4,%%edi\n\t"
"repne\n\t"
"scasb\n\t"
"notl %%ecx\n\t"
"decl %%ecx\n\t"
"movl %%ecx,%%edx\n"
"1:\tlodsb\n\t"
"testb %%al,%%al\n\t"
"je 2f\n\t"
"movl %4,%%edi\n\t"
"movl %%edx,%%ecx\n\t"
"repne\n\t"
"scasb\n\t"
"je 1b\n"
"2:\tdecl %0"
:"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
:/*"ax","cx",*/"dx","di"); /* TODO : constraint may be wrong*/
return __res-cs;
}
extern inline int strcspn(const char * cs, const char * ct)
{
register char * __res;// __asm__("si");
__asm__("cld\n\t"
"movl %4,%%edi\n\t"
"repne\n\t"
"scasb\n\t"
"notl %%ecx\n\t"
"decl %%ecx\n\t"
"movl %%ecx,%%edx\n"
"1:\tlodsb\n\t"
"testb %%al,%%al\n\t"
"je 2f\n\t"
"movl %4,%%edi\n\t"
"movl %%edx,%%ecx\n\t"
"repne\n\t"
"scasb\n\t"
"jne 1b\n"
"2:\tdecl %0"
:"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
:/*"ax","cx",*/"dx","di"); /* TODO : constraint may be wrong*/
return __res-cs;
}
extern inline char * strpbrk(const char * cs,const char * ct)
{
register char * __res;// __asm__("si");
__asm__("cld\n\t"
"movl %4,%%edi\n\t"
"repne\n\t"
"scasb\n\t"
"notl %%ecx\n\t"
"decl %%ecx\n\t"
"movl %%ecx,%%edx\n"
"1:\tlodsb\n\t"
"testb %%al,%%al\n\t"
"je 2f\n\t"
"movl %4,%%edi\n\t"
"movl %%edx,%%ecx\n\t"
"repne\n\t"
"scasb\n\t"
"jne 1b\n\t"
"decl %0\n\t"
"jmp 3f\n"
"2:\txorl %0,%0\n"
"3:"
:"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
:/*"ax","cx",*/"dx","di");/* TODO : constraint may be wrong*/
return __res;
}
extern inline char * strstr(const char * cs,const char * ct)
{
register char * __res;// __asm__("ax");
__asm__("cld\n\t" \
"movl %4,%%edi\n\t"
"repne\n\t"
"scasb\n\t"
"notl %%ecx\n\t"
"decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */
"movl %%ecx,%%edx\n"
"1:\tmovl %4,%%edi\n\t"
"movl %%esi,%%eax\n\t"
"movl %%edx,%%ecx\n\t"
"repe\n\t"
"cmpsb\n\t"
"je 2f\n\t" /* also works for empty string, see above */
"xchgl %%eax,%%esi\n\t"
"incl %%esi\n\t"
"cmpb $0,-1(%%eax)\n\t"
"jne 1b\n\t"
"xorl %%eax,%%eax\n\t"
"2:"
:"=a" (__res):"0" (0),"c" (0xffffffff),"S" (cs),"g" (ct)
:/*"cx",*/"dx","di"/*,"si"*/); /* TODO : constraint may be wrong*/
return __res;
}
extern inline int strlen(const char * s)
{
int d0;
register int __res;
__asm__ __volatile__("cld\n\t"
"repne\n\t"
"scasb\n\t"
"notl %0\n\t"
"decl %0"
:"=c" (__res), "=&D" (d0)
:"1" (s),"a" (0), "0" (0xffffffffu)
:"memory");
return __res;
}
extern char * ___strtok;
extern inline char * strtok(char * s,const char * ct)
{
register char * __res;// __asm__("si");
__asm__("testl %1,%1\n\t"
"jne 1f\n\t"
"testl %0,%0\n\t"
"je 8f\n\t"
"movl %0,%1\n"
"1:\txorl %0,%0\n\t"
"movl $-1,%%ecx\n\t"
"xorl %%eax,%%eax\n\t"
"cld\n\t"
"movl %4,%%edi\n\t"
"repne\n\t"
"scasb\n\t"
"notl %%ecx\n\t"
"decl %%ecx\n\t"
"je 7f\n\t" /* empty delimeter-string */
"movl %%ecx,%%edx\n"
"2:\tlodsb\n\t"
"testb %%al,%%al\n\t"
"je 7f\n\t"
"movl %4,%%edi\n\t"
"movl %%edx,%%ecx\n\t"
"repne\n\t"
"scasb\n\t"
"je 2b\n\t"
"decl %1\n\t"
"cmpb $0,(%1)\n\t"
"je 7f\n\t"
"movl %1,%0\n"
"3:\tlodsb\n\t"
"testb %%al,%%al\n\t"
"je 5f\n\t"
"movl %4,%%edi\n\t"
"movl %%edx,%%ecx\n\t"
"repne\n\t"
"scasb\n\t"
"jne 3b\n\t"
"decl %1\n\t"
"cmpb $0,(%1)\n\t"
"je 5f\n\t"
"movb $0,(%1)\n\t"
"incl %1\n\t"
"jmp 6f\n"
"5:\txorl %1,%1\n"
"6:\tcmpb $0,(%0)\n\t"
"jne 7f\n\t"
"xorl %0,%0\n"
"7:\ttestl %0,%0\n\t"
"jne 8f\n\t"
"movl %0,%1\n"
"8:"
:"=b" (__res),"=S" (___strtok)
:"0" (___strtok),"1" (s),"g" (ct)
:"ax","cx","dx","di"); /* TODO : constraint may be wrong*/
return __res;
}
extern inline void * memcpy(void * dest,const void * src, int n)
{
int d0,d1,d2;
__asm__ __volatile("cld\n\t"
"rep\n\t"
"movsb"
:"=&c" (d0), "=&S" (d1), "=&D" (d2)
:"0" (n),"1" (src),"2" (dest)
:"memory");
return dest;
}
extern inline void * memmove(void * dest,const void * src, int n)
{
int d0, d1, d2;
if (dest < src) {
memcpy(dest,src,n);
} else {
__asm__ __volatile__(
"std\n\t"
"rep\n\t"
"movsb\n\t"
"cld"
: "=&c" (d0), "=&S" (d1), "=&D" (d2)
:"0" (n),
"1" (n-1+(const char *)src),
"2" (n-1+(char *)dest)
:"memory");
}
return dest;
}
extern inline int memcmp(const void * cs,const void * ct,int count)
{
register int __res;// __asm__("ax");
__asm__("cld\n\t"
"repe\n\t"
"cmpsb\n\t"
"je 1f\n\t"
"movl $1,%%eax\n\t"
"jl 1f\n\t"
"negl %%eax\n"
"1:"
:"=a" (__res):"0" (0),"D" (cs),"S" (ct),"c" (count)
/*:"si","di","cx"*/); /* TODO : constraint may be wrong*/
return __res;
}
extern inline void * memchr(const void * cs,char c,int count)
{
int d0;
register void * __res;
if (!count)
return NULL;
__asm__ __volatile__("cld\n\t"
"repne\n\t"
"scasb\n\t"
"je 1f\n\t"
"movl $1,%0\n"
"1:\tdecl %0"
:"=D" (__res), "=&c" (d0)
:"a" (c),"0" (cs),"1" (count)
:"memory");
return __res;
}
extern inline void * memset(void * s,int c,int count)
{
int d0, d1;
__asm__ __volatile__("cld\n\t"
"rep\n\t"
"stosb"
: "=&c" (d0), "=&D" (d1)
:"a" (c),"1" (s),"0" (count)
:"memory");
return s;
}
#endif
+102
Ver Arquivo
@@ -0,0 +1,102 @@
#ifndef _SYS_STAT_H
#define _SYS_STAT_H
#include <sys/types.h>
#include <stdint.h>
struct stat {
uint16_t st_dev;
uint16_t __pad1;
unsigned long st_ino;
uint16_t st_mode;
uint16_t st_nlink;
uint16_t st_uid;
uint16_t st_gid;
uint16_t st_rdev;
uint16_t __pad2;
unsigned long st_size;
unsigned long st_blksize;
unsigned long st_blocks;
time_t st_atime;
unsigned long __unused1;
time_t st_mtime;
unsigned long __unused2;
time_t st_ctime;
unsigned long __unused3;
unsigned long __unused4;
unsigned long __unused5;
};
struct stat64 {
uint16_t st_dev;
unsigned char __pad0[10];
#define STAT64_HAS_BROKEN_ST_INO 1
unsigned long __st_ino;
uint32_t st_mode;
uint32_t st_nlink;
unsigned long st_uid;
unsigned long st_gid;
uint16_t st_rdev;
unsigned char __pad3[10];
__extension__ long long st_size __attribute__((__packed__));
unsigned long st_blksize;
unsigned long st_blocks; /* Number 512-byte blocks allocated. */
unsigned long __pad4; /* future possible st_blocks high bits */
time_t st_atime;
unsigned long __pad5;
time_t st_mtime;
unsigned long __pad6;
time_t st_ctime;
unsigned long __pad7; /* will be high 32 bits of ctime someday */
__extension__ unsigned long long st_ino __attribute__((__packed__));
};
#define S_IFMT 00170000
#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_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 fstat64(int fildes, struct stat64 *stat_buf);
extern int mkdir(const char *_path, mode_t mode);
extern int mkfifo(const char *_path, mode_t mode);
extern int stat64(const char *filename, struct stat64 *stat_buf);
extern mode_t umask(mode_t mask);
#endif
+15
Ver Arquivo
@@ -0,0 +1,15 @@
#ifndef _TIMES_H
#define _TIMES_H
#include <sys/types.h>
struct tms {
time_t tms_utime;
time_t tms_stime;
time_t tms_cutime;
time_t tms_cstime;
};
extern time_t times(struct tms * tp);
#endif
+46
Ver Arquivo
@@ -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
+35
Ver Arquivo
@@ -0,0 +1,35 @@
#ifndef _SYS_UTSNAME_H
#define _SYS_UTSNAME_H 1
/* Length of the entries in `struct utsname' is 65. */
#define _UTSNAME_LENGTH 65
#define _UTSNAME_NODENAME_LENGTH _UTSNAME_LENGTH
/* Linux provides as additional information in the `struct utsname'
the name of the current domain. Define _UTSNAME_DOMAIN_LENGTH
to a value != 0 to activate this entry. */
#define _UTSNAME_DOMAIN_LENGTH _UTSNAME_LENGTH
struct utsname {
/* Name of the implementation of the operating system. */
char sysname[_UTSNAME_LENGTH];
/* Name of this node on the network. */
char nodename[_UTSNAME_NODENAME_LENGTH];
/* Current release level of this implementation. */
char release[_UTSNAME_LENGTH];
/* Current version level of this release. */
char version[_UTSNAME_LENGTH];
/* Name of the hardware type the system is running on. */
char machine[_UTSNAME_LENGTH];
/* Name of the domain of this node on the network. */
char domainname[_UTSNAME_DOMAIN_LENGTH];
};
extern int uname (struct utsname *__name);
#endif
+23
Ver Arquivo
@@ -0,0 +1,23 @@
#ifndef _SYS_WAIT_H
#define _SYS_WAIT_H
#include <sys/types.h>
#define _LOW(v) ( (v) & 0377)
#define _HIGH(v) ( ((v) >> 8) & 0377)
/* options for waitpid, WUNTRACED not supported */
#define WNOHANG 1
#define WUNTRACED 2
#define WIFEXITED(s) (!((s)&0xFF)
#define WIFSTOPPED(s) (((s)&0xFF)==0x7F)
#define WEXITSTATUS(s) (((s)>>8)&0xFF)
#define WTERMSIG(s) ((s)&0x7F)
#define WSTOPSIG(s) (((s)>>8)&0xFF)
#define WIFSIGNALED(s) (((unsigned int)(s)-1 & 0xFFFF) < 0xFF)
pid_t wait(int *stat_loc);
pid_t waitpid(pid_t pid, int *stat_loc, int options);
#endif
+222
Ver Arquivo
@@ -0,0 +1,222 @@
#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
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 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 */
/* c_lflag bits */
#define ISIG 0000001
#define ICANON 0000002
#define XCASE 0000004
#define ECHO 0000010
#define ECHOE 0000020
#define ECHOK 0000040
#define ECHONL 0000100
#define NOFLSH 0000200
#define TOSTOP 0000400
#define ECHOCTL 0001000
#define ECHOPRT 0002000
#define ECHOKE 0004000
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
/* modem lines */
#define TIOCM_LE 0x001
#define TIOCM_DTR 0x002
#define TIOCM_RTS 0x004
#define TIOCM_ST 0x008
#define TIOCM_SR 0x010
#define TIOCM_CTS 0x020
#define TIOCM_CAR 0x040
#define TIOCM_RNG 0x080
#define TIOCM_DSR 0x100
#define TIOCM_CD TIOCM_CAR
#define TIOCM_RI TIOCM_RNG
/* tcflow() and TCXONC use these */
#define TCOOFF 0
#define TCOON 1
#define TCIOFF 2
#define TCION 3
/* tcflush() and TCFLSH use these */
#define TCIFLUSH 0
#define TCOFLUSH 1
#define TCIOFLUSH 2
/* tcsetattr uses these */
#define TCSANOW 0
#define TCSADRAIN 1
#define TCSAFLUSH 2
typedef int speed_t;
extern speed_t cfgetispeed(struct termios *termios_p);
extern speed_t cfgetospeed(struct termios *termios_p);
extern int cfsetispeed(struct termios *termios_p, speed_t speed);
extern int cfsetospeed(struct termios *termios_p, speed_t speed);
extern int tcdrain(int fildes);
extern int tcflow(int fildes, int action);
extern int tcflush(int fildes, int queue_selector);
extern int tcgetattr(int fildes, struct termios *termios_p);
extern int tcsendbreak(int fildes, int duration);
extern int tcsetattr(int fildes, int optional_actions,
struct termios *termios_p);
#endif
+42
Ver Arquivo
@@ -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
+260
Ver Arquivo
@@ -0,0 +1,260 @@
#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*/ /* pathname truncation (but see in kernel) */
#define _POSIX_VDISABLE '\0' /* character to disable things like ^C */
/*#define _POSIX_SAVED_IDS */ /* we'll get to this yet */
/*#define _POSIX_JOB_CONTROL */ /* we aren't there quite yet. Soon hopefully */
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
#ifndef NULL
#define NULL ((void *)0)
#endif
/* access */
#define F_OK 0
#define X_OK 1
#define W_OK 2
#define R_OK 4
/* lseek */
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
/* _SC stands for System Configuration. We don't use them much */
#define _SC_ARG_MAX 1
#define _SC_CHILD_MAX 2
#define _SC_CLOCKS_PER_SEC 3
#define _SC_NGROUPS_MAX 4
#define _SC_OPEN_MAX 5
#define _SC_JOB_CONTROL 6
#define _SC_SAVED_IDS 7
#define _SC_VERSION 8
/* more (possibly) configurable things - now pathnames */
#define _PC_LINK_MAX 1
#define _PC_MAX_CANON 2
#define _PC_MAX_INPUT 3
#define _PC_NAME_MAX 4
#define _PC_PATH_MAX 5
#define _PC_PIPE_BUF 6
#define _PC_NO_TRUNC 7
#define _PC_VDISABLE 8
#define _PC_CHOWN_RESTRICTED 9
#include <sys/stat.h>
#include <sys/times.h>
#include <sys/utsname.h>
#include <utime.h>
#include <dirent.h>
#ifdef __LIBRARY__
#define __NR_setup 0 /* used only by init, to get system going */
#define __NR_exit 1
#define __NR_fork 2
#define __NR_read 3
#define __NR_write 4
#define __NR_open 5
#define __NR_close 6
#define __NR_waitpid 7
#define __NR_creat 8
#define __NR_link 9
#define __NR_unlink 10
#define __NR_execve 11
#define __NR_chdir 12
#define __NR_time 13
#define __NR_mknod 14
#define __NR_chmod 15
#define __NR_chown 16
#define __NR_break 17
#define __NR_oldstat 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_oldfstat 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_oldolduname 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_stat 106
#define __NR_lstat 107
#define __NR_fstat 108
#define __NR_uname 122
#define __NR_getdents 141
#define __NR_stat64 195
#define __NR_ltat64 196
#define __NR_fstat64 197
#define __NR_getdents64 220
#define __NR_fcntl64 221
#define _syscall0(type,name) \
type name(void) \
{ \
type __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name)); \
if (__res >= 0) \
return __res; \
errno = -__res; \
return -1; \
}
#define _syscall1(type,name,atype,a) \
type name(atype a) \
{ \
type __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" (a)); \
if (__res >= 0) \
return __res; \
errno = -__res; \
return -1; \
}
#define _syscall2(type,name,atype,a,btype,b) \
type name(atype a,btype b) \
{ \
type __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" (a),"c" (b)); \
if (__res >= 0) \
return __res; \
errno = -__res; \
return -1; \
}
#define _syscall3(type,name,atype,a,btype,b,ctype,c) \
type name(atype a,btype b,ctype c) \
{ \
type __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" (a),"c" (b),"d" (c)); \
if (__res<0) \
errno=-__res , __res = -1; \
return __res;\
}
#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, ...);
void exit(int status);
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 stat64(const char * filename, struct stat64 * stat_buf);
int fstat64(int fildes, struct stat64 * 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 getdents(unsigned int fd, struct dirent *dirp, unsigned int count);
int getdents64(unsigned int fd, struct dirent64 *dirp, unsigned int count);
#endif
+13
Ver Arquivo
@@ -0,0 +1,13 @@
#ifndef _UTIME_H
#define _UTIME_H
#include <sys/types.h> /* I know - shouldn't do this, but .. */
struct utimbuf {
time_t actime;
time_t modtime;
};
extern int utime(const char *filename, struct utimbuf *times);
#endif
+147
Ver Arquivo
@@ -0,0 +1,147 @@
#define __LIBRARY__
#include <unistd.h>
#include <time.h>
/*
* we need this inline - forking from kernel space will result
* in NO COPY ON WRITE (!!!), until an execve is executed. This
* is no problem, but for the stack. This is handled by not letting
* main() use the stack at all after fork(). Thus, no function
* calls - which means inline code for fork too, as otherwise we
* would use the stack upon exit from 'fork()'.
*
* Actually only pause and fork are needed inline, so that there
* won't be any messing with the stack from main(), but we define
* some others too.
*/
static inline _syscall0(int,fork)
static inline _syscall0(int,pause)
static inline _syscall0(int,setup)
static inline _syscall0(int,sync)
#include <linux/tty.h>
#include <linux/sched.h>
#include <linux/head.h>
#include <asm/system.h>
#include <asm/io.h>
#include <stddef.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <linux/fs.h>
static char printbuf[1024];
extern int vsprintf();
extern void init(void);
extern void hd_init(void);
extern long kernel_mktime(struct tm * tm);
extern long startup_time;
/*
* 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)-1;
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);
startup_time = kernel_mktime(&time);
}
int 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
*/
time_init();
tty_init();
trap_init();
sched_init();
buffer_init();
hd_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();
return 0;
}
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[] = { "/bin/sh",NULL };
static char * envp[] = { "HOME=/root","PATH=/bin","PWD=/", NULL };
void init(void)
{
int i,j;
setup();
(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(" Ok.\n\r");
if ((i=fork())<0)
printf("Fork failed in init\r\n");
else if (!i) {
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));
}
j=wait(&i);
printf("child %d died with code %04x\n",j,i);
sync();
_exit(0); /* NOTE! _exit, not exit() */
}
+90
Ver Arquivo
@@ -0,0 +1,90 @@
#
# Makefile for the FREAX-kernel.
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
AR =ar
AS =as --32
LD =ld -m elf_i386
LDFLAGS =-g #-s -x
CC =gcc
CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer -m32 \
-finline-functions -fno-stack-protector -nostdinc -fno-builtin -g -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 = sched.o system_call.o traps.o asm.o fork.o \
panic.o printk.o vsprintf.o tty_io.o console.o \
keyboard.o rs_io.o hd.o sys.o exit.o serial.o \
mktime.o
kernel.o: $(OBJS)
$(LD) -r -o kernel.o $(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:
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/linux/tty.h ../include/termios.h ../include/asm/io.h \
../include/asm/system.h
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/linux/kernel.h ../include/asm/segment.h \
../include/asm/system.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/linux/kernel.h ../include/linux/hdreg.h \
../include/asm/system.h ../include/asm/io.h ../include/asm/segment.h
mktime.s mktime.o : mktime.c ../include/time.h
panic.s panic.o : panic.c ../include/linux/kernel.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/linux/kernel.h ../include/signal.h ../include/linux/sys.h \
../include/asm/system.h ../include/asm/io.h ../include/asm/segment.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/asm/system.h \
../include/asm/io.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/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/linux/kernel.h ../include/asm/system.h \
../include/asm/segment.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
vsprintf.s vsprintf.o : vsprintf.c ../include/stdarg.h ../include/string.h
+157
Ver Arquivo
@@ -0,0 +1,157 @@
/*
* asm.s contains the low-level code for most hardware faults.
* page_exception is handled by the mm, so that isn't here. This
* file also handles (hopefully) fpu-exceptions due to TS-bit, as
* the fpu must be properly saved/resored. This hasn't been tested.
*/
.globl divide_error,debug,nmi,int3,overflow,bounds,invalid_op
.globl device_not_available,double_fault,coprocessor_segment_overrun
.globl invalid_TSS,segment_not_present,stack_segment
.globl general_protection,coprocessor_error,reserved
divide_error:
pushl $do_divide_error
no_error_code:
xchgl %eax,(%esp)
pushl %ebx
pushl %ecx
pushl %edx
pushl %edi
pushl %esi
pushl %ebp
push %ds
push %es
push %fs
pushl $0 # "error code"
lea 44(%esp),%edx
pushl %edx
movl $0x10,%edx
mov %dx,%ds
mov %dx,%es
mov %dx,%fs
call *%eax
addl $8,%esp
pop %fs
pop %es
pop %ds
popl %ebp
popl %esi
popl %edi
popl %edx
popl %ecx
popl %ebx
popl %eax
iret
debug:
pushl $do_int3 # _do_debug
jmp no_error_code
nmi:
pushl $do_nmi
jmp no_error_code
int3:
pushl $do_int3
jmp no_error_code
overflow:
pushl $do_overflow
jmp no_error_code
bounds:
pushl $do_bounds
jmp no_error_code
invalid_op:
pushl $do_invalid_op
jmp no_error_code
math_emulate:
popl %eax
pushl $do_device_not_available
jmp no_error_code
device_not_available:
pushl %eax
movl %cr0,%eax
bt $2,%eax # EM (math emulation bit)
jc math_emulate
clts # clear TS so that we can use math
movl current,%eax
cmpl last_task_used_math,%eax
je 1f # shouldn't happen really ...
pushl %ecx
pushl %edx
push %ds
movl $0x10,%eax
mov %ax,%ds
call math_state_restore
pop %ds
popl %edx
popl %ecx
1: popl %eax
iret
coprocessor_segment_overrun:
pushl $do_coprocessor_segment_overrun
jmp no_error_code
reserved:
pushl $do_reserved
jmp no_error_code
coprocessor_error:
pushl $do_coprocessor_error
jmp no_error_code
double_fault:
pushl $do_double_fault
error_code:
xchgl %eax,4(%esp) # error code <-> %eax
xchgl %ebx,(%esp) # &function <-> %ebx
pushl %ecx
pushl %edx
pushl %edi
pushl %esi
pushl %ebp
push %ds
push %es
push %fs
pushl %eax # error code
lea 44(%esp),%eax # offset
pushl %eax
movl $0x10,%eax
mov %ax,%ds
mov %ax,%es
mov %ax,%fs
call *%ebx
addl $8,%esp
pop %fs
pop %es
pop %ds
popl %ebp
popl %esi
popl %edi
popl %edx
popl %ecx
popl %ebx
popl %eax
iret
invalid_TSS:
pushl $do_invalid_TSS
jmp error_code
segment_not_present:
pushl $do_segment_not_present
jmp error_code
stack_segment:
pushl $do_stack_segment
jmp error_code
general_protection:
pushl $do_general_protection
jmp error_code
+565
Ver Arquivo
@@ -0,0 +1,565 @@
/*
* 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.
*
*/
/*
* 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.
*/
#include <linux/sched.h>
#include <linux/tty.h>
#include <asm/io.h>
#include <asm/system.h>
#define SCREEN_START 0xb8000
#define SCREEN_END 0xc0000
#define LINES 25
#define COLUMNS 80
#define NPAR 16
extern void keyboard_interrupt(void);
static unsigned long origin=SCREEN_START;
static unsigned long scr_end=SCREEN_START+LINES*COLUMNS*2;
static unsigned long pos;
static unsigned long x,y;
static unsigned long top=0,bottom=LINES;
static unsigned long lines=LINES,columns=COLUMNS;
static unsigned long state=0;
static unsigned long npar,par[NPAR];
static unsigned long ques=0;
static unsigned char attr=0x07;
/*
* this is what the terminal answers to a ESC-Z or csi0c
* query (= vt100 response).
*/
#define RESPONSE "\033[?1;2c"
static inline void gotoxy(unsigned int new_x,unsigned int new_y)
{
if (new_x>=columns || new_y>=lines)
return;
x=new_x;
y=new_y;
pos=origin+((y*columns+x)<<1);
}
static inline void set_origin(void)
{
cli();
outb_p(12,0x3d4);
outb_p(0xff&((origin-SCREEN_START)>>9),0x3d5);
outb_p(13,0x3d4);
outb_p(0xff&((origin-SCREEN_START)>>1),0x3d5);
sti();
}
static void scrup(void)
{
if (!top && bottom==lines) {
origin += columns<<1;
pos += columns<<1;
scr_end += columns<<1;
if (scr_end>SCREEN_END) {
int d0,d1,d2,d3;
__asm__ __volatile("cld\n\t"
"rep\n\t"
"movsl\n\t"
"movl %[columns],%1\n\t"
"rep\n\t"
"stosw"
:"=&a" (d0), "=&c" (d1), "=&D" (d2), "=&S" (d3)
:"0" (0x0720),
"1" ((lines-1)*columns>>1),
"2" (SCREEN_START),
"3" (origin),
[columns] "r" (columns)
:"memory");
scr_end -= origin-SCREEN_START;
pos -= origin-SCREEN_START;
origin = SCREEN_START;
} else {
int d0,d1,d2;
__asm__ __volatile("cld\n\t"
"rep\n\t"
"stosl"
:"=&a" (d0), "=&c" (d1), "=&D" (d2)
:"0" (0x07200720),
"1" (columns>>1),
"2" (scr_end-(columns<<1))
:"memory");
}
set_origin();
} else {
int d0,d1,d2,d3;
__asm__ __volatile__("cld\n\t"
"rep\n\t"
"movsl\n\t"
"movl %[columns],%%ecx\n\t"
"rep\n\t"
"stosw"
:"=&a" (d0), "=&c" (d1), "=&D" (d2), "=&S" (d3)
:"0" (0x0720),
"1" ((bottom-top-1)*columns>>1),
"2" (origin+(columns<<1)*top),
"3" (origin+(columns<<1)*(top+1)),
[columns] "r" (columns)
:"memory");
}
}
static void scrdown(void)
{
int d0,d1,d2,d3;
__asm__ __volatile__("std\n\t"
"rep\n\t"
"movsl\n\t"
"addl $2,%%edi\n\t" /* %edi has been decremented by 4 */
"movl %[columns],%%ecx\n\t"
"rep\n\t"
"stosw"
:"=&a" (d0), "=&c" (d1), "=&D" (d2), "=&S" (d3)
:"0" (0x0720),
"1" ((bottom-top-1)*columns>>1),
"2" (origin+(columns<<1)*bottom-4),
"3" (origin+(columns<<1)*(bottom-1)-4),
[columns] "r" (columns)
:"memory");
}
static void lf(void)
{
if (y+1<bottom) {
y++;
pos += columns<<1;
return;
}
scrup();
}
static void ri(void)
{
if (y>top) {
y--;
pos -= columns<<1;
return;
}
scrdown();
}
static void cr(void)
{
pos -= x<<1;
x=0;
}
static void del(void)
{
if (x) {
pos -= 2;
x--;
*(unsigned short *)pos = 0x0720;
}
}
static void csi_J(int par)
{
long count;
long start;
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 = columns*lines;
start = origin;
break;
default:
return;
}
int d0,d1,d2;
__asm__ __volatile__("cld\n\t"
"rep\n\t"
"stosw\n\t"
:"=&c" (d0), "=&D" (d1), "=&a" (d2)
:"0" (count),"1" (start),"2" (0x0720)
:"memory");
}
static void csi_K(int par)
{
long count;
long start;
switch (par) {
case 0: /* erase from cursor to end of line */
if (x>=columns)
return;
count = columns-x;
start = pos;
break;
case 1: /* erase from start of line to cursor */
start = pos - (x<<1);
count = (x<columns)?x:columns;
break;
case 2: /* erase whole line */
start = pos - (x<<1);
count = columns;
break;
default:
return;
}
int d0,d1,d2;
__asm__ __volatile__("cld\n\t"
"rep\n\t"
"stosw\n\t"
:"=&c" (d0), "=&D" (d1), "=&a" (d2)
:"0" (count),"1" (start),"2" (0x0720)
:"memory");
}
void csi_m(void)
{
int i;
for (i=0;i<=npar;i++)
switch (par[i]) {
case 0:attr=0x07;break;
case 1:attr=0x0f;break;
case 4:attr=0x0f;break;
case 7:attr=0x70;break;
case 27:attr=0x07;break;
}
}
static inline void set_cursor(void)
{
cli();
outb_p(14,0x3d4);
outb_p(0xff&((pos-SCREEN_START)>>9),0x3d5);
outb_p(15,0x3d4);
outb_p(0xff&((pos-SCREEN_START)>>1),0x3d5);
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=0x0720;
unsigned short * p = (unsigned short *) pos;
while (i++<columns) {
tmp=*p;
*p=old;
old=tmp;
p++;
}
}
static void insert_line(void)
{
int oldtop,oldbottom;
oldtop=top;
oldbottom=bottom;
top=y;
bottom=lines;
scrdown();
top=oldtop;
bottom=oldbottom;
}
static void delete_char(void)
{
int i;
unsigned short * p = (unsigned short *) pos;
if (x>=columns)
return;
i = x;
while (++i < columns) {
*p = *(p+1);
p++;
}
*p=0x0720;
}
static void delete_line(void)
{
int oldtop,oldbottom;
oldtop=top;
oldbottom=bottom;
top=y;
bottom=lines;
scrup();
top=oldtop;
bottom=oldbottom;
}
static void csi_at(int nr)
{
if (nr>columns)
nr=columns;
else if (!nr)
nr=1;
while (nr--)
insert_char();
}
static void csi_L(int nr)
{
if (nr>lines)
nr=lines;
else if (!nr)
nr=1;
while (nr--)
insert_line();
}
static void csi_P(int nr)
{
if (nr>columns)
nr=columns;
else if (!nr)
nr=1;
while (nr--)
delete_char();
}
static void csi_M(int nr)
{
if (nr>lines)
nr=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)
{
x=saved_x;
y=saved_y;
pos=origin+((y*columns+x)<<1);
}
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>=columns) {
x -= columns;
pos -= columns<<1;
lf();
}
__asm__("movb attr,%%ah\n\t"
"movw %%ax,%1\n\t"
::"a" (c),"m" (*(short *)pos)
/*:"ax"*/);
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>columns) {
x -= columns;
pos -= columns<<1;
lf();
}
c=9;
}
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<NPAR;npar++)
par[npar]=0;
npar=0;
state=3;
if ((ques=(c=='?')))
break;
case 3:
if (c==';' && npar<NPAR-1) {
npar++;
break;
} else if (c>='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]=lines;
if (par[0] < par[1] &&
par[1] <= 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.
*/
void con_init(void)
{
register unsigned char a;
gotoxy(*(unsigned char *)(0x90000+510),*(unsigned char *)(0x90000+511));
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);
}
+135
Ver Arquivo
@@ -0,0 +1,135 @@
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/tty.h>
#include <asm/segment.h>
int sys_pause(void);
int sys_close(int fd);
void release(struct task_struct * p)
{
int i;
if (!p)
return;
for (i=1 ; i<NR_TASKS ; i++)
if (task[i]==p) {
task[i]=NULL;
free_page((long)p);
schedule();
return;
}
panic("trying to release non-existent task");
}
static inline void send_sig(long sig,struct task_struct * p,int priv)
{
if (!p || sig<1 || sig>32)
return;
if (priv ||
current->uid==p->uid ||
current->euid==p->uid ||
current->uid==p->euid ||
current->euid==p->euid)
p->signal |= (1<<(sig-1));
}
void do_kill(long pid,long sig,int priv)
{
struct task_struct **p = NR_TASKS + task;
if (!pid) while (--p > &FIRST_TASK) {
if (*p && (*p)->pgrp == current->pid)
send_sig(sig,*p,priv);
} else if (pid>0) while (--p > &FIRST_TASK) {
if (*p && (*p)->pid == pid)
send_sig(sig,*p,priv);
} else if (pid == -1) while (--p > &FIRST_TASK)
send_sig(sig,*p,priv);
else while (--p > &FIRST_TASK)
if (*p && (*p)->pgrp == -pid)
send_sig(sig,*p,priv);
}
int sys_kill(int pid,int sig)
{
do_kill(pid,sig,!(current->uid || current->euid));
return 0;
}
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 ; i<NR_TASKS ; i++)
if (task[i] && task[i]->father == current->pid)
task[i]->father = 0;
for (i=0 ; i<NR_OPEN ; i++)
if (current->filp[i])
sys_close(i);
iput(current->pwd);
current->pwd=NULL;
iput(current->root);
current->root=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->father) {
current->state = TASK_ZOMBIE;
do_kill(current->father,SIGCHLD,1);
current->exit_code = code;
} else
release(current);
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,int * stat_addr, int options)
{
int flag=0;
struct task_struct ** p;
verify_area(stat_addr,4);
repeat:
for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
if (*p && *p != current &&
(pid==-1 || (*p)->pid==pid ||
(pid==0 && (*p)->pgrp==current->pgrp) ||
(pid<0 && (*p)->pgrp==-pid)))
if ((*p)->father == current->pid) {
flag=1;
if ((*p)->state==TASK_ZOMBIE) {
put_fs_long((*p)->exit_code,
(unsigned long *) stat_addr);
current->cutime += (*p)->utime;
current->cstime += (*p)->stime;
flag = (*p)->pid;
release(*p);
return flag;
}
}
if (flag) {
if (options & WNOHANG)
return 0;
sys_pause();
if (!(current->signal &= ~(1<<(SIGCHLD-1))))
goto repeat;
else
return -EINTR;
}
return -ECHILD;
}
+140
Ver Arquivo
@@ -0,0 +1,140 @@
/*
* 'fork.c' contains the help-routines for the 'fork' system call
* (see also system_call.s), and some misc functions ('verify_area').
* Fork is rather simple, once you get the hang of it, but the memory
* management can be a bitch. See 'mm/mm.c': 'copy_page_tables()'
*/
#include <errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/segment.h>
#include <asm/system.h>
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;
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;
#if 0 /* This statement breaks *p memory (gcc 4.4.5). */
*p = *current; /* NOTE! this doesn't copy the supervisor stack */
#else
memcpy(p, current, sizeof(struct task_struct));
#endif
p->state = TASK_RUNNING;
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__("fnsave %0"::"m" (p->tss.i387));
if (copy_mem(nr,p)) {
free_page((long) p);
return -EAGAIN;
}
for (i=0; i<NR_OPEN;i++)
if ((f=p->filp[i]))
f->f_count++;
if (current->pwd)
current->pwd->i_count++;
if (current->root)
current->root->i_count++;
set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss));
set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&(p->ldt));
task[nr] = p; /* 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 ; i<NR_TASKS ; i++)
if (task[i] && task[i]->pid == last_pid) goto repeat;
for(i=1 ; i<NR_TASKS ; i++)
if (!task[i])
return i;
return -EAGAIN;
}
+421
Ver Arquivo
@@ -0,0 +1,421 @@
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/hdreg.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/segment.h>
/*
* This code handles all hd-interrupts, and read/write requests to
* the hard-disk. It is relatively straigthforward (not obvious maybe,
* but interrupts never are), while still being efficient, and never
* disabling interrupts (except to overcome possible race-condition).
* The elevator block-seek algorithm doesn't need to disable interrupts
* due to clever programming.
*/
/* Max read/write errors/sector */
#define MAX_ERRORS 5
#define MAX_HD 2
#define NR_REQUEST 32
/*
* This struct defines the HD's and their types.
* Currently defined for CP3044's, ie a modified
* type 17.
*/
static struct hd_i_struct{
int head,sect,cyl,wpcom,lzone,ctl;
} hd_info[]= { HD_TYPE };
#define NR_HD ((sizeof (hd_info))/(sizeof (struct hd_i_struct)))
static struct hd_struct {
long start_sect;
long nr_sects;
} hd[5*MAX_HD]={{0,0},};
static struct hd_request {
int hd; /* -1 if no request */
int nsector;
int sector;
int head;
int cyl;
int cmd;
int errors;
struct buffer_head * bh;
struct hd_request * next;
} request[NR_REQUEST];
#define IN_ORDER(s1,s2) \
(((s1)->hd<(s2)->hd || (s1)->hd==(s2)->hd) && \
(((s1)->cyl<(s2)->cyl || (s1)->cyl==(s2)->cyl) && \
(((s1)->head<(s2)->head || (s1)->head==(s2)->head) && \
((s1)->sector<(s2)->sector))))
static struct hd_request * this_request = NULL;
static int sorting=0;
static void do_request(void);
static void reset_controller(void);
static void rw_abs_hd(int rw,unsigned int nr,unsigned int sec,unsigned int head,
unsigned int cyl,struct buffer_head * bh);
void hd_init(void);
#define port_read(port,buf,nr) \
__asm__("cld;rep;insw"::"d" (port),"D" (buf),"c" (nr)/*:"cx","di"*/)
#define port_write(port,buf,nr) \
__asm__("cld;rep;outsw"::"d" (port),"S" (buf),"c" (nr)/*:"cx","si"*/)
extern void hd_interrupt(void);
static struct task_struct * wait_for_request=NULL;
static inline void lock_buffer(struct buffer_head * bh)
{
if (bh->b_lock)
printk("hd.c: buffer multiply locked\n");
bh->b_lock=1;
}
static inline void unlock_buffer(struct buffer_head * bh)
{
if (!bh->b_lock)
printk("hd.c: free buffer being unlocked\n");
bh->b_lock=0;
wake_up(&bh->b_wait);
}
static inline void wait_on_buffer(struct buffer_head * bh)
{
cli();
while (bh->b_lock)
sleep_on(&bh->b_wait);
sti();
}
void rw_hd(int rw, struct buffer_head * bh)
{
unsigned int block,dev;
unsigned int sec,head,cyl;
block = bh->b_blocknr << 1;
dev = MINOR(bh->b_dev);
if (dev >= 5*NR_HD || block+2 > hd[dev].nr_sects)
return;
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));
rw_abs_hd(rw,dev,sec+1,head,cyl,bh);
}
/* This may be used only once, enforced by 'static int callable' */
int sys_setup(void)
{
static int callable = 1;
int i,drive;
struct partition *p;
if (!callable)
return -1;
callable = 0;
for (drive=0 ; drive<NR_HD ; drive++) {
rw_abs_hd(READ,drive,1,0,0,(struct buffer_head *) start_buffer);
if (!start_buffer->b_uptodate) {
printk("Unable to read partition table of drive %d\n\r",
drive);
panic("");
}
if (start_buffer->b_data[510] != 0x55 || (unsigned char)
start_buffer->b_data[511] != 0xAA) {
printk("Bad partition table on drive %d\n\r",drive);
panic("");
}
p = 0x1BE + (void *)start_buffer->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;
}
}
printk("Partition table%s ok.\n\r",(NR_HD>1)?"s":"");
mount_root();
return (0);
}
/*
* This is the pointer to a routine to be executed at every hd-interrupt.
* Interesting way of doing things, but should be rather practical.
*/
void (*do_hd)(void) = NULL;
static int controller_ready(void)
{
int retries=1000;
while (--retries && (inb(HD_STATUS)&0xc0)!=0x40);
return (retries);
}
static int win_result(void)
{
int i=inb(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(_CTL,HD_CMD);
port=HD_DATA;
outb_p(_WPCOM,++port);
outb_p(nsect,++port);
outb_p(sect,++port);
outb_p(cyl,++port);
outb_p(cyl>>8,++port);
/*0xB0 for slave, 0xA0 for master*/
outb_p(0xB0|(drive<<4)|head,++port);
outb(cmd,++port);
}
static int drive_busy(void)
{
unsigned int i;
for (i = 0; i < 100000; i++)
if (READY_STAT == (inb(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 < 1000; i++) nop();
outb(0,HD_CMD);
for(i = 0; i < 10000 && drive_busy(); i++) /* nothing */;
if (drive_busy())
printk("HD-controller still busy\n\r");
if((i = inb(HD_STATUS)) & ERR_STAT)
printk("HD-controller reset failed: %02x\n\r",i);
}
static void reset_hd(int nr)
{
reset_controller();
hd_out(nr,_SECT,_SECT,_HEAD-1,_CYL,WIN_SPECIFY,&do_request);
}
void unexpected_hd_interrupt(void)
{
panic("Unexpected HD interrupt\n\r");
}
static void bad_rw_intr(void)
{
int i = this_request->hd;
if (this_request->errors++ >= MAX_ERRORS) {
this_request->bh->b_uptodate = 0;
unlock_buffer(this_request->bh);
wake_up(&wait_for_request);
this_request->hd = -1;
this_request=this_request->next;
}
reset_hd(i);
}
static void read_intr(void)
{
if (win_result()) {
bad_rw_intr();
return;
}
if (this_request->nsector==2){
this_request->nsector--;
port_read(HD_DATA,this_request->bh->b_data,256);
}
else{
port_read(HD_DATA,this_request->bh->b_data+512,256);
return;
}
this_request->errors = 0;
this_request->bh->b_uptodate = 1;
this_request->bh->b_dirt = 0;
wake_up(&wait_for_request);
unlock_buffer(this_request->bh);
this_request->hd = -1;
this_request=this_request->next;
do_request();
}
static void write_intr(void)
{
if (win_result()) {
bad_rw_intr();
return;
}
if (--this_request->nsector) {
port_write(HD_DATA,this_request->bh->b_data+512,256);
return;
}
this_request->bh->b_uptodate = 1;
this_request->bh->b_dirt = 0;
wake_up(&wait_for_request);
unlock_buffer(this_request->bh);
this_request->hd = -1;
this_request=this_request->next;
do_request();
}
static void do_request(void)
{
int i,r;
if (sorting)
return;
if (!this_request) {
do_hd=NULL;
return;
}
if (this_request->cmd == WIN_WRITE) {
hd_out(this_request->hd,this_request->nsector,this_request->
sector,this_request->head,this_request->cyl,
this_request->cmd,&write_intr);
for(i=0 ; i<3000 && !(r=inb_p(HD_STATUS)&DRQ_STAT) ; i++)
/* nothing */ ;
if (!r) {
reset_hd(this_request->hd);
return;
}
port_write(HD_DATA,this_request->bh->b_data+
512*(this_request->nsector&1),256);
} else if (this_request->cmd == WIN_READ) {
hd_out(this_request->hd,this_request->nsector,this_request->
sector,this_request->head,this_request->cyl,
this_request->cmd,&read_intr);
} else
panic("unknown hd-command");
}
/*
* add-request adds a request to the linked list.
* It sets the 'sorting'-variable when doing something
* that interrupts shouldn't touch.
*/
static void add_request(struct hd_request * req)
{
struct hd_request * tmp;
if (req->nsector != 2)
panic("nsector!=2 not implemented");
/*
* Not to mess up the linked lists, we never touch the two first
* entries (not this_request, as it is used by current interrups,
* and not this_request->next, as it can be assigned to this_request).
* This is not too high a price to pay for the ability of not
* disabling interrupts.
*/
sorting=1;
if (!(tmp=this_request))
this_request=req;
else {
if (!(tmp->next))
tmp->next=req;
else {
tmp=tmp->next;
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;
}
}
sorting=0;
/*
* NOTE! As a result of sorting, the interrupts may have died down,
* as they aren't redone due to locking with sorting=1. They might
* also never have started, if this is the first request in the queue,
* so we restart them if necessary.
*/
if (!do_hd)
do_request();
}
void rw_abs_hd(int rw,unsigned int nr,unsigned int sec,unsigned int head,
unsigned int cyl,struct buffer_head * bh)
{
struct hd_request * req;
if (rw!=READ && rw!=WRITE)
panic("Bad hd command, must be R/W");
lock_buffer(bh);
repeat:
for (req=0+request ; req<NR_REQUEST+request ; req++)
if (req->hd<0)
break;
if (req==NR_REQUEST+request) {
sleep_on(&wait_for_request);
goto repeat;
}
req->hd=nr;
req->nsector=2;
req->sector=sec;
req->head=head;
req->cyl=cyl;
req->cmd = ((rw==READ)?WIN_READ:WIN_WRITE);
req->bh=bh;
req->errors=0;
req->next=NULL;
add_request(req);
wait_on_buffer(bh);
}
void hd_init(void)
{
int i;
for (i=0 ; i<NR_REQUEST ; i++) {
request[i].hd = -1;
request[i].next = NULL;
}
for (i=0 ; i<NR_HD ; i++) {
hd[i*5].start_sect = 0;
hd[i*5].nr_sects = hd_info[i].head*
hd_info[i].sect*hd_info[i].cyl;
}
set_trap_gate(0x2E,&hd_interrupt);
outb_p(inb_p(0x21)&0xfb,0x21);
outb(inb_p(0xA1)&0xbf,0xA1);
}
+409
Ver Arquivo
@@ -0,0 +1,409 @@
/*
* keyboard.s
*/
.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
num_table:
.ascii "789 456 1230,"
cur_table:
.ascii "HA5 DGC YB623"
/*
* this routine handles function keys
*/
func:
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
key_map:
.byte 0,27
.ascii "1234567890+'"
.byte 127,9
.ascii "qwertyuiop}"
.byte 0,10,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 10,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 '~,10,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
/*
* 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 $'z,%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
+52
Ver Arquivo
@@ -0,0 +1,52 @@
#include <time.h>
/*
* 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;
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;
}
+11
Ver Arquivo
@@ -0,0 +1,11 @@
/*
* This function is used through-out the kernel (includeinh mm and fs)
* to indicate a major problem.
*/
#include <linux/kernel.h>
void panic(const char * s)
{
printk("Kernel panic: %s\n\r",s);
for(;;);
}
+34
Ver Arquivo
@@ -0,0 +1,34 @@
/*
* 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 <stdarg.h>
#include <stddef.h>
#include <linux/kernel.h>
extern int vsprintf();
static char buf[1024];
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;
}
+141
Ver Arquivo
@@ -0,0 +1,141 @@
/*
* rs_io.s
*
* This module implements the rs232 io interrupts.
*/
.text
.globl rs1_interrupt,rs2_interrupt
size = 1024 /* must be power of two !
and must match the value
in tty_io.c!!! */
/* these are the offsets into the read/write buffer structures */
rs_addr = 0
head = 4
tail = 8
proc_list = 12
buf = 16
startup = 256 /* chars left in write queue when we restart it */
/*
* These are the actual interrupt routines. They look where
* the interrupt is coming from, and take appropriate action.
*/
.align 2
rs1_interrupt:
pushl $table_list+8
jmp rs_int
.align 2
rs2_interrupt:
pushl $table_list+16
rs_int:
pushl %edx
pushl %ecx
pushl %ebx
pushl %eax
push %es
push %ds /* as this is an interrupt, we cannot */
pushl $0x10 /* know that bs is ok. Load it */
pop %ds
pushl $0x10
pop %es
movl 24(%esp),%edx
movl (%edx),%edx
movl rs_addr(%edx),%edx
addl $2,%edx /* interrupt ident. reg */
rep_int:
xorl %eax,%eax
inb %dx,%al
testb $1,%al
jne end
cmpb $6,%al /* this shouldn't happen, but ... */
ja end
movl 24(%esp),%ecx
pushl %edx
subl $2,%edx
call *jmp_table(,%eax,2) /* NOTE! not *4, bit0 is 0 already */
popl %edx
jmp rep_int
end: movb $0x20,%al
outb %al,$0x20 /* EOI */
pop %ds
pop %es
popl %eax
popl %ebx
popl %ecx
popl %edx
addl $4,%esp # jump over _table_list entry
iret
jmp_table:
.long modem_status,write_char,read_char,line_status
.align 2
modem_status:
addl $6,%edx /* clear intr by reading modem status reg */
inb %dx,%al
ret
.align 2
line_status:
addl $5,%edx /* clear intr by reading line status reg. */
inb %dx,%al
ret
.align 2
read_char:
inb %dx,%al
movl %ecx,%edx
subl $table_list,%edx
shrl $3,%edx
movl (%ecx),%ecx # read-queue
movl head(%ecx),%ebx
movb %al,buf(%ecx,%ebx)
incl %ebx
andl $size-1,%ebx
cmpl tail(%ecx),%ebx
je 1f
movl %ebx,head(%ecx)
pushl %edx
call do_tty_interrupt
addl $4,%esp
1: ret
.align 2
write_char:
movl 4(%ecx),%ecx # write-queue
movl head(%ecx),%ebx
subl tail(%ecx),%ebx
andl $size-1,%ebx # nr chars in queue
je write_buffer_empty
cmpl $startup,%ebx
ja 1f
movl proc_list(%ecx),%ebx # wake up sleeping process
testl %ebx,%ebx # is there any?
je 1f
movl $0,(%ebx)
1: movl tail(%ecx),%ebx
movb buf(%ecx,%ebx),%al
outb %al,%dx
incl %ebx
andl $size-1,%ebx
movl %ebx,tail(%ecx)
cmpl head(%ecx),%ebx
je write_buffer_empty
ret
.align 2
write_buffer_empty:
movl proc_list(%ecx),%ebx # wake up sleeping process
testl %ebx,%ebx # is there any?
je 1f
movl $0,(%ebx)
1: incl %edx
inb %dx,%al
jmp 1f
1: jmp 1f
1: andb $0xd,%al /* disable transmit interrupt */
outb %al,%dx
ret
+254
Ver Arquivo
@@ -0,0 +1,254 @@
/*
* '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 <linux/sched.h>
#include <linux/kernel.h>
#include <signal.h>
#include <linux/sys.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/segment.h>
#define LATCH (1193180/HZ)
extern void mem_use(void);
extern int timer_interrupt(void);
extern int system_call(void);
union task_union {
struct task_struct task;
char stack[PAGE_SIZE];
};
static union task_union init_task = {INIT_TASK,};
long volatile jiffies=0;
long startup_time=0;
struct task_struct *current = &(init_task.task), *last_task_used_math = NULL;
struct task_struct * task[NR_TASKS] = {&(init_task.task), };
long user_stack [ PAGE_SIZE>>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)
__asm__("fnsave %0"::"m" (last_task_used_math->tss.i387));
if (current->used_math)
__asm__("frstor %0"::"m" (current->tss.i387));
else {
__asm__("fninit"::);
current->used_math=1;
}
last_task_used_math=current;
}
/*
* '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 && (*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;
}
}
void do_timer(long cpl)
{
if (cpl)
current->utime++;
else
current->stime++;
if ((--current->counter)>0) return;
current->counter=0;
if (!cpl) return;
schedule();
}
int sys_alarm(long seconds)
{
current->alarm = (seconds>0)?(jiffies+HZ*seconds):0;
return seconds;
}
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;
}
int sys_signal(long signal,long addr,long restorer)
{
long i;
switch (signal) {
case SIGHUP: case SIGINT: case SIGQUIT: case SIGILL:
case SIGTRAP: case SIGABRT: case SIGFPE: case SIGUSR1:
case SIGSEGV: case SIGUSR2: case SIGPIPE: case SIGALRM:
case SIGCHLD:
i=(long) current->sig_fn[signal-1];
current->sig_fn[signal-1] = (fn_ptr) addr;
current->sig_restorer = (fn_ptr) restorer;
return i;
default: return -1;
}
}
void sched_init(void)
{
int i;
struct desc_struct * p;
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;i<NR_TASKS;i++) {
task[i] = NULL;
p->a=p->b=0;
p++;
p->a=p->b=0;
p++;
}
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);
}
+53
Ver Arquivo
@@ -0,0 +1,53 @@
/*
* serial.c
*
* This module implements the rs232 io functions
* void rs_write(struct tty_struct * queue);
* void rs_init(void);
* and all interrupts pertaining to serial IO.
*/
#include <linux/tty.h>
#include <linux/sched.h>
#include <asm/system.h>
#include <asm/io.h>
#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();
}
+237
Ver Arquivo
@@ -0,0 +1,237 @@
#include <errno.h>
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/kernel.h>
#include <asm/segment.h>
#include <sys/times.h>
#include <sys/utsname.h>
int sys_ftime()
{
return -ENOSYS;
}
int sys_mknod()
{
return -ENOSYS;
}
int sys_break()
{
return -ENOSYS;
}
int sys_mount()
{
return -ENOSYS;
}
int sys_umount()
{
return -ENOSYS;
}
int sys_ustat(int dev,struct ustat * ubuf)
{
return -1;
}
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_setgid(int gid)
{
if (current->euid && current->uid)
if (current->gid==gid || current->sgid==gid)
current->egid=gid;
else
return -EPERM;
else
current->gid=current->egid=gid;
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;
}
int sys_setuid(int uid)
{
if (current->euid && current->uid)
if (uid==current->uid || current->suid==current->uid)
current->euid=uid;
else
return -EPERM;
else
current->euid=current->uid=uid;
return 0;
}
int sys_stime(long * tptr)
{
if (current->euid && current->uid)
return -1;
startup_time = get_fs_long((unsigned long *)tptr) - jiffies/HZ;
return 0;
}
int sys_times(struct tms * tbuf)
{
if (!tbuf)
return jiffies;
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 = pid;
for (i=0 ; i<NR_TASKS ; i++)
if (task[i] && task[i]->pid==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->uid && current->euid)
return -EPERM;
if (current->leader)
return -EPERM;
current->leader = 1;
current->session = current->pgrp = current->pid;
current->tty = -1;
return current->pgrp;
}
int sys_oldolduname(void* v)
{
printk("calling obsolete system call oldolduname\n");
return -ENOSYS;
// return (0);
}
int sys_uname(struct utsname * name)
{
static struct utsname thisname = {
"linux 0.01-3.x","nodename","release ","3.x","i386"
};
int i;
if (!name) return -1;
verify_area(name,sizeof *name);
for(i=0;i<sizeof *name;i++)
put_fs_byte(((char *) &thisname)[i],i+(char *) name);
return (0);
}
int sys_umask(int mask)
{
int old = current->umask;
current->umask = mask & 0777;
return (old);
}
int sys_null(int nr)
{
static int prev_nr=-2;
if (nr==174 || nr==175) return -ENOSYS;
if (prev_nr!=nr)
{
prev_nr=nr;
// printk("system call num %d not available\n",nr);
}
return -ENOSYS;
}
+227
Ver Arquivo
@@ -0,0 +1,227 @@
/*
* 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-interrupt is 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
restorer = 16 # address of info-restorer
sig_fn = 20 # table of 32 signal addresses
nr_system_calls = 319
.globl system_call,sys_fork,timer_interrupt,hd_interrupt,sys_execve
.align 2
bad_sys_call:
movl $-1,%eax
iret
.align 2
reschedule:
pushl $ret_from_sys_call
jmp schedule
.align 2
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
movl sys_call_table(,%eax,4),%edx # if sys_null
cmpl $sys_null,%edx # then the syscall is not
jne 1f # implemented.
popl %edx # 1st argument is syscall nr
pushl %eax
1:
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
movl CS(%esp),%ebx # was old code segment supervisor
testl $3,%ebx # mode? If so - don't check signals
je 3f
cmpw $0x17,OLDSS(%esp) # was stack segment = 0x17 ?
jne 3f
2: movl signal(%eax),%ebx # signals (bitmap, 32 signals)
bsfl %ebx,%ecx # %ecx is signal nr, return if none
je 3f
btrl %ecx,%ebx # clear it
movl %ebx,signal(%eax)
movl sig_fn(%eax,%ecx,4),%ebx # %ebx is signal handler address
cmpl $1,%ebx
jb default_signal # 0 is default signal handler - exit
je 2b # 1 is ignore - find next signal
movl $0,sig_fn(%eax,%ecx,4) # reset signal handler address
incl %ecx
xchgl %ebx,EIP(%esp) # put new return address on stack
subl $28,OLDESP(%esp)
movl OLDESP(%esp),%edx # push old return address on stack
pushl %eax # but first check that it's ok.
pushl %ecx
pushl $28
pushl %edx
call verify_area
popl %edx
addl $4,%esp
popl %ecx
popl %eax
movl restorer(%eax),%eax
movl %eax,%fs:(%edx) # flag/reg restorer
movl %ecx,%fs:4(%edx) # signal nr
movl EAX(%esp),%eax
movl %eax,%fs:8(%edx) # old eax
movl ECX(%esp),%eax
movl %eax,%fs:12(%edx) # old ecx
movl EDX(%esp),%eax
movl %eax,%fs:16(%edx) # old edx
movl EFLAGS(%esp),%eax
movl %eax,%fs:20(%edx) # old eflags
movl %ebx,%fs:24(%edx) # old return addr
3: popl %eax
popl %ebx
popl %ecx
popl %edx
pop %fs
pop %es
pop %ds
iret
default_signal:
incl %ecx
cmpl $SIG_CHLD,%ecx
je 2b
pushl %ecx
call do_exit # remember to set bit 7 when dumping core
addl $4,%esp
jmp 3b
.align 2
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 2
sys_execve:
lea EIP(%esp),%eax
pushl %eax
call do_execve
addl $4,%esp
ret
.align 2
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,$0x20 # EOI to interrupt controller #1
jmp 1f # give port chance to breathe
1: jmp 1f
1: outb %al,$0xA0 # same to controller #2
movl do_hd,%eax
testl %eax,%eax
jne 1f
movl $unexpected_hd_interrupt,%eax
1: call *%eax # "interesting" way of handling intr.
pop %fs
pop %es
pop %ds
popl %edx
popl %ecx
popl %eax
iret
+199
Ver Arquivo
@@ -0,0 +1,199 @@
/*
* '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 <string.h>
#include <linux/head.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/system.h>
#include <asm/segment.h>
#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);
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)
{
die("coprocessor error",esp,error_code);
}
void do_reserved(long esp, long error_code)
{
die("reserved (15,17-31) error",esp,error_code);
}
void trap_init(void)
{
int i;
set_trap_gate(0,&divide_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<32;i++)
set_trap_gate(i,&reserved);
/* __asm__("movl $0x3ff000,%%eax\n\t"
"movl %%eax,%%db0\n\t"
"movl $0x000d0303,%%eax\n\t"
"movl %%eax,%%db7"
:::"ax");*/
}
+307
Ver Arquivo
@@ -0,0 +1,307 @@
/*
* 'tty_io.c' gives an orthogonal feeling to tty's, be they consoles
* or rs-channels. It also implements echoing, cooked mode etc (well,
* not currently, but ...)
*/
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#define ALRMMASK (1<<(SIGALRM-1))
#include <linux/sched.h>
#include <linux/tty.h>
#include <asm/segment.h>
#include <asm/system.h>
#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[] = {
{
{0,
OPOST|ONLCR, /* change outgoing NL to CRNL */
0,
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, /*IGNCR*/
OPOST | ONLRET, /* change outgoing NL to CR */
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, /*IGNCR*/
OPOST | ONLRET, /* change outgoing NL to CR */
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 signal)
{
int i;
if (tty->pgrp <= 0)
return;
for (i=0;i<NR_TASKS;i++)
if (task[i] && task[i]->pgrp==tty->pgrp)
task[i]->signal |= 1<<(signal-1);
}
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 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==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,SIGINT);
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 = (unsigned) 10*tty->termios.c_cc[VTIME];
minimum = (unsigned) tty->termios.c_cc[VMIN];
if (time && !minimum) {
minimum=1;
if ((flag=(!oldalarm || time+jiffies<oldalarm)))
current->alarm = 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+jiffies<oldalarm)))
current->alarm = 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 int 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.
*/
void do_tty_interrupt(int tty)
{
copy_to_cooked(tty_table+tty);
}
+229
Ver Arquivo
@@ -0,0 +1,229 @@
/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
/*
* Wirzenius wrote this portably, Torvalds fucked it up :-)
*/
#include <stdarg.h>
#include <string.h>
/* 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(i<precision--)
*str++ = '0';
while(i-->0)
*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;
}
+44
Ver Arquivo
@@ -0,0 +1,44 @@
#
# Makefile for some libs needed in the kernel.
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
AR =ar
AS =as --32
LD =ld -m elf_i386
LDFLAGS =-g #-s -x
CC =gcc
CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer -m32\
-finline-functions -fno-stack-protector -nostdinc -fno-builtin -g -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 = ctype.o _exit.o open.o close.o errno.o write.o dup.o setsid.o \
execve.o wait.o string.o
lib.a: $(OBJS)
$(AR) rcs lib.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:
+7
Ver Arquivo
@@ -0,0 +1,7 @@
#define __LIBRARY__
#include <unistd.h>
void _exit(int exit_code)
{
__asm__("int $0x80"::"a" (__NR_exit),"b" (exit_code));
}
+4
Ver Arquivo
@@ -0,0 +1,4 @@
#define __LIBRARY__
#include <unistd.h>
_syscall1(int,close,int,fd)
+29
Ver Arquivo
@@ -0,0 +1,29 @@
#include <ctype.h>
signed 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 */
+4
Ver Arquivo
@@ -0,0 +1,4 @@
#define __LIBRARY__
#include <unistd.h>
_syscall1(int,dup,int,fd)
+1
Ver Arquivo
@@ -0,0 +1 @@
int errno;
+4
Ver Arquivo
@@ -0,0 +1,4 @@
#define __LIBRARY__
#include <unistd.h>
_syscall3(int,execve,const char *,file,char **,argv,char **,envp)
+19
Ver Arquivo
@@ -0,0 +1,19 @@
#define __LIBRARY__
#include <unistd.h>
#include <stdarg.h>
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;
}
+4
Ver Arquivo
@@ -0,0 +1,4 @@
#define __LIBRARY__
#include <unistd.h>
_syscall0(pid_t,setsid)
+8
Ver Arquivo
@@ -0,0 +1,8 @@
#ifndef __GNUC__
#error I want gcc!
#endif
#define extern
#define inline
#define __LIBRARY__
#include <string.h>
+10
Ver Arquivo
@@ -0,0 +1,10 @@
#define __LIBRARY__
#include <unistd.h>
#include <sys/wait.h>
_syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
pid_t wait(int * wait_stat)
{
return waitpid(-1,wait_stat,0);
}
+4
Ver Arquivo
@@ -0,0 +1,4 @@
#define __LIBRARY__
#include <unistd.h>
_syscall3(int,write,int,fd,const char *,buf,off_t,count)
+271
Ver Arquivo
@@ -0,0 +1,271 @@
diff -rc linux-0.01-rm-3.5.orig/fs/Makefile linux-0.01-rm-3.5/fs/Makefile
*** linux-0.01-rm-3.5.orig/fs/Makefile 2008-01-14 05:58:48.000000000 +0900
--- linux-0.01-rm-3.5/fs/Makefile 2011-01-12 15:19:16.412242974 +0900
***************
*** 3,9 ****
CC =gcc
LD =ld
CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer \
! -fno-stack-protector -nostdinc -I../include
CPP =gcc -E -nostdinc -I../include
.c.s:
--- 3,9 ----
CC =gcc
LD =ld
CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer \
! -fno-stack-protector -nostdinc -fno-builtin -g -I../include
CPP =gcc -E -nostdinc -I../include
.c.s:
diff -rc linux-0.01-rm-3.5.orig/fs/stat.c linux-0.01-rm-3.5/fs/stat.c
*** linux-0.01-rm-3.5.orig/fs/stat.c 2008-01-14 05:58:48.000000000 +0900
--- linux-0.01-rm-3.5/fs/stat.c 2011-01-10 22:17:58.000062644 +0900
***************
*** 102,108 ****
int sys_lstat64(char* filename, struct stat * statbuf)
{
! return sys_stat64(filename,statbuf);
}
int sys_oldstat()
--- 102,108 ----
int sys_lstat64(char* filename, struct stat * statbuf)
{
! return sys_stat64(filename, (struct stat64 *)statbuf);
}
int sys_oldstat()
diff -rc linux-0.01-rm-3.5.orig/include/asm/segment.h linux-0.01-rm-3.5/include/asm/segment.h
*** linux-0.01-rm-3.5.orig/include/asm/segment.h 2008-01-14 05:58:48.000000000 +0900
--- linux-0.01-rm-3.5/include/asm/segment.h 2011-01-12 14:13:26.278253365 +0900
***************
*** 24,30 ****
extern inline void put_fs_byte(char val,char *addr)
{
! __asm__ ("movb %0,%%fs:%1"::"r" (val),"m" (*addr));
}
extern inline void put_fs_word(short val,short * addr)
--- 24,30 ----
extern inline void put_fs_byte(char val,char *addr)
{
! __asm__ ("movb %0,%%fs:%1"::"q" (val),"m" (*addr));
}
extern inline void put_fs_word(short val,short * addr)
diff -rc linux-0.01-rm-3.5.orig/kernel/console.c linux-0.01-rm-3.5/kernel/console.c
*** linux-0.01-rm-3.5.orig/kernel/console.c 2008-01-14 05:58:48.000000000 +0900
--- linux-0.01-rm-3.5/kernel/console.c 2011-01-12 15:22:17.037152184 +0900
***************
*** 76,89 ****
__asm__ __volatile("cld\n\t"
"rep\n\t"
"movsl\n\t"
! "movl columns,%1\n\t"
"rep\n\t"
"stosw"
:"=&a" (d0), "=&c" (d1), "=&D" (d2), "=&S" (d3)
:"0" (0x0720),
"1" ((lines-1)*columns>>1),
"2" (SCREEN_START),
! "3" (origin)
:"memory");
scr_end -= origin-SCREEN_START;
--- 76,90 ----
__asm__ __volatile("cld\n\t"
"rep\n\t"
"movsl\n\t"
! "movl %[columns],%1\n\t"
"rep\n\t"
"stosw"
:"=&a" (d0), "=&c" (d1), "=&D" (d2), "=&S" (d3)
:"0" (0x0720),
"1" ((lines-1)*columns>>1),
"2" (SCREEN_START),
! "3" (origin),
! [columns] "r" (columns)
:"memory");
scr_end -= origin-SCREEN_START;
***************
*** 106,119 ****
__asm__ __volatile__("cld\n\t"
"rep\n\t"
"movsl\n\t"
! "movl columns,%%ecx\n\t"
"rep\n\t"
"stosw"
:"=&a" (d0), "=&c" (d1), "=&D" (d2), "=&S" (d3)
:"0" (0x0720),
"1" ((bottom-top-1)*columns>>1),
"2" (origin+(columns<<1)*top),
! "3" (origin+(columns<<1)*(top+1))
:"memory");
}
}
--- 107,121 ----
__asm__ __volatile__("cld\n\t"
"rep\n\t"
"movsl\n\t"
! "movl %[columns],%%ecx\n\t"
"rep\n\t"
"stosw"
:"=&a" (d0), "=&c" (d1), "=&D" (d2), "=&S" (d3)
:"0" (0x0720),
"1" ((bottom-top-1)*columns>>1),
"2" (origin+(columns<<1)*top),
! "3" (origin+(columns<<1)*(top+1)),
! [columns] "r" (columns)
:"memory");
}
}
***************
*** 125,138 ****
"rep\n\t"
"movsl\n\t"
"addl $2,%%edi\n\t" /* %edi has been decremented by 4 */
! "movl columns,%%ecx\n\t"
"rep\n\t"
"stosw"
:"=&a" (d0), "=&c" (d1), "=&D" (d2), "=&S" (d3)
:"0" (0x0720),
"1" ((bottom-top-1)*columns>>1),
"2" (origin+(columns<<1)*bottom-4),
! "3" (origin+(columns<<1)*(bottom-1)-4)
:"memory");
}
--- 127,141 ----
"rep\n\t"
"movsl\n\t"
"addl $2,%%edi\n\t" /* %edi has been decremented by 4 */
! "movl %[columns],%%ecx\n\t"
"rep\n\t"
"stosw"
:"=&a" (d0), "=&c" (d1), "=&D" (d2), "=&S" (d3)
:"0" (0x0720),
"1" ((bottom-top-1)*columns>>1),
"2" (origin+(columns<<1)*bottom-4),
! "3" (origin+(columns<<1)*(bottom-1)-4),
! [columns] "r" (columns)
:"memory");
}
diff -rc linux-0.01-rm-3.5.orig/kernel/fork.c linux-0.01-rm-3.5/kernel/fork.c
*** linux-0.01-rm-3.5.orig/kernel/fork.c 2008-01-14 05:58:48.000000000 +0900
--- linux-0.01-rm-3.5/kernel/fork.c 2011-01-12 15:14:01.272244170 +0900
***************
*** 70,76 ****
--- 70,80 ----
p = (struct task_struct *) get_free_page();
if (!p)
return -EAGAIN;
+ #if 0 /* This statement breaks *p memory (gcc 4.4.5). */
*p = *current; /* NOTE! this doesn't copy the supervisor stack */
+ #else
+ memcpy(p, current, sizeof(struct task_struct));
+ #endif
p->state = TASK_RUNNING;
p->pid = last_pid;
p->father = current->pid;
diff -rc linux-0.01-rm-3.5.orig/kernel/Makefile linux-0.01-rm-3.5/kernel/Makefile
*** linux-0.01-rm-3.5.orig/kernel/Makefile 2008-01-14 05:58:48.000000000 +0900
--- linux-0.01-rm-3.5/kernel/Makefile 2011-01-12 15:22:49.318242168 +0900
***************
*** 9,18 ****
AR =ar
AS =as
LD =ld
! LDFLAGS =-s -x
CC =gcc
CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer \
! -finline-functions -fno-stack-protector -nostdinc -I../include
CPP =gcc -E -nostdinc -I../include
.c.s:
--- 9,18 ----
AR =ar
AS =as
LD =ld
! LDFLAGS =-g #-s -x
CC =gcc
CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer \
! -finline-functions -fno-stack-protector -nostdinc -fno-builtin -g -I../include
CPP =gcc -E -nostdinc -I../include
.c.s:
diff -rc linux-0.01-rm-3.5.orig/lib/Makefile linux-0.01-rm-3.5/lib/Makefile
*** linux-0.01-rm-3.5.orig/lib/Makefile 2008-01-14 05:58:48.000000000 +0900
--- linux-0.01-rm-3.5/lib/Makefile 2011-01-12 15:20:03.508243026 +0900
***************
*** 9,18 ****
AR =ar
AS =as
LD =ld
! LDFLAGS =-s -x
CC =gcc
CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer \
! -finline-functions -fno-stack-protector -nostdinc -I../include
CPP =gcc -E -nostdinc -I../include
.c.s:
--- 9,18 ----
AR =ar
AS =as
LD =ld
! LDFLAGS =-g #-s -x
CC =gcc
CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer \
! -finline-functions -fno-stack-protector -nostdinc -fno-builtin -g -I../include
CPP =gcc -E -nostdinc -I../include
.c.s:
diff -rc linux-0.01-rm-3.5.orig/Makefile linux-0.01-rm-3.5/Makefile
*** linux-0.01-rm-3.5.orig/Makefile 2008-01-24 22:17:39.000000000 +0900
--- linux-0.01-rm-3.5/Makefile 2011-01-12 15:19:49.900242989 +0900
***************
*** 10,18 ****
AS =as
LD =ld
! LDFLAGS =-s -x -M -Ttext 0 -e startup_32
CC =gcc
! CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer -fno-stack-protector
CPP =gcc -E -nostdinc -Iinclude
ARCHIVES=kernel/kernel.o mm/mm.o fs/fs.o
--- 10,19 ----
AS =as
LD =ld
! LDFLAGS =-M -Ttext 0 -e startup_32
! #LDFLAGS =-s -x -M -Ttext 0 -e startup_32
CC =gcc
! CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer -fno-stack-protector -fno-builtin -g
CPP =gcc -E -nostdinc -Iinclude
ARCHIVES=kernel/kernel.o mm/mm.o fs/fs.o
diff -rc linux-0.01-rm-3.5.orig/mm/Makefile linux-0.01-rm-3.5/mm/Makefile
*** linux-0.01-rm-3.5.orig/mm/Makefile 2008-01-14 05:58:48.000000000 +0900
--- linux-0.01-rm-3.5/mm/Makefile 2011-01-12 15:18:38.900966175 +0900
***************
*** 1,6 ****
CC =gcc
CFLAGS =-O -Wall -fstrength-reduce -fomit-frame-pointer \
! -fno-stack-protector -finline-functions -nostdinc -I../include
AS =as
AR =ar
LD =ld
--- 1,6 ----
CC =gcc
CFLAGS =-O -Wall -fstrength-reduce -fomit-frame-pointer \
! -fno-stack-protector -finline-functions -nostdinc -fno-builtin -g -I../include
AS =as
AR =ar
LD =ld
Arquivo binário não exibido.
+37
Ver Arquivo
@@ -0,0 +1,37 @@
CC =gcc
CFLAGS =-O -Wall -fstrength-reduce -fomit-frame-pointer -m32 \
-fno-stack-protector -finline-functions -nostdinc -fno-builtin -g -I../include
AS =as --32
AR =ar
LD =ld -m elf_i386
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/linux/config.h ../include/linux/head.h ../include/linux/kernel.h \
../include/asm/system.h
+278
Ver Arquivo
@@ -0,0 +1,278 @@
#include <signal.h>
#include <linux/config.h>
#include <linux/head.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <asm/system.h>
int do_exit(long code);
inline void invalidate()
{
int d0;
__asm__ __volatile(
"movl %%eax,%%cr3"
:"=&a" (d0)
:"0" (0) );
}
#if (BUFFER_END < 0x100000)
#define LOW_MEM 0x100000
#else
#define LOW_MEM BUFFER_END
#endif
/* these are not to be changed - thay are calculated from the above */
#define PAGING_MEMORY (HIGH_MEMORY - LOW_MEM)
#define PAGING_PAGES (PAGING_MEMORY/4096)
#define MAP_NR(addr) (((addr)-LOW_MEM)>>12)
#if (PAGING_PAGES < 10)
#error "Won't work"
#endif
inline void copy_page(unsigned long from,unsigned long to)
{
int d0,d1,d2;
__asm__ __volatile("cld\n\t"
"rep\n\t"
"movsl\n\t"
:"=&c" (d0), "=&S" (d1), "=&D" (d2)
:"0" (PAGE_SIZE/4),"1" (from),"2" (to)
:"memory");
}
static unsigned short 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__ __volatile__("std ; repne ; scasw\n\t"
"jne 1f\n\t"
"movw $1,2(%%edi)\n\t"
"sall $12,%%ecx\n\t"
"movl %%ecx,%%edx\n\t"
"addl %2,%%edx\n\t"
"movl $1024,%%ecx\n\t"
"leal 4092(%%edx),%%edi\n\t"
"rep ; stosl\n\t"
"movl %%edx,%%eax\n"
"1:"
:"=a" (__res)
:"0" (0),"i" (LOW_MEM),"c" (PAGING_PAGES),
"D" (mem_map+PAGING_PAGES-1)
:"dx");
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;
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;
return;
}
if (!(new_page=get_free_page()))
do_exit(SIGSEGV);
if (old_page >= LOW_MEM)
mem_map[MAP_NR(old_page)]--;
*table_entry = new_page | 7;
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.
*/
void do_wp_page(unsigned long error_code,unsigned long address)
{
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 do_no_page(unsigned long error_code,unsigned long address)
{
unsigned long tmp;
if ((tmp=get_free_page()))
if (put_page(tmp,address))
return;
do_exit(SIGSEGV);
}
void calc_mem(void)
{
int i,j,k,free=0;
long * pg_tbl;
for(i=0 ; i<PAGING_PAGES ; i++)
if (!mem_map[i]) free++;
printk("%d pages free (of %d)\n\r",free,PAGING_PAGES);
for(i=2 ; i<1024 ; i++) {
if (1&pg_dir[i]) {
pg_tbl=(long *) (0xfffff000 & pg_dir[i]);
for(j=k=0 ; j<1024 ; j++)
if (pg_tbl[j]&1)
k++;
printk("Pg-dir[%d] uses %d pages\n",i,k);
}
}
}
+34
Ver Arquivo
@@ -0,0 +1,34 @@
/*
* page.s contains the low-level page-exception code.
* the real work is done in mm.c
*/
.globl page_fault
page_fault:
xchgl %eax,(%esp)
pushl %ecx
pushl %edx
push %ds
push %es
push %fs
movl $0x10,%edx
mov %dx,%ds
mov %dx,%es
mov %dx,%fs
movl %cr2,%edx
pushl %edx
pushl %eax
testl $1,%eax
jne 1f
call do_no_page
jmp 2f
1: call do_wp_page
2: addl $8,%esp
pop %fs
pop %es
pop %ds
popl %edx
popl %ecx
popl %eax
iret
+76
Ver Arquivo
@@ -0,0 +1,76 @@
#include <stdio.h> /* fprintf */
#include <stdlib.h> /* contains exit */
#include <sys/types.h> /* unistd.h needs this */
#include <unistd.h> /* contains read/write */
#include <fcntl.h>
#include <string.h>
#define MINIX_HEADER 32
#define GCC_HEADER 1024
void die(char * str)
{
fprintf(stderr,"%s\n",str);
exit(1);
}
void usage(void)
{
die("Usage: build boot system [> image]");
}
int main(int argc, char ** argv)
{
int i,c,id;
char buf[1024];
if (argc != 3)
usage();
for (i=0;i<sizeof buf; i++) buf[i]=0;
if ((id=open(argv[1],O_RDONLY,0))<0)
die("Unable to open 'boot'");
if (read(id,buf,MINIX_HEADER) != MINIX_HEADER)
die("Unable to read header of 'boot'");
if (((long *) buf)[0]!=0x04100301)
die("Non-Minix header of 'boot'");
if (((long *) buf)[1]!=MINIX_HEADER)
die("Non-Minix header of 'boot'");
if (((long *) buf)[3]!=0)
die("Illegal data segment in 'boot'");
if (((long *) buf)[4]!=0)
die("Illegal bss in 'boot'");
if (((long *) buf)[5] != 0)
die("Non-Minix header of 'boot'");
if (((long *) buf)[7] != 0)
die("Illegal symbol table in 'boot'");
i=read(id,buf,sizeof buf);
fprintf(stderr,"Boot sector %d bytes.\n",i);
if (i>510)
die("Boot block may not exceed 510 bytes");
buf[510]=0x55;
buf[511]=0xAA;
i=write(1,buf,512);
if (i!=512)
die("Write call failed");
close (id);
if ((id=open(argv[2],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");
/* only needed by qemu. ( qemu may not read last sector if
* size is < 512 bytes )
*/
memset(buf,0,512);
write(1,buf,512);
close(id);
fprintf(stderr,"System %d bytes.\n",i);
return(0);
}