diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..8971a8ef70775d6cd2a949131e74d274ca3be070 --- /dev/null +++ b/Makefile @@ -0,0 +1,40 @@ +AS := as +LD := ld -m elf_x86_64 + +LDFLAG := -Ttext 0x0 -s --oformat binary + +image : linux.img + +linux.img : tools/build bootsect setup kernel/system + ./tools/build bootsect setup kernel/system > $@ + +tools/build : tools/build.c + gcc -o $@ $< + +kernel/system : kernel/head.S kernel/*.c mm/*.c kernel/blk_drv/*.c + cd kernel; make system; cd .. + +bootsect : bootsect.o + $(LD) $(LDFLAG) -o $@ $< + +bootsect.o : bootsect.S + $(AS) -o $@ $< + +setup : setup.o + $(LD) $(LDFLAG) -e _start_setup -o $@ $< + +setup.o : setup.S + $(AS) -o $@ $< + +chr_drv/chr_drv.a: chr_drv/*.c + cd chr_drv; make chr_drv.a; cd .. + +clean: + rm -f *.o + rm -f bootsect + rm -f setup + rm -f tools/build + rm -f linux.img + cd kernel; make clean; cd .. + cd tools; make clean; cd .. + diff --git a/bootsect.S b/bootsect.S new file mode 100644 index 0000000000000000000000000000000000000000..fb4da86b7c46f0876fe6d8342111dcc8264d3479 --- /dev/null +++ b/bootsect.S @@ -0,0 +1,211 @@ +SYSSIZE = 0x3000 + +SETUPLEN = 4 + +BOOTSEG = 0x7c0 + +INITSEG = 0x9000 + +SETUPSEG = 0x9020 + +SYSSEG = 0x1000 + +ENDSEG = SYSSEG + SYSSIZE + +ROOT_DEV = 0x000 + +.code16 +.text + +.global _start +_start: + + jmpl $BOOTSEG, $start2 + +start2: + movw $BOOTSEG, %ax + movw %ax, %ds + movw $INITSEG, %ax + movw %ax, %es + movw $256, %cx + subw %si, %si + subw %di, %di + + rep + movsw + + jmpl $INITSEG, $go + +go: + movw %cs, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + movw $0xFF00, %sp + +load_setup: + movw $0x0000, %dx + movw $0x0002, %cx + movw $0x0200, %bx + movb $SETUPLEN, %al + movb $0x02, %ah + int $0x13 + jnc ok_load_setup + movw $0x0000, %dx + movw $0x0000, %ax + int $0x13 + jmp load_setup + +ok_load_setup: + movb $0x00, %dl + movw $0x0800, %ax + int $0x13 + movb $0x00, %ch + movw %cx, %cs:sectors + movw $INITSEG, %ax + movw %ax, %es + + movw $SYSSEG, %ax + movw %ax, %es + call read_it + call kill_motor + + movw %cs:root_dev, %ax + cmpw $0, %ax + jne root_defined + movw %cs:sectors, %bx + movw $0x0208, %ax + cmpw $15, %bx + je root_defined + movw $0x021c, %ax + cmpw $18, %bx + je root_defined +undef_root: + jmp undef_root +root_defined: + mov %ax, %cs:root_dev + + movw %cs, %ax + movw %ax, %ds + movw %ax, %es + + movw $0x600, %ax + movw $0x700, %bx + movw $0x0, %cx + movw $0x184f,%dx + int $0x10 + + movw $msg, %ax + movw %ax, %bp + movw $0x01301, %ax + movw $0x0c, %bx + movw $23, %cx + movw $0, %dx + int $0x010 + + jmpl $SETUPSEG, $0 + +sread: + .word 1+SETUPLEN +head: + .word 0 +track: + .word 0 +read_it: + movw %es, %ax + testw $0x0fff, %ax +die: + jne die + xor %bx, %bx +rp_read: + movw %es, %ax + cmpw $ENDSEG, %ax + jb ok1_read + ret +ok1_read: + movw %cs:sectors, %ax + subw sread, %ax + movw %ax, %cx + shlw $9, %cx + addw %bx, %cx + jnc ok2_read + je ok2_read + xorw %ax, %ax + subw %bx, %ax + shrw $9, %ax +ok2_read: + call read_track + movw %ax, %cx + addw sread, %ax + cmpw %cs:sectors, %ax + jne ok3_read + movw $1, %ax + subw head, %ax + jne ok4_read + incw track +ok4_read: + movw %ax, head + xorw %ax, %ax +ok3_read: + movw %ax, sread + shlw $9, %cx + addw %cx, %bx + jnc rp_read + movw %es, %ax + addw $0x1000, %ax + movw %ax, %es + xorw %bx, %bx + jmp rp_read + +read_track: + pushw %ax + pushw %bx + pushw %cx + pushw %dx + movw track, %dx + movw sread, %cx + incw %cx + movb %dl, %ch + movw head, %dx + movb %dl, %dh + movb $0, %dl + andw $0x0100, %dx + movb $2, %ah + int $0x13 + jc bad_rt + popw %dx + popw %cx + popw %bx + popw %ax + ret +bad_rt: + movw $0x0, %ax + movw $0x0, %dx + int $0x13 + popw %dx + popw %cx + popw %bx + popw %ax + jmp read_track + +kill_motor: + pushw %dx + movw $0x3f2, %dx + movb $0, %al + outb %al, %dx + popw %dx + ret + +sectors: + .word 0 + +msg: +.byte 13, 10 +.ascii "Linux is booting..." +.byte 13, 10 +.org 508 +root_dev: + .word ROOT_DEV +boot_flag: + .word 0xaa55 + diff --git a/fs/Makefile b/fs/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..109874236dde7bf55971148a4d85727ac58e837b --- /dev/null +++ b/fs/Makefile @@ -0,0 +1,68 @@ +GCC := gcc +LD := ld +CCFLAG := -I../include -nostdinc -ffreestanding -Wall -fomit-frame-pointer -c -fno-stack-protector -fno-pie -fno-pic -m32 +LDFLAG := -Ttext 0x0 -s --oformat binary -m elf_i386 +INCDIR := ../include +OBJS := read_write.o ioctl.o buffer.o super.o file_table.o inode.o open.o namei.o bitmap.o \ + fcntl.o char_dev.o truncate.o exec.o file_dev.o pipe.o stat.o + +fs.o : $(OBJS) + $(LD) -m elf_i386 -r -o $@ $^ + +read_write.o : read_write.c + $(GCC) $(CCFLAG) -o $@ $< + +ioctl.o : ioctl.c + $(GCC) $(CCFLAG) -o $@ $< + +buffer.o : buffer.c + $(GCC) $(CCFLAG) -o $@ $< + +super.o : super.c + $(GCC) $(CCFLAG) -o $@ $< + +file_table.o : file_table.c + $(GCC) $(CCFLAG) -o $@ $< + +inode.o : inode.c + $(GCC) $(CCFLAG) -o $@ $< + +bitmap.o : bitmap.c + $(GCC) $(CCFLAG) -o $@ $< + +truncate.o : truncate.c + $(GCC) $(CCFLAG) -o $@ $< + +namei.o : namei.c + $(GCC) $(CCFLAG) -o $@ $< + +open.o : open.c + $(GCC) $(CCFLAG) -o $@ $< + +bitmap.o : bitmap.c + $(GCC) $(CCFLAG) -o $@ $< + +char_dev.o : char_dev.c + $(GCC) $(CCFLAG) -o $@ $< + +fcntl.o : fcntl.c + $(GCC) $(CCFLAG) -o $@ $< + +runcate.o : truncate.c + $(GCC) $(CCFLAG) -o $@ $< + +pipe.o : pipe.c + $(GCC) $(CCFLAG) -o $@ $< + +file_dev.o : file_dev.c + $(GCC) $(CCFLAG) -o $@ $< + +exec.o : exec.c + $(GCC) $(CCFLAG) -o $@ $< + +stat.o : stat.c + $(GCC) $(CCFLAG) -o $@ $< + +clean : + rm -f *.o + diff --git a/fs/bitmap.c b/fs/bitmap.c new file mode 100644 index 0000000000000000000000000000000000000000..9a56b4f7243c2a8a76f69cf57365543ca24dc99a --- /dev/null +++ b/fs/bitmap.c @@ -0,0 +1,172 @@ +#include + +#include +#include + +#define clear_block(addr) \ + __asm__("cld\n\t" \ + "rep\n\t" \ + "stosl" \ + ::"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr)):) + + +#define set_bit(nr,addr) ({\ + register int res __asm__("ax"); \ + __asm__ __volatile__("btsl %2,%3\n\tsetb %%al": \ + "=a" (res):"a" (0),"r" (nr),"m" (*(addr))); \ + res;}) + +#define clear_bit(nr, addr) ({\ + register int res __asm__("ax"); \ + __asm__ __volatile__("btrl %2,%3\n\tsetnb %%al": \ + "=a" (res):"a" (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"); \ + __res;}) + + +int new_block(int dev) { + struct buffer_head * bh; + struct super_block * psb; + int i, j; + + psb = &sb; + j = 8192; + for (i=0 ; i<8 ; i++) { + if ((bh = psb->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 + psb->s_firstdatazone-1; + if (j >= psb->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; +} + +int free_block(int dev, int block) { + struct super_block * psb; + struct buffer_head * bh; + + psb = &sb; + + if (block < psb->s_firstdatazone || block >= psb->s_nzones) + panic("trying to free block not in datazone"); + + bh = get_hash_table(dev,block); + if (bh) { + if (bh->b_count > 1) { + brelse(bh); + return 0; + } + bh->b_dirt=0; + bh->b_uptodate=0; + if (bh->b_count) + brelse(bh); + } + + block -= psb->s_firstdatazone - 1; + if (clear_bit(block&8191,psb->s_zmap[block/8192]->b_data)) { + printk("block (%04x:%d) ",dev,block+psb->s_firstdatazone-1); + panic("free_block: bit already cleared\n"); + } + psb->s_zmap[block/8192]->b_dirt = 1; + return 1; +} + +struct m_inode * new_inode(int dev) { + struct m_inode * inode; + struct super_block * psb; + struct buffer_head * bh; + int i, j; + + if (!(inode=get_empty_inode())) + return NULL; + + psb = &sb; + j = 8192; + for (i=0 ; i<8 ; i++) { + if ((bh=psb->s_imap[i])) { + if ((j=find_first_zero(bh->b_data))<8192) + break; + } + } + + if (!bh || j >= 8192 || j+i*8192 > psb->s_ninodes) { + iput(inode); + return NULL; + } + + if (set_bit(j,bh->b_data)) + panic("new_inode: bit already set"); + + bh->b_dirt = 1; + inode->i_count = 1; + inode->i_nlinks = 1; + inode->i_dev = dev; + inode->i_uid = 0; + inode->i_gid = 0; + inode->i_dirt=1; + inode->i_num = j + i*8192; + inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; + return inode; +} + +void free_inode(struct m_inode * inode) { + struct super_block * psb = &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 (inode->i_num < 1 || inode->i_num > psb->s_ninodes) + panic("trying to free inode 0 or nonexistant inode"); + if (!(bh=psb->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.\n\r"); + bh->b_dirt = 1; + memset(inode,0,sizeof(*inode)); +} + diff --git a/fs/buffer.c b/fs/buffer.c new file mode 100644 index 0000000000000000000000000000000000000000..6883825acf68d5d0c08e627e7a3e826f8d65fabf --- /dev/null +++ b/fs/buffer.c @@ -0,0 +1,271 @@ +#include +#include +#include +#include +#include +#include + +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; + +void wait_on_buffer(struct buffer_head * bh) { + cli(); + while (bh->b_lock) { + sleep_on(&bh->b_wait); + } + sti(); +} + +int sys_sync() { + int i; + struct buffer_head * bh; + + sync_inodes(); + bh = start_buffer; + for (i=0 ; ib_dirt) + ll_rw_block(WRITE,bh); + } + return 0; +} + +int sync_dev(int dev) { + int i; + struct buffer_head * bh; + + bh = start_buffer; + for (i=0 ; ib_dev != dev) + continue; + wait_on_buffer(bh); + if (bh->b_dev == dev && bh->b_dirt) + ll_rw_block(WRITE,bh); + } + + sync_inodes(); + + bh = start_buffer; + for (i=0 ; ib_dev != dev) + continue; + wait_on_buffer(bh); + if (bh->b_dev == dev && bh->b_dirt) + ll_rw_block(WRITE,bh); + } + return 0; +} + +#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) { + 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; + + 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) { + 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; + + 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; + if (bh->b_next) + 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; +} + +struct buffer_head * get_hash_table(int dev, int block) { + struct buffer_head * bh; + for (;;) { + if (!(bh=find_buffer(dev,block))) + return NULL; + bh->b_count++; + wait_on_buffer(bh); + if (bh->b_dev == dev && bh->b_blocknr == block) + return bh; + bh->b_count--; + } +} + +#define BADNESS(bh) (((bh)->b_dirt<<1)+(bh)->b_lock) + +struct buffer_head * getblk(int dev,int block) { + struct buffer_head * tmp, * bh; + +repeat: + bh = get_hash_table(dev, block); + if (bh) return bh; + + tmp = free_list; + do { + if (tmp->b_count) + continue; + + if (!bh || BADNESS(tmp)b_next_free) != free_list); + + if (!bh) { + sleep_on(&buffer_wait); + goto repeat; + } + + wait_on_buffer(bh); + if (bh->b_count) + goto repeat; + + /* + while (bh->b_dirt) { + sync_dev(bh->b_dev); + wait_on_buffer(bh); + if (bh->b_count) + goto repeat; + }*/ + + if (find_buffer(dev,block)) + goto repeat; + + bh = tmp; + bh->b_count=1; + bh->b_dirt=0; + bh->b_uptodate=0; + remove_from_queues(bh); + bh->b_dev=dev; + bh->b_blocknr=block; + insert_into_queues(bh); + return bh; +} + +void brelse(struct buffer_head * buf) { + if (!buf) + return; + + wait_on_buffer(buf); + if (!(buf->b_count--)) + panic("Trying to free free buffer"); + wake_up(&buffer_wait); +} + +struct buffer_head * bread(int dev,int block) { + struct buffer_head * bh; + if (!(bh=getblk(dev,block))) { + panic("bread: getblk returned NULL\n"); + } + if (bh->b_uptodate) + return bh; + ll_rw_block(READ,bh); + wait_on_buffer(bh); + if (bh->b_uptodate) + return bh; + + brelse(bh); + return NULL; +} + +void buffer_init(long buffer_end) { + struct buffer_head * h = start_buffer; + void * b; + int i; + + if (buffer_end == 1<<20) + b = (void *) (640*1024); + else + b = (void *) buffer_end; + + while ( (b -= BLOCK_SIZE) >= ((void *) (h+1)) ) { + h->b_dev = 0; + h->b_dirt = 0; + h->b_count = 0; + h->b_lock = 0; + h->b_uptodate = 0; + h->b_wait = NULL; + h->b_next = NULL; + h->b_prev = NULL; + h->b_data = (char *) b; + h->b_prev_free = h-1; + h->b_next_free = h+1; + h++; + NR_BUFFERS++; + if (b == (void *) 0x100000) + b = (void *) 0xA0000; + } + h--; + free_list = start_buffer; + free_list->b_prev_free = h; + h->b_next_free = free_list; + + for (i = 0; i < NR_HASH; i++) + hash_table[i] = NULL; +} + +#define COPYBLK(from,to) \ +__asm__("cld\n\t" \ + "rep\n\t" \ + "movsl\n\t" \ + ::"c" (BLOCK_SIZE/4),"S" (from),"D" (to) \ + :) + +void bread_page(unsigned long address,int dev,int b[4]) { + struct buffer_head * bh[4]; + int i; + + for (i = 0; i < 4; i++) { + if (b[i]) { + if ((bh[i] = getblk(dev,b[i]))) { + if (!bh[i]->b_uptodate) { + ll_rw_block(READ,bh[i]); + } + } + } + else { + bh[i] = NULL; + } + } + + for (i=0 ; i<4 ; i++,address += BLOCK_SIZE) { + if (bh[i]) { + wait_on_buffer(bh[i]); + if (bh[i]->b_uptodate) + COPYBLK((unsigned long) bh[i]->b_data,address); + brelse(bh[i]); + } + } +} + diff --git a/fs/char_dev.c b/fs/char_dev.c new file mode 100644 index 0000000000000000000000000000000000000000..6c68f43d42f5c4a7b1737f48cc92d1141e86ad94 --- /dev/null +++ b/fs/char_dev.c @@ -0,0 +1,53 @@ +#include +#include + +#include +#include + +#include +#include + +extern int tty_read(unsigned minor,char * buf,int count); +extern int tty_write(unsigned minor,char * buf,int count); + +typedef int (*crw_ptr)(int rw,unsigned minor,char * buf,int count,off_t * pos); + +int rw_ttyx(int rw,unsigned minor,char * buf,int count,off_t * pos) { + if (rw == WRITE) { + return tty_write(minor, buf, count); + } + else if (rw == READ) { + return tty_read(minor, buf, count); + } + else + return -EINVAL; +} + +static int rw_tty(int rw,unsigned minor,char * buf,int count, off_t * pos) { + if (current->tty<0) + return -EPERM; + return rw_ttyx(rw,current->tty,buf,count,pos); +} + +#define NRDEVS ((sizeof (crw_table))/(sizeof (crw_ptr))) + +static crw_ptr crw_table[]={ + NULL, + NULL, + NULL, + NULL, + rw_ttyx, + rw_tty, + NULL, + NULL, +}; + +int rw_char(int rw,int dev, char * buf, int count, off_t * pos) { + crw_ptr call_addr; + if (MAJOR(dev)>=NRDEVS) + return -ENODEV; + if (!(call_addr=crw_table[MAJOR(dev)])) + return -ENODEV; + return call_addr(rw,MINOR(dev),buf,count,pos); +} + diff --git a/fs/exec.c b/fs/exec.c new file mode 100644 index 0000000000000000000000000000000000000000..ff31a5c0c68f7310ded7fb1daa5bdab776663f47 --- /dev/null +++ b/fs/exec.c @@ -0,0 +1,233 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define MAX_ARG_PAGES 32 + +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; +} + +int count(char ** argv) { + int i=0; + char ** tmp; + if ((tmp = argv)) { + while (get_fs_long((unsigned long *) (tmp++))) + i++; + } + return i; +} + +unsigned long copy_strings(int argc,char ** argv,unsigned long *page, + unsigned long p, int from_kmem) { + char *tmp, *pag; + int len, offset = 0; + unsigned long old_fs, new_fs; + + if (!p) + return 0; + new_fs = get_ds(); + old_fs = get_fs(); + + if (from_kmem==2) + set_fs(new_fs); + + while (argc-- > 0) { + if (from_kmem == 1) + set_fs(new_fs); + if (!(tmp = (char *)get_fs_long(((unsigned long *)argv)+argc))) + panic("argc is wrong"); + if (from_kmem == 1) + set_fs(old_fs); + len = 0; + do { + len++; + } while (get_fs_byte(tmp++)); + + if (p-len < 0) { + set_fs(old_fs); + return 0; + } + + while (len) { + --p; --tmp; --len; + if (--offset < 0) { + offset = p % PAGE_SIZE; + if (from_kmem==2) + set_fs(old_fs); + if (!(pag = (char *) page[p/PAGE_SIZE])) { + page[p / PAGE_SIZE] = (unsigned long*) get_free_page(); + pag = (char*) page[p / PAGE_SIZE]; + + if (!pag) + return 0; + } + if (from_kmem==2) + set_fs(new_fs); + } + *(pag + offset) = get_fs_byte(tmp); + } + } + + if (from_kmem==2) + set_fs(old_fs); + + return p; +} + +static unsigned long change_ldt(unsigned long text_size,unsigned long * page) { + unsigned long code_limit,data_limit,code_base,data_base; + int i; + + code_limit = TASK_SIZE; + data_limit = TASK_SIZE; + 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); + __asm__("pushl $0x17\n\tpop %%fs"::); + data_base += data_limit - LIBRARY_SIZE; + for (i=MAX_ARG_PAGES-1 ; i>=0 ; i--) { + data_base -= PAGE_SIZE; + if (page[i]) + put_dirty_page(page[i],data_base); + } + return data_limit; +} + +int do_execve(unsigned long * eip,long tmp,char * filename, + char ** argv, char ** envp) { + struct m_inode * inode; + struct buffer_head * bh; + struct exec ex; + unsigned long page[MAX_ARG_PAGES]; + int i,argc,envc; + int e_uid, e_gid; + int retval; + int sh_bang = 0; + unsigned long p=PAGE_SIZE*MAX_ARG_PAGES-4; + + if ((0xffff & eip[1]) != 0x000f) + panic("execve called from supervisor mode"); + for (i=0 ; ii_mode)) { + retval = -EACCES; + goto exec_error2; + } + + i = inode->i_mode; + e_uid = (i & S_ISUID) ? inode->i_uid : current->euid; + e_gid = (i & S_ISGID) ? inode->i_gid : current->egid; + + if (current->euid == inode->i_uid) + i >>= 6; + else if (in_group_p(inode->i_gid)) + i >>= 3; + if (!(i & 1) && + !((inode->i_mode & 0111) && suser())) { + retval = -ENOEXEC; + goto exec_error2; + } + + if (!(bh = bread(inode->i_dev,inode->i_zone[0]))) { + retval = -EACCES; + goto exec_error2; + } + ex = *((struct exec *) bh->b_data); + brelse(bh); + + if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize || ex.a_drsize || + ex.a_text+ex.a_data+ex.a_bss>0x3000000 || + inode->i_size < ex.a_text+ex.a_syms+N_TXTOFF(ex)) { + retval = -ENOEXEC; + goto exec_error2; + } + + if (N_TXTOFF(ex) != BLOCK_SIZE) { + printk("%s: N_TXTOFF != BLOCK_SIZE. See a.out.h.", filename); + retval = -ENOEXEC; + goto exec_error2; + } + + if (!sh_bang) { + p = copy_strings(envc,envp,page,p,0); + p = copy_strings(argc,argv,page,p,0); + if (!p) { + retval = -ENOMEM; + goto exec_error2; + } + } + + if (current->executable) + iput(current->executable); + current->executable = inode; + + for (i=0 ; iclose_on_exec>>i)&1) + sys_close(i); + current->close_on_exec = 0; + + free_page_tables(get_base(current->ldt[1]),get_limit(0x0f)); + free_page_tables(get_base(current->ldt[2]),get_limit(0x17)); + + p += change_ldt(ex.a_text,page); + p -= LIBRARY_SIZE + MAX_ARG_PAGES*PAGE_SIZE; + p = (unsigned long) create_tables((char *)p,argc,envc); + + current->brk = ex.a_bss + + (current->end_data = ex.a_data + + (current->end_code = ex.a_text)); + current->start_stack = p & 0xfffff000; + current->suid = current->euid = e_uid; + current->sgid = current->egid = e_gid; + eip[0] = ex.a_entry; + eip[3] = p; + return 0; +exec_error2: + iput(inode); +exec_error1: + for (i=0 ; i +#include +#include +#include +#include + +#include +#include + +static int dupfd(unsigned int fd, unsigned int arg) { + if (fd >= NR_OPEN || !current->filp[fd]) + return -EBADF; + if (arg >= NR_OPEN) + return -EINVAL; + + while (arg < NR_OPEN) { + if (current->filp[arg]) + arg++; + else + break; + } + + if (arg >= NR_OPEN) + return -EMFILE; + + current->close_on_exec &= ~(1<filp[arg] = current->filp[fd])->f_count++; + return arg; +} + +int sys_dup(unsigned int fildes) { + return dupfd(fildes, 0); +} + +int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) { + struct file * filp; + + if (fd >= NR_OPEN || !(filp = current->filp[fd])) + return -EBADF; + switch (cmd) { + case F_DUPFD: + return dupfd(fd,arg); + case F_GETFD: + return (current->close_on_exec>>fd)&1; + case F_SETFD: + if (arg&1) + current->close_on_exec |= (1<close_on_exec &= ~(1<f_flags; + case F_SETFL: + filp->f_flags &= ~(O_APPEND | O_NONBLOCK); + filp->f_flags |= arg & (O_APPEND | O_NONBLOCK); + return 0; + case F_GETLK: case F_SETLK: case F_SETLKW: + return -1; + default: + return -1; + } +} diff --git a/fs/file_dev.c b/fs/file_dev.c new file mode 100644 index 0000000000000000000000000000000000000000..8b692880907ce1bd754f1ee6772be0f6890d8eeb --- /dev/null +++ b/fs/file_dev.c @@ -0,0 +1,79 @@ +#include +#include + +#include +#include +#include + +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + +int file_read(struct m_inode * inode, struct file * filp, char * buf, int count) +{ + int left,chars,nr; + struct buffer_head * bh; + + if ((left=count)<=0) + return 0; + while (left) { + if ((nr = bmap(inode,(filp->f_pos)/BLOCK_SIZE))) { + printk("block index is %d\n\r", nr); + 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++); + } + } + 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; + + if (filp->f_flags & O_APPEND) + pos = inode->i_size; + else + pos = filp->f_pos; + while (ii_dev,block))) + break; + c = pos % BLOCK_SIZE; + p = c + bh->b_data; + bh->b_dirt = 1; + c = BLOCK_SIZE-c; + if (c > count-i) c = count-i; + pos += c; + if (pos > inode->i_size) { + inode->i_size = pos; + inode->i_dirt = 1; + } + i += c; + while (c-->0) + *(p++) = get_fs_byte(buf++); + brelse(bh); + } + if (!(filp->f_flags & O_APPEND)) { + filp->f_pos = pos; + } + return (i?i:-1); +} + diff --git a/fs/file_table.c b/fs/file_table.c new file mode 100644 index 0000000000000000000000000000000000000000..94460f24797d35432f2508918f9ac5e1b185607a --- /dev/null +++ b/fs/file_table.c @@ -0,0 +1,4 @@ +#include + +struct file file_table[NR_FILE]; + diff --git a/fs/inode.c b/fs/inode.c new file mode 100644 index 0000000000000000000000000000000000000000..8eeb295251e9d85cb03e50d6224cd38a0a31ed9e --- /dev/null +++ b/fs/inode.c @@ -0,0 +1,299 @@ +#include +#include + +#include +#include +#include +#include + +extern struct super_block sb; + +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 iput(struct m_inode * inode) { + if (!inode) + return; + wait_on_inode(inode); + if (!inode->i_count) + printk("iput: trying to free free inode"); + if (!inode->i_dev) { + inode->i_count--; + return; + } +repeat: + if (inode->i_count>1) { + inode->i_count--; + return; + } + if (!inode->i_nlinks) { + truncate(inode); + free_inode(inode); + return; + } + if (inode->i_dirt) { + write_inode(inode); + wait_on_inode(inode); + goto repeat; + } + inode->i_count--; + return; +} + +void sync_inodes() { + int i; + struct m_inode * inode; + + inode = 0+inode_table; + for(i=0 ; ii_dirt && !inode->i_pipe) { + write_inode(inode); + } + } +} + +static int _bmap(struct m_inode * inode,int block,int create) { + struct buffer_head * bh; + int i; + + if (block<0) { + printk("_bmap: block<0"); + } + + if (block >= 7+512+512*512) { + printk("_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_ctime=CURRENT_TIME; + inode->i_dirt=1; + } + } + 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); +} + +struct m_inode * get_empty_inode() { + struct m_inode * inode; + static struct m_inode * last_inode = inode_table; + int i; + + do { + inode = NULL; + for (i = NR_INODE; i ; i--) { + if (++last_inode >= inode_table + NR_INODE) + last_inode = inode_table; + + if (!last_inode->i_count) { + inode = last_inode; + if (!inode->i_dirt && !inode->i_lock) + break; + } + } + + if (!inode) { + for (i=0 ; ii_dirt) { + write_inode(inode); + wait_on_inode(inode); + } + } while (inode->i_count); + + memset(inode,0,sizeof(*inode)); + inode->i_count = 1; + return inode; +} + +struct m_inode * get_pipe_inode(void) { + struct m_inode * inode; + + if (!(inode = get_empty_inode())) + return NULL; + if (!(inode->i_size=get_free_page())) { + inode->i_count = 0; + return NULL; + } + inode->i_count = 2; /* sum of readers/writers */ + PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0; + inode->i_pipe = 1; + return inode; +} + +struct m_inode * iget(int dev, int nr) { + struct m_inode * inode, * empty; + if (!dev) + printk("iget with dev==0"); + + 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++; + continue; + } + inode->i_count++; + return inode; + } + + empty = get_empty_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 * psb; + struct buffer_head * bh; + int block; + + psb = &sb; + lock_inode(inode); + block = 2 + psb->s_imap_blocks + psb->s_zmap_blocks + + (inode->i_num-1)/INODES_PER_BLOCK; + + if (!(bh=bread(inode->i_dev,block))) + printk("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 * psb = &sb; + struct buffer_head * bh; + int block; + + lock_inode(inode); + if (!inode->i_dirt || !inode->i_dev) { + unlock_inode(inode); + return; + } + + block = 2 + psb->s_imap_blocks + psb->s_zmap_blocks + + (inode->i_num-1)/INODES_PER_BLOCK; + + if (!(bh=bread(inode->i_dev,block))) + printk("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); +} + diff --git a/fs/ioctl.c b/fs/ioctl.c new file mode 100644 index 0000000000000000000000000000000000000000..330dd66cad86b69ce4d788d77f0fecf395e30cde --- /dev/null +++ b/fs/ioctl.c @@ -0,0 +1,14 @@ +#include +#include +#include +#include + +extern int tty_ioctl(int dev, int cmd, int arg); + +int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) { + if (fd == 0 || fd == 1) { + tty_ioctl(0, cmd, arg); + } + return 0; +} + diff --git a/fs/namei.c b/fs/namei.c new file mode 100644 index 0000000000000000000000000000000000000000..727bf396641ca917ed6e00ad1881be7085905134 --- /dev/null +++ b/fs/namei.c @@ -0,0 +1,721 @@ +#include +#include +#include + +#include +#include +#include +#include +#include + +#define MAY_EXEC 1 +#define MAY_WRITE 2 +#define MAY_READ 4 + +#define ACC_MODE(x) ("\004\002\006\377"[(x)&O_ACCMODE]) + +struct m_inode * _namei(const char * pathname, struct m_inode * base, + int follow_links); + +static int permission(struct m_inode * inode,int mask) { + int mode = inode->i_mode; + +/* special case: not even root can read/write a deleted file */ + if (inode->i_dev && !inode->i_nlinks) + return 0; + else if (current->euid==inode->i_uid) + mode >>= 6; + else if (in_group_p(inode->i_gid)) + mode >>= 3; + if (((mode & mask & 0007) == mask) || suser()) + return 1; + return 0; + +} + +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 && (de->name[0]=='.') && (de->name[1]=='\0')) + return 1; + + if (len < NAME_LEN && de->name[len]) + return 0; + + __asm__("cld\n\t" + "fs ; repe ; cmpsb\n\t" + "setz %%al" + :"=a" (same) + :"a" (0),"S" ((long) name),"D" ((long) de->name),"c" (len):); + + return same; +} + +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; + + entries = (*dir)->i_size / (sizeof (struct dir_entry)); + *res_dir = NULL; + + if (namelen==2 && get_fs_byte(name)=='.' && get_fs_byte(name+1)=='.') { + if ((*dir) == current->root) + namelen=1; + } + + 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; +} + +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; + 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) { + for (i=0; i < NAME_LEN ; i++) + de->name[i]=(ib_dirt = 1; + dir->i_mtime = CURRENT_TIME; + *res_dir = de; + return bh; + } + de++; + i++; + } +} + +static struct m_inode * follow_link(struct m_inode * dir, struct m_inode * inode) { + unsigned short fs; + struct buffer_head * bh; + + if (!dir) { + dir = current->root; + dir->i_count++; + } + if (!inode) { + iput(dir); + return NULL; + } + if (!S_ISLNK(inode->i_mode)) { + iput(dir); + return inode; + } + __asm__("mov %%fs,%0":"=r" (fs)); + if (fs != 0x17 || !inode->i_zone[0] || + !(bh = bread(inode->i_dev, inode->i_zone[0]))) { + iput(dir); + iput(inode); + return NULL; + } + iput(inode); + __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10)); + inode = _namei(bh->b_data,dir,0); + __asm__("mov %0,%%fs"::"r" (fs)); + brelse(bh); + return inode; +} + +static struct m_inode * get_dir(const char * pathname, struct m_inode * inode) { + char c; + const char * thisname; + struct buffer_head * bh; + int namelen,inr; + struct dir_entry * de; + struct m_inode * dir; + + if (!inode) { + inode = current->pwd; + inode->i_count++; + } + if ((c=get_fs_byte(pathname))=='/') { + iput(inode); + inode = current->root; + pathname++; + 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; + brelse(bh); + dir = inode; + if (!(inode = iget(dir->i_dev,inr))) { + iput(dir); + return NULL; + } + + if (!(inode = follow_link(dir,inode))) + return NULL; + } + + return NULL; +} + +static struct m_inode * dir_namei(const char * pathname, + int * namelen, const char ** name, struct m_inode * base) { + char c; + const char * basename; + struct m_inode * dir; + + if (!(dir = get_dir(pathname,base))) + return NULL; + + basename = pathname; + while ((c = get_fs_byte(pathname++))) { + if (c == '/') + basename = pathname; + } + + *namelen = pathname-basename-1; + *name = basename; + + return dir; +} + +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,NULL))) + return -ENOENT; + + bh = find_entry(&dir,basename,namelen,&de); + if (!bh) { + return -EINVAL; + } + + inr = de->inode; + dev = dir->i_dev; + brelse(bh); + + if (!(inode = follow_link(dir,iget(dev,inr)))) + return -EACCES; + + if ((S_ISDIR(inode->i_mode) && (flag & O_ACCMODE)) || + !permission(inode,ACC_MODE(flag))) { + iput(inode); + return -EPERM; + } + if (flag & O_TRUNC) + truncate(inode); + + inode = iget(dev,inr); + inode->i_atime = CURRENT_TIME; + *res_inode = inode; + return 0; +} + +struct m_inode * _namei(const char * pathname, struct m_inode * base, + int follow_links) { + const char * basename; + int inr,namelen; + struct m_inode * inode; + struct buffer_head * bh; + struct dir_entry * de; + + if (!(base = dir_namei(pathname,&namelen,&basename,base))) + return NULL; + + if (!namelen) + return base; + + bh = find_entry(&base,basename,namelen,&de); + if (!bh) { + iput(base); + return NULL; + } + + inr = de->inode; + brelse(bh); + if (!(inode = iget(base->i_dev,inr))) { + iput(base); + return NULL; + } + + if (follow_links) + inode = follow_link(base,inode); + else + iput(base); + + inode->i_atime=CURRENT_TIME; + inode->i_dirt=1; + return inode; +} + +struct m_inode * namei(const char * pathname) { + return _namei(pathname,NULL,1); +} + +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 (!(dir = dir_namei(pathname,&namelen,&basename, NULL))) + 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); + 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); + inode->i_nlinks--; + 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; +} + +static int empty_dir(struct m_inode * inode) { + int nr,block; + int len; + struct buffer_head * bh; + struct dir_entry * de; + + len = inode->i_size / sizeof (struct dir_entry); + if (len<2 || !inode->i_zone[0] || + !(bh=bread(inode->i_dev,inode->i_zone[0]))) { + printk("warning - bad directory on dev %04x\n",inode->i_dev); + return 0; + } + + de = (struct dir_entry *) bh->b_data; + if (de[0].inode != inode->i_num || !de[1].inode || + strcmp(".",de[0].name) || strcmp("..",de[1].name)) { + printk("warning - bad directory on dev %04x\n",inode->i_dev); + return 0; + } + + nr = 2; + de += 2; + while (nr= (void *) (bh->b_data+BLOCK_SIZE)) { + brelse(bh); + block=bmap(inode,nr/DIR_ENTRIES_PER_BLOCK); + if (!block) { + nr += DIR_ENTRIES_PER_BLOCK; + break; + } + 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 (!(dir = dir_namei(name,&namelen,&basename, NULL))) + return -ENOENT; + + if (!namelen) { + iput(dir); + return -ENOENT; + } + + if (!permission(dir,MAY_WRITE)) { + iput(dir); + return -EPERM; + } + + bh = find_entry(&dir,basename,namelen,&de); + if (!bh) { + iput(dir); + return -ENOENT; + } + if (!(inode = iget(dir->i_dev, de->inode))) { + iput(dir); + brelse(bh); + return -EPERM; + } + + if (inode->i_dev != dir->i_dev || inode->i_count>1) { + iput(dir); + iput(inode); + brelse(bh); + return -EPERM; + } + + if (inode == dir) { + iput(dir); + iput(inode); + brelse(bh); + return -EPERM; + } + + if (!S_ISDIR(inode->i_mode)) { + iput(dir); + iput(inode); + 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_dirt=1; + iput(dir); + iput(inode); + + return 0; +} + +int sys_symlink(const char * oldname, const char * newname) { + struct dir_entry * de; + struct m_inode * dir, * inode; + struct buffer_head * bh, * name_block; + const char * basename; + int namelen, i; + char c; + + dir = dir_namei(newname,&namelen,&basename, NULL); + if (!dir) + return -EACCES; + if (!namelen) { + iput(dir); + return -EPERM; + } + if (!permission(dir,MAY_WRITE)) { + iput(dir); + return -EACCES; + } + if (!(inode = new_inode(dir->i_dev))) { + iput(dir); + return -ENOSPC; + } + inode->i_mode = S_IFLNK | (0777 & ~current->umask); + inode->i_dirt = 1; + if (!(inode->i_zone[0]=new_block(inode->i_dev))) { + iput(dir); + inode->i_nlinks--; + iput(inode); + return -ENOSPC; + } + inode->i_dirt = 1; + if (!(name_block=bread(inode->i_dev,inode->i_zone[0]))) { + iput(dir); + inode->i_nlinks--; + iput(inode); + return -ERROR; + } + i = 0; + while (i < 1023 && (c=get_fs_byte(oldname++))) + name_block->b_data[i++] = c; + name_block->b_data[i] = 0; + name_block->b_dirt = 1; + brelse(name_block); + inode->i_size = i; + inode->i_dirt = 1; + bh = find_entry(&dir,basename,namelen,&de); + if (bh) { + inode->i_nlinks--; + iput(inode); + brelse(bh); + iput(dir); + return -EEXIST; + } + 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); + iput(inode); + 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_ISDIR(oldinode->i_mode)) { + iput(oldinode); + return -EPERM; + } + dir = dir_namei(newname,&namelen,&basename, NULL); + 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_dirt = 1; + iput(oldinode); + 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, NULL))) + return -ENOENT; + if (!namelen) { + iput(dir); + return -ENOENT; + } + if (!permission(dir,MAY_WRITE)) { + iput(dir); + return -EPERM; + } + bh = find_entry(&dir,basename,namelen,&de); + if (!bh) { + iput(dir); + return -ENOENT; + } + if (!(inode = iget(dir->i_dev, de->inode))) { + iput(dir); + brelse(bh); + return -ENOENT; + } + + if ((dir->i_mode & S_ISVTX) && !suser() && + current->euid != inode->i_uid && + current->euid != dir->i_uid) { + iput(dir); + iput(inode); + brelse(bh); + return -EPERM; + } + + if (S_ISDIR(inode->i_mode)) { + iput(inode); + iput(dir); + brelse(bh); + return -EPERM; + } + if (!inode->i_nlinks) { + printk("Deleting nonexistent file (%04x:%d), %d\n", + inode->i_dev,inode->i_num,inode->i_nlinks); + inode->i_nlinks=1; + } + de->inode = 0; + bh->b_dirt = 1; + brelse(bh); + inode->i_nlinks--; + inode->i_dirt = 1; + iput(inode); + iput(dir); + return 0; +} + diff --git a/fs/open.c b/fs/open.c new file mode 100644 index 0000000000000000000000000000000000000000..ac31400e2105e8e519c58c80256f93477d68939f --- /dev/null +++ b/fs/open.c @@ -0,0 +1,144 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +int sys_utime(char * filename, struct utimbuf * times) { + struct m_inode * inode; + long actime,modtime; + + if (!(inode=namei(filename))) + return -ENOENT; + if (times) { + actime = get_fs_long((unsigned long *) ×->actime); + modtime = get_fs_long((unsigned long *) ×->modtime); + } else + actime = modtime = CURRENT_TIME; + inode->i_atime = actime; + inode->i_mtime = modtime; + inode->i_dirt = 1; + iput(inode); + return 0; +} + +int sys_ls() { + printk("in sys_ls\n\r"); + int block, i, j; + int entries; + struct buffer_head * bh; + struct dir_entry * de; + struct m_inode* inode = current->root; + printk("mode is %d\n\r", inode->i_mode); + + if (S_ISDIR(inode->i_mode)) { + entries = inode->i_size / (sizeof (struct dir_entry)); + printk("there are %d files in root.\n\r", entries); + + if (!(block = inode->i_zone[0])) { + printk("empty i_zone\n"); + return -1; + } + + if (!(bh = bread(inode->i_dev,block))) { + printk("can not read block %d\n", block); + return -1; + } + + de = (struct dir_entry *) bh->b_data; + + for (i = 0; i < entries; i++) { + if (!de->inode) { + continue; + } + for (j = 0; j < 14; j++) { + printk("%c", de->name[j]); + } + printk("\n"); + de++; + } + } + + return 0; +} + +int sys_open(const char * filename,int flag,int mode) { + struct m_inode * inode; + struct file * f; + int i,fd; + + mode &= 0777 & ~current->umask; + for(fd=0 ; fdfilp[fd]) + break; + } + + if (fd>=NR_OPEN) + return -EINVAL; + + current->close_on_exec &= ~(1<f_count) break; + if (i>=NR_FILE) + return -EINVAL; + + (current->filp[fd]=f)->f_count++; + if ((i=open_namei(filename, flag, mode, &inode))<0) { + current->filp[fd]=NULL; + f->f_count=0; + return i; + } + + if (S_ISCHR(inode->i_mode)) { + printk("open char dev %d\n", fd); + } + + 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_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_close(unsigned int fd) { + struct file * filp; + + if (fd >= NR_OPEN) + return -EINVAL; + current->close_on_exec &= ~(1<filp[fd])) + return -EINVAL; + current->filp[fd] = NULL; + if (filp->f_count == 0) + panic("Close: file count is 0"); + if (--filp->f_count) + return (0); + iput(filp->f_inode); + return (0); +} + diff --git a/fs/pipe.c b/fs/pipe.c new file mode 100644 index 0000000000000000000000000000000000000000..0fb6bd83d63657299eeb6712a52ee84ff1687d54 --- /dev/null +++ b/fs/pipe.c @@ -0,0 +1,108 @@ +#include +#include +#include + +#include +#include /* for get_free_page */ +#include +#include + +int read_pipe(struct m_inode * inode, char * buf, int count) { + int chars, size, read = 0; + + while (count>0) { + while (!(size=PIPE_SIZE(*inode))) { + wake_up(& PIPE_WRITE_WAIT(*inode)); + if (inode->i_count != 2) /* are there any writers? */ + return read; + if (current->signal & ~current->blocked) + return read?read:-ERESTARTSYS; + interruptible_sleep_on(& PIPE_READ_WAIT(*inode)); + } + chars = PAGE_SIZE-PIPE_TAIL(*inode); + if (chars > count) + chars = count; + if (chars > size) + chars = size; + count -= chars; + read += chars; + size = PIPE_TAIL(*inode); + PIPE_TAIL(*inode) += chars; + PIPE_TAIL(*inode) &= (PAGE_SIZE-1); + while (chars-->0) + put_fs_byte(((char *)inode->i_size)[size++],buf++); + } + wake_up(& PIPE_WRITE_WAIT(*inode)); + return read; +} + +int write_pipe(struct m_inode * inode, char * buf, int count) { + int chars, size, written = 0; + + while (count>0) { + while (!(size=(PAGE_SIZE-1)-PIPE_SIZE(*inode))) { + wake_up(& PIPE_READ_WAIT(*inode)); + if (inode->i_count != 2) { /* no readers */ + current->signal |= (1<<(SIGPIPE-1)); + return written?written:-1; + } + sleep_on(& PIPE_WRITE_WAIT(*inode)); + } + chars = PAGE_SIZE-PIPE_HEAD(*inode); + if (chars > count) + chars = count; + if (chars > size) + chars = size; + count -= chars; + written += chars; + size = PIPE_HEAD(*inode); + PIPE_HEAD(*inode) += chars; + PIPE_HEAD(*inode) &= (PAGE_SIZE-1); + while (chars-->0) + ((char *)inode->i_size)[size++]=get_fs_byte(buf++); + } + wake_up(& PIPE_READ_WAIT(*inode)); + return written; +} + +int sys_pipe(unsigned long * fildes) { + struct m_inode * inode; + struct file * f[2]; + int fd[2]; + int i,j; + + j=0; + for(i=0;j<2 && if_count++; + if (j==1) + f[0]->f_count=0; + if (j<2) + return -1; + j=0; + for(i=0;j<2 && ifilp[i]) { + current->filp[ fd[j]=i ] = f[j]; + j++; + } + if (j==1) + current->filp[fd[0]]=NULL; + if (j<2) { + f[0]->f_count=f[1]->f_count=0; + return -1; + } + if (!(inode=get_pipe_inode())) { + current->filp[fd[0]] = + current->filp[fd[1]] = NULL; + f[0]->f_count = f[1]->f_count = 0; + return -1; + } + f[0]->f_inode = f[1]->f_inode = inode; + f[0]->f_pos = f[1]->f_pos = 0; + f[0]->f_mode = 1; /* read */ + f[1]->f_mode = 2; /* write */ + put_fs_long(fd[0],0+fildes); + put_fs_long(fd[1],1+fildes); + return 0; +} + diff --git a/fs/read_write.c b/fs/read_write.c new file mode 100644 index 0000000000000000000000000000000000000000..bd08405c02cf61e033d33b304e8018b8cabd8ef1 --- /dev/null +++ b/fs/read_write.c @@ -0,0 +1,70 @@ +#include +#include +#include + +#include +#include + +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); + +extern int rw_char(int rw,int dev, char * buf, int count, off_t * pos); + +extern int read_pipe(struct m_inode * inode, char * buf, int count); +extern int write_pipe(struct m_inode * inode, char * buf, int count); + +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; + + inode = file->f_inode; + if (inode->i_pipe) + return (file->f_mode&1)?read_pipe(inode,buf,count):-EIO; + if (S_ISCHR(inode->i_mode)) { + return rw_char(READ, inode->i_zone[0], buf, count, &file->f_pos); + } + + if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode)) { + if (count+file->f_pos > inode->i_size) + count = inode->i_size - file->f_pos; + if (count<=0) + return 0; + return file_read(inode,file,buf,count); + } + + printk("(Read)inode->i_mode=%06o\n\r",inode->i_mode); + return -EINVAL; +} + +int sys_write(unsigned int fd,char * buf,int count) { + struct file * file; + struct m_inode * inode; + + if (fd>=NR_OPEN || count <0 || !(file=current->filp[fd])) + return -EINVAL; + + if (!count) + return 0; + + inode=file->f_inode; + + if (inode->i_pipe) + return (file->f_mode&2)?write_pipe(inode,buf,count):-EIO; + if (S_ISCHR(inode->i_mode)) { + return rw_char(WRITE,inode->i_zone[0],buf,count,&file->f_pos); + } + + if (S_ISREG(inode->i_mode)) + return file_write(inode,file,buf,count); + + printk("(Write)inode->i_mode=%06o\n\r",inode->i_mode); + return -EINVAL; +} + diff --git a/fs/stat.c b/fs/stat.c new file mode 100644 index 0000000000000000000000000000000000000000..136315083d20f7cd95df64332929b4af515f1b31 --- /dev/null +++ b/fs/stat.c @@ -0,0 +1,48 @@ +#include +#include + +#include +#include +#include +#include + +static void cp_stat(struct m_inode * inode, struct stat * statbuf) { + struct stat tmp; + int i; + + verify_area(statbuf,sizeof (struct stat)); + tmp.st_dev = inode->i_dev; + tmp.st_ino = inode->i_num; + tmp.st_mode = inode->i_mode; + tmp.st_nlink = inode->i_nlinks; + tmp.st_uid = inode->i_uid; + tmp.st_gid = inode->i_gid; + tmp.st_rdev = inode->i_zone[0]; + tmp.st_size = inode->i_size; + tmp.st_atime = inode->i_atime; + tmp.st_mtime = inode->i_mtime; + tmp.st_ctime = inode->i_ctime; + for (i=0 ; i= NR_OPEN || !(f=current->filp[fd]) || !(inode=f->f_inode)) + return -EBADF; + cp_stat(inode,statbuf); + return 0; +} + +int sys_stat(char * filename, struct stat * statbuf) { + struct m_inode * inode; + + if (!(inode=namei(filename))) + return -ENOENT; + cp_stat(inode,statbuf); + iput(inode); + return 0; +} + diff --git a/fs/super.c b/fs/super.c new file mode 100644 index 0000000000000000000000000000000000000000..a1830f455f60cfeb6442da9566e0661366ca73fd --- /dev/null +++ b/fs/super.c @@ -0,0 +1,107 @@ +#include +#include +#include +#include + +#include + +#define test_bit(bitnr,addr) ({ \ +register int __res __asm__("ax"); \ +__asm__("bt %2,%3;setb %%al":"=a" (__res):"a" (0),"r" (bitnr),"m" (*(addr))); \ +__res; }) + +int ROOT_DEV = 0; + +struct super_block sb; + +struct super_block * read_super(int dev) { + struct super_block * s = &sb; + struct buffer_head * bh; + int i,block; + + if (!(bh = bread(dev,1))) { + printk("read super error!\n"); + } + + brelse(bh); + + *((struct d_super_block *) s) = + *((struct d_super_block *) bh->b_data); + + if (s->s_magic != SUPER_MAGIC) { + printk("read super error!\n"); + return NULL; + } + printk("check magic ok!\n\r"); + + for (i=0;is_imap[i] = NULL; + for (i=0;is_zmap[i] = NULL; + block=2; + for (i=0 ; i < s->s_imap_blocks ; i++) { + if ((s->s_imap[i] = bread(dev,block))) + block++; + else + break; + } + for (i=0 ; i < s->s_zmap_blocks ; i++) { + if ((s->s_zmap[i] = bread(dev,block))) + block++; + else + break; + } + + if (block != 2+s->s_imap_blocks+s->s_zmap_blocks) { + for(i=0;is_imap[i]); + for(i=0;is_zmap[i]); + s->s_dev=0; + return NULL; + } + + s->s_imap[0]->b_data[0] |= 1; + s->s_zmap[0]->b_data[0] |= 1; + + printk("read super successfully! %d, %d\n", s->s_imap_blocks, + s->s_zmap_blocks); + + return s; +} + +void mount_root() { + int i,free; + struct super_block * p; + struct m_inode * mi; + + for(i=0;ii_count += 3 ; + p->s_isup = p->s_imount = mi; + current->pwd = mi; + current->root = mi; + + free = 0; + i = p->s_nzones; + while (-- i >= 0) + if (!test_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 (!test_bit(i&8191,p->s_imap[i>>13]->b_data)) + free++; + printk("%d/%d free inodes\n\r",free,p->s_ninodes); +} + diff --git a/fs/truncate.c b/fs/truncate.c new file mode 100644 index 0000000000000000000000000000000000000000..56df71f5d4ad42c5a8b7d8e887dcfc525ca71840 --- /dev/null +++ b/fs/truncate.c @@ -0,0 +1,106 @@ +#include +#include + +static int free_ind(int dev,int block) { + struct buffer_head * bh; + unsigned short * p; + int i; + int block_busy; + + if (!block) + return 1; + + block_busy = 0; + + if ((bh=bread(dev,block))) { + p = (unsigned short *) bh->b_data; + for (i = 0; i < 512; i++,p++) { + if (*p) { + if (free_block(dev,*p)) { + *p = 0; + bh->b_dirt = 1; + } + else + block_busy = 1; + } + } + brelse(bh); + } + + if (block_busy) + return 0; + else + return free_block(dev,block); +} + +static int free_dind(int dev,int block) { + struct buffer_head * bh; + unsigned short * p; + int i; + int block_busy; + + if (!block) + return 1; + + block_busy = 0; + + if ((bh=bread(dev,block))) { + p = (unsigned short *) bh->b_data; + for (i = 0; i < 512; i++,p++) { + if (*p) { + if (free_ind(dev,*p)) { + *p = 0; + bh->b_dirt = 1; + } + else + block_busy = 1; + } + } + brelse(bh); + } + + if (block_busy) + return 0; + else + return free_block(dev,block); +} + +void truncate(struct m_inode * inode) { + int i; + int block_busy; + + if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || + S_ISLNK(inode->i_mode))) + return; + +repeat: + block_busy = 0; + for (i = 0; i < 7; i++) { + if (inode->i_zone[i]) { + if (free_block(inode->i_dev,inode->i_zone[i])) + inode->i_zone[i] = 0; + else + block_busy = 1; + } + } + + if (free_ind(inode->i_dev,inode->i_zone[7])) + inode->i_zone[7] = 0; + else + block_busy = 1; + + if (free_dind(inode->i_dev,inode->i_zone[8])) + inode->i_zone[8] = 0; + else + block_busy = 1; + + inode->i_dirt = 1; + if (block_busy) { + current->counter = 0; + schedule(); + goto repeat; + } + inode->i_size = 0; + inode->i_mtime = inode->i_ctime = CURRENT_TIME; +} + diff --git a/include/a.out.h b/include/a.out.h new file mode 100644 index 0000000000000000000000000000000000000000..a41052a3484e5c8a0db41e9fb948efd8e4bc29dc --- /dev/null +++ b/include/a.out.h @@ -0,0 +1,153 @@ +#ifndef _A_OUT_H +#define _A_OUT_H + +#define __GNU_EXEC_MACROS__ + +struct exec { + unsigned long a_magic; + unsigned a_text; + unsigned a_data; + unsigned a_bss; + unsigned a_syms; + unsigned a_entry; + unsigned a_trsize; + unsigned a_drsize; +}; + +#ifndef N_MAGIC +#define N_MAGIC(exec) ((exec).a_magic) +#endif + +#ifndef OMAGIC +#define OMAGIC 0407 +#define NMAGIC 0410 +#define ZMAGIC 0413 +#endif + +#ifndef N_BADMAG +#define N_BADMAG(x) \ + (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \ + && N_MAGIC(x) != ZMAGIC) +#endif + +#define _N_BADMAG(x) \ + (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \ + && N_MAGIC(x) != ZMAGIC) + +#define _N_HDROFF(x) (SEGMENT_SIZE - sizeof (struct exec)) + +#ifndef N_TXTOFF +#define N_TXTOFF(x) \ + (N_MAGIC(x) == ZMAGIC ? SEGMENT_SIZE : sizeof (struct exec)) +#endif + +#ifndef N_DATOFF +#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text) +#endif + +#ifndef N_TRELOFF +#define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data) +#endif + +#ifndef N_DRELOFF +#define N_DRELOFF(x) (N_TRELOFF(x) + (x).a_trsize) +#endif + +#ifndef N_SYMOFF +#define N_SYMOFF(x) (N_DRELOFF(x) + (x).a_drsize) +#endif + +#ifndef N_STROFF +#define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms) +#endif + +#ifndef N_TXTADDR +#define N_TXTADDR(x) 0 +#endif + +#define PAGE_SIZE 4096 +#define SEGMENT_SIZE 1024 + +#define _N_SEGMENT_ROUND(x) (((x) + SEGMENT_SIZE - 1) & ~(SEGMENT_SIZE - 1)) +#define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text) + +#ifndef N_DATADDR +#define N_DATADDR(x) \ + (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \ + : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x)))) +#endif + +#ifndef N_BSSADDR +#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data) +#endif + +#ifndef N_NLIST_DECLARED +struct nlist { + union { + char *n_name; + struct nlist *n_next; + long n_strx; + } n_un; + + unsigned char n_type; + char n_other; + short n_desc; + unsigned long n_value; +}; +#endif + +#ifndef N_UNDF +#define N_UNDF 0 +#endif +#ifndef N_ABS +#define N_ABS 2 +#endif +#ifndef N_TEXT +#define N_TEXT 4 +#endif +#ifndef N_DATA +#define N_DATA 6 +#endif +#ifndef N_BSS +#define N_BSS 8 +#endif +#ifndef N_COMM +#define N_COMM 10 +#endif +#ifndef N_FN +#define N_FN 15 +#endif + +#ifndef N_EXT +#define N_EXT 1 +#endif +#ifndef N_TYPE +#define N_TYPE 036 +#endif +#ifndef N_STAB +#define N_STAB 0340 +#endif + +#define N_INDR 0xa + +/* constants for ld. */ +#define N_SETA 0x14 +#define N_SETT 0x16 +#define N_SETD 0x18 +#define N_SETB 0x1A + +#define N_SETV 0x1C + +#ifndef N_RELOCATION_INFO_DECLARED +struct relocation_info { + int r_address; + unsigned int r_symbolnum:24; + unsigned int r_pcrel:1; + unsigned int r_length:2; + unsigned int r_extern:1; + unsigned int r_pad:4; +}; +#endif + +#endif + diff --git a/include/asm/io.h b/include/asm/io.h new file mode 100644 index 0000000000000000000000000000000000000000..86a051bd21a7360aae8709744d505df546f507bc --- /dev/null +++ b/include/asm/io.h @@ -0,0 +1,29 @@ +#ifndef _IO_H +#define _IO_H + +#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; \ +}) + +#endif + diff --git a/include/asm/segment.h b/include/asm/segment.h new file mode 100644 index 0000000000000000000000000000000000000000..717bc1a6694be2f73bb75cf8c920d5456bf8a178 --- /dev/null +++ b/include/asm/segment.h @@ -0,0 +1,14 @@ +#ifndef _SEGMENT_H +#define _SEGMENT_H + +void put_fs_byte(char val,char *addr); +char get_fs_byte(const char * addr); +void put_fs_long(unsigned long val,unsigned long * addr); +unsigned long get_fs_long(const unsigned long *addr); + +unsigned long get_fs(); +unsigned long get_ds(); +void set_fs(unsigned long val); + +#endif + diff --git a/include/asm/system.h b/include/asm/system.h new file mode 100644 index 0000000000000000000000000000000000000000..0f71874395c36c212ca9fd60957f126855eb7b97 --- /dev/null +++ b/include/asm/system.h @@ -0,0 +1,61 @@ +#ifndef _SYSTEM_H +#define _SYSTEM_H + +#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\t" \ + "1:\tmovl $0x17, %%eax\n\t" \ + "movw %%ax, %%ds\n\t" \ + "movw %%ax, %%es\n\t" \ + "movw %%ax, %%fs\n\t" \ + "movw %%ax, %%gs\n\t" \ + :::"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_trap_gate(n, addr) \ + _set_gate(&idt[n], 15, 0, addr) + +#define set_intr_gate(n, addr) \ + _set_gate(&idt[n], 14, 0, addr) + +#define set_system_gate(n, addr) \ + _set_gate(&idt[n], 15, 3, addr) + +#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\n\t" \ + ::"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") + +#endif + diff --git a/include/const.h b/include/const.h new file mode 100644 index 0000000000000000000000000000000000000000..5ff6b4aa2a4c70ffca518bafcd79c82530c99d48 --- /dev/null +++ b/include/const.h @@ -0,0 +1,15 @@ +#ifndef _CONST_H +#define _CONST_H + +#define BUFFER_END 0x200000 + +#define I_TYPE 0170000 +#define I_DIRECTORY 0040000 +#define I_REGULAR 0100000 +#define I_BLOCK_SPECIAL 0060000 +#define I_CHAR_SPECIAL 0020000 +#define I_NAMED_PIPE 0010000 +#define I_SET_UID_BIT 0004000 +#define I_SET_GID_BIT 0002000 + +#endif diff --git a/include/ctype.h b/include/ctype.h new file mode 100644 index 0000000000000000000000000000000000000000..04839bdff904c8b72ce0c6d6520274add9189bc1 --- /dev/null +++ b/include/ctype.h @@ -0,0 +1,23 @@ +#ifndef _CTYPE_H +#define _CTYPE_H + +#define _U 0x01 /* upper */ +#define _L 0x02 /* lower */ +#define _D 0x04 /* digit */ +#define _C 0x08 /* cntrl */ +#define _P 0x10 /* punct */ +#define _S 0x20 /* white space (space/lf/tab) */ +#define _X 0x40 /* hex digit */ +#define _SP 0x80 /* hard space (0x20) */ + + +extern unsigned char _ctype[]; +extern char _ctmp; + +#define islower(c) ((_ctype+1)[(int)c]&(_L)) +#define isupper(c) ((_ctype+1)[(int)c]&(_U)) + +#define tolower(c) (_ctmp=c,isupper(_ctmp)?_ctmp-('A'-'a'):_ctmp) +#define toupper(c) (_ctmp=c,islower(_ctmp)?_ctmp-('a'-'A'):_ctmp) + +#endif diff --git a/include/errno.h b/include/errno.h new file mode 100644 index 0000000000000000000000000000000000000000..68be9db1a03d24e18282235ecc54cc6ea7c948bd --- /dev/null +++ b/include/errno.h @@ -0,0 +1,52 @@ +#ifndef _ERRNO_H +#define _ERRNO_H + +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 + +/* Should never be seen by user programs */ +#define ERESTARTSYS 512 +#define ERESTARTNOINTR 513 + +#endif + diff --git a/include/fcntl.h b/include/fcntl.h new file mode 100644 index 0000000000000000000000000000000000000000..a4065b8359cfa48e34f4edb0eb963bb6f03bf8e2 --- /dev/null +++ b/include/fcntl.h @@ -0,0 +1,56 @@ +#ifndef _FCNTL_H +#define _FCNTL_H + +#include + +/* open/fcntl - NOCTTY, NDELAY isn't implemented yet */ +#define O_ACCMODE 00003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 00100 /* not fcntl */ +#define O_EXCL 00200 /* not fcntl */ +#define O_NOCTTY 00400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 /* not fcntl */ +#define O_NDELAY O_NONBLOCK + +/* Defines for fcntl-commands. Note that currently + * locking isn't supported, and other things aren't really + * tested. + */ +#define F_DUPFD 0 /* dup */ +#define F_GETFD 1 /* get f_flags */ +#define F_SETFD 2 /* set f_flags */ +#define F_GETFL 3 /* more flags (cloexec) */ +#define F_SETFL 4 +#define F_GETLK 5 /* not implemented */ +#define F_SETLK 6 +#define F_SETLKW 7 + +/* for F_[GET|SET]FL */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* Ok, these are locking features, and aren't implemented at any + * level. POSIX wants them. + */ +#define F_RDLCK 0 +#define F_WRLCK 1 +#define F_UNLCK 2 + +/* Once again - not implemented, but ... */ +struct flock { + short l_type; + short l_whence; + off_t l_start; + off_t l_len; + pid_t l_pid; +}; + +extern int creat(const char * filename,mode_t mode); +extern int fcntl(int fildes,int cmd, ...); +extern int open(const char * filename, int flags, ...); + +#endif + diff --git a/include/linux/config.h b/include/linux/config.h new file mode 100644 index 0000000000000000000000000000000000000000..d3801e328d3548aec0f1e10230a2d181c1c75c50 --- /dev/null +++ b/include/linux/config.h @@ -0,0 +1,18 @@ +#ifndef _CONFIG_H +#define _CONFIG_H + +#define UTS_SYSNAME "Linux" +#define UTS_NODENAME "(none)" +#define UTS_RELEASE "" +#define UTS_VERSION "0.12" +#define UTS_MACHINE "i386" + +#define DEF_INITSEG 0x9000 +#define DEF_SYSSEG 0x1000 +#define DEF_SETUPSEG 0x9020 +#define DEF_SYSSIZE 0x3000 + +/* HD_TYPE, if you know what hard disk you have. */ + +#endif + diff --git a/include/linux/fdreg.h b/include/linux/fdreg.h new file mode 100644 index 0000000000000000000000000000000000000000..195476c108c610a4fab1f016436a3404c3ebdde0 --- /dev/null +++ b/include/linux/fdreg.h @@ -0,0 +1,33 @@ +#ifndef _FDREG_H +#define _FDREG_H + +extern int ticks_to_floppy_on(unsigned int nr); +extern void floppy_on(unsigned int nr); +extern void floppy_off(unsigned int nr); +extern void floppy_select(unsigned int nr); +extern void floppy_deselect(unsigned int nr); + +#define FD_STATUS 0x3f4 +#define FD_DATA 0x3f5 +#define FD_DOR 0x3f2 +#define FD_DIR 0x3f7 +#define FD_DCR 0x3f7 + +#define STATUS_BUSYMASK 0x0F +#define STATUS_BUSY 0x10 +#define STATUS_DMA 0x20 +#define STATUS_DIR 0x40 +#define STATUS_READY 0x80 + +#define FD_RECALIBRATE 0x07 +#define FD_SEEK 0x0F +#define FD_READ 0xE6 +#define FD_WRITE 0xC5 +#define FD_SENSEI 0x08 +#define FD_SPECIFY 0x03 + +#define DMA_READ 0x46 +#define DMA_WRITE 0x4A + +#endif + diff --git a/include/linux/fs.h b/include/linux/fs.h new file mode 100644 index 0000000000000000000000000000000000000000..36dd303d86e2d523a4b1c07e6b8f01722cd2fff0 --- /dev/null +++ b/include/linux/fs.h @@ -0,0 +1,188 @@ +#ifndef _FS_H +#define _FS_H + +#include + +#define READ 0 +#define WRITE 1 +#define READA 2 +#define WRITEA 3 + +void buffer_init(long buffer_end); + +#define MAJOR(a) (((unsigned)(a))>>8) +#define MINOR(a) ((a)&0xff) + +#define NAME_LEN 14 +#define ROOT_INO 1 + +#define I_MAP_SLOTS 8 +#define Z_MAP_SLOTS 8 + +#define SUPER_MAGIC 0x137F + +#define NR_OPEN 20 +#define NR_INODE 32 +#define NR_FILE 64 +#define NR_SUPER 8 +#define NR_HASH 307 +#define 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))) + +#define PIPE_READ_WAIT(inode) ((inode).i_wait) +#define PIPE_WRITE_WAIT(inode) ((inode).i_wait2) +#define PIPE_HEAD(inode) ((inode).i_zone[0]) +#define PIPE_TAIL(inode) ((inode).i_zone[1]) +#define PIPE_SIZE(inode) ((PIPE_HEAD(inode)-PIPE_TAIL(inode))&(PAGE_SIZE-1)) +#define PIPE_EMPTY(inode) (PIPE_HEAD(inode)==PIPE_TAIL(inode)) +#define PIPE_FULL(inode) (PIPE_SIZE(inode)==(PAGE_SIZE-1)) + +struct buffer_head { + char * b_data; + unsigned long b_blocknr; + unsigned short b_dev; + unsigned char b_uptodate; + unsigned char b_dirt; + unsigned char b_count; + unsigned char b_lock; + 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]; + + struct task_struct * i_wait; + struct task_struct * i_wait2; + unsigned long i_atime; + unsigned long i_ctime; + unsigned short i_dev; + unsigned short i_num; + unsigned short i_count; + unsigned char i_lock; + unsigned char i_dirt; + unsigned char i_pipe; + unsigned char i_mount; + unsigned char i_seek; + unsigned char i_update; +}; + +struct file { + unsigned short f_mode; + unsigned short f_flags; + unsigned short f_count; + struct m_inode * f_inode; + off_t f_pos; +}; + +struct super_block { + unsigned short s_ninodes; + unsigned short s_nzones; + unsigned short s_imap_blocks; + unsigned short s_zmap_blocks; + unsigned short s_firstdatazone; + unsigned short s_log_zone_size; + unsigned long s_max_size; + unsigned short s_magic; + struct buffer_head * s_imap[8]; + struct buffer_head * s_zmap[8]; + unsigned short s_dev; + struct m_inode * s_isup; + struct m_inode * s_imount; + unsigned long s_time; + struct task_struct * s_wait; + unsigned char s_lock; + unsigned char s_rd_only; + unsigned char s_dirt; +}; + +struct d_super_block { + unsigned short s_ninodes; + unsigned short s_nzones; + unsigned short s_imap_blocks; + unsigned short s_zmap_blocks; + unsigned short s_firstdatazone; + unsigned short s_log_zone_size; + unsigned long s_max_size; + unsigned short s_magic; +}; + +extern struct file file_table[NR_FILE]; +extern struct super_block sb; + +extern int bmap(struct m_inode * inode,int block); + +extern void sync_inodes(void); +extern void iput(struct m_inode * inode); +extern struct m_inode * iget(int dev,int nr); + +struct dir_entry { + unsigned short inode; + char name[NAME_LEN]; +}; + +extern struct m_inode inode_table[NR_INODE]; + +extern void check_disk_change(int dev); +extern int floppy_change(unsigned int nr); +extern int ticks_to_floppy_on(unsigned int dev); +extern void floppy_on(unsigned int dev); +extern void floppy_off(unsigned int dev); +extern void truncate(struct m_inode * inode); +extern void sync_inodes(void); +extern void wait_on(struct m_inode * inode); +extern int bmap(struct m_inode * inode,int block); +extern int create_block(struct m_inode * inode,int block); +extern struct m_inode * namei(const char * pathname); +extern struct m_inode * lnamei(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 ll_rw_page(int rw, int dev, int nr, char * buffer); +extern void brelse(struct buffer_head * buf); +extern struct buffer_head * bread(int dev,int block); +extern void bread_page(unsigned long addr,int dev,int b[4]); +extern struct buffer_head * breada(int dev,int block,...); +extern int new_block(int dev); +extern int free_block(int dev, int block); +extern struct m_inode * new_inode(int dev); +extern void free_inode(struct m_inode * inode); +extern int sync_dev(int dev); +extern struct super_block * get_super(int dev); + +extern int ROOT_DEV; +void mount_root(); + +#endif + diff --git a/include/linux/hdreg.h b/include/linux/hdreg.h new file mode 100644 index 0000000000000000000000000000000000000000..5d2cf704b4d42d37efd933dbb5d97974856ca7ad --- /dev/null +++ b/include/linux/hdreg.h @@ -0,0 +1,52 @@ +#ifndef _HDREG_H +#define _HDREG_H + +#define HD_DATA 0x1f0 +#define HD_ERROR 0x1f1 +#define HD_NSECTOR 0x1f2 +#define HD_SECTOR 0x1f3 +#define HD_LCYL 0x1f4 +#define HD_HCYL 0x1f5 +#define HD_CURRENT 0x1f6 +#define HD_STATUS 0x1f7 +#define HD_PRECOMP HD_ERROR +#define HD_COMMAND HD_STATUS + +#define HD_CMD 0x3f6 + +/* Bits of HD_STATUS */ +#define ERR_STAT 0x01 +#define INDEX_STAT 0x02 +#define ECC_STAT 0x04 +#define DRQ_STAT 0x08 +#define SEEK_STAT 0x10 +#define WRERR_STAT 0x20 +#define READY_STAT 0x40 +#define BUSY_STAT 0x80 + +#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 +#define WIN_IDENTIFY 0xEC + +struct partition { + unsigned char boot_ind; + 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; + unsigned int nr_sects; +}; + +#endif + diff --git a/include/linux/head.h b/include/linux/head.h new file mode 100644 index 0000000000000000000000000000000000000000..107a1c5c136c5507f2335a1be713c740bdf5c479 --- /dev/null +++ b/include/linux/head.h @@ -0,0 +1,12 @@ +#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; + +#endif + diff --git a/include/linux/kernel.h b/include/linux/kernel.h new file mode 100644 index 0000000000000000000000000000000000000000..c329ff9e914267cc6c8c034654fcb7d23cafb2da --- /dev/null +++ b/include/linux/kernel.h @@ -0,0 +1,37 @@ +#ifndef KERNEL_H +#define KERNEL_H +/* + * 'kernel.h' contains some often-used function prototypes etc + */ +void verify_area(void * addr,int count); +volatile void panic(const char * str); +volatile void do_exit(long error_code); +int printf(const char * fmt, ...); +int printk(const char * fmt, ...); +void console_print(const char * str); +int tty_write(unsigned ch,char * buf,int count); +void * malloc(unsigned int size); +void free_s(void * obj, int size); +extern void hd_times_out(void); +extern void sysbeepstop(void); +extern void blank_screen(void); +extern void unblank_screen(void); + +extern int beepcount; +extern int hd_timeout; +extern int blankinterval; +extern int blankcount; + +#define free(x) free_s((x), 0) + +/* + * This is defined as a macro, but at some point this might become a + * real subroutine that sets a flag if it returns true (to do + * BSD-style accounting where the process is flagged if it uses root + * privs). The implication of this is that you should do normal + * permissions checks first, and check suser() last. + */ +#define suser() (current->euid == 0) + +#endif + diff --git a/include/linux/mm.h b/include/linux/mm.h new file mode 100644 index 0000000000000000000000000000000000000000..156ecdef920cb9444e12b69a96dfc4ba7c43c497 --- /dev/null +++ b/include/linux/mm.h @@ -0,0 +1,26 @@ +#ifndef _MM_H +#define _MM_H + +#include + +#define PAGE_SIZE 4096 + +extern unsigned long get_free_page(); +extern void free_page(unsigned long addr); +extern unsigned long put_dirty_page(unsigned long page,unsigned long address); + +#define invalidate() \ +__asm__("movl %%eax,%%cr3"::"a" (0)) + +#define LOW_MEM 0x100000 +extern unsigned long HIGH_MEMORY; +#define PAGING_MEMORY (15*1024*1024) +#define PAGING_PAGES (PAGING_MEMORY>>12) +#define MAP_NR(addr) (((addr)-LOW_MEM)>>12) +#define USED 100 +#define PAGE_DIRTY 0x40 + +extern unsigned char mem_map [ PAGING_PAGES ]; + +#endif + diff --git a/include/linux/sched.h b/include/linux/sched.h new file mode 100644 index 0000000000000000000000000000000000000000..a82291e5bbc16d7f48e6977d92a2c3e0e7bcfe37 --- /dev/null +++ b/include/linux/sched.h @@ -0,0 +1,231 @@ +#ifndef _SCHED_H +#define _SCHED_H + +#define HZ 100 + +#define NR_TASKS 64 +#define TASK_SIZE 0x04000000 +#define LIBRARY_SIZE 0x00400000 + +#if (TASK_SIZE & 0x3fffff) +#error "TASK_SIZE must be multiple of 4M" +#endif + +#if (((TASK_SIZE>>16)*NR_TASKS) != 0x10000) +#error "TASK_SIZE*NR_TASKS must be 4GB" +#endif + +#define LIBRARY_OFFSET (TASK_SIZE - LIBRARY_SIZE) + +#define FIRST_TASK task[0] +#define LAST_TASK task[NR_TASKS-1] + +#include +#include +#include +#include + +#include + +#define TASK_RUNNING 0 +#define TASK_INTERRUPTIBLE 1 +#define TASK_UNINTERRUPTIBLE 2 +#define TASK_ZOMBIE 3 +#define TASK_STOPPED 4 + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +extern int copy_page_tables(unsigned long from, unsigned long to, long size); +extern int free_page_tables(unsigned long from, unsigned long size); + +extern void trap_init(); +extern void panic(const char * str); +extern int tty_write(unsigned minor,char * buf,int count); +extern void sched_init(); +extern void schedule(); +extern void panic(const char* s); +void add_timer(long jiffies, void (*fn)(void)); +void sleep_on(struct task_struct ** p); +void wake_up(struct task_struct ** p); + +void test_a(); +void test_b(); +void test_c(); + +extern struct task_struct *task[NR_TASKS]; +extern struct task_struct *current; + +extern unsigned long volatile jiffies; +extern unsigned long startup_time; + +#define CURRENT_TIME (startup_time + jiffies / HZ) + +typedef int (*fn_ptr)(); + +struct tss_struct { + long back_link; + long esp0; + long ss0; + long esp1; + long ss1; + long esp2; + long ss2; + long cr3; + long eip; + long eflags; + long eax, ecx, edx, ebx; + long esp; + long ebp; + long esi; + long edi; + long es; + long cs; + long ss; + long ds; + long fs; + long gs; + long ldt; + long trace_bitmap; +}; + +struct task_struct { +/* these are hardcoded - don't touch */ + long state; /* -1 unrunnable, 0 runnable, >0 stopped */ + long counter; + long priority; + long signal; + struct sigaction sigaction[32]; + long blocked; /* bitmap of masked signals */ +/* various fields */ + int exit_code; + unsigned long start_code,end_code,end_data,brk,start_stack; + long pid,pgrp,session,leader; + int groups[NGROUPS]; + /* + * pointers to parent process, youngest child, younger sibling, + * older sibling, respectively. (p->father can be replaced with + * p->p_pptr->pid) + */ + struct task_struct *p_pptr, *p_cptr, *p_ysptr, *p_osptr; + unsigned short uid,euid,suid; + unsigned short gid,egid,sgid; + unsigned long timeout,alarm; + long utime,stime,cutime,cstime,start_time; + unsigned int flags; /* per process flags, defined below */ + unsigned short used_math; +/* file system info */ + int tty; /* -1 if no tty, so it must be signed */ + unsigned short umask; + struct m_inode * pwd; + struct m_inode * root; + struct m_inode * executable; + struct m_inode * library; + 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; +}; + +#define INIT_TASK \ +/* state etc */ { 0,15,15, \ +/* signals */ 0,{{},},0, \ +/* ec,brk... */ 0,0,0,0,0,0, \ +/* pid etc.. */ 0,0,0,0, \ +/* suppl grps*/ {NOGROUP,}, \ +/* proc links*/ &init_task.task,0,0,0, \ +/* uid etc */ 0,0,0,0,0,0, \ +/* timeout */ 0,0,0,0,0,0,0, \ +/* flags */ 0, \ +/* math */ 0, \ +/* fs info */ -1,0022,NULL,NULL,NULL,NULL,0, \ +/* filp */ {NULL,}, \ + { \ + {0,0}, \ +/* ldt */ {0x9f,0xc0fa00}, \ + {0x9f,0xc0f200}, \ + }, \ +/*tss*/ {0,PAGE_SIZE+(long)&init_task,0x10,0,0,0,0,(long)&pg_dir,\ + 0,0,0,0,0,0,0,0, \ + 0,0,0x17,0x17,0x17,0x17,0x17,0x17, \ + _LDT(0),0x80000000, \ + }, \ +} + +extern void sleep_on(struct task_struct ** p); +extern void interruptible_sleep_on(struct task_struct ** p); +extern void wake_up(struct task_struct ** p); +extern int in_group_p(gid_t grp); + +/* + * In linux is 4, because we add video selector, + * so, it is 5 here. + * */ +#define FIRST_TSS_ENTRY 5 +#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 switch_to(n) {\ + struct {long a,b;} __tmp; \ + __asm__("cmpl %%ecx,current\n\t" \ + "je 1f\n\t" \ + "movw %%dx,%1\n\t" \ + "xchgl %%ecx,current\n\t" \ + "ljmp *%0\n\t" \ + "1:" \ + ::"m" (*&__tmp.a),"m" (*&__tmp.b), \ + "d" (_TSS(n)),"c" ((long) task[n])); \ +} + +#define _set_base(addr,base) \ +__asm__("movw %%dx,%0\n\t" \ + "rorl $16,%%edx\n\t" \ + "movb %%dl,%1\n\t" \ + "movb %%dh,%2" \ + ::"m" (*((addr)+2)), \ + "m" (*((addr)+4)), \ + "m" (*((addr)+7)), \ + "d" (base) \ + :) + +#define _set_limit(addr,limit) \ +__asm__("movw %%dx,%0\n\t" \ + "rorl $16,%%edx\n\t" \ + "movb %1,%%dh\n\t" \ + "andb $0xf0,%%dh\n\t" \ + "orb %%dh,%%dl\n\t" \ + "movb %%dl,%1" \ + ::"m" (*(addr)), \ + "m" (*((addr)+6)), \ + "d" (limit) \ + :) + +#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , base ) +#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 ) + +#define _get_base(addr) ({\ +unsigned long __base = 0; \ +__asm__("movb %3,%%dh\n\t" \ + "movb %2,%%dl\n\t" \ + "shll $16,%%edx\n\t" \ + "movw %1,%%dx" \ + :"+d" (__base) \ + :"m" (*((addr)+2)), \ + "m" (*((addr)+4)), \ + "m" (*((addr)+7))); \ +__base;}) + +#define get_base(ldt) _get_base( ((char *)&(ldt)) ) + +#define get_limit(segment) ({ \ +unsigned long __limit = 0; \ +__asm__("lsll %1,%0\n\tincl %0":"=r" (__limit):"r" (segment)); \ +__limit;}) + +#endif diff --git a/include/linux/sys.h b/include/linux/sys.h new file mode 100644 index 0000000000000000000000000000000000000000..90ab25fe0ad2b1e49bcf283276efceffe43f1fdd --- /dev/null +++ b/include/linux/sys.h @@ -0,0 +1,193 @@ +extern int sys_setup(); +extern int sys_exit(); +extern int sys_fork(); +extern int sys_read(); +extern int sys_write(); +extern int sys_open(); +extern int sys_close(); +extern int sys_waitpid(); +//extern int sys_creat(); +extern int sys_link(); +extern int sys_unlink(); +extern int sys_execve(); +extern int sys_chdir(); +extern int sys_time(); +//extern int sys_mknod(); +//extern int sys_chmod(); +//extern int sys_chown(); +//extern int sys_break(); +extern int sys_stat(); +//extern int sys_lseek(); +extern int sys_getpid(); +//extern int sys_mount(); +//extern int sys_umount(); +extern int sys_setuid(); +extern int sys_getuid(); +//extern int sys_stime(); +//extern int sys_ptrace(); +extern int sys_alarm(); +extern int sys_fstat(); +//extern int sys_pause(); +extern int sys_utime(); +//extern int sys_stty(); +//extern int sys_gtty(); +//extern int sys_access(); +//extern int sys_nice(); +//extern int sys_ftime(); +extern int sys_sync(); +extern int sys_kill(); +//extern int sys_rename(); +extern int sys_mkdir(); +extern int sys_rmdir(); +extern int sys_dup(); +extern int sys_pipe(); +//extern int sys_times(); +//extern int sys_prof(); +//extern int sys_brk(); +//extern int sys_setgid(); +//extern int sys_getgid(); +extern int sys_signal(); +extern int sys_geteuid(); +extern int sys_getegid(); +//extern int sys_acct(); +//extern int sys_phys(); +//extern int sys_lock(); +extern int sys_ioctl(); +extern int sys_fcntl(); +//extern int sys_mpx(); +//extern int sys_setpgid(); +//extern int sys_ulimit(); +//extern int sys_uname(); +//extern int sys_umask(); +//extern int sys_chroot(); +//extern int sys_ustat(); +//extern int sys_dup2(); +extern int sys_getppid(); +//extern int sys_getpgrp(); +//extern int sys_setsid(); +extern int sys_sigaction(); +//extern int sys_sgetmask(); +//extern int sys_ssetmask(); +//extern int sys_setreuid(); +//extern int sys_setregid(); +//extern int sys_sigpending(); +//extern int sys_sigsuspend(); +//extern int sys_sethostname(); +//extern int sys_setrlimit(); +//extern int sys_getrlimit(); +//extern int sys_getrusage(); +//extern int sys_gettimeofday(); +//extern int sys_settimeofday(); +//extern int sys_getgroups(); +//extern int sys_setgroups(); +//extern int sys_select(); +extern int sys_symlink(); +//extern int sys_lstat(); +//extern int sys_readlink(); +//extern int sys_uselib(); +extern int sys_ls(); + +fn_ptr sys_call_table[] = { + sys_setup, + sys_exit, + sys_fork, + sys_read, + sys_write, + sys_open, + sys_close, + sys_waitpid, + 0,// sys_creat, + sys_link, + + sys_unlink, + sys_execve, + sys_chdir, + sys_time, + 0,// sys_mknod, + 0,// sys_chmod, + + 0,// sys_chown, + 0,// sys_break, + sys_stat, + 0,// sys_lseek, + sys_getpid, + 0,// sys_mount, + + 0, // sys_umount, + sys_setuid, + sys_getuid, + 0, // sys_stime, + 0, // sys_ptrace, + sys_alarm, + + sys_fstat, + 0, //sys_pause, + sys_utime, + 0,// sys_stty, + 0,// sys_gtty, + 0,// sys_access, + + 0,// sys_nice, + 0,// sys_ftime, + sys_sync, + sys_kill, + 0,// sys_rename, + sys_mkdir, + + sys_rmdir, + sys_dup, + sys_pipe, + 0,// sys_times, + 0,// sys_prof, + 0,// sys_brk, + 0,// sys_setgid, + + 0,// sys_getgid, + sys_signal, + sys_geteuid, + sys_getegid, + 0,// sys_acct, + 0,// sys_phys, + + 0, // sys_lock, + sys_ioctl, + sys_fcntl, + 0, // sys_mpx, + 0, // sys_setpgid, + 0, // sys_ulimit, + + 0, // sys_uname, + 0, // sys_umask, + 0, // sys_chroot, + 0, // sys_ustat, + 0, // sys_dup2, + sys_getppid, + + 0, // sys_getpgrp, + 0, // sys_setsid, + sys_sigaction, + 0, // sys_sgetmask, + 0, // sys_ssetmask, + + 0, // sys_setreuid, + 0, // sys_setregid, + 0, // sys_sigsuspend, + 0, // sys_sigpending, + 0, // sys_sethostname, + 0, // sys_setrlimit, + 0, // sys_getrlimit, + 0, // sys_getrusage, + 0, // sys_gettimeofday, + 0, // sys_settimeofday, + 0, // sys_getgroups, + 0, // sys_setgroups, + 0, // sys_select, + sys_symlink, + 0, // sys_lstat, + 0, // sys_readlink, + 0, // sys_uselib + sys_ls, +}; + +int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr); + diff --git a/include/linux/tty.h b/include/linux/tty.h new file mode 100644 index 0000000000000000000000000000000000000000..3f4b7a14bc416321d9d75d3a183291e0459b5d0d --- /dev/null +++ b/include/linux/tty.h @@ -0,0 +1,60 @@ +#ifndef _TTY_H +#define _TTY_H + +#include + +#define TTY_BUF_SIZE 1024 + +struct tty_queue { + unsigned long data; + unsigned long head; + unsigned long tail; + struct task_struct * proc_list; + char buf[TTY_BUF_SIZE]; +}; + +#define DEC(a) ((a) = ((a)-1) & (TTY_BUF_SIZE-1)) +#define LAST(a) ((a).buf[(TTY_BUF_SIZE-1)&((a).head-1)]) +#define LEFT(a) (((a).tail-(a).head-1)&(TTY_BUF_SIZE-1)) +#define FULL(a) (!LEFT(a)) + +unsigned long CHARS(struct tty_queue* q); +void PUTCH(char c, struct tty_queue* q); +char GETCH(struct tty_queue* q); +char EMPTY(struct tty_queue* q); + +#define INTR_CHAR(tty) ((tty)->termios.c_cc[VINTR]) +#define QUIT_CHAR(tty) ((tty)->termios.c_cc[VQUIT]) +#define ERASE_CHAR(tty) ((tty)->termios.c_cc[VERASE]) +#define KILL_CHAR(tty) ((tty)->termios.c_cc[VKILL]) +#define EOF_CHAR(tty) ((tty)->termios.c_cc[VEOF]) +#define START_CHAR(tty) ((tty)->termios.c_cc[VSTART]) +#define STOP_CHAR(tty) ((tty)->termios.c_cc[VSTOP]) +#define SUSPEND_CHAR(tty) ((tty)->termios.c_cc[VSUSP]) + +struct tty_struct { + struct termios termios; + int pgrp; + int session; + 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[]; + +#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0" + +void con_init(); +void tty_init(); + +void con_print(const char* buf, int nr); +void do_tty_interrupt(int tty); +void con_write(struct tty_struct * tty); + +void copy_to_cooked(struct tty_struct * tty); + +#endif + diff --git a/include/signal.h b/include/signal.h new file mode 100644 index 0000000000000000000000000000000000000000..54c430dcef49ec39eb4c842e6b6c03528afd7f0e --- /dev/null +++ b/include/signal.h @@ -0,0 +1,75 @@ +#ifndef _SIGNAL_H +#define _SIGNAL_H + +#include + +typedef int sig_atomic_t; +typedef unsigned int sigset_t; /* 32 bits */ + +#define _NSIG 32 +#define NSIG _NSIG + +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGTRAP 5 +#define SIGABRT 6 +#define SIGIOT 6 +#define SIGUNUSE D 7 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGUSR1 10 +#define SIGSEGV 11 +#define SIGUSR2 12 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGSTKFLT 16 +#define SIGCHLD 17 +#define SIGCONT 18 +#define SIGSTOP 19 +#define SIGTSTP 20 +#define SIGTTIN 21 +#define SIGTTOU 22 + +/* Ok, I haven't implemented sigactions, but trying to keep headers POSIX */ +#define SA_NOCLDSTOP 1 +#define SA_INTERRUPT 0x20000000 +#define SA_NOMASK 0x40000000 +#define SA_ONESHOT 0x80000000 + +#define SIG_BLOCK 0 /* for blocking signals */ +#define SIG_UNBLOCK 1 /* for unblocking signals */ +#define SIG_SETMASK 2 /* for setting the signal mask */ + +#define SIG_DFL ((void (*)(int))0) /* default signal handling */ +#define SIG_IGN ((void (*)(int))1) /* ignore signal */ +#define SIG_ERR ((void (*)(int))-1) /* error return from signal */ + +#ifdef notdef +#define sigemptyset(mask) ((*(mask) = 0), 1) +#define sigfillset(mask) ((*(mask) = ~0), 1) +#endif + +struct sigaction { + void (*sa_handler)(int); + sigset_t sa_mask; + int sa_flags; + void (*sa_restorer)(void); +}; + +void (*signal(int _sig, void (*_func)(int)))(int); +int raise(int sig); +int kill(pid_t pid, int sig); +int sigaddset(sigset_t *mask, int signo); +int sigdelset(sigset_t *mask, int signo); +int sigemptyset(sigset_t *mask); +int sigfillset(sigset_t *mask); +int sigismember(sigset_t *mask, int signo); /* 1 - is, 0 - not, -1 error */ +int sigpending(sigset_t *set); +int sigprocmask(int how, sigset_t *set, sigset_t *oldset); +int sigsuspend(sigset_t *sigmask); +int sigaction(int sig, struct sigaction *act, struct sigaction *oldact); + +#endif /* _SIGNAL_H */ diff --git a/include/stdarg.h b/include/stdarg.h new file mode 100644 index 0000000000000000000000000000000000000000..ebb37ccc2b12ba032eed3d9ffd8adb2573629ad9 --- /dev/null +++ b/include/stdarg.h @@ -0,0 +1,29 @@ +#ifndef _STDARG_H +#define _STDARG_H + +typedef char *va_list; + +/* Amount of space required in an argument list for an arg of type TYPE. + * TYPE may alternatively be an expression whose type is used. */ + +#define __va_rounded_size(TYPE) \ + (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) + +#ifndef __sparc__ +#define va_start(AP, LASTARG) \ + (AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG))) +#else +#define va_start(AP, LASTARG) \ + (__builtin_saveregs (), \ + AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG))) +#endif + +void va_end (va_list); /* Defined in gnulib */ +#define va_end(AP) + +#define va_arg(AP, TYPE) \ + (AP += __va_rounded_size (TYPE), \ + *((TYPE *) (AP - __va_rounded_size (TYPE)))) + +#endif /* _STDARG_H */ + diff --git a/include/stddef.h b/include/stddef.h new file mode 100644 index 0000000000000000000000000000000000000000..c340e05fb2b43243450038c8b8ca792552b59952 --- /dev/null +++ b/include/stddef.h @@ -0,0 +1,19 @@ +#ifndef _STDDEF_H +#define _STDDEF_H + +#ifndef _PTRDIFF_T +#define _PTRDIFF_T +typedef long ptrdiff_t; +#endif + +#ifndef _SIZE_T +#define _SIZE_T +typedef unsigned long size_t; +#endif + +#undef NULL +#define NULL ((void *)0) + +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + diff --git a/include/string.h b/include/string.h new file mode 100644 index 0000000000000000000000000000000000000000..3c55bef3d918ae758c03e9b6de2e3ecfe5ddf8f7 --- /dev/null +++ b/include/string.h @@ -0,0 +1,66 @@ +#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 + +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 + */ + +char * strcpy(char * dest,const char *src); + +char * strncpy(char * dest,const char *src,int count); + +char * strcat(char * dest,const char * src); + +char * strncat(char * dest,const char * src,int count); + +int strcmp(const char * cs,const char * ct); + +int strncmp(const char * cs,const char * ct,int count); + +char * strchr(const char * s,char c); + +char * strrchr(const char * s,char c); + +int strspn(const char * cs, const char * ct); + +int strcspn(const char * cs, const char * ct); + +char * strpbrk(const char * cs,const char * ct); + +char * strstr(const char * cs,const char * ct); + +int strlen(const char * s); + +char * strtok(char * s,const char * ct); + +void * memcpy(void * dest,const void * src, int n); + +void * memmove(void * dest,const void * src, int n); + +int memcmp(const void * cs,const void * ct,int count); + +void * memchr(const void * cs,char c,int count); + +void * memset(void * s,char c,int count); + +#endif + diff --git a/include/sys/param.h b/include/sys/param.h new file mode 100644 index 0000000000000000000000000000000000000000..9140cea97a4621bada082fcf6afc5062cfcf44b2 --- /dev/null +++ b/include/sys/param.h @@ -0,0 +1,13 @@ +#ifndef _SYS_PARAM_H +#define _SYS_PARAM_H + +#define HZ 100 +#define EXEC_PAGESIZE 4096 + +#define NGROUPS 32 /* Max number of groups per user */ +#define NOGROUP -1 + +#define MAXHOSTNAMELEN 8 + +#endif + diff --git a/include/sys/stat.h b/include/sys/stat.h new file mode 100644 index 0000000000000000000000000000000000000000..fedbfba20eb316b79c1553353e3726d32ccd8a69 --- /dev/null +++ b/include/sys/stat.h @@ -0,0 +1,61 @@ +#ifndef _SYS_STAT_H +#define _SYS_STAT_H + +#include + +struct stat { + dev_t st_dev; + ino_t st_ino; + umode_t st_mode; + nlink_t st_nlink; + uid_t st_uid; + gid_t st_gid; + dev_t st_rdev; + off_t st_size; + time_t st_atime; + time_t st_mtime; + time_t st_ctime; +}; + +#define S_IFMT 00170000 +#define S_IFLNK 0120000 +#define S_IFREG 0100000 +#define S_IFBLK 0060000 +#define S_IFDIR 0040000 +#define S_IFCHR 0020000 +#define S_IFIFO 0010000 +#define S_ISUID 0004000 +#define S_ISGID 0002000 +#define S_ISVTX 0001000 + +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) + +#define S_IRWXU 00700 +#define S_IRUSR 00400 +#define S_IWUSR 00200 +#define S_IXUSR 00100 + +#define S_IRWXG 00070 +#define S_IRGRP 00040 +#define S_IWGRP 00020 +#define S_IXGRP 00010 + +#define S_IRWXO 00007 +#define S_IROTH 00004 +#define S_IWOTH 00002 +#define S_IXOTH 00001 + +extern int chmod(const char *_path, mode_t mode); +extern int fstat(int fildes, struct stat *stat_buf); +extern int mkdir(const char *_path, mode_t mode); +extern int mkfifo(const char *_path, mode_t mode); +extern int stat(const char *filename, struct stat *stat_buf); +extern mode_t umask(mode_t mask); + +#endif + diff --git a/include/sys/time.h b/include/sys/time.h new file mode 100644 index 0000000000000000000000000000000000000000..c49f6b7eb791c30bcb0fa4ff0f97e44e7a302788 --- /dev/null +++ b/include/sys/time.h @@ -0,0 +1,17 @@ +#ifndef _SYS_TIME_H +#define _SYS_TIME_H + +struct timeval { + long tv_sec; + long tv_usec; +}; + +struct timezone { + int tz_minuteswest; + int tz_dsttime; +}; + +#include + +#endif + diff --git a/include/sys/types.h b/include/sys/types.h new file mode 100644 index 0000000000000000000000000000000000000000..aa260c84b9b4809cc0f5d6d9934cc12f7ae14d61 --- /dev/null +++ b/include/sys/types.h @@ -0,0 +1,52 @@ +#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 short 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 unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned long tcflag_t; + +typedef unsigned long fd_set; + +typedef struct { int quot,rem; } div_t; +typedef struct { long quot,rem; } ldiv_t; + +struct ustat { + daddr_t f_tfree; + ino_t f_tinode; + char f_fname[6]; + char f_fpack[6]; +}; + +#endif diff --git a/include/sys/wait.h b/include/sys/wait.h new file mode 100644 index 0000000000000000000000000000000000000000..58e36d61e5033b7ef3b41072f9d31900f2086003 --- /dev/null +++ b/include/sys/wait.h @@ -0,0 +1,24 @@ +#ifndef _SYS_WAIT_H +#define _SYS_WAIT_H + +#include + +#define _LOW(v) ( (v) & 0377) +#define _HIGH(v) ( ((v) >> 8) & 0377) + +/* options for waitpid, WUNTRACED not supported */ +#define WNOHANG 1 +#define WUNTRACED 2 + +#define WIFEXITED(s) (!((s)&0xFF)) +#define WIFSTOPPED(s) (((s)&0xFF)==0x7F) +#define WEXITSTATUS(s) (((s)>>8)&0xFF) +#define WTERMSIG(s) ((s)&0x7F) +#define WCOREDUMP(s) ((s)&0x80) +#define WSTOPSIG(s) (((s)>>8)&0xFF) +#define WIFSIGNALED(s) (((unsigned int)(s)-1 & 0xFFFF) < 0xFF) + +pid_t wait(int *stat_loc); +pid_t waitpid(pid_t pid, int *stat_loc, int options); + +#endif diff --git a/include/termios.h b/include/termios.h new file mode 100644 index 0000000000000000000000000000000000000000..6eb605d6be89346c29d36887a3bb1559c2b1241d --- /dev/null +++ b/include/termios.h @@ -0,0 +1,123 @@ +#ifndef _TERMIOS_H +#define _TERMIOS_H + +#define TTY_BUF_SIZE 1024 + +#define TCGETS 0x5401 +#define TCSETS 0x5402 +#define TCSETSW 0x5403 +#define TCSETSF 0x5404 +#define TCGETA 0x5405 +#define TCSETA 0x5406 +#define TCSETAW 0x5407 +#define TCSETAF 0x5408 +#define TCSBRK 0x5409 +#define TCXONC 0x540A +#define TCFLSH 0x540B +#define TIOCEXCL 0x540C +#define TIOCNXCL 0x540D +#define TIOCSCTTY 0x540E +#define TIOCGPGRP 0x540F +#define TIOCSPGRP 0x5410 +#define TIOCOUTQ 0x5411 +#define TIOCSTI 0x5412 +#define TIOCGWINSZ 0x5413 +#define TIOCSWINSZ 0x5414 +#define TIOCMGET 0x5415 +#define TIOCMBIS 0x5416 +#define TIOCMBIC 0x5417 +#define TIOCMSET 0x5418 +#define TIOCGSOFTCAR 0x5419 +#define TIOCSSOFTCAR 0x541A +#define FIONREAD 0x541B +#define TIOCINQ FIONREAD + +#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 short c_iflag; + unsigned short c_oflag; + unsigned short c_cflag; + unsigned short c_lflag; + unsigned char c_line; + unsigned char c_cc[NCCS]; +}; + +/* 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 + +// iflag +#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 + +// oflag +#define OPOST 0000001 +#define OLCUC 0000002 +#define ONLCR 0000004 +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 + + +// lflag +#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 + +/* tcflow() and TCXONC use these */ +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +#endif + diff --git a/include/time.h b/include/time.h new file mode 100644 index 0000000000000000000000000000000000000000..904902ef1dadd7e0d6a75d5a1d92c36930fb000b --- /dev/null +++ b/include/time.h @@ -0,0 +1,42 @@ +#ifndef _TIME_H +#define _TIME_H + +#ifndef _TIME_T +#define _TIME_T +typedef long time_t; +#endif + +#ifndef _SIZE_T +#define _SIZE_T +typedef unsigned int size_t; +#endif + +#ifndef NULL +#define NULL ((void *) 0) +#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; +}; + +#define __isleap(year) \ + ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 1000 == 0)) + +clock_t clock(); +int time(time_t * tp); +time_t mktime(struct tm * tp); + +#endif + diff --git a/include/unistd.h b/include/unistd.h new file mode 100644 index 0000000000000000000000000000000000000000..d5d4df6b3e3f6d8cc9dc37067075a73f900882b5 --- /dev/null +++ b/include/unistd.h @@ -0,0 +1,173 @@ +#ifndef _UNISTD_H +#define _UNISTD_H + +#include + +#ifndef NULL +#define NULL ((void*)0) +#endif + +#include + +#ifdef __LIBRARY__ + +#define __NR_setup 0 /* used only by init, to get system going */ +#define __NR_exit 1 +#define __NR_fork 2 +#define __NR_read 3 +#define __NR_write 4 +#define __NR_open 5 +#define __NR_close 6 +#define __NR_waitpid 7 +#define __NR_creat 8 +#define __NR_link 9 +#define __NR_unlink 10 +#define __NR_execve 11 +#define __NR_chdir 12 +#define __NR_time 13 +#define __NR_mknod 14 +#define __NR_chmod 15 +#define __NR_chown 16 +#define __NR_break 17 +#define __NR_stat 18 +#define __NR_lseek 19 +#define __NR_getpid 20 +#define __NR_mount 21 +#define __NR_umount 22 +#define __NR_setuid 23 +#define __NR_getuid 24 +#define __NR_stime 25 +#define __NR_ptrace 26 +#define __NR_alarm 27 +#define __NR_fstat 28 +#define __NR_pause 29 +#define __NR_utime 30 +#define __NR_stty 31 +#define __NR_gtty 32 +#define __NR_access 33 +#define __NR_nice 34 +#define __NR_ftime 35 +#define __NR_sync 36 +#define __NR_kill 37 +#define __NR_rename 38 +#define __NR_mkdir 39 +#define __NR_rmdir 40 +#define __NR_dup 41 +#define __NR_pipe 42 +#define __NR_times 43 +#define __NR_prof 44 +#define __NR_brk 45 +#define __NR_setgid 46 +#define __NR_getgid 47 +#define __NR_signal 48 +#define __NR_geteuid 49 +#define __NR_getegid 50 +#define __NR_acct 51 +#define __NR_phys 52 +#define __NR_lock 53 +#define __NR_ioctl 54 +#define __NR_fcntl 55 +#define __NR_mpx 56 +#define __NR_setpgid 57 +#define __NR_ulimit 58 +#define __NR_uname 59 +#define __NR_umask 60 +#define __NR_chroot 61 +#define __NR_ustat 62 +#define __NR_dup2 63 +#define __NR_getppid 64 +#define __NR_getpgrp 65 +#define __NR_setsid 66 +#define __NR_sigaction 67 +#define __NR_sgetmask 68 +#define __NR_ssetmask 69 +#define __NR_setreuid 70 +#define __NR_setregid 71 +#define __NR_sigsuspend 72 +#define __NR_sigpending 73 +#define __NR_sethostname 74 +#define __NR_setrlimit 75 +#define __NR_getrlimit 76 +#define __NR_getrusage 77 +#define __NR_gettimeofday 78 +#define __NR_settimeofday 79 +#define __NR_getgroups 80 +#define __NR_setgroups 81 +#define __NR_select 82 +#define __NR_symlink 83 +#define __NR_lstat 84 +#define __NR_readlink 85 +#define __NR_uselib 86 +#define __NR_ls 87 + +#define _syscall0(type, name) \ +type name() { \ + long __res; \ +__asm__ volatile("int $0x80\n\r"\ + : "=a"(__res) \ + : "a"(__NR_##name)); \ + if (__res >= 0) \ + return (type)__res; \ + errno = -__res; \ + return -1; \ +} + +#define _syscall1(type, name, atype, a) \ +type name(atype a) { \ + long __res; \ +__asm__ volatile("int $0x80\n\r"\ + : "=a"(__res) \ + : "a"(__NR_##name), "b"((long)(a))); \ + if (__res >= 0) \ + return (type)__res; \ + errno = -__res; \ + return -1; \ +} + +#define _syscall2(type, name, atype, a, btype, b) \ +type name(atype a, btype b) { \ + long __res; \ +__asm__ volatile("int $0x80\n\r"\ + : "=a"(__res) \ + : "a"(__NR_##name), "b"((long)(a)), "c"((long)(b))); \ + if (__res >= 0) \ + return (type)__res; \ + errno = -__res; \ + return -1; \ +} + +#define _syscall3(type,name,atype,a,btype,b,ctype,c) \ +type name(atype a, btype b, ctype c) { \ + long __res; \ +__asm__ volatile("int $0x80\n\r"\ + : "=a"(__res) \ + : "a"(__NR_##name), "b"((long)a), "c"((long)b), "d"((long)c)); \ + if (__res >= 0) \ + return (type)__res; \ + errno = -__res; \ + return -1; \ +} + +#endif /* __LIBRARY__ */ + +extern int errno; + +int fork(); +int read(int fildes, const char * buf, off_t count); +int write(int fildes, const char * buf, off_t count); +int ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); +int setup(void* BIOS); +int ls(); +int dup(int fildes); +int mkdir(const char *_path, mode_t mode); +int fstat(); +int rmdir(const char *_path); +int chdir(const char *_path); +int sync(); +int execve(const char * filename, char ** argv, char ** envp); +int time(time_t * tloc); + +int printf(const char* fmt, ...); + +#endif + diff --git a/include/utime.h b/include/utime.h new file mode 100644 index 0000000000000000000000000000000000000000..83f07c7bbfe72a5807214c0c0b3ffc5ece519e04 --- /dev/null +++ b/include/utime.h @@ -0,0 +1,13 @@ +#ifndef _UTIME_H +#define _UTIME_H + +#include /* I know - shouldn't do this, but .. */ + +struct utimbuf { + time_t actime; + time_t modtime; +}; + +extern int utime(const char *filename, struct utimbuf *times); + +#endif diff --git a/kernel/Makefile b/kernel/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..b09dc9cf5d116d2eb57c49955cd5142a53927227 --- /dev/null +++ b/kernel/Makefile @@ -0,0 +1,85 @@ +GCC := gcc +USE_DEBUG := +CCFLAG := -I../include -nostdinc -ffreestanding -Wall -fomit-frame-pointer -fno-pic -fno-stack-protector -c -m32 $(USE_DEBUG) +LDFLAG := -Ttext 0x0 -s --oformat binary -m elf_i386 +INCDIR := ../include +OBJS := head.o main.o sched.o fork.o printk.o sys_call.o vsprintf.o traps.o asm.o \ + sys.o panic.o segment.o mktime.o signal.o exit.o \ + ../fs/fs.o chr_drv/chr_drv.a blk_drv/blk_drv.a ../mm/mm.o ../lib/lib.a + +system: $(OBJS) + $(LD) $(LDFLAG) -e startup_32 -o $@ $^ -M > System.map + +head.o : head.S + $(GCC) -m32 -traditional -c -o $@ $< + +sys_call.o : sys_call.S + $(GCC) -m32 -traditional -c -o $@ $< + +main.o : main.c + $(GCC) $(CCFLAG) -o $@ $< + +sched.o : sched.c + $(GCC) $(CCFLAG) -o $@ $< + +fork.o : fork.c + $(GCC) $(CCFLAG) -o $@ $< + +panic.o : panic.c + $(GCC) $(CCFLAG) -o $@ $< + +asm.o : asm.S + $(GCC) -m32 -traditional -c -o $@ $< + +printk.o : printk.c + $(GCC) $(CCFLAG) -o $@ $< + +vsprintf.o : vsprintf.c + $(GCC) $(CCFLAG) -o $@ $< + +traps.o : traps.c + $(GCC) $(CCFLAG) -o $@ $< + +panic.o : panic.c + $(GCC) $(CCFLAG) -o $@ $< + +mktime.o : mktime.c + $(GCC) $(CCFLAG) -o $@ $< + +segment.o : segment.c + $(GCC) $(CCFLAG) -o $@ $< + +sys.o : sys.c + $(GCC) $(CCFLAG) -o $@ $< + +signal.o : signal.c + $(GCC) $(CCFLAG) -o $@ $< + +exit.o : exit.c + $(GCC) $(CCFLAG) -o $@ $< + +chr_drv/chr_drv.a: chr_drv/*.c + cd chr_drv; make chr_drv.a; cd .. + +blk_drv/blk_drv.a: blk_drv/*.c + cd blk_drv; make blk_drv.a; cd .. + +../mm/mm.o : ../mm/*.c + cd ../mm; make mm.o; cd .. + +../fs/fs.o : ../fs/*.c + cd ../fs; make fs.o; cd .. + +../lib/lib.a : ../lib/*.c + cd ../lib; make lib.a; cd ../kernel + +clean : + rm -f *.o + rm -f system + rm -f System.map + cd chr_drv; make clean; cd .. + cd blk_drv; make clean; cd .. + cd ../lib; make clean; cd ../kernel + cd ../mm; make clean; cd ../kernel + cd ../fs; make clean; cd ../kernel + diff --git a/kernel/asm.S b/kernel/asm.S new file mode 100644 index 0000000000000000000000000000000000000000..ce927e6fbf2df0d4db8b9f18ed99902a6d45de12 --- /dev/null +++ b/kernel/asm.S @@ -0,0 +1,128 @@ +.code32 +.globl divide_error, debug, nmi, int3, overflow, bounds, invalid_op +.globl double_fault, coprocessor_segment_overrun +.globl invalid_TSS, segment_not_present, stack_segment +.globl general_protection, coprocessor_error, reserved +.globl alignment_check + +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 + leal 44(%esp), %edx + pushl %edx + movl $0x10, %edx + movw %dx, %ds + movw %dx, %es + movw %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 + jmp no_error_code + +nmi: + pushl $do_nmi + jmp no_error_code + +int3: + pushl $do_int3 + jmp no_error_code + +overflow: + pushl $do_overflow + jmp no_error_code + +bounds: + pushl $do_bounds + jmp no_error_code + +invalid_op: + pushl $do_invalid_op + jmp no_error_code + +coprocessor_segment_overrun: + pushl $do_coprocessor_segment_overrun + jmp no_error_code + +reserved: + pushl $do_reserved + jmp no_error_code + + +double_fault: + pushl $do_double_fault +error_code: + xchgl %eax, 4(%esp) + xchgl %ebx, (%esp) + pushl %ecx + pushl %edx + pushl %edi + pushl %esi + pushl %ebp + push %ds + push %es + push %fs + pushl %eax + leal 44(%esp), %eax + pushl %eax + movl $0x10, %eax + movw %ax, %ds + movw %ax, %es + movw %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 + +alignment_check: + pushl $do_alignment_check + jmp error_code + diff --git a/kernel/blk_drv/Makefile b/kernel/blk_drv/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..6da5111a1229144ca841917ed88cc3b578ceb614 --- /dev/null +++ b/kernel/blk_drv/Makefile @@ -0,0 +1,23 @@ +AR := ar +LD := ld +GCC := gcc +CCFLAG := -I../../include -nostdinc -ffreestanding -Wall -fomit-frame-pointer -c -fno-stack-protector -fno-pie -fno-pic -m32 +OBJS := hd.o ll_rw_blk.o floppy.o + +blk_drv.a : $(OBJS) + $(AR) rcs $@ $^ + sync + +hd.o : hd.c + $(GCC) $(CCFLAG) -o $@ $< + +floppy.o : floppy.c + $(GCC) $(CCFLAG) -o $@ $< + +ll_rw_blk.o : ll_rw_blk.c + $(GCC) $(CCFLAG) -o $@ $< + +clean : + rm -f *.o + rm -f blk_drv.a + diff --git a/kernel/blk_drv/blk.h b/kernel/blk_drv/blk.h new file mode 100644 index 0000000000000000000000000000000000000000..62646c8df9c50445b8fb0e39d023af7a2a0aac60 --- /dev/null +++ b/kernel/blk_drv/blk.h @@ -0,0 +1,104 @@ +#ifndef _BLK_H +#define _BLK_H + +#define NR_BLK_DEV 7 + +#define NR_REQUEST 32 + +struct request { + int dev; + int cmd; + int errors; + unsigned long sector; + unsigned long nr_sectors; + char * buffer; + struct task_struct * waiting; + struct buffer_head * bh; + struct request * next; +}; + +#define IN_ORDER(s1,s2) \ +((s1)->cmd<(s2)->cmd || ((s1)->cmd==(s2)->cmd && \ +((s1)->dev < (s2)->dev || ((s1)->dev == (s2)->dev && \ +(s1)->sector < (s2)->sector)))) + +struct blk_dev_struct { + void (*request_fn)(void); + struct request * current_request; +}; + +extern struct blk_dev_struct blk_dev[NR_BLK_DEV]; +extern struct request request[NR_REQUEST]; +extern struct task_struct * wait_for_request; + +extern int * blk_size[NR_BLK_DEV]; + +#ifdef MAJOR_NR + +#if (MAJOR_NR == 2) +#define DEVICE_NAME "floppy" +#define DEVICE_INTR do_floppy +#define DEVICE_REQUEST do_fd_request +#define DEVICE_NR(device) ((device) & 3) +#define DEVICE_ON(device) floppy_on(DEVICE_NR(device)) +#define DEVICE_OFF(device) floppy_off(DEVICE_NR(device)) + +#elif (MAJOR_NR == 3) +#define DEVICE_NAME "harddisk" +#define DEVICE_INTR do_hd +#define DEVICE_TIMEOUT hd_timeout +#define DEVICE_REQUEST do_hd_request +#define DEVICE_NR(device) (MINOR(device)/5) +#define DEVICE_ON(device) +#define DEVICE_OFF(device) +#endif + +#define CURRENT (blk_dev[MAJOR_NR].current_request) +#define CURRENT_DEV DEVICE_NR(CURRENT->dev) + +#ifdef DEVICE_INTR +void (*DEVICE_INTR)(void) = NULL; +#endif + +extern void unlock_buffer(struct buffer_head * bh); +extern void lock_buffer(struct buffer_head * bh); +extern void end_request(int dev, int uptodate); + +#ifdef DEVICE_TIMEOUT +int DEVICE_TIMEOUT = 0; +#define SET_INTR(x) (DEVICE_INTR = (x),DEVICE_TIMEOUT = 200) +#else +#define SET_INTR(x) (DEVICE_INTR = (x)) +#endif + +void (DEVICE_REQUEST)(void); + +#ifdef DEVICE_TIMEOUT +#define CLEAR_DEVICE_TIMEOUT DEVICE_TIMEOUT = 0; +#else +#define CLEAR_DEVICE_TIMEOUT +#endif + +#ifdef DEVICE_INTR +#define CLEAR_DEVICE_INTR DEVICE_INTR = 0; +#else +#define CLEAR_DEVICE_INTR +#endif + +#define INIT_REQUEST \ +repeat: \ + if (!CURRENT) {\ + CLEAR_DEVICE_INTR \ + CLEAR_DEVICE_TIMEOUT \ + return; \ + }\ + if (MAJOR(CURRENT->dev) != MAJOR_NR) \ + printk(DEVICE_NAME ": request list destroyed"); \ + if (CURRENT->bh) { \ + if (!CURRENT->bh->b_lock) \ + printk(DEVICE_NAME ": block not locked"); \ + } + +#endif + +#endif diff --git a/kernel/blk_drv/floppy.c b/kernel/blk_drv/floppy.c new file mode 100644 index 0000000000000000000000000000000000000000..bf898a73641c99b152261e70641364ac94c0ffc5 --- /dev/null +++ b/kernel/blk_drv/floppy.c @@ -0,0 +1,361 @@ +#include +#include +#include +#include +#include +#include +#include + +#define MAJOR_NR 2 +#include "blk.h" + +static int recalibrate = 0; +static int reset = 0; +static int seek = 0; + +extern unsigned char current_DOR; + +#define immoutb_p(val,port) \ +__asm__("outb %0,%1\n\tjmp 1f\n1:\tjmp 1f\n1:"::"a" ((char) (val)),"i" (port)) + +#define TYPE(x) ((x)>>2) +#define DRIVE(x) ((x)&0x03) + +#define MAX_ERRORS 8 +#define MAX_REPLIES 7 +static unsigned char reply_buffer[MAX_REPLIES]; +#define ST0 (reply_buffer[0]) +#define ST1 (reply_buffer[1]) +#define ST2 (reply_buffer[2]) +#define ST3 (reply_buffer[3]) + +static struct floppy_struct { + unsigned int size, sect, head, track, stretch; + unsigned char gap,rate,spec1; +} floppy_type[] = { + { 0, 0,0, 0,0,0x00,0x00,0x00 }, + { 720, 9,2,40,0,0x2A,0x02,0xDF }, + { 2400,15,2,80,0,0x1B,0x00,0xDF }, + { 720, 9,2,40,1,0x2A,0x02,0xDF }, + { 1440, 9,2,80,0,0x2A,0x02,0xDF }, + { 720, 9,2,40,1,0x23,0x01,0xDF }, + { 1440, 9,2,80,0,0x23,0x01,0xDF }, + { 2880,18,2,80,0,0x1B,0x00,0xCF }, +}; + +extern void floppy_interrupt(); +extern char tmp_floppy_area[1024]; + +static int cur_spec1 = -1; +static int cur_rate = -1; +static struct floppy_struct * floppy = floppy_type; +static unsigned char current_drive = 0; +static unsigned char sector = 0; +static unsigned char head = 0; +static unsigned char track = 0; +static unsigned char seek_track = 0; +static unsigned char current_track = 255; +static unsigned char command = 0; +unsigned char selected = 0; +struct task_struct * wait_on_floppy_select = NULL; + +#define copy_buffer(from,to) \ +__asm__("cld ; rep ; movsl" \ + ::"c" (BLOCK_SIZE/4),"S" ((long)(from)),"D" ((long)(to)) \ + :) + +void floppy_deselect(unsigned int nr) { + if (nr != (current_DOR & 3)) + printk("floppy_deselect: drive not selected\n\r"); + selected = 0; + wake_up(&wait_on_floppy_select); +} + +int result() { + int i = 0, counter, status; + if (reset) + return -1; + for (counter = 0 ; counter < 10000 ; counter++) { + status = inb_p(FD_STATUS)&(STATUS_DIR|STATUS_READY|STATUS_BUSY); + if (status == STATUS_READY) + return i; + if (status == (STATUS_DIR|STATUS_READY|STATUS_BUSY)) { + if (i >= MAX_REPLIES) + break; + reply_buffer[i++] = inb_p(FD_DATA); + } + } + reset = 1; + printk("Getstatus times out\n\r"); + return -1; +} + +void bad_flp_intr() { + CURRENT->errors++; + if (CURRENT->errors > MAX_ERRORS) { + floppy_deselect(current_drive); + end_request(MAJOR_NR, 0); + } + + if (CURRENT->errors > MAX_ERRORS/2) + reset = 1; + else + recalibrate = 1; +} + +void setup_DMA() { + long addr = (long) CURRENT->buffer; + cli(); + if (addr >= 0x100000) { + addr = (long) tmp_floppy_area; + if (command == FD_WRITE) + copy_buffer(CURRENT->buffer,tmp_floppy_area); + } + immoutb_p(4|2,10); + __asm__("outb %%al,$12\n\tjmp 1f\n1:\tjmp 1f\n1:\t" + "outb %%al,$11\n\tjmp 1f\n1:\tjmp 1f\n1:":: + "a" ((char) ((command == FD_READ)?DMA_READ:DMA_WRITE))); + immoutb_p(addr,4); + addr >>= 8; + immoutb_p(addr,4); + addr >>= 8; + immoutb_p(addr,0x81); + immoutb_p(0xff,5); + immoutb_p(3,5); + immoutb_p(0|2,10); + sti(); +} + +void output_byte(char byte) { + int counter; + unsigned char status; + if (reset) + return; + for(counter = 0 ; counter < 10000 ; counter++) { + status = inb_p(FD_STATUS) & (STATUS_READY | STATUS_DIR); + if (status == STATUS_READY) { + outb(byte,FD_DATA); + return; + } + } + reset = 1; + printk("Unable to send byte to FDC\n\r"); +} + +void rw_interrupt() { + if (result() != 7 || (ST0 & 0xf8) || (ST1 & 0xbf) || (ST2 & 0x73)) { + if (ST1 & 0x02) { + printk("Drive %d is write protected\n\r",current_drive); + floppy_deselect(current_drive); + end_request(MAJOR_NR, 0); + } + else { + bad_flp_intr(); + } + + do_fd_request(); + return; + } + + if (command == FD_READ && (unsigned long)(CURRENT->buffer) >= 0x100000) + copy_buffer(tmp_floppy_area,CURRENT->buffer); + floppy_deselect(current_drive); + end_request(MAJOR_NR, 1); + do_fd_request(); +} + +static inline void setup_rw_floppy() { + setup_DMA(); + do_floppy = rw_interrupt; + output_byte(command); + output_byte(head<<2 | current_drive); + output_byte(track); + output_byte(head); + output_byte(sector); + output_byte(2); + output_byte(floppy->sect); + output_byte(floppy->gap); + output_byte(0xFF); + + if (reset) + do_fd_request(); +} + +void seek_interrupt() { + output_byte(FD_SENSEI); + if (result() != 2 || (ST0 & 0xF8) != 0x20 || ST1 != seek_track) { + bad_flp_intr(); + do_fd_request(); + return; + } + current_track = ST1; + setup_rw_floppy(); +} + +void unexpected_floppy_interrupt() { + output_byte(FD_SENSEI); + int res = result(); + printk("unexpected floppy interrupt %d, %d\n", res, ST0); + if (res != 2 || (ST0 & 0xE0) == 0x60) + reset = 1; + else + recalibrate = 1; +} + +void transfer() { + if (cur_spec1 != floppy->spec1) { + cur_spec1 = floppy->spec1; + output_byte(FD_SPECIFY); + output_byte(cur_spec1); + output_byte(6); + } + if (cur_rate != floppy->rate) + outb_p(cur_rate = floppy->rate,FD_DCR); + + if (reset) { + do_fd_request(); + return; + } + + if (!seek) { + setup_rw_floppy(); + return; + } + do_floppy = seek_interrupt; + if (seek_track) { + output_byte(FD_SEEK); + output_byte(head<<2 | current_drive); + output_byte(seek_track); + } + else { + output_byte(FD_RECALIBRATE); + output_byte(head<<2 | current_drive); + } + + if (reset) + do_fd_request(); +} + +void recal_interrupt() { + output_byte(FD_SENSEI); + if (result()!=2 || (ST0 & 0xE0) == 0x60) + reset = 1; + else + recalibrate = 0; + do_fd_request(); +} + +void recalibrate_floppy() { + recalibrate = 0; + current_track = 0; + do_floppy = recal_interrupt; + output_byte(FD_RECALIBRATE); + output_byte(head<<2 | current_drive); + if (reset) + do_fd_request(); +} + +void reset_interrupt() { + output_byte(FD_SENSEI); + (void) result(); + output_byte(FD_SPECIFY); + output_byte(cur_spec1); + output_byte(6); + do_fd_request(); +} + +void reset_floppy() { + int i; + reset = 0; + cur_spec1 = -1; + cur_rate = -1; + recalibrate = 1; + printk("Reset-floppy called\n\r"); + cli(); + do_floppy = reset_interrupt; + outb_p(current_DOR & ~0x04,FD_DOR); + for (i=0 ; i<100 ; i++) + __asm__("nop"); + outb(current_DOR,FD_DOR); + sti(); +} + +void floppy_on_interrupt() { + selected = 1; + if (current_drive != (current_DOR & 3)) { + current_DOR &= 0xFC; + current_DOR |= current_drive; + outb(current_DOR,FD_DOR); + add_timer(2,&transfer); + } + else { + transfer(); + } +} + +void do_fd_request() { + //printk("hinus debug: do_fd_request, reset: %d, recal: %d, current dev:%d\n", + // reset, recalibrate, CURRENT->dev); + unsigned int block; + seek = 0; + + if (reset) { + reset_floppy(); + return; + } + + if (recalibrate) { + recalibrate_floppy(); + return; + } + + INIT_REQUEST; + floppy = (MINOR(CURRENT->dev)>>2) + floppy_type; + + if (current_drive != CURRENT_DEV) + seek = 1; + + current_drive = CURRENT_DEV; + block = CURRENT->sector; + if (block+2 > floppy->size) { + end_request(MAJOR_NR, 0); + goto repeat; + } + + sector = block % floppy->sect; + block /= floppy->sect; + head = block % floppy->head; + track = block / floppy->head; + seek_track = track << floppy->stretch; + + if (seek_track != current_track) + seek = 1; + sector++; + if (CURRENT->cmd == READ) + command = FD_READ; + else if (CURRENT->cmd == WRITE) + command = FD_WRITE; + else + printk("do_fd_request: unknown command"); + + add_timer(ticks_to_floppy_on(current_drive),&floppy_on_interrupt); +} + +static int floppy_sizes[] ={ + 0, 0, 0, 0, + 360, 360 ,360, 360, + 1200,1200,1200,1200, + 360, 360, 360, 360, + 720, 720, 720, 720, + 360, 360, 360, 360, + 720, 720, 720, 720, + 1440,1440,1440,1440 +}; + +void floppy_init() { + blk_size[MAJOR_NR] = floppy_sizes; + blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; + set_trap_gate(0x26,&floppy_interrupt); + outb(inb_p(0x21)&~0x40,0x21); +} + diff --git a/kernel/blk_drv/hd.c b/kernel/blk_drv/hd.c new file mode 100644 index 0000000000000000000000000000000000000000..2b7233ac97b6dba14300b187979d8cb5a2f45e0a --- /dev/null +++ b/kernel/blk_drv/hd.c @@ -0,0 +1,260 @@ +#include +#include +#include +#include +#include +#include +#include + +#define MAJOR_NR 3 + +#include "blk.h" + +#define CMOS_READ(addr) ({ \ +outb_p(0x80|addr,0x70); \ +inb_p(0x71); \ +}) + +#define MAX_HD 2 + +struct hd_i_struct { + int head,sect,cyl,wpcom,lzone,ctl; +}; + +struct task_struct* waiting; + +struct buffer_head* bh; + +#ifdef HD_TYPE +struct hd_i_struct hd_info[] = { HD_TYPE }; +#define NR_HD ((sizeof (hd_info))/(sizeof (struct hd_i_struct))) +#else +struct hd_i_struct hd_info[] = { {0,0,0,0,0,0},{0,0,0,0,0,0} }; +static int NR_HD = 0; +#endif + +static struct hd_struct { + long start_sect; + long nr_sects; +} hd[5*MAX_HD]={{0,0},}; + +static int hd_sizes[5*MAX_HD] = {0, }; + +#define port_read(port,buf,nr) \ +__asm__("cld;rep;insw"::"d" (port),"D" (buf),"c" (nr):) + +#define port_write(port,buf,nr) \ +__asm__("cld;rep;outsw"::"d" (port),"S" (buf),"c" (nr):) + +extern void hd_interrupt(void); + +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"); + + SET_INTR(intr_addr); + outb_p(hd_info[drive].ctl,HD_CMD); + port=HD_DATA; + outb_p(hd_info[drive].wpcom>>2,++port); + outb_p(nsect,++port); + outb_p(sect,++port); + outb_p(cyl,++port); + outb_p(cyl>>8,++port); + outb_p(0xA0|(drive<<4)|head,++port); + outb(cmd,++port); +} + +void identity_callback() { + port_read(HD_DATA, bh->b_data, 256); + wake_up(&waiting); +} + +void hd_identity() { + bh = getblk(3, 0); + lock_buffer(bh); + + hd_out(0, 0, 0, 0, 0, WIN_IDENTIFY, identity_callback); + sleep_on(&waiting); + short* buf = (short*)bh->b_data; + int sectors = ((int)buf[61] << 16) + buf[60]; + printk("HD size: %dMB\n", sectors * 512 / 1024 / 1024); +} + +int sys_setup(void * BIOS) { + int i,drive; + unsigned char cmos_disks; + struct partition *p; + //struct buffer_head * bh; + +#ifndef HD_TYPE + for (drive=0 ; drive<2 ; drive++) { + hd_info[drive].cyl = *(unsigned short *) BIOS; + hd_info[drive].head = *(unsigned char *) (2+BIOS); + hd_info[drive].wpcom = *(unsigned short *) (5+BIOS); + hd_info[drive].ctl = *(unsigned char *) (8+BIOS); + hd_info[drive].lzone = *(unsigned short *) (12+BIOS); + hd_info[drive].sect = *(unsigned char *) (14+BIOS); + BIOS += 16; + } + + if (hd_info[1].cyl) + NR_HD = 2; + else + NR_HD = 1; +#endif + + printk("computer has %d disks\n\r", NR_HD); + + for (i=0 ; ib_data[510] != 0x55 || (unsigned char) bh->b_data[511] != 0xAA) { + printk("Bad partition table on drive %d\n\r",drive); + } + + p = 0x1BE + (void *)bh->b_data; + for (i=1;i<5;i++,p++) { + hd[i+5*drive].start_sect = p->start_sect; + hd[i+5*drive].nr_sects = p->nr_sects; + + printk("table %d: start at %d, has %d sects\n", drive, + hd[i+5*drive].start_sect, + hd[i+5*drive].nr_sects); + } + } + + for (i=0 ; i<5*MAX_HD ; i++) + hd_sizes[i] = hd[i].nr_sects>>1; + blk_size[MAJOR_NR] = hd_sizes; + + add_timer(300, test_c); + mount_root(); + return 0; +} + +static int win_result(void) { + int i = inb_p(HD_STATUS); + if ((i & (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT)) + == (READY_STAT | SEEK_STAT)) + return 0; + if (i&1) i = inb(HD_ERROR); + return (1); +} + +void unexpected_hd_interrupt() { + printk("Unexpected HD interrupt\n\r"); +} + +static void read_intr(void) { + if (win_result()) { + printk("hd read error.\n"); + do_hd_request(); + return; + } + port_read(HD_DATA,CURRENT->buffer,256); + CURRENT->errors = 0; + CURRENT->buffer += 512; + CURRENT->sector++; + if (--CURRENT->nr_sectors) { + //printk("nr_sectors:%d\n", CURRENT->nr_sectors); + SET_INTR(&read_intr); + return; + } + end_request(MAJOR_NR, 1); + do_hd_request(); +} + +static void write_intr() { + if (win_result()) { + do_hd_request(); + } + + if (--CURRENT->nr_sectors) { + CURRENT->sector++; + CURRENT->buffer += 512; + SET_INTR(&write_intr); + port_write(HD_DATA,CURRENT->buffer,256); + return; + } + + end_request(MAJOR_NR, 1); + do_hd_request(); +} + +void do_hd_request() { + int i,r; + unsigned int block,dev; + unsigned int sec,head,cyl; + unsigned int nsect; + + INIT_REQUEST; + dev = MINOR(CURRENT->dev); + block = CURRENT->sector; + + if (dev >= 5*NR_HD || block+2 > hd[dev].nr_sects) { + end_request(MAJOR_NR, 0); + goto repeat; + } + + block += hd[dev].start_sect; + dev /= 5; + + __asm__("divl %4":"=a" (block),"=d" (sec):"0" (block),"1" (0), + "r" (hd_info[dev].sect)); + __asm__("divl %4":"=a" (cyl),"=d" (head):"0" (block),"1" (0), + "r" (hd_info[dev].head)); + sec++; + nsect = CURRENT->nr_sectors; + + if (CURRENT->cmd == WRITE) { + hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr); + for(i=0 ; i<10000 && !(r=inb_p(HD_STATUS)&DRQ_STAT) ; i++) + /*nothing*/; + port_write(HD_DATA,CURRENT->buffer,256); + } + else if (CURRENT->cmd == READ) { + hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr); + } + else + printk("unknown hd-command"); +} + +void hd_init() { + blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; + set_intr_gate(0x2E,&hd_interrupt); + outb_p(inb_p(0x21)&0xfb,0x21); + outb(inb_p(0xA1)&0xbf,0xA1); +} + diff --git a/kernel/blk_drv/ll_rw_blk.c b/kernel/blk_drv/ll_rw_blk.c new file mode 100644 index 0000000000000000000000000000000000000000..d3ae35943c1000bb77ce5d620de2afe6480972f0 --- /dev/null +++ b/kernel/blk_drv/ll_rw_blk.c @@ -0,0 +1,139 @@ +#include +#include +#include +#include + +#include "blk.h" + +struct request request[NR_REQUEST]; + +struct blk_dev_struct blk_dev[NR_BLK_DEV] = { + { NULL, NULL }, + { NULL, NULL }, + { NULL, NULL }, + { NULL, NULL }, + { NULL, NULL }, + { NULL, NULL }, + { NULL, NULL }, +}; + +int * blk_size[NR_BLK_DEV] = { NULL, NULL, }; + +struct task_struct * wait_for_request = NULL; + +void lock_buffer(struct buffer_head * bh) { + cli(); + while (bh->b_lock) + sleep_on(&bh->b_wait); + bh->b_lock=1; + sti(); +} + +void unlock_buffer(struct buffer_head * bh) { + if (!bh->b_lock) + printk("ll_rw_block.c: buffer not locked\n\r"); + bh->b_lock = 0; + wake_up(&bh->b_wait); +} + +static void add_request(struct blk_dev_struct * dev, struct request * req) { + struct request * tmp; + req->next = NULL; + cli(); + + if (req->bh) + req->bh->b_dirt = 0; + + if (!(tmp = dev->current_request)) { + dev->current_request = req; + sti(); + (dev->request_fn)(); + return; + } + + for ( ; tmp->next ; tmp=tmp->next) { + if (!req->bh) { + if (tmp->next->bh) + break; + else + continue; + } + + if ((IN_ORDER(tmp,req) || + !IN_ORDER(tmp,tmp->next)) && + IN_ORDER(req,tmp->next)) + break; + } + + req->next=tmp->next; + tmp->next=req; + sti(); +} + +static void make_request(int major,int rw, struct buffer_head * bh) { + struct request * req; + lock_buffer(bh); + if ((rw == WRITE && !bh->b_dirt) || (rw == READ && bh->b_uptodate)) { + unlock_buffer(bh); + return; + } + +repeat: + if (rw == READ) + req = request+NR_REQUEST; + else + req = request+((NR_REQUEST*2)/3); + + while (--req >= request) + if (req->dev<0) + break; + + if (req < request) { + sleep_on(&wait_for_request); + goto repeat; + } + + req->dev = bh->b_dev; + req->cmd = rw; + req->errors=0; + req->sector = bh->b_blocknr<<1; + req->nr_sectors = 2; + req->buffer = bh->b_data; + req->waiting = NULL; + req->bh = bh; + req->next = NULL; + add_request(major+blk_dev,req); +} + +void ll_rw_block(int rw, struct buffer_head * bh) { + unsigned int major; + major = MAJOR(bh->b_dev); + + make_request(major,rw,bh); +} + +void end_request(int dev, int uptodate) { + struct request * req = blk_dev[dev].current_request; + //printk("end request\n"); + //DEVICE_OFF(dev); + if (req->bh) { + req->bh->b_uptodate = uptodate; + unlock_buffer(req->bh); + } + if (!uptodate) { + printk("I/O error\n\r"); + printk("dev %04x, block %d\n\r", dev, + req->bh->b_blocknr); + } + req->dev = -1; + blk_dev[dev].current_request = req->next; +} + +void blk_dev_init() { + int i; + + for (i=0 ; i +#include +#include + +#include +#include + +#define ORIG_X (*(unsigned char *)0x90000) +#define ORIG_Y (*(unsigned char *)0x90001) +#define ORIG_VIDEO_PAGE (*(unsigned short *)0x90004) +#define ORIG_VIDEO_MODE ((*(unsigned short *)0x90006) & 0xff) +#define ORIG_VIDEO_COLS (((*(unsigned short *)0x90006) & 0xff00) >> 8) +#define ORIG_VIDEO_LINES ((*(unsigned short *)0x9000e) & 0xff) +#define ORIG_VIDEO_EGA_AX (*(unsigned short *)0x90008) +#define ORIG_VIDEO_EGA_BX (*(unsigned short *)0x9000a) +#define ORIG_VIDEO_EGA_CX (*(unsigned short *)0x9000c) + +#define VIDEO_TYPE_MDA 0x10 /* Monochrome Text Display */ +#define VIDEO_TYPE_CGA 0x11 /* CGA Display */ +#define VIDEO_TYPE_EGAM 0x20 /* EGA/VGA in Monochrome Mode */ +#define VIDEO_TYPE_EGAC 0x21 /* EGA/VGA in Color Mode */ + +#define NPAR 16 + +extern void keyboard_interrupt(void); + +static unsigned char video_type; /* Type of display being used */ +static unsigned long video_num_columns; /* Number of text columns */ +static unsigned long video_num_lines; /* Number of test lines */ +static unsigned long video_mem_base; /* Base of video memory */ +static unsigned long video_mem_term; /* End of video memory */ +static unsigned long video_size_row; /* Bytes per row */ +static unsigned char video_page; /* Initial video page */ +static unsigned short video_port_reg; /* Video register select port */ +static unsigned short video_port_val; /* Video register value port */ +static unsigned short video_erase_char; + +static unsigned long origin; +static unsigned long scr_end; +static unsigned long pos; +static unsigned long x, y; +static unsigned long top, bottom; +static unsigned long state = 0; +static unsigned long npar, par[NPAR]; +static unsigned long ques = 0; +static unsigned long attr = 0x07; +static unsigned long def_attr = 0x07; + +#define RESPONSE "\033[?1;2c" + +static inline void gotoxy(int new_x,unsigned int new_y) { + if (new_x > video_num_columns || new_y >= video_num_lines) + return; + + x = new_x; + y = new_y; + pos = origin + y*video_size_row + (x << 1); +} + +static inline void set_origin() { + cli(); + outb_p(12, video_port_reg); + outb_p(0xff & ((origin - video_mem_base) >> 9), video_port_val); + outb_p(13, video_port_reg); + outb_p(0xff & ((origin - video_mem_base) >> 1), video_port_val); + sti(); +} + +static inline void set_cursor() { + cli(); + outb_p(14, video_port_reg); + outb_p(0xff&((pos-video_mem_base)>>9), video_port_val); + outb_p(15, video_port_reg); + outb_p(0xff&((pos-video_mem_base)>>1), video_port_val); + sti(); +} + +static void respond(struct tty_struct * tty) { + char * p = RESPONSE; + + cli(); + while (*p) { + PUTCH(*p, &tty->read_q); + p++; + } + sti(); + copy_to_cooked(tty); +} + +static void scrup() { + if (!top && bottom == video_num_lines) { + origin += video_size_row; + pos += video_size_row; + scr_end += video_size_row; + + if (scr_end > video_mem_term) { + __asm__("cld\n\t" + "rep\n\t" + "movsl\n\t" + "movl video_num_columns,%1\n\t" + "rep\n\t" + "stosw" + ::"a" (video_erase_char), + "c" ((video_num_lines-1)*video_num_columns>>1), + "D" (video_mem_base), + "S" (origin):); + scr_end -= origin-video_mem_base; + pos -= origin-video_mem_base; + origin = video_mem_base; + } + else { + __asm__("cld\n\t" + "rep\n\t" + "stosw" + ::"a" (video_erase_char), + "c" (video_num_columns), + "D" (scr_end-video_size_row):); + } + set_origin(); + } + else { + __asm__("cld\n\t" + "rep\n\t" + "movsl\n\t" + "movl video_num_columns,%%ecx\n\t" + "rep\n\t" + "stosw" + ::"a" (video_erase_char), + "c" ((bottom-top-1)*video_num_columns>>1), + "D" (origin+video_size_row*top), + "S" (origin+video_size_row*(top+1)):); + } +} + +static void scrdown() { + if (bottom <= top) + return; + + __asm__("std\n\t" + "rep\n\t" + "movsl\n\t" + "addl $2,%%edi\n\t" + "movl video_num_columns,%%ecx\n\t" + "rep\n\t" + "stosw" + ::"a" (video_erase_char), + "c" ((bottom-top-1)*video_num_columns>>1), + "D" (origin+video_size_row*bottom-4), + "S" (origin+video_size_row*(bottom-1)-4):); +} + +static void ri() { + if (y>top) { + y--; + pos -= video_size_row; + return; + } + scrdown(); +} + +static void lf() { + if (y + 1 < bottom) { + y++; + pos += video_size_row; + return; + } + scrup(); +} + +static void cr() { + pos -= x << 1; + x = 0; +} + +static void del() { + if (x) { + pos -= 2; + x--; + *(unsigned short*)pos = video_erase_char; + } +} + +static void csi_J(int vpar) { + long count, start; + + switch (vpar) { + case 0: + count = (scr_end-pos)>>1; + start = pos; + break; + case 1: + count = (pos-origin)>>1; + start = origin; + break; + case 2: + count = video_num_columns * video_num_lines; + start = origin; + break; + default: + return; + } + + __asm__("cld\n\t" + "rep\n\t" + "stosw\n\t" + ::"c" (count), + "D" (start),"a" (video_erase_char) + :); +} + +static void csi_K(int vpar) { + long count, start; + + switch (vpar) { + case 0: + if (x>=video_num_columns) + return; + count = video_num_columns-x; + start = pos; + break; + case 1: + start = pos - (x<<1); + count = (x>4);break; /* negative */ + case 22: attr=attr&0xf7;break; /* not bold */ + case 24: attr=attr&0xfe;break; /* not underline */ + case 25: attr=attr&0x7f;break; /* not blinking */ + case 27: attr=def_attr;break; /* positive image */ + case 39: attr=(attr & 0xf0)|(def_attr & 0x0f); break; + case 49: attr=(attr & 0x0f)|(def_attr & 0xf0); break; + default: + if ((par[i]>=30) && (par[i]<=38)) + attr = (attr & 0xf0) | (par[i]-30); + else if ((par[i]>=40) && (par[i]<=48)) + attr = (attr & 0x0f) | ((par[i]-40)<<4); + else + break; + } + } +} + +static void delete_char() { + int i; + unsigned short * p = (unsigned short *) pos; + if (x>=video_num_columns) + return; + i = x; + while (++i < video_num_columns) { + *p = *(p+1); + p++; + } + *p = video_erase_char; +} + +static void delete_line() { + int oldtop,oldbottom; + + oldtop = top; + oldbottom = bottom; + top = y; + bottom = video_num_lines; + scrup(); + top = oldtop; + bottom = oldbottom; +} + +static void insert_char() { + int i=x; + unsigned short tmp, old = video_erase_char; + unsigned short * p = (unsigned short *) pos; + + while (i++ video_num_columns) + nr = video_num_columns; + else if (!nr) + nr = 1; + while (nr--) + insert_char(); +} + +static void csi_L(unsigned int nr) { + if (nr > video_num_lines) + nr = video_num_lines; + else if (!nr) + nr = 1; + while (nr--) + insert_line(); +} + +static void csi_P(unsigned int nr) { + if (nr > video_num_columns) + nr = video_num_columns; + else if (!nr) + nr = 1; + while (nr--) + delete_char(); +} + +static void csi_M(unsigned int nr) { + if (nr > video_num_lines) + nr = video_num_lines; + else if (!nr) + nr=1; + while (nr--) + delete_line(); +} + +static int saved_x = 0; +static int saved_y = 0; + +static void save_cur() { + saved_x=x; + saved_y=y; +} + +static void restore_cur() { + gotoxy(saved_x, saved_y); +} + +void con_init() { + register unsigned char a; + + char * display_desc = "????"; + char * display_ptr; + + video_num_columns = ORIG_VIDEO_COLS; + video_size_row = video_num_columns * 2; + video_num_lines = ORIG_VIDEO_LINES; + video_page = ORIG_VIDEO_PAGE; + video_erase_char = 0x0720; + + /* Is this a monochrome display? */ + if (ORIG_VIDEO_MODE == 7) { + video_mem_base = 0xb0000; + video_port_reg = 0x3b4; + video_port_val = 0x3b5; + if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) { + video_type = VIDEO_TYPE_EGAM; + video_mem_term = 0xb8000; + display_desc = "EGAm"; + } + else { + video_type = VIDEO_TYPE_MDA; + video_mem_term = 0xb2000; + display_desc = "*MDA"; + } + } + else { /* color display */ + video_mem_base = 0xb8000; + video_port_reg = 0x3d4; + video_port_val = 0x3d5; + + if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) { + video_type = VIDEO_TYPE_EGAC; + video_mem_term = 0xc0000; + display_desc = "EGAc"; + } + else { + video_type = VIDEO_TYPE_CGA; + video_mem_term = 0xba000; + display_desc = "*CGA"; + } + } + + display_ptr = ((char *)video_mem_base) + video_size_row - 8; + while (*display_desc) { + *display_ptr++ = *display_desc++; + display_ptr++; + } + + origin = video_mem_base; + scr_end = video_mem_base + video_num_lines * video_size_row; + top = 0; + bottom = video_num_lines; + + gotoxy(ORIG_X, ORIG_Y); + set_cursor(); + + set_trap_gate(0x21,&keyboard_interrupt); + outb_p(inb_p(0x21)&0xfd,0x21); + a=inb_p(0x61); + outb_p(a|0x80,0x61); + outb_p(a,0x61); +} + +enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey, + ESsetterm, ESsetgraph }; + +void con_write(struct tty_struct* tty) { + int nr; + char c; + + nr = CHARS(&tty->write_q); + + while(nr--) { + c = GETCH(&tty->write_q); + switch (state) { + case 0: + if (c > 31 && c < 127) { + if (x >= video_num_columns) { + x -= video_num_columns; + pos -= video_size_row; + lf(); + } + + *(char *)pos = c; + *(((char*)pos) + 1) = attr; + pos += 2; + x++; + } + else if (c == 27) { + state = ESesc; + } + else if (c == 10 || c == 11 || c == 12) + lf(); + else if (c == 13) + cr(); + else if (c == 127) { + del(); + } + else if (c == 8) { + if (x) { + x--; + pos -= 2; + } + } + else if (c == 9) { + c=8-(x&7); + x += c; + pos += c<<1; + if (x > video_num_columns) { + x -= video_num_columns; + pos -= video_size_row; + lf(); + } + c = 9; + } + break; + case ESesc: + state = ESnormal; + switch (c) { + case '[': + state = ESsquare; + break; + case 'E': + gotoxy(0, y+1); + break; + case 'M': + ri(); + break; + case 'D': + lf(); + break; + case 'Z': + respond(tty); + break; + case '7': + save_cur(); + break; + case '8': + restore_cur(); + break; + case '(': case ')': + state = ESsetgraph; + break; + case 'P': + state = ESsetterm; + break; + case '#': + state = -1; + break; + case 'c': + top = 0; + bottom = video_num_lines; + break; + } + break; + case ESsquare: + for(npar=0;npar='0' && c<='9') { + par[npar]=10*par[npar]+c-'0'; + break; + } + else + state=ESgotpars; + case ESgotpars: + state = ESnormal; + if (ques) { + ques = 0; + break; + } + 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(par[0]); + break; + case 'r': + if (par[0]) par[0]--; + if (!par[1]) par[1] = video_num_lines; + if (par[0] < par[1] && + par[1] <= video_num_lines) { + top=par[0]; + bottom=par[1]; + } + break; + case 's': + save_cur(); + break; + case 'u': + restore_cur(); + break; + } + break; + case ESsetterm: + state = ESnormal; + if (c == 'S') { + def_attr = attr; + video_erase_char = (video_erase_char&0x0ff) | (def_attr<<8); + } else if (c == 'L') + ; /*linewrap on*/ + else if (c == 'l') + ; /*linewrap off*/ + break; + } + } + + gotoxy(x, y); + set_cursor(); +} + +void con_print(const char* buf, int nr) { + const char* s = buf; + + while(nr--) { + char c = *s++; + if (c > 31 && c < 127) { + if (x >= video_num_columns) { + x -= video_num_columns; + pos -= video_size_row; + lf(); + } + + *(char *)pos = c; + *(((char*)pos) + 1) = attr; + pos += 2; + x++; + } + else if (c == 10 || c == 11 || c == 12) + lf(); + else if (c == 13) + cr(); + else if (c == 127) { + del(); + } + else if (c == 8) { + if (x) { + x--; + pos -= 2; + } + } + } + + gotoxy(x, y); + set_cursor(); +} + diff --git a/kernel/chr_drv/kboard.c b/kernel/chr_drv/kboard.c new file mode 100644 index 0000000000000000000000000000000000000000..a64a40052227504be16cbfa26d7dd7b31c9ce882 --- /dev/null +++ b/kernel/chr_drv/kboard.c @@ -0,0 +1,289 @@ +#include +#include +#include +#include + +extern struct tty_struct tty_table[1]; + +typedef void (*key_fn)(); +void do_self(); +void ctrl(); +void func(); + +void cursor(); + +void lshift(); +void rshift(); +void unlshift(); +void unrshift(); + +void caps(); +void uncaps(); + +void alt() {} +void unalt() {} +void unctrl(); +void minus(); +void num(); +void scroll(); + +static key_fn key_table[] = { + 0,do_self,do_self,do_self, /* 00-03 s0 esc 1 2 */ + do_self,do_self,do_self,do_self, /* 04-07 3 4 5 6 */ + do_self,do_self,do_self,do_self, /* 08-0B 7 8 9 0 */ + do_self,do_self,do_self,do_self, /* 0C-0F + ' bs tab */ + do_self,do_self,do_self,do_self, /* 10-13 q w e r */ + do_self,do_self,do_self,do_self, /* 14-17 t y u i */ + do_self,do_self,do_self,do_self, /* 18-1B o p } ^ */ + do_self,ctrl,do_self,do_self, /* 1C-1F enter ctrl a s */ + do_self,do_self,do_self,do_self, /* 20-23 d f g h */ + do_self,do_self,do_self,do_self, /* 24-27 j k l | */ + do_self,do_self,lshift,do_self, /* 28-2B { para lshift , */ + do_self,do_self,do_self,do_self, /* 2C-2F z x c v */ + do_self,do_self,do_self,do_self, /* 30-33 b n m , */ + do_self,minus,rshift,do_self, /* 34-37 . - rshift * */ + alt,do_self,caps,func, /* 38-3B alt sp caps f1 */ + func,func,func,func, /* 3C-3F f2 f3 f4 f5 */ + func,func,func,func, /* 40-43 f6 f7 f8 f9 */ + func,num,scroll,cursor, /* 44-47 f10 num scr home */ + cursor,cursor,do_self,cursor, /* 48-4B up pgup - left */ + cursor,cursor,do_self,cursor, /* 4C-4F n5 right + end */ + cursor,cursor,cursor,cursor, /* 50-53 dn pgdn ins del */ + 0,0,do_self,func, /* 54-57 sysreq ? < f11 */ + func,0,0,0, /* 58-5B f12 ? ? ? */ + 0,0,0,0, /* 5C-5F ? ? ? ? */ + 0,0,0,0, /* 60-63 ? ? ? ? */ + 0,0,0,0, /* 64-67 ? ? ? ? */ + 0,0,0,0, /* 68-6B ? ? ? ? */ + 0,0,0,0, /* 6C-6F ? ? ? ? */ + 0,0,0,0, /* 70-73 ? ? ? ? */ + 0,0,0,0, /* 74-77 ? ? ? ? */ + 0,0,0,0, /* 78-7B ? ? ? ? */ + 0,0,0,0, /* 7C-7F ? ? ? ? */ + 0,0,0,0, /* 80-83 ? br br br */ + 0,0,0,0, /* 84-87 br br br br */ + 0,0,0,0, /* 88-8B br br br br */ + 0,0,0,0, /* 8C-8F br br br br */ + 0,0,0,0, /* 90-93 br br br br */ + 0,0,0,0, /* 94-97 br br br br */ + 0,0,0,0, /* 98-9B br br br br */ + 0,unctrl,0,0, /* 9C-9F br unctrl br br */ + 0,0,0,0, /* A0-A3 br br br br */ + 0,0,0,0, /* A4-A7 br br br br */ + 0,0,unlshift,0, /* A8-AB br br unlshift br */ + 0,0,0,0, /* AC-AF br br br br */ + 0,0,0,0, /* B0-B3 br br br br */ + 0,0,unrshift,0, /* B4-B7 br br unrshift br */ + unalt,0,uncaps,0, /* B8-BB unalt br uncaps br */ + 0,0,0,0, /* BC-BF br br br br */ + 0,0,0,0, /* C0-C3 br br br br */ + 0,0,0,0, /* C4-C7 br br br br */ + 0,0,0,0, /* C8-CB br br br br */ + 0,0,0,0, /* CC-CF br br br br */ + 0,0,0,0, /* D0-D3 br br br br */ + 0,0,0,0, /* D4-D7 br br br br */ + 0,0,0,0, /* D8-DB br ? ? ? */ + 0,0,0,0, /* DC-DF ? ? ? ? */ + 0,0,0,0, /* E0-E3 e0 e1 ? ? */ + 0,0,0,0, /* E4-E7 ? ? ? ? */ + 0,0,0,0, /* E8-EB ? ? ? ? */ + 0,0,0,0, /* EC-EF ? ? ? ? */ + 0,0,0,0, /* F0-F3 ? ? ? ? */ + 0,0,0,0, /* F4-F7 ? ? ? ? */ + 0,0,0,0, /* F8-FB ? ? ? ? */ + 0,0,0,0, /* FC-FF ? ? ? ? */ +}; + +void kb_wait(); + +static char key_map[0x7f] = { + 0, 27, + '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', + 127, 9, + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', + 10, 0, + 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', + '`', 0, + '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', + 0, '*', 0, 32, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + '-', 0, 0, 0, '+', + 0,0,0,0,0,0,0, + '>', + 0,0,0,0,0,0,0,0,0,0 +}; + +static char shift_map[0x7f] = { + 0,27, + '!', '@', '#', '$', '%', '^', '&', '*','(',')','_','+', + 127,9, + 'Q','W','E','R','T','Y','U','I','O','P','{','}', + 10,0, + 'A','S','D','F','G','H','J','K','L',':','\"', + '~',0, + '|','Z','X','C','V','B','N','M','<','>','?', + 0,'*',0,32, //36h-39h + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, //3Ah-49h + '-',0,0,0,'+', //4A-4E + 0,0,0,0,0,0,0, //4F-55 + '>', + 0,0,0,0,0,0,0,0,0,0 +}; + +unsigned char scan_code, leds, mode, e0; + +void keyboard_handler(void) { + scan_code = inb_p(0x60); + outb(0x20, 0x20); + + if (scan_code == 0xE0) { + e0 = 1; + } + else if (scan_code == 0xE1) { + e0 = 2; + } + else { + key_fn func = key_table[scan_code]; + if (func) + func(); + } + + do_tty_interrupt(0); +} + +void do_self() { + char* rmap = key_map; + char c = 0; + if (mode & 0x3) // shift + rmap = shift_map; + + c = rmap[scan_code]; + if (!c) + return; + + if (mode & 0x4c) { + if (c >= 'a' && c <= '}') + c -= 0x20; + if (mode & 0xc && c >= 64 && c < 96) + c -= 0x40; + } + + PUTCH(c, &tty_table[0].read_q); +} + +void lshift() { + mode |= 0x1; +} + +void unlshift() { + mode &= 0xfe; +} + +void rshift() { + mode |= 0x2; +} + +void unrshift() { + mode &= 0xfd; +} + +void kb_wait() { + unsigned char a; + while(1) { + a = inb(0x64); + if (a == 0x2) + return; + } +} + +void set_leds() { + kb_wait(); + outb(0xed, 0x60); + kb_wait(); + outb(leds, 0x60); +} + +void caps() { + if (mode & 0x80) + return; + + leds ^= 0x4; + mode ^= 0x40; + mode |= 0x80; + set_leds(); +} + +void uncaps() { + mode &= 0x7f; +} + +void scroll() { + leds ^= 0x1; + set_leds(); +} + +void num() { + leds ^= 0x2; + set_leds(); +} + +void ctrl() { + if (e0) { + mode |= 0x8; + } + else { + mode |= 0x4; + } +} + +void unctrl() { + if (e0) { + mode &= 0xf7; + } + else { + mode &= 0xfb; + } +} + +char* cur_table = "HA5 DGC YB623"; +char* num_table = "789 456 1230."; + +void cursor() { + char c = 0; + scan_code -= 0x47; + if (scan_code < 0 || scan_code > 12) return; + if (e0 || (leds & 0x2)) { + c = cur_table[scan_code]; + if (c < '9') { + PUTCH('~', &tty_table[0].read_q); + } + PUTCH(0x1b, &tty_table[0].read_q); + PUTCH(0x5b, &tty_table[0].read_q); + } + else { + c = num_table[scan_code]; + } + PUTCH(c, &tty_table[0].read_q); +} + +void func() { + scan_code -= 0x3b; + if (scan_code > 9) { + scan_code -= 18; + } + if (scan_code < 0 || scan_code > 11) { + return; + } + PUTCH(0x1b, &tty_table[0].read_q); + PUTCH(0x5b, &tty_table[0].read_q); + PUTCH(0x5b, &tty_table[0].read_q); + PUTCH('A' + scan_code, &tty_table[0].read_q); +} + +void minus() { + if (e0 == 1) { + PUTCH('/', &tty_table[0].read_q); + return; + } + do_self(); +} diff --git a/kernel/chr_drv/keyboard.S b/kernel/chr_drv/keyboard.S new file mode 100644 index 0000000000000000000000000000000000000000..caa9060a05c0395f4287b56cd072693e940b4e44 --- /dev/null +++ b/kernel/chr_drv/keyboard.S @@ -0,0 +1,30 @@ +.code32 +.text +.globl keyboard_interrupt + +.align 4 +keyboard_interrupt: + pushw %ds + pushw %es + pushw %fs + pushl %edx + pushl %ecx + pushl %ebx + pushl %eax + movl $0x10, %eax + movw %ax, %ds + movw %ax, %es + movl $0x17, %eax + movw %ax, %fs + pushl %eax + call keyboard_handler + popl %eax + popl %eax + popl %ebx + popl %ecx + popl %edx + popw %fs + popw %es + popw %ds + iret + diff --git a/kernel/chr_drv/tty_io.c b/kernel/chr_drv/tty_io.c new file mode 100644 index 0000000000000000000000000000000000000000..ccdf5ac00c05616429a4d2e6af84b5f4cf5dd440 --- /dev/null +++ b/kernel/chr_drv/tty_io.c @@ -0,0 +1,249 @@ +#include + +#include +#include +#include + +int kill_pg(int pgrp, int sig, int priv); + +#define _L_FLAG(tty,f) ((tty)->termios.c_lflag & f) +#define _O_FLAG(tty,f) ((tty)->termios.c_oflag & f) +#define _I_FLAG(tty,f) ((tty)->termios.c_iflag & 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_ECHOCTL(tty) _L_FLAG((tty),ECHOCTL) + +#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) + +#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) + +struct tty_struct tty_table[] = { + { + { + ICRNL, + OPOST | ONLCR, + 0, + ISIG | ICANON | ECHO | ECHOCTL | ECHOKE, + 0, + INIT_C_CC + }, + 0, + 0, + 0, + con_write, + {0, 0, 0, 0, ""}, + {0, 0, 0, 0, ""}, + {0, 0, 0, 0, ""}, + } +}; + +unsigned long CHARS(struct tty_queue* q) { + return (q->head - q->tail) & (TTY_BUF_SIZE - 1); +} + +void PUTCH(char c, struct tty_queue* q) { + q->buf[q->head++] = c; + q->head &= (TTY_BUF_SIZE - 1); +} + +char GETCH(struct tty_queue* q) { + char c = q->buf[q->tail++]; + q->tail &= (TTY_BUF_SIZE - 1); + return c; +} + +char EMPTY(struct tty_queue* q) { + return q->tail == q->head; +} + +void tty_init() { + con_init(); +} + +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 = tty_table + channel; + while (nr > 0) { + 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); + return (b-buf); +} + +int tty_read(unsigned channel, char * buf, int nr) { + struct tty_struct * tty; + char c, * b=buf; + + if (channel > 2 || nr < 0) + return -1; + + tty = tty_table + channel; + + while (nr > 0) { + if (EMPTY(&tty->secondary) || (L_CANON(tty) && + !FULL(tty->read_q) && !tty->secondary.data)) { + interruptible_sleep_on(&tty->secondary.proc_list); + continue; + } + + do { + c = GETCH(&tty->secondary); + 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 (L_CANON(tty) && (b - buf)) { + break; + } + } + + return (b - buf); +} + +void copy_to_cooked(struct tty_struct * tty) { + signed char c; + + while (!EMPTY(&tty->read_q) && !FULL(tty->secondary)) { + c = GETCH(&tty -> read_q); + + if (c == 13) { + if (I_CRNL(tty)) + c = 10; + else if (I_NOCR(tty)) + continue; + } + else if (c == 10 && I_NLCR(tty)) + c = 13; + + if (I_UCLC(tty)) + c = tolower(c); + + if (L_CANON(tty)) { + if (c == KILL_CHAR(tty)) { + while (!(EMPTY(&tty->secondary) || + (c = LAST(tty->secondary)) == 10 || + c == EOF_CHAR(tty))) { + if (L_ECHO(tty)) { + if (c < 32) + PUTCH(127, &tty->write_q); + PUTCH(127, &tty->write_q); + tty->write(tty); + } + DEC(tty->secondary.head); + } + continue; + } + + if (c == ERASE_CHAR(tty)) { + if (EMPTY(&tty->secondary) || + (c = LAST(tty->secondary)) == 10 || + c == EOF_CHAR(tty)) + continue; + if (L_ECHO(tty)) { + if (c < 32) + PUTCH(127, &tty->write_q); + PUTCH(127, &tty->write_q); + tty->write(tty); + } + DEC(tty->secondary.head); + continue; + } + + if (c == STOP_CHAR(tty)) { + tty->stopped = 1; + continue; + } + + if (c == START_CHAR(tty)) { + tty->stopped = 0; + continue; + } + } + + if (L_ISIG(tty)) { + if (c==INTR_CHAR(tty)) { + kill_pg(tty->pgrp, SIGINT, 1); + continue; + } + if (c==QUIT_CHAR(tty)) { + kill_pg(tty->pgrp, SIGQUIT, 1); + continue; + } + if (c==SUSPEND_CHAR(tty)) { + //if (!is_orphaned_pgrp(tty->pgrp)) + kill_pg(tty->pgrp, SIGTSTP, 1); + 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); +} + +void do_tty_interrupt(int tty) { + copy_to_cooked(tty_table + tty); +} + diff --git a/kernel/chr_drv/tty_ioctl.c b/kernel/chr_drv/tty_ioctl.c new file mode 100644 index 0000000000000000000000000000000000000000..f69ba306841be91506d5f258b2957f532ad01feb --- /dev/null +++ b/kernel/chr_drv/tty_ioctl.c @@ -0,0 +1,179 @@ +#include +#include + +#include +#include +#include + +#include +#include +#include + +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 channel) { + int i; + + for (i=0 ; i< (sizeof (*termios)) ; i++) + ((char *)&tty->termios)[i]=get_fs_byte(i+(char *)termios); + //change_speed(tty); + return 0; +} + +static int get_termio(struct tty_struct * tty, struct termio * termio) { + int i; + struct termio tmp_termio; + + verify_area(termio, sizeof (*termio)); + tmp_termio.c_iflag = tty->termios.c_iflag; + tmp_termio.c_oflag = tty->termios.c_oflag; + tmp_termio.c_cflag = tty->termios.c_cflag; + tmp_termio.c_lflag = tty->termios.c_lflag; + tmp_termio.c_line = tty->termios.c_line; + for(i=0 ; i < NCC ; i++) + tmp_termio.c_cc[i] = tty->termios.c_cc[i]; + for (i=0 ; i< (sizeof (*termio)) ; i++) + put_fs_byte( ((char *)&tmp_termio)[i] , i+(char *)termio ); + return 0; +} + +static int set_termio(struct tty_struct * tty, struct termio * termio, + int channel) { + int i; + struct termio tmp_termio; + + for (i=0 ; i< (sizeof (*termio)) ; i++) + ((char *)&tmp_termio)[i]=get_fs_byte(i+(char *)termio); + *(unsigned short *)&tty->termios.c_iflag = tmp_termio.c_iflag; + *(unsigned short *)&tty->termios.c_oflag = tmp_termio.c_oflag; + *(unsigned short *)&tty->termios.c_cflag = tmp_termio.c_cflag; + *(unsigned short *)&tty->termios.c_lflag = tmp_termio.c_lflag; + tty->termios.c_line = tmp_termio.c_line; + for(i=0 ; i < NCC ; i++) + tty->termios.c_cc[i] = tmp_termio.c_cc[i]; + //change_speed(tty); + return 0; +} + +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 */ +} + +int tty_ioctl(int dev, int cmd, int arg) { + struct tty_struct * tty; + + tty = tty_table + dev; + 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, dev); + 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, dev); + case TCSBRK: + if (!arg) { + wait_until_sent(tty); + send_break(tty); + } + return 0; + case TCXONC: + switch (arg) { + case TCOOFF: + tty->stopped = 1; + tty->write(tty); + return 0; + case TCOON: + tty->stopped = 0; + tty->write(tty); + return 0; + case TCIOFF: + if (STOP_CHAR(tty)) + PUTCH(STOP_CHAR(tty), &tty->write_q); + return 0; + case TCION: + if (START_CHAR(tty)) + PUTCH(START_CHAR(tty), &tty->write_q); + return 0; + } + 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: + return 0; + case TIOCOUTQ: + verify_area((void *) arg,4); + put_fs_long(CHARS(&tty->write_q),(unsigned long *) arg); + return 0; + case TIOCINQ: + verify_area((void *) arg,4); + put_fs_long(CHARS(&tty->secondary), + (unsigned long *) arg); + return 0; + case TIOCSTI: + return -EINVAL; /* not implemented */ + case TIOCGWINSZ: + return -EINVAL; /* not implemented */ + case TIOCSWINSZ: + return -EINVAL; /* not implemented */ + case TIOCMGET: + return -EINVAL; /* not implemented */ + case TIOCMBIS: + return -EINVAL; /* not implemented */ + case TIOCMBIC: + return -EINVAL; /* not implemented */ + case TIOCMSET: + return -EINVAL; /* not implemented */ + case TIOCGSOFTCAR: + return -EINVAL; /* not implemented */ + case TIOCSSOFTCAR: + return -EINVAL; /* not implemented */ + default: + return -EINVAL; + } +} diff --git a/kernel/exit.c b/kernel/exit.c new file mode 100644 index 0000000000000000000000000000000000000000..b25e01e31102fdbdc71101d34d51b728c7067ae6 --- /dev/null +++ b/kernel/exit.c @@ -0,0 +1,293 @@ +#include +#include + +#include +#include +#include +#include +#include + +void release(struct task_struct * p) { + int i; + + if (!p) + return; + if (p == current) { + printk("task releasing itself\n\r"); + return; + } + for (i=1 ; ip_osptr) + p->p_osptr->p_ysptr = p->p_ysptr; + if (p->p_ysptr) + p->p_ysptr->p_osptr = p->p_osptr; + else + p->p_pptr->p_cptr = p->p_osptr; + free_page((long)p); + schedule(); + return; + } + } + panic("trying to release non-existent task"); +} + +static inline int send_sig(long sig,struct task_struct * p,int priv) { + if (!p) + return -EINVAL; + if (!priv && (current->euid != p->euid) && !suser()) + return -EPERM; + if ((sig == SIGKILL) || (sig == SIGCONT)) { + if (p->state == TASK_STOPPED) + p->state = TASK_RUNNING; + p->exit_code = 0; + p->signal &= ~( (1<<(SIGSTOP-1)) | (1<<(SIGTSTP-1)) | + (1<<(SIGTTIN-1)) | (1<<(SIGTTOU-1)) ); + } + /* If the signal will be ignored, don't even post it */ + if ((int) p->sigaction[sig-1].sa_handler == 1) + return 0; + /* Depends on order SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU */ + if ((sig >= SIGSTOP) && (sig <= SIGTTOU)) + p->signal &= ~(1<<(SIGCONT-1)); + /* Actually deliver the signal */ + p->signal |= (1<<(sig-1)); + return 0; +} + +int kill_pg(int pgrp, int sig, int priv) { + struct task_struct **p; + int err,retval = -ESRCH; + int found = 0; + + if (sig<1 || sig>32 || pgrp <= 0) + return -EINVAL; + for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) { + if ((*p)->pgrp == pgrp) { + if (sig && (err = send_sig(sig,*p,priv))) + retval = err; + else + found++; + } + } + + return(found ? 0 : retval); +} + +int kill_proc(int pid, int sig, int priv) +{ + struct task_struct **p; + + if (sig<1 || sig>32) + return -EINVAL; + for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) + if ((*p)->pid == pid) + return(sig ? send_sig(sig,*p,priv) : 0); + return(-ESRCH); +} + +int sys_kill(int pid,int sig) { + struct task_struct **p = NR_TASKS + task; + int err, retval = 0; + + if (!pid) + return(kill_pg(current->pid,sig,0)); + if (pid == -1) { + while (--p > &FIRST_TASK) + if (err = send_sig(sig,*p,0)) + retval = err; + return(retval); + } + if (pid < 0) + return(kill_pg(-pid,sig,0)); + /* Normal kill */ + return(kill_proc(pid,sig,0)); +} + +int is_orphaned_pgrp(int pgrp) { + struct task_struct **p; + + for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) { + if (!(*p) || + ((*p)->pgrp != pgrp) || + ((*p)->state == TASK_ZOMBIE) || + ((*p)->p_pptr->pid == 1)) + continue; + if (((*p)->p_pptr->pgrp != pgrp) && + ((*p)->p_pptr->session == (*p)->session)) + return 0; + } + return(1); /* (sighing) "Often!" */ +} + +static int has_stopped_jobs(int pgrp) { + struct task_struct ** p; + + for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) { + if ((*p)->pgrp != pgrp) + continue; + if ((*p)->state == TASK_STOPPED) + return(1); + } + return(0); +} + +volatile void do_exit(long code) { + struct task_struct *p; + 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 ; ifilp[i]) + sys_close(i); + iput(current->pwd); + current->pwd = NULL; + iput(current->root); + current->root = NULL; + iput(current->executable); + current->executable = NULL; + iput(current->library); + current->library = NULL; + current->state = TASK_ZOMBIE; + current->exit_code = code; + /* + * Check to see if any process groups have become orphaned + * as a result of our exiting, and if they have any stopped + * jobs, send them a SIGUP and then a SIGCONT. (POSIX 3.2.2.2) + * + * Case i: Our father is in a different pgrp than we are + * and we were the only connection outside, so our pgrp + * is about to become orphaned. + */ + if ((current->p_pptr->pgrp != current->pgrp) && + (current->p_pptr->session == current->session) && + is_orphaned_pgrp(current->pgrp) && + has_stopped_jobs(current->pgrp)) { + kill_pg(current->pgrp,SIGHUP,1); + kill_pg(current->pgrp,SIGCONT,1); + } + /* Let father know we died */ + current->p_pptr->signal |= (1<<(SIGCHLD-1)); + + /* + * This loop does two things: + * + * A. Make init inherit all the child processes + * B. Check to see if any process groups have become orphaned + * as a result of our exiting, and if they have any stopped + * jons, send them a SIGUP and then a SIGCONT. (POSIX 3.2.2.2) + */ + if (p = current->p_cptr) { + while (1) { + p->p_pptr = task[1]; + if (p->state == TASK_ZOMBIE) + task[1]->signal |= (1<<(SIGCHLD-1)); + /* + * process group orphan check + * Case ii: Our child is in a different pgrp + * than we are, and it was the only connection + * outside, so the child pgrp is now orphaned. + */ + if ((p->pgrp != current->pgrp) && + (p->session == current->session) && + is_orphaned_pgrp(p->pgrp) && + has_stopped_jobs(p->pgrp)) { + kill_pg(p->pgrp,SIGHUP,1); + kill_pg(p->pgrp,SIGCONT,1); + } + if (p->p_osptr) { + p = p->p_osptr; + continue; + } + /* + * This is it; link everything into init's children + * and leave + */ + p->p_osptr = task[1]->p_cptr; + task[1]->p_cptr->p_ysptr = p; + task[1]->p_cptr = current->p_cptr; + current->p_cptr = 0; + break; + } + } + if (current->leader) { + struct task_struct **p; + struct tty_struct *tty; + + if (current->tty >= 0) { + tty = tty_table + current->tty; + if (tty->pgrp>0) + kill_pg(tty->pgrp, SIGHUP, 1); + tty->pgrp = 0; + tty->session = 0; + } + for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) + if ((*p)->session == current->session) + (*p)->tty = -1; + } + + schedule(); +} + +int sys_exit(int error_code) { + do_exit((error_code&0xff)<<8); +} + +int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options) { + int flag; + struct task_struct *p; + unsigned long oldblocked; + + verify_area(stat_addr,4); +repeat: + flag=0; + for (p = current->p_cptr ; p ; p = p->p_osptr) { + if (pid>0) { + if (p->pid != pid) + continue; + } else if (!pid) { + if (p->pgrp != current->pgrp) + continue; + } else if (pid != -1) { + if (p->pgrp != -pid) + continue; + } + switch (p->state) { + case TASK_STOPPED: + if (!(options & WUNTRACED) || + !p->exit_code) + continue; + put_fs_long((p->exit_code << 8) | 0x7f, + stat_addr); + p->exit_code = 0; + return p->pid; + case TASK_ZOMBIE: + current->cutime += p->utime; + current->cstime += p->stime; + flag = p->pid; + put_fs_long(p->exit_code, stat_addr); + release(p); + return flag; + default: + flag=1; + continue; + } + } + if (flag) { + if (options & WNOHANG) + return 0; + current->state=TASK_INTERRUPTIBLE; + oldblocked = current->blocked; + current->blocked &= ~(1<<(SIGCHLD-1)); + schedule(); + current->blocked = oldblocked; + if (current->signal & ~(current->blocked | (1<<(SIGCHLD-1)))) + return -ERESTARTSYS; + else + goto repeat; + } + return -ECHILD; +} diff --git a/kernel/fork.c b/kernel/fork.c new file mode 100644 index 0000000000000000000000000000000000000000..368d242efa60e69e88fc83eac14eec6da579a507 --- /dev/null +++ b/kernel/fork.c @@ -0,0 +1,164 @@ +#include +#include + +#include +#include +#include + +extern void write_verify(unsigned long address); + +long last_pid = 0; + +void verify_area(void * addr,int size) { + unsigned long start; + + start = (unsigned long) addr; + size += start & 0xfff; + start &= 0xfffff000; + start += get_base(current->ldt[2]); + while (size>0) { + size -= 4096; + write_verify(start); + start += 4096; + } +} + +int copy_mem(int nr, struct task_struct* p) { + unsigned long old_data_base,new_data_base,data_limit; + unsigned long old_code_base,new_code_base,code_limit; + + code_limit = get_limit(0x0f); + data_limit = get_limit(0x17); + old_code_base = get_base(current->ldt[1]); + old_data_base = get_base(current->ldt[2]); + if (old_data_base != old_code_base) + panic("We don't support separate I&D"); + if (data_limit < code_limit) + panic("Bad data_limit"); + + new_data_base = new_code_base = nr * TASK_SIZE; + p->start_code = new_code_base; + set_base(p->ldt[1],new_code_base); + set_base(p->ldt[2],new_data_base); + if (copy_page_tables(old_data_base,new_data_base,data_limit)) { + free_page_tables(new_data_base,data_limit); + return -ENOMEM; + } + + return 0; +} + +int copy_process(int nr,long ebp,long edi,long esi,long gs,long none, + long ebx,long ecx,long edx, long orig_eax, + long fs,long es,long ds, + long eip,long cs,long eflags,long esp,long ss) { + struct task_struct *p; + int i; + struct file *f; + + p = (struct task_struct *) get_free_page(); + if (!p) + return -EAGAIN; + + task[nr] = p; + memcpy(p, current, sizeof(struct task_struct)); + + p->pid = last_pid; + p->p_pptr = current; + + p->alarm = 0; + + 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.cr3 = current->tss.cr3; + 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 (copy_mem(nr, p)) { + task[nr] = NULL; + free_page((long)p); + return -EAGAIN; + } + + for (i = 0; i < NR_OPEN; i++) { + p->filp[i] = current->filp[i]; + if ((f = p->filp[i])) + f->f_count++; + } + + p->tty = current->tty; + p->umask = current->umask; + + p->pwd = current->pwd; + if (current->pwd) + current->pwd->i_count++; + + p->root = current->root; + if (current->root) + current->root->i_count++; + + p->executable = current->executable; + if (current->executable) + current->executable->i_count++; + + p->library = current->library; + if (current->library) + current->library->i_count++; + + p->close_on_exec = current->close_on_exec; + + set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss)); + set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&(p->ldt)); + + p->p_pptr = current; + p->p_cptr = 0; + p->p_ysptr = 0; + p->p_osptr = current->p_cptr; + if (p->p_osptr) + p->p_osptr->p_ysptr = p; + current->p_cptr = p; + + p->state = TASK_RUNNING; + + return last_pid; +} + +int find_empty_process() { + int i; +repeat: + if ((++last_pid)<0) last_pid=1; + + for(i=0 ; ipid == last_pid)) + goto repeat; + } + + for (i = 1; i < NR_TASKS; i++) { + if (!task[i]) + return i; + } + + return -EAGAIN; +} + diff --git a/kernel/head.S b/kernel/head.S new file mode 100644 index 0000000000000000000000000000000000000000..c5d6ee7b3995c13e17af1a0e03fb8ba37ee3f527 --- /dev/null +++ b/kernel/head.S @@ -0,0 +1,159 @@ +.code32 +.text +.globl startup_32, idt, gdt, pg_dir, tmp_floppy_area +pg_dir: +startup_32: + movl $0x10, %eax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + + lss stack_start, %esp + call setup_idt + call setup_gdt + + movl $0x10, %eax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + + movl $0x18, %eax + movw %ax, %gs + + xorl %eax, %eax +1: + incl %eax + movl %eax, 0x000000 + cmpl %eax, 0x100000 + je 1b + + + jmp after_page_tables + + +setup_idt: + leal ignore_int, %edx + movl $0x00080000, %eax + movw %dx, %ax + movw $0x8e00, %dx + leal idt, %edi + movl $256, %ecx +rp_sidt: + movl %eax, (%edi) + movl %edx, 4(%edi) + addl $8, %edi + decl %ecx + jne rp_sidt + lidt idt_descr + ret + +setup_gdt: + lgdt gdt_descr + ret + +.org 0x1000 +pg0: + +.org 0x2000 +pg1: + +.org 0x3000 +pg2: + +.org 0x4000 +pg3: + +.org 0x5000 + +tmp_floppy_area: +.fill 1024, 1, 0 + +after_page_tables: +/*we call jump to main at this*/ + pushl $0 + pushl $0 + pushl $0 + pushl $L6 + pushl $main + jmp setup_paging +L6: + jmp L6 + +ignore_int: + /* we do not have function _printk now, so trick it */ + pushl %eax + pushl %ecx + pushl %edx + pushw %ds + pushw %es + pushw %fs + movl $0x10, %eax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + /* call _printk */ + movl $0x96, %edi + movb $'I', %al + movb $0x0c, %ah + movw %ax, %gs:(%edi) + popw %fs + popw %es + popw %ds + popl %edx + popl %ecx + popl %eax + iret + +.align 4 +setup_paging: + movl $1024*5, %ecx + xorl %eax, %eax + xorl %edi, %edi + cld + rep + stosl + + movl $pg0 + 7, pg_dir + movl $pg1 + 7, pg_dir + 4 + movl $pg2 + 7, pg_dir + 8 + movl $pg3 + 7, pg_dir + 12 + movl $pg3 + 4092, %edi + movl $0xfff007, %eax + std +1: + stosl + subl $0x1000, %eax + jge 1b + xorl %eax, %eax + movl %eax, %cr3 + movl %cr0, %eax + orl $0x80000000, %eax + movl %eax, %cr0 + + ret + +.align 4 +.word 0 +idt_descr: + .word 256*8-1 + .long idt + +.align 4 +.word 0 +gdt_descr: + .word 256 * 8 - 1 + .long gdt + +.align 8 +idt: + .fill 256, 8, 0 + +gdt: + .quad 0x0000000000000000 + .quad 0x00c09a0000000fff + .quad 0x00c0920000000fff + .quad 0x00c0f20b8000ffff + .quad 0x0000000000000000 + .fill 251, 8,0 + diff --git a/kernel/main.c b/kernel/main.c new file mode 100644 index 0000000000000000000000000000000000000000..482616c13dbbf3fdf0ab3ae7a4ca86b263f1664d --- /dev/null +++ b/kernel/main.c @@ -0,0 +1,138 @@ +#define __LIBRARY__ + +#include +#include +#include +#include + +inline _syscall0(int, fork); +inline _syscall1(int,setup,void *,BIOS) +inline _syscall2(int, kill, int, pid, int, sig) + +int errno; + +#include +#include + +#include +#include +#include + +extern void mem_init(long start, long end); +extern void hd_init(void); +extern void blk_dev_init(void); +extern void floppy_init(); +extern long kernel_mktime(struct tm * tm); + +void init(); + +#define EXT_MEM_K (*(unsigned short *)0x90002) +#define DRIVE_INFO (*(struct drive_info *)0x90080) +#define ORIG_ROOT_DEV (*(unsigned short *)0x901FC) +#define ORIG_SWAP_DEV (*(unsigned short *)0x901FA) + +static long memory_end = 0; +static long buffer_memory_end = 0; +static long main_memory_start = 0; + +struct drive_info { char dummy[32]; } drive_info; + +#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() { + struct tm time; + do { + time.tm_sec = CMOS_READ(0); + time.tm_min = CMOS_READ(2); + time.tm_hour = CMOS_READ(4); + time.tm_mday = CMOS_READ(7); + time.tm_mon = CMOS_READ(8); + time.tm_year = CMOS_READ(9); + } while (time.tm_sec != CMOS_READ(0)); + + BCD_TO_BIN(time.tm_sec); + BCD_TO_BIN(time.tm_min); + BCD_TO_BIN(time.tm_hour); + BCD_TO_BIN(time.tm_mday); + BCD_TO_BIN(time.tm_mon); + BCD_TO_BIN(time.tm_year); + time.tm_mon--; + startup_time = kernel_mktime(&time); +} + +static char * argv_rc[] = { "/bin/sh", NULL }; +static char * envp_rc[] = { "HOME=/", NULL ,NULL }; + +static char * argv[] = { "-/bin/sh",NULL }; +static char * envp[] = { "HOME=/usr/root", NULL, NULL }; + +void main(void) { + ROOT_DEV = ORIG_ROOT_DEV; + + drive_info = DRIVE_INFO; + + memory_end = (1<<20) + (EXT_MEM_K<<10); + memory_end &= 0xfffff000; + if (memory_end > 16*1024*1024) + memory_end = 16*1024*1024; + if (memory_end > 12*1024*1024) + buffer_memory_end = 4*1024*1024; + else if (memory_end > 6*1024*1024) + buffer_memory_end = 2*1024*1024; + else + buffer_memory_end = 1*1024*1024; + + main_memory_start = buffer_memory_end; + mem_init(main_memory_start, memory_end); + + trap_init(); + + tty_init(); + + time_init(); + sched_init(); + + printk("\n\rmemory start: %d, end: %d\n\r", main_memory_start, memory_end); + + buffer_init(buffer_memory_end); + blk_dev_init(); + hd_init(); + floppy_init(); + move_to_user_mode(); + printf("\x1b[31m In user mode!\n\r\x1b[0m"); + + struct termios tms; + + if (fork() == 0) { + init(); + } + + while (1) {} +} + +void init() { + int pid = 0; + setup((void *) &drive_info); + (void)open("/dev/tty0", O_RDWR, 0); + dup(0); + dup(0); + +/* + if ((pid = fork()) == 0) { + test_b(); + } + else { + test_c(pid); + } +*/ + if (!fork()) { + printf("read to start shell\n"); + execve("/hello", argv,envp); + } +} + diff --git a/kernel/mktime.c b/kernel/mktime.c new file mode 100644 index 0000000000000000000000000000000000000000..7f8d664b77f04b5ae09d64e0bfc5d153fd7a99e4 --- /dev/null +++ b/kernel/mktime.c @@ -0,0 +1,39 @@ +#include + +#define MINUTE 60 +#define HOUR (60*MINUTE) +#define DAY (24*HOUR) +#define YEAR (365*DAY) + +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), + DAY*(31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31) +}; + +long kernel_mktime(struct tm * tm) { + long res; + int year; + + year = tm->tm_year - 70; + res = YEAR*year + DAY*((year+1)/4); + res += month[tm->tm_mon]; + if (tm->tm_mon>1 && ((year+2)%4)) + res -= DAY; + res += DAY*(tm->tm_mday-1); + res += HOUR*tm->tm_hour; + res += MINUTE*tm->tm_min; + res += tm->tm_sec; + return res; +} + diff --git a/kernel/panic.c b/kernel/panic.c new file mode 100644 index 0000000000000000000000000000000000000000..7975a9101bdc13ba4854d7bb6dd66ab0409a568f --- /dev/null +++ b/kernel/panic.c @@ -0,0 +1,17 @@ +#include +#include + +int sys_sync(); + +void panic(const char * s) { + printk("Kernel panic: %s\n\r",s); + if (current == task[0]) { + printk("In swapper task - not syncing\n\r"); + } + else { + sys_sync(); + } + + for (;;); +} + diff --git a/kernel/printk.c b/kernel/printk.c new file mode 100644 index 0000000000000000000000000000000000000000..8b247b77505ae4cd9bb57bf4377835c81b6ed8e7 --- /dev/null +++ b/kernel/printk.c @@ -0,0 +1,31 @@ +#include +#include +#include + +static char buf[1024]; + +extern int vsprintf(char* buf, const char* fmt, va_list args); + +int printk(const char* fmt, ...) { + va_list args; + int i; + + va_start(args, fmt); + i = vsprintf(buf, fmt, args); + va_end(args); + + __asm__("pushw %%fs\n\t" + "pushw %%ds\n\t" + "popw %%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" + "popw %%fs" + ::"r"(i):"ax", "cx", "dx"); + + return i; +} + diff --git a/kernel/sched.c b/kernel/sched.c new file mode 100644 index 0000000000000000000000000000000000000000..3930a4ffc2ea697a8d520b151e4225cb1c184207 --- /dev/null +++ b/kernel/sched.c @@ -0,0 +1,375 @@ +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#define _S(nr) (1<<((nr)-1)) +#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) + +#define COUNTER 100 + +#define LATCH (1193180/HZ) +#define PAGE_SIZE 4096 + +extern int system_call(); +extern void timer_interrupt(); +extern int kill(int pid, int sig); + +union task_union { + struct task_struct task; + char stack[PAGE_SIZE]; +}; + +static union task_union init_task = {INIT_TASK, }; + +unsigned long volatile jiffies = 0; +unsigned long startup_time = 0; + +struct task_struct * current = &(init_task.task); +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}; + + +void schedule() { + int i,next,c; + struct task_struct ** p; + + for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) { + if (*p) { + if ((*p)->timeout && (*p)->timeout < jiffies) { + (*p)->timeout = 0; + if ((*p)->state == TASK_INTERRUPTIBLE) + (*p)->state = TASK_RUNNING; + } + if ((*p)->alarm && (*p)->alarm < jiffies) { + (*p)->signal |= (1<<(SIGALRM-1)); + (*p)->alarm = 0; + } + if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) && + (*p)->state==TASK_INTERRUPTIBLE) + (*p)->state=TASK_RUNNING; + } + } + + 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)) + continue; + + (*p)->counter = ((*p)->counter >> 1) + (*p)->priority; + } + } + switch_to(next); +} + +static inline void __sleep_on(struct task_struct** p, int state) { + struct task_struct* tmp; + + if (!p) + return; + if (current == &(init_task.task)) + panic("task[0] trying to sleep"); + + tmp = *p; + *p = current; + current->state = state; + +repeat: + schedule(); + + if (*p && *p != current) { + (**p).state = 0; + current->state = TASK_UNINTERRUPTIBLE; + goto repeat; + } + + if (!*p) + printk("Warning: *P = NULL\n\r"); + *p = tmp; + if (*p) + tmp->state = 0; +} + +void interruptible_sleep_on(struct task_struct** p) { + __sleep_on(p, TASK_INTERRUPTIBLE); +} + +void sleep_on(struct task_struct** p) { + __sleep_on(p, TASK_UNINTERRUPTIBLE); +} + +void wake_up(struct task_struct **p) { + if (p && *p) { + if ((**p).state == TASK_STOPPED) + printk("wake_up: TASK_STOPPED"); + if ((**p).state == TASK_ZOMBIE) + printk("wake_up: TASK_ZOMBIE"); + (**p).state=0; + } +} + +static struct task_struct * wait_motor[4] = {NULL,NULL,NULL,NULL}; +static int mon_timer[4]={0,0,0,0}; +static int moff_timer[4]={0,0,0,0}; + +unsigned char current_DOR = 0x0C; + +int ticks_to_floppy_on(unsigned int nr) { + extern unsigned char selected; + unsigned char mask = 0x10 << nr; + + if (nr>3) + panic("floppy_on: nr>3"); + moff_timer[nr]=10000; + cli(); + + mask |= current_DOR; + if (!selected) { + mask &= 0xFC; + mask |= nr; + } + if (mask != current_DOR) { + outb(mask,FD_DOR); + if ((mask ^ current_DOR) & 0xf0) + mon_timer[nr] = HZ/2; + else if (mon_timer[nr] < 2) + mon_timer[nr] = 2; + current_DOR = mask; + } + sti(); + return mon_timer[nr]; +} + +void floppy_off(unsigned int nr) { + moff_timer[nr]=3*HZ; +} + + +void do_floppy_timer() { + int i; + unsigned char mask = 0x10; + + for (i=0 ; i<4 ; i++,mask <<= 1) { + if (!(mask & current_DOR)) + continue; + if (mon_timer[i]) { + if (!--mon_timer[i]) + wake_up(i+wait_motor); + } + else if (!moff_timer[i]) { + current_DOR &= ~mask; + outb(current_DOR,FD_DOR); + } + else { + moff_timer[i]--; + } + } +} + +#define TIME_REQUESTS 64 + +static struct timer_list { + long jiffies; + void (*fn)(); + struct timer_list * next; +} timer_list[TIME_REQUESTS], * next_timer = NULL; + +void add_timer(long jiffies, void (*fn)()) { + struct timer_list * p; + if (!fn) + return; + cli(); + + if (jiffies <= 0) + (fn)(); + else { + for (p = timer_list ; p < timer_list + TIME_REQUESTS ; p++) + if (!p->fn) + break; + if (p >= timer_list + TIME_REQUESTS) + panic("No more time requests free"); + + p->fn = fn; + p->jiffies = jiffies; + p->next = next_timer; + next_timer = p; + + if (p->next && p->jiffies < p->next->jiffies) { + p->next->jiffies -= p->jiffies; + } + + while (p->next && p->next->jiffies < p->jiffies) { + p->jiffies -= p->next->jiffies; + fn = p->fn; + p->fn = p->next->fn; + p->next->fn = fn; + jiffies = p->jiffies; + p->jiffies = p->next->jiffies; + p->next->jiffies = jiffies; + p = p->next; + } + } + sti(); +} + +void do_timer(long cpl) { + if (cpl) + current->utime++; + else + current->stime++; + + if (next_timer) { + next_timer->jiffies--; + while (next_timer && next_timer->jiffies <= 0) { + void (*fn)(void); + fn = next_timer->fn; + next_timer->fn = NULL; + next_timer = next_timer->next; + (fn)(); + } + } + + if (current_DOR & 0xf0) + do_floppy_timer(); + + if ((--current->counter)>0) return; + current->counter=0; + if (!cpl) return; + schedule(); +} + +void sched_init() { + 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;ia = p->b = 0; + p++; + p->a = p->b = 0; + p++; + } + + __asm__("pushfl; andl $0xffffbfff, (%esp); popfl"); + ltr(0); + lldt(0); + + /* open the clock interruption! */ + outb_p(0x36, 0x43); + outb_p(LATCH & 0xff, 0x40); + outb(LATCH >> 8, 0x40); + set_intr_gate(0x20, &timer_interrupt); + outb(inb_p(0x21) & ~0x01, 0x21); + + set_system_gate(0x80, &system_call); +} + +void test_a(void) { + char a[10]; + int i; + + while (1) { + i = read(0, a, 9); + a[i - 1] = 0; + + if (strcmp(a, "mk") == 0) { + mkdir("/hinusDocs", 0); + } + else if (strcmp(a, "rm") == 0) { + rmdir("/hinusDocs"); + } + else if (strcmp(a, "ls") == 0) { + ls(); + } + else if (strcmp(a, "q") == 0) { + break; + } + } +} + +void test_c() { +__asm__("movl $0x0, %edi\n\r" + "movw $0x1b, %ax\n\t" + "movw %ax, %gs \n\t" + "movb $0x0c, %ah\n\r" + "movb $'C', %al\n\r" + "movw %ax, %gs:(%edi)\n\r"); +} + +void test_b(void) { +__asm__("movl $0x0, %edi\n\r" + "movw $0x1b, %ax\n\t" + "movw %ax, %gs \n\t" + "movb $0x0f, %ah\n\r" + "movb $'B', %al\n\r" + "loopb:\n\r" + "movw %ax, %gs:(%edi)\n\r" + "jmp loopb"); +} + +int sys_alarm(long seconds) { + int old = current->alarm; + + if (old) + old = (old - jiffies) / HZ; + current->alarm = (seconds>0)?(jiffies+HZ*seconds):0; + return (old); +} + +int sys_getuid(void) { + return current->uid; +} + +int sys_getpid(void) { + return current->pid; +} + +int sys_getppid(void) { + return current->p_pptr->pid; +} + +int sys_geteuid(void) { + return current->euid; +} + +int sys_getgid(void) { + return current->gid; +} + +int sys_getegid(void) { + return current->egid; +} + diff --git a/kernel/segment.c b/kernel/segment.c new file mode 100644 index 0000000000000000000000000000000000000000..db50750bd5da94ee6bd4cb003285dc0ce1e1c458 --- /dev/null +++ b/kernel/segment.c @@ -0,0 +1,38 @@ +#include + +void put_fs_byte(char val,char *addr) { + __asm__ ("movb %0,%%fs:%1"::"r" (val),"m" (*addr)); +} + +char get_fs_byte(const char * addr) { + unsigned register char _v; + __asm__ ("movb %%fs:%1,%0":"=r" (_v):"m" (*addr)); + return _v; +} + +void put_fs_long(unsigned long val,unsigned long * addr) { + __asm__ ("movl %0,%%fs:%1"::"r" (val),"m" (*addr)); +} + +unsigned long get_fs_long(const unsigned long *addr) { + unsigned long _v; + __asm__ ("movl %%fs:%1,%0":"=r" (_v):"m" (*addr)); \ + return _v; +} + +unsigned long get_fs() { + unsigned short _v; + __asm__("mov %%fs,%%ax":"=a" (_v):); + return _v; +} + +unsigned long get_ds() { + unsigned short _v; + __asm__("mov %%ds,%%ax":"=a" (_v):); + return _v; +} + +void set_fs(unsigned long val) { + __asm__("mov %0,%%fs"::"a" ((unsigned short) val)); +} + diff --git a/kernel/signal.c b/kernel/signal.c new file mode 100644 index 0000000000000000000000000000000000000000..2130663834496d169ecf4fc8bf1e921478391a5e --- /dev/null +++ b/kernel/signal.c @@ -0,0 +1,149 @@ +#include +#include +#include + +#include +#include + +static inline void save_old(char * from,char * to) +{ + int i; + + verify_area(to, sizeof(struct sigaction)); + for (i=0 ; i< sizeof(struct sigaction) ; i++) { + put_fs_byte(*from,to); + from++; + to++; + } +} + +static inline void get_new(char * from,char * to) { + int i; + + for (i=0 ; i< sizeof(struct sigaction) ; i++) + *(to++) = get_fs_byte(from++); +} + + +int sys_signal(int signum, long handler, long restorer) { + struct sigaction tmp; + + if (signum<1 || signum>32 || signum==SIGKILL || signum==SIGSTOP) + return -EINVAL; + tmp.sa_handler = (void (*)(int)) handler; + tmp.sa_mask = 0; + tmp.sa_flags = SA_ONESHOT | SA_NOMASK; + tmp.sa_restorer = (void (*)(void)) restorer; + handler = (long) current->sigaction[signum-1].sa_handler; + current->sigaction[signum-1] = tmp; + return handler; +} + +int sys_sigaction(int signum, const struct sigaction * action, + struct sigaction * oldaction) { + struct sigaction tmp; + + if (signum<1 || signum>32 || signum==SIGKILL || signum==SIGSTOP) + return -EINVAL; + tmp = current->sigaction[signum-1]; + get_new((char *) action, + (char *) (signum-1+current->sigaction)); + if (oldaction) + save_old((char *) &tmp,(char *) oldaction); + if (current->sigaction[signum-1].sa_flags & SA_NOMASK) + current->sigaction[signum-1].sa_mask = 0; + else + current->sigaction[signum-1].sa_mask |= (1<<(signum-1)); + return 0; +} + + +/* + * Routine writes a core dump image in the current directory. + * Currently not implemented. + */ +int core_dump(long signr) { + return(0); /* We didn't do a dump */ +} + + +int do_signal(long signr,long eax,long ebx, long ecx, long edx, long orig_eax, + long fs, long es, long ds, + long eip, long cs, long eflags, + unsigned long * esp, long ss) { + unsigned long sa_handler; + long old_eip=eip; + struct sigaction * sa = current->sigaction + signr - 1; + int longs; + + unsigned long * tmp_esp; + + printk("pid: %d, signr: %x, eax=%d, oeax = %d, int=%d\n", + current->pid, signr, eax, orig_eax, + sa->sa_flags & SA_INTERRUPT); + + if ((orig_eax != -1) && + ((eax == -ERESTARTSYS) || (eax == -ERESTARTNOINTR))) { + if ((eax == -ERESTARTSYS) && ((sa->sa_flags & SA_INTERRUPT) || + signr < SIGCONT || signr > SIGTTOU)) + *(&eax) = -EINTR; + else { + *(&eax) = orig_eax; + *(&eip) = old_eip -= 2; + } + } + sa_handler = (unsigned long) sa->sa_handler; + if (sa_handler==1) + return(1); /* Ignore, see if there are more signals... */ + if (!sa_handler) { + switch (signr) { + case SIGCONT: + case SIGCHLD: + return(1); /* Ignore, ... */ + + case SIGSTOP: + case SIGTSTP: + case SIGTTIN: + case SIGTTOU: + current->state = TASK_STOPPED; + current->exit_code = signr; + if (!(current->p_pptr->sigaction[SIGCHLD-1].sa_flags & + SA_NOCLDSTOP)) + current->p_pptr->signal |= (1<<(SIGCHLD-1)); + return(1); /* Reschedule another event */ + + case SIGQUIT: + case SIGILL: + case SIGTRAP: + case SIGIOT: + case SIGFPE: + case SIGSEGV: + if (core_dump(signr)) + do_exit(signr|0x80); + /* fall through */ + default: + do_exit(signr); + } + } + /* + * OK, we're invoking a handler + */ + if (sa->sa_flags & SA_ONESHOT) + sa->sa_handler = NULL; + *(&eip) = sa_handler; + longs = (sa->sa_flags & SA_NOMASK)?7:8; + *(&esp) -= longs; + verify_area(esp,longs*4); + tmp_esp=esp; + put_fs_long((long) sa->sa_restorer,tmp_esp++); + put_fs_long(signr,tmp_esp++); + if (!(sa->sa_flags & SA_NOMASK)) + put_fs_long(current->blocked,tmp_esp++); + put_fs_long(eax,tmp_esp++); + put_fs_long(ecx,tmp_esp++); + put_fs_long(edx,tmp_esp++); + put_fs_long(eflags,tmp_esp++); + put_fs_long(old_eip,tmp_esp++); + current->blocked |= sa->sa_mask; + return(0); /* Continue, execute handler */ +} diff --git a/kernel/sys.c b/kernel/sys.c new file mode 100644 index 0000000000000000000000000000000000000000..1707815061dbcfdb9eb0ded38c13b7c963b3bdf3 --- /dev/null +++ b/kernel/sys.c @@ -0,0 +1,52 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +int sys_time(long * tloc) { + int i; + i = CURRENT_TIME; + if (tloc) { + put_fs_long(i,(unsigned long *)tloc); + } + return i; +} + +int sys_setsid(void) { + if (current->leader && !suser()) + return -EPERM; + current->leader = 1; + current->session = current->pgrp = current->pid; + current->tty = -1; + return current->pgrp; +} + +int in_group_p(gid_t grp) { + int i; + + if (grp == current->egid) + return 1; + + for (i = 0; i < NGROUPS; i++) { + if (current->groups[i] == NOGROUP) + break; + if (current->groups[i] == grp) + return 1; + } + return 0; +} + +int sys_setuid(int uid) { + if (suser()) + current->uid = current->euid = current->suid = uid; + else if ((uid == current->uid) || (uid == current->suid)) + current->euid = uid; + else + return -EPERM; + return(0); +} + diff --git a/kernel/sys_call.S b/kernel/sys_call.S new file mode 100644 index 0000000000000000000000000000000000000000..bf98bb7d0fea9d5b6b79b558b4a943cd716d1334 --- /dev/null +++ b/kernel/sys_call.S @@ -0,0 +1,158 @@ +.code32 +.text +.globl system_call, timer_interrupt, sys_fork +.globl hd_interrupt, floppy_interrupt, sys_execve + +EAX = 0x00 +EBX = 0x04 +ECX = 0x08 +EDX = 0x0C +ORIG_EAX = 0x10 +FS = 0x14 +ES = 0x18 +DS = 0x1c +EIP = 0x20 +CS = 0x24 +EFLAGS = 0x28 +OLDESP = 0x2c +OLDSS = 0x30 + +int_msg: + .asciz "In kernel interrupt\n\r" + +system_call: + pushl %ds + pushl %es + pushl %fs + pushl %eax + pushl %edx + pushl %ecx + pushl %ebx + movl $0x10, %edx + movw %dx, %ds + movw %dx, %es + movl $0x17, %edx + movw %dx, %fs + + call sys_call_table(, %eax, 4) + pushl %eax + +ret_from_sys_call: + popl %eax + popl %ebx + popl %ecx + popl %edx + addl $4, %esp + popl %fs + popl %es + popl %ds + iret + +.align 4 +timer_interrupt: + pushl %ds + pushl %es + pushl %fs + pushl $-1 + pushl %edx + pushl %ecx + pushl %ebx + pushl %eax + movl $0x10, %eax + movw %ax, %ds + movw %ax, %es + movl $0x17, %eax + movw %ax, %fs + incl jiffies + movb $0x20, %al + outb %al, $0x20 + movl CS(%esp), %eax + andl $3, %eax + pushl %eax + call do_timer + addl $4, %esp + jmp ret_from_sys_call + +.align 4 +sys_execve: + lea EIP(%esp), %eax + pushl %eax + call do_execve + addl $4, %esp + ret + +.align 4 +sys_fork: + call find_empty_process + testl %eax, %eax + js 1f + pushl %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 + pushl %ds + pushl %es + pushl %fs + movl $0x10, %eax + movw %ax, %ds + movw %ax, %es + movl $0x17, %eax + movw %ax, %fs + movb $0x20, %al + outb %al, $0xA0 + jmp 1f +1: jmp 1f +1: xorl %edx, %edx + movl %edx, hd_timeout + xchgl do_hd, %edx + testl %edx, %edx + jne 1f + movl $unexpected_hd_interrupt, %edx +1: call *%edx + movb $0x20, %al + outb %al, $0x20 + popl %fs + popl %es + popl %ds + popl %edx + popl %ecx + popl %eax + iret + +floppy_interrupt: + pushl %eax + pushl %ecx + pushl %edx + pushl %ds + pushl %es + pushl %fs + movl $0x10, %eax + movw %ax, %ds + movw %ax, %es + movl $0x17, %eax + movw %ax, %fs + xorl %edx, %edx + xchgl do_floppy, %edx + testl %edx, %edx + jne 1f + movl $unexpected_floppy_interrupt, %edx +1: call *%edx + movb $0x20, %al + outb %al, $0x20 + popl %fs + popl %es + popl %ds + popl %edx + popl %ecx + popl %eax + iret + diff --git a/kernel/traps.c b/kernel/traps.c new file mode 100644 index 0000000000000000000000000000000000000000..ec23563e745484c52176314701f4cb2b6794c4c5 --- /dev/null +++ b/kernel/traps.c @@ -0,0 +1,170 @@ +#include +#include +#include +#include + +#define get_seg_byte(seg,addr) ({ \ +register char __res; \ +__asm__("push %%fs;mov %%ax,%%fs;movb %%fs:%2,%%al;pop %%fs" \ + :"=a" (__res):"0" (seg),"m" (*(addr))); \ +__res;}) + +#define get_seg_long(seg,addr) ({ \ +register unsigned long __res; \ +__asm__("push %%fs;mov %%ax,%%fs;movl %%fs:%2,%%eax;pop %%fs" \ + :"=a" (__res):"0" (seg),"m" (*(addr))); \ +__res;}) + + +#define _fs() ({ \ +register unsigned short __res; \ +__asm__("mov %%fs,%%ax":"=a" (__res):); \ +__res;}) + + +void divide_error(); +void debug(); +void nmi(); +void int3(); +void overflow(); +void bounds(); +void invalid_op(); +void double_fault(); +void coprocessor_segment_overrun(); +void invalid_TSS(); +void segment_not_present(); +void stack_segment(); +void page_fault(); +void general_protection(); +void reserved(); +void irq13(); +void alignment_check(); + +static void die(char* str, long esp_ptr, long nr) { + int i = 0; + long* esp = (long*)esp_ptr; + + printk("\n\r%s: %04x\n\r", str, nr & 0xffff); + printk("EIP:\t%04x:%p\n\rEFLAGS:\t%p\n\rESP:\t%04x:%p\n\r", + esp[1],esp[0],esp[2],esp[4],esp[3]); + + printk("fs: %04x\n\r",_fs()); + printk("base: %p, limit: %p\n\r",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\r"); + } + + for(i=0;i<10;i++) + printk("%02x ",0xff & get_seg_byte(esp[1],(i+(char *)esp[0]))); + printk("\n\r"); + + while (1) { + } +} + +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_alignment_check(long esp, long error_code) { + die("alignment check", 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)); + 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_op", 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_segment_not_present(long esp, long error_code) { + die("segment not present", esp, error_code); +} + +void do_invalid_TSS(long esp, long error_code) { + die("invalid tss", esp, error_code); +} + +void do_stack_segment(long esp, long error_code) { + die("stack segment", esp, error_code); +} + +void do_reserved(long esp, long error_code) { + die("reserved (15,17-47) error",esp,error_code); +} + +void trap_init() { + int i; + + set_trap_gate(0, ÷_error); + set_trap_gate(1,&debug); + set_trap_gate(2,&nmi); + set_system_gate(3,&int3); + set_system_gate(4,&overflow); + set_system_gate(5,&bounds); + set_trap_gate(6,&invalid_op); + 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(17,&alignment_check); + + for (i=18;i<48;i++) + set_trap_gate(i,&reserved); + + outb_p(inb_p(0x21)&0xfb,0x21); + outb(inb_p(0xA1)&0xdf,0xA1); +} + diff --git a/kernel/vsprintf.c b/kernel/vsprintf.c new file mode 100644 index 0000000000000000000000000000000000000000..64aa7bc6266d70fc36d4e0458ad849001ecd5dab --- /dev/null +++ b/kernel/vsprintf.c @@ -0,0 +1,243 @@ +#include +#include + +#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 = 0; + + 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--; + } + + if (num==0) + tmp[i++]='0'; + else { + while (num!=0) { + tmp[i++]=digits[do_div(num,base)]; + } + } + + if (i>precision) precision=i; + size -= precision; + + if (!(type&(ZEROPAD+LEFT))) { + while(size-->0) + *str++ = ' '; + } + + if (sign) + *str++ = sign; + + if (type&SPECIAL) { + if (base==8) + *str++ = '0'; + else if (base==16) { + *str++ = '0'; + *str++ = digits[33]; + } + } + + if (!(type&LEFT)) { + while(size-->0) + *str++ = c; + } + + while(i0) + *str++ = tmp[i]; + + while(size-->0) + *str++ = ' '; + + return str; +} + +int vsprintf(char *buf, const char *fmt, va_list args) { + int len; + int i; + char * str; + char *s; + int *ip; + + int flags; /* flags to number() */ + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier; /* 'h', 'l', or 'L' for integer fields */ + + for (str = buf; *fmt; fmt++) { + if (*fmt != '%') { + *str++ = *fmt; + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case '-': flags |= LEFT; goto repeat; + case '+': flags |= PLUS; goto repeat; + case ' ': flags |= SPACE; goto repeat; + case '#': flags |= SPECIAL; goto repeat; + case '0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if (is_digit(*fmt)) { + field_width = skip_atoi(&fmt); + } + else if (*fmt == '*') { + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == '.') { + ++fmt; + if (is_digit(*fmt)) + precision = skip_atoi(&fmt); + else if (*fmt == '*') { + /* it's the next argument */ + precision = va_arg(args, int); + } + + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { + qualifier = *fmt; + ++fmt; + } + + switch (*fmt) { + case 'c': + if (!(flags & LEFT)) + while (--field_width > 0) + *str++ = ' '; + *str++ = (unsigned char) va_arg(args, int); + while (--field_width > 0) + *str++ = ' '; + break; + case 's': + s = va_arg(args, char *); + len = strlen(s); + + if (precision < 0) + precision = len; + else if (len > precision) + len = precision; + + if (!(flags & LEFT)) + while (len < field_width--) + *str++ = ' '; + for (i = 0; i < len; ++i) + *str++ = *s++; + while (len < field_width--) + *str++ = ' '; + break; + + case 'o': + str = number(str, va_arg(args, unsigned long), 8, + field_width, precision, flags); + break; + + case 'p': + if (field_width == -1) { + field_width = 8; + flags |= ZEROPAD; + } + str = number(str, + (unsigned long) va_arg(args, void *), 16, + field_width, precision, flags); + break; + + case 'x': + flags |= SMALL; + case 'X': + str = number(str, va_arg(args, unsigned long), 16, + field_width, precision, flags); + break; + + case 'd': + case 'i': + flags |= SIGN; + case 'u': + str = number(str, va_arg(args, unsigned long), 10, + field_width, precision, flags); + break; + + case 'n': + ip = va_arg(args, int *); + *ip = (str - buf); + break; + + default: + if (*fmt != '%') + *str++ = '%'; + + if (*fmt) + *str++ = *fmt; + else + --fmt; + break; + } + } + + *str = '\0'; + return str-buf; +} + diff --git a/lib/Makefile b/lib/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..04dbb716151ac71970922b078118bad523eb6281 --- /dev/null +++ b/lib/Makefile @@ -0,0 +1,44 @@ +AR := ar +LD := ld +GCC := gcc +CCFLAG := -m32 -I../include -nostdinc -ffreestanding -fno-pic -Wall -fomit-frame-pointer -fno-stack-protector -c +OBJS := string.o ctype.o file.o open.o dup.o execve.o close.o wait.o _exit.o setsid.o + +lib.a : $(OBJS) + $(AR) rcs $@ $^ + sync + +string.o : string.c + $(GCC) $(CCFLAG) -o $@ $< + +ctype.o : ctype.c + $(GCC) $(CCFLAG) -o $@ $< + +file.o : file.c + $(GCC) $(CCFLAG) -o $@ $< + +open.o : open.c + $(GCC) $(CCFLAG) -o $@ $< + +dup.o : dup.c + $(GCC) $(CCFLAG) -o $@ $< + +close.o : close.c + $(GCC) $(CCFLAG) -o $@ $< + +execve.o : execve.c + $(GCC) $(CCFLAG) -o $@ $< + +wait.o : wait.c + $(GCC) $(CCFLAG) -o $@ $< + +_exit.o : _exit.c + $(GCC) $(CCFLAG) -o $@ $< + +setsid.o : setsid.c + $(GCC) $(CCFLAG) -o $@ $< + +clean : + rm -f *.o + rm -f lib.a + diff --git a/lib/_exit.c b/lib/_exit.c new file mode 100644 index 0000000000000000000000000000000000000000..39f2ae72ab618354de98e51439ba96dc69125de9 --- /dev/null +++ b/lib/_exit.c @@ -0,0 +1,7 @@ +#define __LIBRARY__ +#include + +volatile void _exit(int exit_code) { + __asm__("int $0x80"::"a" (__NR_exit),"b" (exit_code)); +} + diff --git a/lib/close.c b/lib/close.c new file mode 100644 index 0000000000000000000000000000000000000000..182d7eb6be99ed8d6ada07089980cbaca9faa329 --- /dev/null +++ b/lib/close.c @@ -0,0 +1,4 @@ +#define __LIBRARY__ +#include + +_syscall1(int,close,int,fd) diff --git a/lib/ctype.c b/lib/ctype.c new file mode 100644 index 0000000000000000000000000000000000000000..a9379e959bb1d77d1f58c4c6dfcd9a33ee9bfbe5 --- /dev/null +++ b/lib/ctype.c @@ -0,0 +1,30 @@ +#include + +char _ctmp; + +unsigned char _ctype[] = {0x00, + _C,_C,_C,_C,_C,_C,_C,_C, + _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, + _C,_C,_C,_C,_C,_C,_C,_C, + _C,_C,_C,_C,_C,_C,_C,_C, + _S|_SP,_P,_P,_P,_P,_P,_P,_P, + _P,_P,_P,_P,_P,_P,_P,_P, + _D,_D,_D,_D,_D,_D,_D,_D, + _D,_D,_P,_P,_P,_P,_P,_P, + _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, + _U,_U,_U,_U,_U,_U,_U,_U, + _U,_U,_U,_U,_U,_U,_U,_U, + _U,_U,_U,_P,_P,_P,_P,_P, + _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, + _L,_L,_L,_L,_L,_L,_L,_L, + _L,_L,_L,_L,_L,_L,_L,_L, + _L,_L,_L,_P,_P,_P,_P,_C, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + diff --git a/lib/dup.c b/lib/dup.c new file mode 100644 index 0000000000000000000000000000000000000000..a6e54742ced5e7f9fafa93584b33b325a168ec57 --- /dev/null +++ b/lib/dup.c @@ -0,0 +1,6 @@ +#define __LIBRARY__ + +#include + +_syscall1(int,dup,int,fd) + diff --git a/lib/execve.c b/lib/execve.c new file mode 100644 index 0000000000000000000000000000000000000000..bf937e315901fe1699fb7c263a83e64b305d82b3 --- /dev/null +++ b/lib/execve.c @@ -0,0 +1,5 @@ +#define __LIBRARY__ +#include + +_syscall3(int,execve,const char *,file,char **,argv,char **,envp) + diff --git a/lib/file.c b/lib/file.c new file mode 100644 index 0000000000000000000000000000000000000000..5debb5a9adab898087ddad8d79d0c108d2201fa3 --- /dev/null +++ b/lib/file.c @@ -0,0 +1,25 @@ +#define __LIBRARY__ +#include +#include + +_syscall3(int,read,int,fd,const char *,buf,off_t,count) +_syscall3(int,write,int,fd,const char *,buf,off_t,count) +_syscall3(int, ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg); +_syscall2(int, fstat,int, fildes, struct stat *, stat_buf) +_syscall2(int, mkdir, const char *, pathname, mode_t, mode) +_syscall1(int, rmdir, const char *, pathname) + +static char printbuf[1024]; +extern int vsprintf(char* buf, const char* fmt, va_list args); + +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; +} + diff --git a/lib/open.c b/lib/open.c new file mode 100644 index 0000000000000000000000000000000000000000..d4e1e763112103b1f2b984505183430e104335f8 --- /dev/null +++ b/lib/open.c @@ -0,0 +1,22 @@ +#define __LIBRARY__ +#include +#include + +_syscall0(int, ls) + +int open(const char * filename, int flag, ...) { + register int res; + va_list arg; + + va_start(arg,flag); + __asm__("int $0x80" + :"=a" (res) + :"a" (__NR_open),"b" (filename),"c" (flag), + "d" (va_arg(arg,int))); + + if (res >= 0) + return res; + errno = -res; + return -1; +} + diff --git a/lib/setsid.c b/lib/setsid.c new file mode 100644 index 0000000000000000000000000000000000000000..21c4d10a0a535e70ccaafb78dd7f488e02c08374 --- /dev/null +++ b/lib/setsid.c @@ -0,0 +1,5 @@ +#define __LIBRARY__ +#include + +_syscall0(pid_t,setsid) + diff --git a/lib/string.c b/lib/string.c new file mode 100644 index 0000000000000000000000000000000000000000..f821fde8a6d743994fdfdf1d31e30afdc8b839a4 --- /dev/null +++ b/lib/string.c @@ -0,0 +1,370 @@ +#include + +inline char * strcpy(char * dest,const char *src) { +__asm__("cld\n" + "1:\tlodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b" + ::"S" (src),"D" (dest):"ax"); +return dest; +} + +inline char * strncpy(char * dest,const char *src,int count) { +__asm__("cld\n" + "1:\tdecl %2\n\t" + "js 2f\n\t" + "lodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "rep\n\t" + "stosb\n" + "2:" + ::"S" (src),"D" (dest),"c" (count):"ax"); +return dest; +} + +inline char * strcat(char * dest,const char * src) { +__asm__("cld\n\t" + "repne\n\t" + "scasb\n\t" + "decl %1\n" + "1:\tlodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b" + ::"S" (src),"D" (dest),"a" (0),"c" (0xffffffff):); +return dest; +} + +inline char * strncat(char * dest,const char * src,int count) { +__asm__("cld\n\t" + "repne\n\t" + "scasb\n\t" + "decl %1\n\t" + "movl %4,%3\n" + "1:\tdecl %3\n\t" + "js 2f\n\t" + "lodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n" + "2:\txorl %2,%2\n\t" + "stosb" + ::"S" (src),"D" (dest),"a" (0),"c" (0xffffffff),"g" (count) + :); +return dest; +} + +inline int strcmp(const char * cs,const char * ct) { +register int __res __asm__("ax"); +__asm__("cld\n" + "1:\tlodsb\n\t" + "scasb\n\t" + "jne 2f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "xorl %%eax,%%eax\n\t" + "jmp 3f\n" + "2:\tmovl $1,%%eax\n\t" + "jl 3f\n\t" + "negl %%eax\n" + "3:" + :"=a" (__res):"D" (cs),"S" (ct):); +return __res; +} + +inline int strncmp(const char * cs,const char * ct,int count) +{ +register int __res __asm__("ax"); +__asm__("cld\n" + "1:\tdecl %3\n\t" + "js 2f\n\t" + "lodsb\n\t" + "scasb\n\t" + "jne 3f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n" + "2:\txorl %%eax,%%eax\n\t" + "jmp 4f\n" + "3:\tmovl $1,%%eax\n\t" + "jl 4f\n\t" + "negl %%eax\n" + "4:" + :"=a" (__res):"D" (cs),"S" (ct),"c" (count):); +return __res; +} + +inline char * strchr(const char * s,char c) +{ +register char * __res __asm__("ax"); +__asm__("cld\n\t" + "movb %%al,%%ah\n" + "1:\tlodsb\n\t" + "cmpb %%ah,%%al\n\t" + "je 2f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "movl $1,%1\n" + "2:\tmovl %1,%0\n\t" + "decl %0" + :"=a" (__res):"S" (s),"0" (c):); +return __res; +} + +inline char * strrchr(const char * s,char c) +{ +register char * __res __asm__("dx"); +__asm__("cld\n\t" + "movb %%al,%%ah\n" + "1:\tlodsb\n\t" + "cmpb %%ah,%%al\n\t" + "jne 2f\n\t" + "movl %%esi,%0\n\t" + "decl %0\n" + "2:\ttestb %%al,%%al\n\t" + "jne 1b" + :"=d" (__res):"0" (0),"S" (s),"a" (c):); +return __res; +} + +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) + :"dx","di"); +return __res-cs; +} + +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) + :"dx","di"); +return __res-cs; +} + +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) + :"dx","di"); +return __res; +} + +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" + "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" + "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) + :"dx","di"); +return __res; +} + +inline int strlen(const char * s) +{ + const char* p = s; + while (*p) p++; + return p - s; +} + + +inline void * memcpy(void * dest,const void * src, int n) +{ +__asm__("cld\n\t" + "rep\n\t" + "movsb" + ::"c" (n),"S" (src),"D" (dest) + :); +return dest; +} + +inline void * memmove(void * dest,const void * src, int n) +{ +if (dest +#include + +_syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options) + +pid_t wait(int * wait_stat) { + return waitpid(-1,wait_stat,0); +} diff --git a/mm/Makefile b/mm/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..83fb3e4a0c59768cd78b2bc9f1a21dda64d79bf6 --- /dev/null +++ b/mm/Makefile @@ -0,0 +1,22 @@ +GCC := gcc +LD := ld +CCFLAG := -I../include -ffreestanding -fno-pic -Wall -fomit-frame-pointer -fno-stack-protector -c -m32 +LDFLAG := -Ttext 0x0 -s --oformat binary -m elf_i386 +INCDIR := ../include +OBJS := memory.o swap.o page.o + +mm.o : $(OBJS) + $(LD) -m elf_i386 -r -o $@ $^ + +swap.o : swap.c + $(GCC) $(CCFLAG) -o $@ $< + +memory.o : memory.c + $(GCC) $(CCFLAG) -o $@ $< + +page.o : page.S + $(GCC) -m32 -traditional -c -o $@ $< + +clean : + rm -f *.o + diff --git a/mm/memory.c b/mm/memory.c new file mode 100644 index 0000000000000000000000000000000000000000..4f6494e227f1d2e62368a8466de8bf45e33df2a9 --- /dev/null +++ b/mm/memory.c @@ -0,0 +1,330 @@ +#include + +unsigned long HIGH_MEMORY = 0; + +unsigned char mem_map [ PAGING_PAGES ] = {0,}; + +#define copy_page(from,to) \ +__asm__("cld ; rep ; movsl"::"S" (from),"D" (to),"c" (1024):) + +static inline void oom() { + printk("out of memory\n\r"); + //do_exit(SIGSEGV); +} + +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"); +} + +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); + + for ( ; size-->0 ; dir++) { + if (!(1 & *dir)) + continue; + pg_table = (unsigned long *) (0xfffff000 & *dir); + for (nr=0 ; nr<1024 ; nr++) { + if (*pg_table) { + if (1 & *pg_table) + free_page(0xfffff000 & *pg_table); + *pg_table = 0; + } + pg_table++; + } + free_page(0xfffff000 & *dir); + *dir = 0; + } + invalidate(); + return 0; +} + +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"); + } + + /* Get high 10 bits. As PDE is 4 byts, so right shift 20.*/ + from_dir = (unsigned long *) ((from>>20) & 0xffc); + 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; + + *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 (!this_page) + continue; + 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; +} + +void un_wp_page(unsigned long * table_entry) { + unsigned long old_page,new_page; + old_page = 0xfffff000 & *table_entry; + + if (old_page >= LOW_MEM && mem_map[MAP_NR(old_page)]==1) { + *table_entry |= 2; + invalidate(); + return; + } + + new_page=get_free_page(); + if (old_page >= LOW_MEM) + mem_map[MAP_NR(old_page)]--; + copy_page(old_page,new_page); + *table_entry = new_page | 7; + invalidate(); +} + +void do_wp_page(unsigned long error_code, unsigned long address) { + if (address < TASK_SIZE) + panic("\n\rBAD! KERNEL MEMORY WP-ERR!\n\r"); + + 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; +} + +static unsigned long put_page(unsigned long page,unsigned long address) { + unsigned long tmp, *page_table; + 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; +} + +unsigned long put_dirty_page(unsigned long page, unsigned long address) { + unsigned long tmp, *page_table; + + 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 | (PAGE_DIRTY | 7); + return page; +} + +void get_empty_page(unsigned long address) { + unsigned long tmp; + if (!(tmp = get_free_page()) || !put_page(tmp, address)) { + free_page(tmp); + oom(); + } +} + +static int try_to_share(unsigned long address, struct task_struct * p) { + unsigned long from; + unsigned long to; + unsigned long from_page; + unsigned long to_page; + unsigned long phys_addr; + + from_page = to_page = ((address>>20) & 0xffc); + from_page += ((p->start_code>>20) & 0xffc); + to_page += ((current->start_code>>20) & 0xffc); + + from = *(unsigned long *) from_page; + if (!(from & 1)) + return 0; + from &= 0xfffff000; + from_page = from + ((address>>10) & 0xffc); + phys_addr = *(unsigned long *) from_page; + if ((phys_addr & 0x41) != 0x01) + return 0; + phys_addr &= 0xfffff000; + if (phys_addr >= HIGH_MEMORY || phys_addr < LOW_MEM) + return 0; + + to = *(unsigned long *) to_page; + if (!(to & 1)) { + if ((to = get_free_page())) + *(unsigned long *) to_page = to | 7; + else + oom(); + } + + to &= 0xfffff000; + to_page = to + ((address>>10) & 0xffc); + if (1 & *(unsigned long *) to_page) + panic("try_to_share: to_page already exists"); + + *(unsigned long *) from_page &= ~2; + *(unsigned long *) to_page = *(unsigned long *) from_page; + invalidate(); + phys_addr -= LOW_MEM; + phys_addr >>= 12; + mem_map[phys_addr]++; + return 1; +} + +static int share_page(struct m_inode * inode, unsigned long address) { + struct task_struct ** p; + + if (inode->i_count < 2 || !inode) + return 0; + + for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) { + if (!*p) + continue; + if (current == *p) + continue; + if (inode != (*p)->executable) + continue; + if (try_to_share(address, *p)) + return 0; + } + + return 0; +} + +void do_no_page(unsigned long error_code,unsigned long address) { + int nr[4]; + unsigned long tmp; + unsigned long page; + int block,i; + struct m_inode * inode; + + if (address < TASK_SIZE) + panic("\n\rBAD!! KERNEL PAGE MISSING\n\r"); + if (address - current->start_code > TASK_SIZE) { + panic("Bad things happen: nonexistent page error in do_no_page\n\r"); + //do_exit(SIGSEGV); + } + page = *(unsigned long *) ((address >> 20) & 0xffc); + address &= 0xfffff000; + tmp = address - current->start_code; + if (tmp >= LIBRARY_OFFSET ) { + inode = current->library; + block = 1 + (tmp-LIBRARY_OFFSET) / BLOCK_SIZE; + } else if (tmp < current->end_data) { + inode = current->executable; + block = 1 + tmp / BLOCK_SIZE; + } else { + inode = NULL; + block = 0; + } + + if (!inode) { + get_empty_page(address); + return; + } + + if (share_page(inode,tmp)) + return; + if (!(page = get_free_page())) + oom(); +/* remember that 1 block is used for header */ + for (i=0 ; i<4 ; block++,i++) + nr[i] = bmap(inode,block); + bread_page(page,inode->i_dev,nr); + i = tmp + 4096 - current->end_data; + if (i>4095) + i = 0; + tmp = page + 4096; + while (i-- > 0) { + tmp--; + *(char *)tmp = 0; + } + if (put_page(page,address)) + return; + free_page(page); + oom(); +} + +void mem_init(long start_mem, long end_mem) { + int i; + + HIGH_MEMORY = end_mem; + + for (i = 0; i < PAGING_PAGES; i++) { + mem_map[i] = USED; + } + + i = MAP_NR(start_mem); + end_mem -= start_mem; + end_mem >>= 12; + while (end_mem--) { + mem_map[i++] = 0; + } +} + diff --git a/mm/page.S b/mm/page.S new file mode 100644 index 0000000000000000000000000000000000000000..856ce82b1e7f19f1b2c7adc387d221e583880dca --- /dev/null +++ b/mm/page.S @@ -0,0 +1,30 @@ +.globl page_fault + +page_fault: + xchgl %eax, (%esp) + pushl %ecx + pushl %edx + pushl %ds + pushl %es + pushl %fs + movl $0x10, %edx + movw %dx, %ds + movw %dx, %es + movw %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 + popl %fs + popl %es + popl %ds + popl %edx + popl %ecx + popl %eax + iret + diff --git a/mm/swap.c b/mm/swap.c new file mode 100644 index 0000000000000000000000000000000000000000..eaee46c0e64905024cdb4db4f6bfcd44596638a3 --- /dev/null +++ b/mm/swap.c @@ -0,0 +1,28 @@ +#include + +unsigned long get_free_page() { + register unsigned long __res asm("ax") = 0; + +repeat: +__asm__("std ; repne ; scasb\n\t" + "jne 1f\n\t" + "movb $1,1(%%edi)\n\t" + "sall $12, %%ecx\n\t" + "addl %2, %%ecx\n\t" + "movl %%ecx, %%edx\n\t" + "movl $1024, %%ecx\n\t" + "leal 4092(%%edx), %%edi\n\t" + "xor %%eax, %%eax\n\t" + "rep; stosl;\n\t" + "movl %%edx,%%eax\n" + "1:" + :"=a"(__res) + :""(0), "i"(LOW_MEM), "c"(PAGING_PAGES), + "D"(mem_map+PAGING_PAGES-1) + :"dx"); + + if (__res >= HIGH_MEMORY) + goto repeat; + return __res; +} + diff --git a/setup.S b/setup.S new file mode 100644 index 0000000000000000000000000000000000000000..a4f073fa49dfffbca3977b8c24da0f35ecee7118 --- /dev/null +++ b/setup.S @@ -0,0 +1,187 @@ +INITSEG = 0x9000 +SYSSEG = 0x1000 +SETUPSEG = 0x9020 + +.code16 +.text +.globl _start_setup + +_start_setup: + movw %cs, %ax + movw %ax, %ds + movw %ax, %es + + movw $setup_msg, %ax + movw %ax, %bp + movw $0x01301, %ax + movw $0x0c, %bx + movw $16, %cx + movb $3, %dh + movb $0, %dl + int $0x010 + + movw $INITSEG, %ax + movw %ax, %ds + movb $0x03, %ah + xor %bh, %bh + int $0x10 + movw %dx, (0) + movb $0x88, %ah + int $0x15 + movw %ax, (2) + + movb $0x0f, %ah + int $0x10 + movw %bx, (4) + movw %ax, (6) + movb $0x12, %ah + movb $0x10, %bl + int $0x10 + movw %ax, (8) + movw %bx, (10) + movw %cx, (12) + movw $0x5019, (14) + + movw $0x0000, %ax + movw %ax, %ds + ldsw (4 * 0x41), %si + movw $INITSEG, %ax + movw %ax, %es + movw $0x0080, %di + movw $0x10, %cx + rep + movsb + + /* get hd1 data */ + movw $0x0000, %ax + movw %ax, %ds + ldsw (4 * 0x46), %si + movw $INITSEG, %ax + movw %ax, %es + movw $0x0090, %di + movw $0x10, %cx + rep + movsb + + movw $0x1500, %ax + movb $0x81, %dl + int $0x13 + jc no_disk1 + cmpb $3, %ah + je is_disk1 +no_disk1: + movw $INITSEG, %ax + movw %ax, %es + movw $0x0090, %di + movw $0x10, %cx + movw $0x00, %ax + rep + stosb + +is_disk1: + /* prepare for protection mode */ + cli + + movw $0x0000, %ax + cld +do_move: + movw %ax, %es + addw $0x1000, %ax + cmpw $0x9000, %ax + jz end_move + movw %ax, %ds + subw %di, %di + subw %si, %si + movw $0x8000, %cx + rep + movsw + jmp do_move + +end_move: + movw $0xb800, %ax + movw %ax, %gs + movb $0xf, %ah + movb $0x41, %al + movl $0x100, %edi + movw %ax, %gs:(%di) + + movw $SETUPSEG, %ax + movw %ax, %ds + lgdt gdt_48 + + call empty_8042 + movb $0xD1, %al + outb %al, $0x64 + call empty_8042 + movb $0xDF, %al + outb %al, $0x60 + call empty_8042 + + movb $0x11, %al + outb %al, $0x20 + .word 0x00eb, 0x00eb + outb %al, $0xA0 + .word 0x00eb, 0x00eb + movb $0x20, %al + outb %al, $0x21 + .word 0x00eb, 0x00eb + movb $0x28, %al + outb %al, $0xA1 + .word 0x00eb, 0x00eb + movb $0x04, %al + outb %al, $0x21 + .word 0x00eb, 0x00eb + movb $0x02, %al + outb %al, $0xA1 + + .word 0x00eb, 0x00eb + movb $0x01, %al + outb %al, $0x21 + .word 0x00eb, 0x00eb + outb %al, $0xA1 + .word 0x00eb, 0x00eb + movb $0xff, %al + outb %al, $0x21 + .word 0x00eb, 0x00eb + outb %al, $0xA1 + + movl %cr0, %eax + xorb $1, %al + movl %eax, %cr0 + + .byte 0x66, 0xea + .long 0x0 + .word 0x8 + +empty_8042: + .word 0x00eb, 0x00eb + inb $0x64, %al + testb $2, %al + jnz empty_8042 + ret + +gdt: + .word 0,0,0,0 + + .word 0x07ff + .word 0x0000 + .word 0x9A00 + .word 0x00C0 + + .word 0x07ff + .word 0x0000 + .word 0x9200 + .word 0x00c0 + + .word 0xffff + .word 0x8000 + .word 0x920b + .word 0x00c0 + +gdt_48: + .word 0x800 + .word 512+gdt, 0x9 + +setup_msg: + .ascii "setup is running" + diff --git a/tools/build.c b/tools/build.c new file mode 100644 index 0000000000000000000000000000000000000000..df7cf9d2ccd790bbb00366c7b82358f4666c73e9 --- /dev/null +++ b/tools/build.c @@ -0,0 +1,130 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define MINIX_HEADER 32 +#define GCC_HEADER 1024 + +#define SYS_SIZE 0x2000 + +#define DEFAULT_MAJOR_ROOT 2 +#define DEFAULT_MINOR_ROOT 29 + +#define SETUP_SECTS 4 + +#define STRINGIFY(x) #x + +#define ARG_LEN 4 + +void die(char * str) +{ + fprintf(stderr, "%s\n", str); + exit(1); +} + +void usage(void) +{ + die("Usage: build bootsect setup system [rootdev] [> image]"); +} + +int main(int argc, char **argv) +{ + int i, c, id; + char buf[1024]; + char major_root, minor_root; + struct stat sb; + + if ((argc != ARG_LEN) && (argc != ARG_LEN + 1)) + usage(); + + if (argc == ARG_LEN + 1) + { + if (strcmp(argv[ARG_LEN], "FLOPPY")) + { + if (stat(argv[ARG_LEN], &sb)) + { + perror(argv[ARG_LEN]); + die("Couldn't stat root device"); + } + major_root = sb.st_rdev & 0xff00; + minor_root = sb.st_rdev & 0x00ff; + } + else + { + major_root = 0; + minor_root = 0; + } + } + else + { + major_root = DEFAULT_MAJOR_ROOT; + minor_root = DEFAULT_MINOR_ROOT; + } + fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root); + if ((major_root != 2) && (major_root != 3) && (major_root != 0)) + { + fprintf(stderr, "Illegal root device (major = %d)\n", major_root); + die("Bad root device --- major #"); + } + + for (i = 0; i < sizeof(buf); i++) + buf[i] = 0; + + if ((id = open(argv[1], O_RDONLY, 0)) < 0) + die("Unable to open 'boot'"); + + i = read(id, buf, sizeof(buf)); + fprintf(stderr, "Boot sector %d bytes.\n", i); + if (i != 512) + die("Boot block must be exactly 512 bytes"); + + buf[508] = (char) minor_root; + buf[509] = (char) major_root; + 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 'setup'"); + + for (i = 0; (c = read(id, buf, sizeof(buf))) > 0; i += c) + if (write(1, buf, c) != c) + die("Write call failed"); + + close(id); + + if (i > SETUP_SECTS * 512) + die("Setup exceeds" STRINGIFY(SETUP_SECTS) " sectors - rewrite build/boot/setup"); + fprintf(stderr, "Setup is %d bytes.\n", i); + for (c = 0; c < sizeof(buf); c++) + buf[c] ='\0'; + while (i < SETUP_SECTS * 512) + { + c = SETUP_SECTS * 512 - i; + if (c > sizeof(buf)) + c = sizeof(buf); + + if (write(1, buf, c) != c) + die("Write call failed"); + i+=c; + } + + if ((id = open(argv[3], O_RDONLY, 0)) < 0) + die("Unable to open 'system'"); + for (i = 0; (c = read(id, buf, sizeof(buf))) > 0; i += c) + if (write(1, buf, c) != c) + die("Write call failed"); + close(id); + fprintf(stderr, "System is %d bytes.\n", i); + if (i > SYS_SIZE * 16) + die("System is too big"); + + return 0; +} + diff --git a/tools/mkfs/Makefile b/tools/mkfs/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..2de45c9fbc3ac81f35d0aeb193111a3a0a317c0a --- /dev/null +++ b/tools/mkfs/Makefile @@ -0,0 +1,6 @@ +mfs: mfs.cpp utils.cpp minixfs.cpp + g++ -o mfs -g mfs.cpp utils.cpp minixfs.cpp + +clean: + -rm mfs + -rm rt.img diff --git a/tools/mkfs/common.hpp b/tools/mkfs/common.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8890436233c95b312529343479cd16d726787e99 --- /dev/null +++ b/tools/mkfs/common.hpp @@ -0,0 +1,26 @@ +#ifndef _COMMON_HPP +#define _COMMON_HPP + +#define BLOCKS 1440 + +#define UPPER(size,n) ((size+((n)-1))/(n)) + +#define INODE_SIZE (sizeof(struct d_inode)) +#define INODE_BLOCKS UPPER(INODES,INODES_PER_BLOCK) +#define INODE_BUFFER_SIZE (INODE_BLOCKS * BLOCK_SIZE) + +#define BITS_PER_BLOCK (BLOCK_SIZE<<3) + +#define INODES (_super_blk->s_ninodes) +#define ZONESIZE (_super_blk->s_log_zone_size) +#define ZONES (_super_blk->s_nzones) +#define MAXSIZE (_super_blk->s_max_size) +#define IMAPS (_super_blk->s_imap_blocks) +#define ZMAPS (_super_blk->s_zmap_blocks) +#define MAGIC (_super_blk->s_magic) +#define FIRSTZONE (_super_blk->s_firstdatazone) + +#define NORM_FIRSTZONE (2+IMAPS+ZMAPS+INODE_BLOCKS) + +#endif + diff --git a/tools/mkfs/copy_file.cpp b/tools/mkfs/copy_file.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tools/mkfs/mfs.cpp b/tools/mkfs/mfs.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f3b57c9ce119e3de43943cd80587ef45ceacc3ed --- /dev/null +++ b/tools/mkfs/mfs.cpp @@ -0,0 +1,112 @@ +#include +#include +#include +#include +#include + +using namespace std; + +#include "minixfs.hpp" + +// Read an image file. +FILE* read_file() { + return NULL; +} + +// Copy a file into root image. +int write_file(const char* src_file, char* dst_img, char* dst_file) { + cout << src_file << " " << dst_img << " " << dst_file << endl; + FileSystem* fs = new FileSystem(dst_img); + fs->write_file(src_file, dst_file); + delete fs; + return 0; +} + +void init_fs(char* src_img) { + FileSystem* fs = new FileSystem(src_img, true); + fs->init_fs(); + fs->write_image(); + delete fs; +} + +void extract_file(char* img_file, char* filename) { + FileSystem* fs = new FileSystem(img_file); + fs->extract_file(filename); + delete fs; +} + +int copy_file(char* src_img, char* tgt_img, char* src_file, char* tgt_file) { + FileSystem *sfs = new FileSystem(src_img); + FileSystem *tfs = new FileSystem(tgt_img); + sfs->copy_to(tfs, src_file, tgt_file); + tfs->write_image(); + + delete sfs; + delete tfs; + + return 0; +} + +void usage() { +} + +#define LENGTH 32 + +int main(int argc, char** argv) { + char cmd[LENGTH]; + char src_img[LENGTH]; + char dst_img[LENGTH]; + char src_file[LENGTH]; + char dst_file[LENGTH]; + + usage(); + while (true) { + scanf("%s", cmd); + if (strcmp("exit", cmd) == 0) { + break; + } + else if (strcmp("copy", cmd) == 0 || strcmp("cp", cmd) == 0) { + printf("input source image file:"); + scanf("%s", src_img); + printf("input target image file:"); + scanf("%s", dst_img); + printf("input source file:"); + scanf("%s", src_file); + printf("input target file:"); + scanf("%s", dst_file); + + copy_file(src_img, dst_img, src_file, dst_file); + } + else if (strcmp("list", cmd) == 0 || strcmp("ls", cmd) == 0) { + printf("input source image file:"); + scanf("%s", src_img); + printf("input directory need to show:"); + scanf("%s", src_file); + FileSystem* fs = new FileSystem(src_img); + fs->list_dir(src_file); + delete fs; + } + else if (strcmp("init", cmd) == 0) { + printf("input source image file:"); + scanf("%s", src_img); + init_fs(src_img); + } + else if (strcmp("put", cmd) == 0) { + printf("input source local file:"); + scanf("%s", src_file); + printf("input target image file:"); + scanf("%s", dst_img); + printf("input target file:"); + scanf("%s", dst_file); + write_file(src_file, dst_img, dst_file); + } + else if (strcmp("get", cmd) == 0) { + printf("input target image file:"); + scanf("%s", dst_img); + printf("input target file:"); + scanf("%s", dst_file); + extract_file(dst_img, dst_file); + } + } +} + diff --git a/tools/mkfs/mfs.h b/tools/mkfs/mfs.h new file mode 100644 index 0000000000000000000000000000000000000000..a8845b088863799fff4e06faa5a603ff5554187c --- /dev/null +++ b/tools/mkfs/mfs.h @@ -0,0 +1,158 @@ +#ifndef _FS_H +#define _FS_H + +#include +#include + +#define I_DIRECTORY 0040000 +#define I_REGULAR 0100000 + +enum Mode { + READ, + WRITE, + LIST, + EXTRACT, + COPY, + COPY_FILE, + MAKE_DIR, + INIT, +}; + +void buffer_init(long buffer_end); + +#define MAJOR(a) (((unsigned)(a))>>8) +#define MINOR(a) ((a)&0xff) + +#define NAME_LEN 14 +#define ROOT_INO 1 + +#define I_MAP_SLOTS 8 +#define Z_MAP_SLOTS 8 + +#define SUPER_MAGIC 0x137F + +#define NR_OPEN 20 +#define NR_INODE 32 +#define NR_FILE 64 +#define NR_SUPER 8 +#define NR_HASH 307 +#define 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))) + +struct buffer_head { + char * b_data; + unsigned long b_blocknr; + unsigned short b_dev; + unsigned char b_uptodate; + unsigned char b_dirt; + unsigned char b_count; + unsigned char b_lock; + 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 int i_size; + unsigned int i_time; + unsigned char i_gid; + unsigned char i_nlinks; + unsigned short i_zone[9]; +}; + +class m_inode { +public: + d_inode* p; + unsigned short i_num; + + m_inode(d_inode* dp, unsigned short num): p(dp), i_num(num) {} + ~m_inode() { + p = NULL; + } +}; + +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 int s_max_size; + unsigned short s_magic; + char * s_imap[8]; + char * s_zmap[8]; +}; + +struct d_super_block { + unsigned short s_ninodes; + unsigned short s_nzones; + unsigned short s_imap_blocks; + unsigned short s_zmap_blocks; + unsigned short s_firstdatazone; + unsigned short s_log_zone_size; + unsigned int s_max_size; + unsigned short s_magic; +}; + +struct dir_entry { + unsigned short inode; + char name[NAME_LEN]; +}; + + +extern struct m_inode inode_table[NR_INODE]; +extern struct file file_table[NR_FILE]; + +extern void truncate(struct m_inode * inode); +extern void sync_inodes(void); +extern int create_block(struct m_inode * inode,int block); + +extern struct m_inode * new_inode(int dev); +extern void iput(struct m_inode * inode); + +extern inline void wait_on_buffer(struct buffer_head* bh); +extern struct buffer_head * getblk(int dev, int block); +extern void ll_rw_block(int rw, struct buffer_head * bh); +extern void brelse(struct buffer_head * buf); +extern struct buffer_head * bread(int dev,int block); +extern void bread_page(unsigned long addr,int dev,int b[4]); + +extern struct m_inode * namei(const char * pathname); +extern int open_namei(const char * pathname, int flag, int mode, + struct m_inode ** res_inode); + +extern struct m_inode * get_empty_inode(void); +extern struct buffer_head * get_hash_table(int dev, int block); + +extern int new_block(int dev); +extern int free_block(int dev, int block); +extern int sync_dev(int dev); + +extern struct super_block * get_super(int dev); + +char* get_dir_name(char* full_name); +char* get_entry_name(char* full_name); +void free_strings(char** dirs); +char** split(const char* name); +long file_length(FILE* f); + +#endif diff --git a/tools/mkfs/minixfs.cpp b/tools/mkfs/minixfs.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ca0c3fad81606be2df223db1b99458b7b2bc38b8 --- /dev/null +++ b/tools/mkfs/minixfs.cpp @@ -0,0 +1,527 @@ +#include +#include +#include + +#include "minixfs.hpp" + +#define bitop(name,op) \ +static inline int name(char * addr,unsigned int nr) \ +{ \ + int __res; \ + __asm__ __volatile__("bt" op " %1,%2; adcl $0,%0" \ + :"=g" (__res) \ + :"r" (nr),"m" (*(addr)),"0" (0)); \ + return __res; \ +} + +bitop(bit,"") +bitop(setbit,"s") +bitop(clrbit,"r") + +#define mark_inode(x) (setbit(_inode_map,(x))) +#define unmark_inode(x) (clrbit(_inode_map,(x))) + +#define mark_zone(x) (setbit(_zone_map,(x)-FIRSTZONE+1)) +#define unmark_zone(x) (clrbit(_zone_map,(x)-FIRSTZONE+1)) + +FileSystem::FileSystem(char* img_name, bool is_create) { + image_name = img_name; + for (int i = 0; i < BLOCKS; i++) { + _images[i] = NULL; + } + _super_blk = NULL; + _inode_map = NULL; + _zone_map = NULL; + + load_image(is_create); +} + +int FileSystem::read_block(FILE* f, int block) { + if (_images[block] == NULL) { + _images[block] = new char[BLOCK_SIZE]; + } + + if (fread(_images[block], sizeof(char), BLOCK_SIZE, f) != BLOCK_SIZE) { + printf("read file error, block is %d\n", block); + return -1; + } + + return 0; +} + +int FileSystem::load_image(bool is_create) { + if (is_create) { + for (int i = 0; i < BLOCKS; i++) { + _images[i] = new char[BLOCK_SIZE]; + } + setup_super_block(); + setup_map(); + return 0; + } + + FILE* f = fopen(image_name, "r+"); + for (int i = 0; i < BLOCKS; i++) { + if (read_block(f, i) != 0) { + release_images(); + fclose(f); + return -1; + } + } + fclose(f); + + _super_blk = (super_block*)_images[1]; + _inode_map = _images[2]; + _zone_map = _images[2 + IMAPS]; + + _root = iget(ROOT_INO); + + return 0; +} + +void FileSystem::release_images() { + for (int i = 0; i < BLOCKS; i++) { + if (i >= 4 && i < 10) + continue; + if (_images[i]) { + delete[] _images[i]; + _images[i] = NULL; + } + } +} + +m_inode* FileSystem::namei(char* dir_name) { + assert(dir_name[0] == '/'); + char** dirs = split(dir_name); + char** dir_list = dirs; + + m_inode* pwd = new m_inode(_root, 1); + + while (*dir_list) { + m_inode* old = pwd; + pwd = find_entry(pwd, *dir_list); + delete old; + if (!pwd) { + printf("Error: file/dir %s not exists\n", *(dir_list)); + return NULL; + } + dir_list++; + } + + free_strings(dirs); + return pwd; +} + +m_inode* FileSystem::find_entry(m_inode* pwd, char* name) { + char* pwd_block = get_block(bmap(pwd->p, 0)); + + for (int i = 0; i < pwd->p->i_size / sizeof(struct dir_entry); i++) { + struct dir_entry* dir = ((struct dir_entry*)pwd_block) + i; + if (strcmp(dir->name, name) == 0) { + return new m_inode(iget(dir->inode), dir->inode); + } + } + return NULL; +} + +char * FileSystem::get_block(int nblock) { + return _images[nblock]; +} + +unsigned short FileSystem::_bmap(struct d_inode* inode, int n, bool is_create) { + char* ind; + if (n < 7) { + if (is_create && !inode->i_zone[n]) { + inode->i_zone[n] = get_new_block(); + } + return inode->i_zone[n]; + } + + n -= 7; + if (n < 512) { + if (is_create && !inode->i_zone[7]) { + inode->i_zone[7] = get_new_block(); + } + ind = get_block(inode->i_zone[7]); + if (is_create && !((unsigned short*)ind)[n]) + ((unsigned short*)ind)[n] = get_new_block(); + + return *(((unsigned short*)ind) + n); + } + + n -= 512; + if (is_create && !inode->i_zone[8]) + inode->i_zone[8] = get_new_block(); + + ind = get_block(inode->i_zone[8]); + + if (is_create && !((unsigned short*)ind)[n>>9]) + ((unsigned short*)ind)[n>>9] = get_new_block(); + + ind = get_block(*(((unsigned short*)ind) + (n >> 9))); + + if (!(*(((unsigned short*)ind) + (n & 511)))) { + *(((unsigned short*)ind) + (n & 511)) = get_new_block(); + } + + return *(((unsigned short*)ind) + (n & 511)); +} + +unsigned short FileSystem::bmap(struct d_inode* inode, int n) { + return _bmap(inode, n, false); +} + +unsigned short FileSystem::create_block(struct d_inode* inode, int n) { + return _bmap(inode, n, true); +} + +unsigned short FileSystem::get_new_block() { + int i = 0, j = 0, k = 0; + for (i = 0; i < ZMAPS; i++) { + for (j = 0; j < BLOCK_SIZE; j++) { + char bitmap = _zone_map[i * BLOCK_SIZE + j]; + if ((bitmap & 0xff) < 0xff) { + for (k = 0; k < 8; k++) { + if (((1 << k) & bitmap) == 0) { + _zone_map[i*BLOCK_SIZE + j] |= (1 << k); + goto found; + } + } + } + } + } + +found: + return (unsigned short)(i * BLOCK_SIZE * 8 + j * 8 + k) + FIRSTZONE - 1; +} + +struct d_inode* FileSystem::iget(int nr) { + int inode_block = (nr - 1) / INODES_PER_BLOCK; + int index_in_block = (nr - 1) % INODES_PER_BLOCK; + + return (struct d_inode*)(_images[2+IMAPS+ZMAPS+inode_block] + + index_in_block * sizeof(struct d_inode)); +} + +void FileSystem::list_dir(char* dir_name) { + m_inode* inode = namei(dir_name); + if (!inode) { + printf("Error: Can not directory %s\n", dir_name); + return; + } + + char* pwd_block = get_block(bmap(inode->p, 0)); + + for (int i = 0; i < inode->p->i_size / sizeof(struct dir_entry); i++) { + struct dir_entry* dir = ((struct dir_entry*)pwd_block) + i; + printf("inode:%d, mode:%06o, name:%s\n", dir->inode, iget(dir->inode)->i_mode, dir->name); + } + + delete inode; +} + +void FileSystem::init_fs() { + // create an empty dir, root. + delete get_new_dir_inode(NULL); +} + +FileSystem::~FileSystem() { + release_images(); +} + +void FileSystem::setup_map() { + _inode_map = _images[2]; + _zone_map = _images[2 + IMAPS]; + memset(_inode_map,0xff, IMAPS * BLOCK_SIZE); + memset(_zone_map, 0xff, ZMAPS * BLOCK_SIZE); + + for (int i = 0; i < INODE_BLOCKS; i++) { + memset(_images[2+IMAPS+ZMAPS+i], 0, BLOCK_SIZE); + } + + for (int i = FIRSTZONE ; ii_mode = I_DIRECTORY | 0777; + inode->i_nlinks = 2; + inode->i_size = 2 * sizeof(struct dir_entry); + inode->i_zone[0] = get_new_block(); + dir_entry* de = (struct dir_entry*)_images[inode->i_zone[0]]; + de->inode = nr; + strncpy(de->name, ".", NAME_LEN); + + de++; + de->inode = parent ? parent->i_num : nr; + strncpy(de->name, "..", NAME_LEN); + + return new m_inode(inode, nr); +} + +int FileSystem::find_empty_inode() { + int i = 0, j = 0, k = 0; + for (i = 0; i < IMAPS; i++) { + for (j = 0; j < BLOCK_SIZE; j++) { + char bitmap = _inode_map[i * BLOCK_SIZE + j]; + if ((bitmap & 0xff) < 0xff) { + for (k = 0; k < 8; k++) { + if (((1 << k) & bitmap) == 0) { + _inode_map[i*BLOCK_SIZE + j] |= (1 << k); + goto found; + } + } + } + } + } + +found: + return i * BLOCK_SIZE * 8 + j * 8 + k; +} + +void FileSystem::copy_to(FileSystem* tfs, char* sfile, char* tfile) { + m_inode* smi = namei(sfile); + char* parent_name = get_dir_name(tfile); + m_inode* tmi = tfs->namei(tfile); + if (!tmi) { + tfs->make_dir(parent_name); + tmi = tfs->create_new_file(tfile, smi->p->i_size); + } + + if (tmi == NULL) { + printf("Error: Can not create new file %s\n", tfile); + return; + } + + int block = 0; + for (int i = 0; i < smi->p->i_size / BLOCK_SIZE; i++) { + int index = bmap(smi->p, i); + if (index == 0) + continue; + + memcpy(tfs->get_block(tfs->create_block(tmi->p, block++)), + get_block(index), BLOCK_SIZE); + } + + // some thing special in i_zone 0. + if (smi->p->i_size == 0) { + tmi->p->i_zone[0] = smi->p->i_zone[0]; + } + + tmi->p->i_size = smi->p->i_size; + printf("isize is %d\n", tmi->p->i_size); + tmi->p->i_mode = smi->p->i_mode; + printf("imode is %d\n", tmi->p->i_mode); + tmi->p->i_nlinks = smi->p->i_nlinks; + printf("inlinks is %d\n", tmi->p->i_nlinks); + tmi->p->i_time = smi->p->i_time; + tmi->p->i_gid = smi->p->i_gid; + tmi->p->i_uid = smi->p->i_uid; +} + +m_inode* FileSystem::make_dir(char* dir_name) { + m_inode* ndnode = namei(dir_name); + if (ndnode) { + return ndnode; + } + + char* parent_name = get_dir_name(dir_name); + m_inode* parent = namei(parent_name); + + // make sure parent's inode is not null. + if (!parent) { + parent = make_dir(parent_name); + if (!parent) { + printf("Error: can not make dir %s\n", parent_name); + return NULL; + } + } + + char* dname = get_entry_name(dir_name); + printf("mkdir: %s\n", dname); + + ndnode = get_new_dir_inode(parent); + + char* pwd_block = get_block(bmap(parent->p, 0)); + struct dir_entry* dir = (struct dir_entry*)pwd_block; + + int i = 0; + for (i = 0; i < parent->p->i_size / sizeof(struct dir_entry); i++) { + if (!dir->inode) { + dir->inode = ndnode->i_num; + strncpy(dir->name, dname, NAME_LEN); + break; + } + + if ((char*)dir > pwd_block + BLOCK_SIZE) { + pwd_block = get_block(create_block(parent->p, i / DIR_ENTRIES_PER_BLOCK)); + dir = (struct dir_entry*)pwd_block; + } + + dir++; + } + + if (i * sizeof(struct dir_entry) == parent->p->i_size) { + parent->p->i_size = (i + 1) * sizeof(struct dir_entry); + dir->inode = ndnode->i_num; + strncpy(dir->name, dname, NAME_LEN); + } + + list_dir(parent_name); + + delete[] dname; + delete parent; + + return ndnode; +} + +m_inode* FileSystem::get_new_file_inode(long length) { + int nr = find_empty_inode(); + d_inode* inode = iget(nr); + inode->i_size = (unsigned int)length; + for (int i = 0; i < UPPER(inode->i_size, BLOCK_SIZE); i++) { + create_block(inode, i); + } + inode->i_mode = I_REGULAR | 0777; + + return new m_inode(inode, nr); +} + +m_inode* FileSystem::create_new_file(char* dir_name, long length) { + char* parent_name = get_dir_name(dir_name); + m_inode* parent = namei(parent_name); + if (!parent) { + parent= make_dir(parent_name); + } + + if (!parent) { + printf("Error: can not create directory %s\n", parent_name); + return NULL; + } + + char* dname = get_entry_name(dir_name); + printf("new file: %s\n", dname); + + m_inode* ndnode = get_new_file_inode(length); + + char* pwd_block = get_block(bmap(parent->p, 0)); + struct dir_entry* dir = (struct dir_entry*)pwd_block; + + int i = 0; + for (i = 0; i < parent->p->i_size / sizeof(struct dir_entry); i++) { + if (!dir->inode) { + dir->inode = ndnode->i_num; + strncpy(dir->name, dname, NAME_LEN); + break; + } + + if ((char*)dir > pwd_block + BLOCK_SIZE) { + pwd_block = get_block(bmap(parent->p, i / DIR_ENTRIES_PER_BLOCK)); + dir = (struct dir_entry*)pwd_block; + } + + dir++; + } + + if (i * sizeof(struct dir_entry) == parent->p->i_size) { + parent->p->i_size = (i + 1) * sizeof(struct dir_entry); + dir->inode = ndnode->i_num; + strncpy(dir->name, dname, NAME_LEN); + } + + return ndnode; +} + +int FileSystem::write_file(const char* src_file, char* dst_file) { + FILE* srcf = fopen(src_file, "r"); + + m_inode* finode = namei(dst_file); + long length = file_length(srcf); + if (!finode) { + finode = create_new_file(dst_file, length); + } + + finode->p->i_mode = I_REGULAR | 0777; + finode->p->i_size = length; + finode->p->i_uid = 0; + finode->p->i_gid = 0; + finode->p->i_nlinks = 1; + + int total = 0; + for (int i = 0; i < UPPER(finode->p->i_size, BLOCK_SIZE); i++) { + total += fread(get_block(create_block(finode->p, i)), sizeof(char), BLOCK_SIZE, srcf); + printf("%d block write\n", bmap(finode->p, i)); + } + printf("%d bytes read\n", total); + + write_image(); + fclose(srcf); + return 0; +} + +void FileSystem::extract_file(char* file_name) { + m_inode* mi = namei(file_name); + if (mi == NULL) { + printf("Can not find file %s\n", file_name); + return; + } + + printf("file mode is %ud\n", mi->p->i_size); + printf("file nlinks is %d\n", mi->p->i_nlinks); + if (mi->p->i_size == 0) { + printf("file %s is empty and first zone is %d\n", file_name, mi->p->i_zone[0]); + return; + } + + FILE* extract = fopen("extract_temp", "w+"); + for (int i = 0; i < UPPER(mi->p->i_size, BLOCK_SIZE); i++) { + int index = bmap(mi->p, i); + if (index == 0) + continue; + + if (fwrite(_images[index], sizeof(char), BLOCK_SIZE, extract) != BLOCK_SIZE) { + printf("Error: write failed in extacting file"); + fclose(extract); + return; + } + } + + fclose(extract); +} + diff --git a/tools/mkfs/minixfs.hpp b/tools/mkfs/minixfs.hpp new file mode 100644 index 0000000000000000000000000000000000000000..119e3774bfcc6450196c4de0f1f760da20f5c33c --- /dev/null +++ b/tools/mkfs/minixfs.hpp @@ -0,0 +1,57 @@ +#ifndef _MINIX_FS +#define _MINIX_FS + +#include "mfs.h" +#include "common.hpp" + +class FileSystem { +private: + char* _images[BLOCKS]; + char* image_name; + + super_block* _super_blk; + char* _inode_map; + char* _zone_map; + + d_inode* _root; + + int load_image(bool is_create); + void release_images(); + int read_block(FILE* f, int block); + + + // bitmap + int find_empty_inode(); + unsigned short get_new_block(); + + // inode + d_inode* iget(int nr); + m_inode* find_entry(m_inode* pwd, char* name); + + unsigned short _bmap(struct d_inode* inode, int n, bool is_create); + unsigned short bmap(struct d_inode* inode, int n); + + void setup_super_block(); + void setup_map(); + +public: + FileSystem(char* img_name, bool is_create = false); + ~FileSystem(); + + void list_dir(char* dir_name); + void init_fs(); + void write_image(); + void copy_to(FileSystem* tfs, char* sfile, char* tfile); + + m_inode* namei(char* dir_name); + char * get_block(int nblock); + unsigned short create_block(struct d_inode* inode, int n); + m_inode* get_new_dir_inode(m_inode* parent); + m_inode* get_new_file_inode(long length); + m_inode* make_dir(char* dir_name); + int write_file(const char* src_file, char* dst_file); + m_inode* create_new_file(char* tgt_file, long length); + void extract_file(char* filename); +}; + +#endif diff --git a/tools/mkfs/utils.cpp b/tools/mkfs/utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cbd524eba91830336bee7126620a366c456d5d43 --- /dev/null +++ b/tools/mkfs/utils.cpp @@ -0,0 +1,121 @@ +#include "mfs.h" + +#include + +long file_length(FILE* f) { + fseek(f, 0, SEEK_END); + long file_size = ftell(f); + fseek(f, 0, 0); + return file_size; +} + +void free_strings(char** dirs) { + char** dir_list = dirs; + while (*dir_list) { + delete[] (*dir_list); + dir_list++; + } + + delete[] dirs; +} + +char** split(const char* name) { + const char* p = name; + int cnt = 0; + while (*p) { + if (*p == '/') { + cnt += 1; + } + p++; + } + char** array = new char*[cnt+1]; + for (int i = 0; i < cnt + 1; i++) { + array[i] = NULL; + } + + p = name + 1; + int j = 0, i = 0; + while (*p) { + if (*p == '/') { + array[j][i++] = '\0'; + j++; + i = 0; + } + else { + if (array[j] == NULL) { + array[j] = new char[NAME_LEN + 1]; + } + array[j][i++] = *p; + } + p++; + } + if (array[j]) + array[j][i] = '\0'; + + return array; +} + + +char* get_dir_name(char* full_name) { + char* p = full_name; + int len = strlen(full_name); + int dir_len = 0; + + if (full_name[len-1] == '/') { + full_name[len-1] = '\0'; + len--; + } + + p = full_name + len - 1; + + while (p >= full_name) { + if (*p == '/') { + dir_len = p - full_name; + break; + } + p--; + } + + char * d = NULL; + if (dir_len == 0) { + d = new char[2]; + d[0] = '/'; + d[1] = '\0'; + return d; + } + + d = new char[dir_len + 1]; + strncpy(d, full_name, dir_len); + d[dir_len] = '\0'; + + return d; +} + +char* get_entry_name(char* full_name) { + char* p = full_name; + int len = strlen(full_name); + int dir_len = 0; + + if (full_name[len-1] == '/') { + full_name[len-1] = '\0'; + len--; + } + + p = full_name + len - 1; + + while (p >= full_name) { + if (*p == '/') { + dir_len = len - (p - full_name); + break; + } + p--; + } + + char * d = NULL; + d = new char[dir_len + 1]; + strncpy(d, p + 1, dir_len); + d[dir_len] = '\0'; + + return d; +} + diff --git a/tools/tcc/Makefile b/tools/tcc/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..683adb5b07603f523d9773f8dde1d5157f1d08ee --- /dev/null +++ b/tools/tcc/Makefile @@ -0,0 +1,16 @@ +AR := ar +GCC := gcc +CCFLAG := -m32 -I./include -ffreestanding -fno-pic -Wall -fomit-frame-pointer -fno-stack-protector -c + +runtime/libc.a: runtime/*.c + cd runtime; make; cd ..; + +et: tcc runtime/libc.a test/test.c + ./tcc test/test.c et + cp et ../mkfs/ + +clean: + -rm *.o + -rm et + cd runtime; make clean; cd ..; + diff --git a/tools/tcc/include/fcntl.h b/tools/tcc/include/fcntl.h new file mode 100644 index 0000000000000000000000000000000000000000..6679faeb4cae1c3a40ea5b5efc16ecdd35784dca --- /dev/null +++ b/tools/tcc/include/fcntl.h @@ -0,0 +1,9 @@ +#ifndef _FCNTL_H +#define _FCNTL_H + +#define O_ACCMODE 00003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 + +#endif diff --git a/tools/tcc/include/stdarg.h b/tools/tcc/include/stdarg.h new file mode 100644 index 0000000000000000000000000000000000000000..ebb37ccc2b12ba032eed3d9ffd8adb2573629ad9 --- /dev/null +++ b/tools/tcc/include/stdarg.h @@ -0,0 +1,29 @@ +#ifndef _STDARG_H +#define _STDARG_H + +typedef char *va_list; + +/* Amount of space required in an argument list for an arg of type TYPE. + * TYPE may alternatively be an expression whose type is used. */ + +#define __va_rounded_size(TYPE) \ + (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) + +#ifndef __sparc__ +#define va_start(AP, LASTARG) \ + (AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG))) +#else +#define va_start(AP, LASTARG) \ + (__builtin_saveregs (), \ + AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG))) +#endif + +void va_end (va_list); /* Defined in gnulib */ +#define va_end(AP) + +#define va_arg(AP, TYPE) \ + (AP += __va_rounded_size (TYPE), \ + *((TYPE *) (AP - __va_rounded_size (TYPE)))) + +#endif /* _STDARG_H */ + diff --git a/tools/tcc/include/stddef.h b/tools/tcc/include/stddef.h new file mode 100644 index 0000000000000000000000000000000000000000..c340e05fb2b43243450038c8b8ca792552b59952 --- /dev/null +++ b/tools/tcc/include/stddef.h @@ -0,0 +1,19 @@ +#ifndef _STDDEF_H +#define _STDDEF_H + +#ifndef _PTRDIFF_T +#define _PTRDIFF_T +typedef long ptrdiff_t; +#endif + +#ifndef _SIZE_T +#define _SIZE_T +typedef unsigned long size_t; +#endif + +#undef NULL +#define NULL ((void *)0) + +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + diff --git a/tools/tcc/include/stdio.h b/tools/tcc/include/stdio.h new file mode 100644 index 0000000000000000000000000000000000000000..5fd1574e8266dea00602b4c6edce259538f7961d --- /dev/null +++ b/tools/tcc/include/stdio.h @@ -0,0 +1,4 @@ +#include + +int printf(const char* fmt, ...); +int vsprintf(char *buf, const char *fmt, va_list args); diff --git a/tools/tcc/include/string.h b/tools/tcc/include/string.h new file mode 100644 index 0000000000000000000000000000000000000000..3c55bef3d918ae758c03e9b6de2e3ecfe5ddf8f7 --- /dev/null +++ b/tools/tcc/include/string.h @@ -0,0 +1,66 @@ +#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 + +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 + */ + +char * strcpy(char * dest,const char *src); + +char * strncpy(char * dest,const char *src,int count); + +char * strcat(char * dest,const char * src); + +char * strncat(char * dest,const char * src,int count); + +int strcmp(const char * cs,const char * ct); + +int strncmp(const char * cs,const char * ct,int count); + +char * strchr(const char * s,char c); + +char * strrchr(const char * s,char c); + +int strspn(const char * cs, const char * ct); + +int strcspn(const char * cs, const char * ct); + +char * strpbrk(const char * cs,const char * ct); + +char * strstr(const char * cs,const char * ct); + +int strlen(const char * s); + +char * strtok(char * s,const char * ct); + +void * memcpy(void * dest,const void * src, int n); + +void * memmove(void * dest,const void * src, int n); + +int memcmp(const void * cs,const void * ct,int count); + +void * memchr(const void * cs,char c,int count); + +void * memset(void * s,char c,int count); + +#endif + diff --git a/tools/tcc/include/sys/types.h b/tools/tcc/include/sys/types.h new file mode 100644 index 0000000000000000000000000000000000000000..b75fb69c89ccd35e68b1340dbe04c246218a9a20 --- /dev/null +++ b/tools/tcc/include/sys/types.h @@ -0,0 +1,37 @@ +#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 long off_t; + +typedef int pid_t; +typedef unsigned short uid_t; +typedef unsigned short mode_t; +typedef unsigned short ino_t; +typedef unsigned short gid_t; +typedef unsigned short dev_t; +typedef unsigned short umode_t; +typedef unsigned char nlink_t; +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned long tcflag_t; + +#endif diff --git a/tools/tcc/include/unistd.h b/tools/tcc/include/unistd.h new file mode 100644 index 0000000000000000000000000000000000000000..27724d4d8e8565ea0ce01ae341793a11f2e46f54 --- /dev/null +++ b/tools/tcc/include/unistd.h @@ -0,0 +1,160 @@ +#ifndef _UNISTD_H +#define _UNISTD_H + +#include + +#ifndef NULL +#define NULL ((void*)0) +#endif + +#ifdef __LIBRARY__ + +#define __NR_setup 0 /* used only by init, to get system going */ +#define __NR_exit 1 +#define __NR_fork 2 +#define __NR_read 3 +#define __NR_write 4 +#define __NR_open 5 +#define __NR_close 6 +#define __NR_waitpid 7 +#define __NR_creat 8 +#define __NR_link 9 +#define __NR_unlink 10 +#define __NR_execve 11 +#define __NR_chdir 12 +#define __NR_time 13 +#define __NR_mknod 14 +#define __NR_chmod 15 +#define __NR_chown 16 +#define __NR_break 17 +#define __NR_stat 18 +#define __NR_lseek 19 +#define __NR_getpid 20 +#define __NR_mount 21 +#define __NR_umount 22 +#define __NR_setuid 23 +#define __NR_getuid 24 +#define __NR_stime 25 +#define __NR_ptrace 26 +#define __NR_alarm 27 +#define __NR_fstat 28 +#define __NR_pause 29 +#define __NR_utime 30 +#define __NR_stty 31 +#define __NR_gtty 32 +#define __NR_access 33 +#define __NR_nice 34 +#define __NR_ftime 35 +#define __NR_sync 36 +#define __NR_kill 37 +#define __NR_rename 38 +#define __NR_mkdir 39 +#define __NR_rmdir 40 +#define __NR_dup 41 +#define __NR_pipe 42 +#define __NR_times 43 +#define __NR_prof 44 +#define __NR_brk 45 +#define __NR_setgid 46 +#define __NR_getgid 47 +#define __NR_signal 48 +#define __NR_geteuid 49 +#define __NR_getegid 50 +#define __NR_acct 51 +#define __NR_phys 52 +#define __NR_lock 53 +#define __NR_ioctl 54 +#define __NR_fcntl 55 +#define __NR_mpx 56 +#define __NR_setpgid 57 +#define __NR_ulimit 58 +#define __NR_uname 59 +#define __NR_umask 60 +#define __NR_chroot 61 +#define __NR_ustat 62 +#define __NR_dup2 63 +#define __NR_getppid 64 +#define __NR_getpgrp 65 +#define __NR_setsid 66 +#define __NR_sigaction 67 +#define __NR_sgetmask 68 +#define __NR_ssetmask 69 +#define __NR_setreuid 70 +#define __NR_setregid 71 +#define __NR_sigsuspend 72 +#define __NR_sigpending 73 +#define __NR_sethostname 74 +#define __NR_setrlimit 75 +#define __NR_getrlimit 76 +#define __NR_getrusage 77 +#define __NR_gettimeofday 78 +#define __NR_settimeofday 79 +#define __NR_getgroups 80 +#define __NR_setgroups 81 +#define __NR_select 82 +#define __NR_symlink 83 +#define __NR_lstat 84 +#define __NR_readlink 85 +#define __NR_uselib 86 + +#define _syscall0(type, name) \ +type name() { \ + long __res; \ +__asm__ volatile("int $0x80\n\r"\ + : "=a"(__res) \ + : "a"(__NR_##name)); \ + if (__res >= 0) \ + return (type)__res; \ + errno = -__res; \ + return -1; \ +} + +#define _syscall1(type, name, atype, a) \ +type name(atype a) { \ + long __res; \ +__asm__ volatile("int $0x80\n\r"\ + : "=a"(__res) \ + : "a"(__NR_##name), "b"((long)(a))); \ + if (__res >= 0) \ + return (type)__res; \ + errno = -__res; \ + return -1; \ +} + +#define _syscall2(type, name, atype, a, btype, b) \ +type name(atype a, btype b) { \ + long __res; \ +__asm__ volatile("int $0x80\n\r"\ + : "=a"(__res) \ + : "a"(__NR_##name), "b"((long)(a)), "c"((long)(b))); \ + if (__res >= 0) \ + return (type)__res; \ + errno = -__res; \ + return -1; \ +} + +#define _syscall3(type,name,atype,a,btype,b,ctype,c) \ +type name(atype a, btype b, ctype c) { \ + long __res; \ +__asm__ volatile("int $0x80\n\r"\ + : "=a"(__res) \ + : "a"(__NR_##name), "b"((long)(a)), "c"((long)(b)), "d"((long)(c))); \ + if (__res >= 0) \ + return (type)__res; \ + errno = -__res; \ + return -1; \ +} + +#endif /* __LIBRARY__ */ + +extern int errno; + +int write(int fildes, const char * buf, off_t count); +int read(int fildes, const char * buf, off_t count); +int rmdir(const char* pathname); +int open(const char * filename, int flag, ...); +int execve(const char * filename, char ** argv, char ** envp); +int fork(); +int pipe(unsigned int * fds); + +#endif diff --git a/tools/tcc/linkerscript/a.out.header b/tools/tcc/linkerscript/a.out.header new file mode 100644 index 0000000000000000000000000000000000000000..18b9866780b9b5a158de46fb452613b2cec8d4fc Binary files /dev/null and b/tools/tcc/linkerscript/a.out.header differ diff --git a/tools/tcc/linkerscript/a.out.header.c b/tools/tcc/linkerscript/a.out.header.c new file mode 100644 index 0000000000000000000000000000000000000000..d621be101ce04ce1693c921905ddd9b2b9d0cde4 --- /dev/null +++ b/tools/tcc/linkerscript/a.out.header.c @@ -0,0 +1,21 @@ +struct exec { + unsigned long a_magic; + unsigned a_text; + unsigned a_data; + unsigned a_bss; + unsigned a_syms; + unsigned a_entry; + unsigned a_trsize; + unsigned a_drsize; +}; + +struct exec header = { + 0413, /* a_magic */ + 0, /* a_text */ + 0, /* a_data */ + 0, /* a_bss */ + 0, /* a_syms */ + 0, /* a_entry */ + 0, /* a_trsize */ + 0, /* a_drsize */ +}; diff --git a/tools/tcc/linkerscript/a.out.header.s b/tools/tcc/linkerscript/a.out.header.s new file mode 100644 index 0000000000000000000000000000000000000000..e47de5c128bff2bf16da6553739697e3f65771a8 --- /dev/null +++ b/tools/tcc/linkerscript/a.out.header.s @@ -0,0 +1,12 @@ + .section .a.out.header, "a", @progbits + .align 32 + .size header, 32 +header: + .long 267 /* ZMAGIC */ + .long .textsize /* a_text */ + .long .datasize /* a_data */ + .long .bsssize /* a_bss */ + .long .symsize /* a_syms */ + .long 0 /* a_entry */ + .long 0 /* a_trsize */ + .long 0 /* a_drsize */ diff --git a/tools/tcc/linkerscript/a.out.lds b/tools/tcc/linkerscript/a.out.lds new file mode 100644 index 0000000000000000000000000000000000000000..34e25bd3bab31f4759e2e40e954ab400423d9086 --- /dev/null +++ b/tools/tcc/linkerscript/a.out.lds @@ -0,0 +1,46 @@ +OUTPUT_FORMAT(binary) +SECTIONS +{ + . = 0x0; + .text : AT(0x400) { + PROVIDE(.text_begin = .); + *(.text); + PROVIDE(.text_real_end = .); + } + .data ALIGN(0x400) : { + PROVIDE(.text_align_end = .); + PROVIDE(.data_begin = .); + *(.data) + *(.rodata) + *(.rodata1) + PROVIDE(.data_real_end = .); + } + .bss ALIGN(0x400) : { + PROVIDE(.data_align_end = .); + PROVIDE(.bss_begin = .); + *(.bss) + PROVIDE(.bss_real_end = .); + } + .symtab ALIGN(0x400) : { + PROVIDE(.sym_begin = .); + *(.symtab) + PROVIDE(.sym_end = .); + } + .text_end = (SIZEOF(.data) + SIZEOF(.bss) == 0) ? .text_real_end : .text_align_end; + .data_end = (SIZEOF(.bss) == 0) ? .data_real_end : .data_align_end; + .bss_end = .bss_real_end; + PROVIDE(.textsize = .text_end - .text_begin); + PROVIDE(.datasize = .data_end - .data_begin); + PROVIDE(.bsssize = .bss_end - .bss_begin); + PROVIDE(.symsize = 0); + .header ALIGN(0x400) : AT(0x0){ + LONG(267) + LONG(.textsize) + LONG(.datasize) + LONG(.bsssize) + LONG(0) + LONG(_start) + LONG(0) + } + /DISCARD/ : { *(.eh_frame) *(.comment) *(.rel.eh_frame) *(.note.GNU-stack) } +} diff --git a/tools/tcc/linkerscript/sample/build.sh b/tools/tcc/linkerscript/sample/build.sh new file mode 100644 index 0000000000000000000000000000000000000000..ede72aebeabaefac2906ae76cf80ed4fa7220799 --- /dev/null +++ b/tools/tcc/linkerscript/sample/build.sh @@ -0,0 +1,4 @@ +#!/bin/bash +export LDEMULATION=elf_i386 +gcc foo.c -c -fno-pic -m32 +ld -T ../a.out.lds ../a.out.header foo.o -o a.out diff --git a/tools/tcc/linkerscript/sample/foo.c b/tools/tcc/linkerscript/sample/foo.c new file mode 100644 index 0000000000000000000000000000000000000000..3a1571941b3fc2b95eb216904795b0d271249010 --- /dev/null +++ b/tools/tcc/linkerscript/sample/foo.c @@ -0,0 +1,16 @@ +static char c = 'A'; +static int bss = 0; +int compareStr(char *str, int len) { + for (int i = 0; i < len; ++i) { + if (str[i] == c) { + return 1; + } + } + return bss; +} +int _start() { + if (compareStr("Hello World", 11)) { + return 1; + } + return 0; +} diff --git a/tools/tcc/runtime/Makefile b/tools/tcc/runtime/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..ecf068cf553c36983fcbe29572094e0e5fe6a365 --- /dev/null +++ b/tools/tcc/runtime/Makefile @@ -0,0 +1,31 @@ +AR := ar +GCC := gcc +CCFLAG := -m32 -I../include -ffreestanding -fno-pic -Wall -fomit-frame-pointer -fno-stack-protector -c +OBJS := sys_call.o errno.o printf.o vsprintf.o string.o crt0.o + +libc.a: $(OBJS) + $(AR) rcs $@ $^ + sync + +sys_call.o: sys_call.c + $(GCC) $(CCFLAG) -o $@ $< + +errno.o: errno.c + $(GCC) $(CCFLAG) -o $@ $< + +printf.o: printf.c + $(GCC) $(CCFLAG) -o $@ $< + +vsprintf.o: vsprintf.c + $(GCC) $(CCFLAG) -o $@ $< + +string.o: string.c + $(GCC) $(CCFLAG) -o $@ $< + +crt0.o: crt0.S + $(GCC) $(CCFLAG) -o $@ $< + +clean: + -rm *.o + -rm libc.a + diff --git a/tools/tcc/runtime/crt0.S b/tools/tcc/runtime/crt0.S new file mode 100644 index 0000000000000000000000000000000000000000..d9973f184bd3698c7e76f7be193a76730e197ccd --- /dev/null +++ b/tools/tcc/runtime/crt0.S @@ -0,0 +1,17 @@ +.code32 +.text + +.globl _environ, _start + +_start: + movl 8(%esp),%eax + movl %eax,_environ + call main + pushl %eax +1: call exit + jmp 1b + +.data + +_environ: + .long 0 diff --git a/tools/tcc/runtime/errno.c b/tools/tcc/runtime/errno.c new file mode 100644 index 0000000000000000000000000000000000000000..74de031f42380499e701fd6a12b1aea46c1d0b03 --- /dev/null +++ b/tools/tcc/runtime/errno.c @@ -0,0 +1,2 @@ +int errno; + diff --git a/tools/tcc/runtime/printf.c b/tools/tcc/runtime/printf.c new file mode 100644 index 0000000000000000000000000000000000000000..a6545aaaddc4cc849597dbb75cd9a5d91da78578 --- /dev/null +++ b/tools/tcc/runtime/printf.c @@ -0,0 +1,16 @@ +#include +#include + +char printbuf[256]; + +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; +} + diff --git a/tools/tcc/runtime/string.c b/tools/tcc/runtime/string.c new file mode 100644 index 0000000000000000000000000000000000000000..391d351ebf1f8a4c3e1eea82c65de0649322cd89 --- /dev/null +++ b/tools/tcc/runtime/string.c @@ -0,0 +1,369 @@ +#include + +inline char * strcpy(char * dest,const char *src) { +__asm__("cld\n" + "1:\tlodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b" + ::"S" (src),"D" (dest):"ax"); +return dest; +} + +inline char * strncpy(char * dest,const char *src,int count) { +__asm__("cld\n" + "1:\tdecl %2\n\t" + "js 2f\n\t" + "lodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "rep\n\t" + "stosb\n" + "2:" + ::"S" (src),"D" (dest),"c" (count):"ax"); +return dest; +} + +inline char * strcat(char * dest,const char * src) { +__asm__("cld\n\t" + "repne\n\t" + "scasb\n\t" + "decl %1\n" + "1:\tlodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b" + ::"S" (src),"D" (dest),"a" (0),"c" (0xffffffff):); +return dest; +} + +inline char * strncat(char * dest,const char * src,int count) { +__asm__("cld\n\t" + "repne\n\t" + "scasb\n\t" + "decl %1\n\t" + "movl %4,%3\n" + "1:\tdecl %3\n\t" + "js 2f\n\t" + "lodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n" + "2:\txorl %2,%2\n\t" + "stosb" + ::"S" (src),"D" (dest),"a" (0),"c" (0xffffffff),"g" (count) + :); +return dest; +} + +inline int strcmp(const char * cs,const char * ct) { +register int __res __asm__("ax"); +__asm__("cld\n" + "1:\tlodsb\n\t" + "scasb\n\t" + "jne 2f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "xorl %%eax,%%eax\n\t" + "jmp 3f\n" + "2:\tmovl $1,%%eax\n\t" + "jl 3f\n\t" + "negl %%eax\n" + "3:" + :"=a" (__res):"D" (cs),"S" (ct):); +return __res; +} + +inline int strncmp(const char * cs,const char * ct,int count) +{ +register int __res __asm__("ax"); +__asm__("cld\n" + "1:\tdecl %3\n\t" + "js 2f\n\t" + "lodsb\n\t" + "scasb\n\t" + "jne 3f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n" + "2:\txorl %%eax,%%eax\n\t" + "jmp 4f\n" + "3:\tmovl $1,%%eax\n\t" + "jl 4f\n\t" + "negl %%eax\n" + "4:" + :"=a" (__res):"D" (cs),"S" (ct),"c" (count):); +return __res; +} + +inline char * strchr(const char * s,char c) +{ +register char * __res __asm__("ax"); +__asm__("cld\n\t" + "movb %%al,%%ah\n" + "1:\tlodsb\n\t" + "cmpb %%ah,%%al\n\t" + "je 2f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "movl $1,%1\n" + "2:\tmovl %1,%0\n\t" + "decl %0" + :"=a" (__res):"S" (s),"0" (c):); +return __res; +} + +inline char * strrchr(const char * s,char c) +{ +register char * __res __asm__("dx"); +__asm__("cld\n\t" + "movb %%al,%%ah\n" + "1:\tlodsb\n\t" + "cmpb %%ah,%%al\n\t" + "jne 2f\n\t" + "movl %%esi,%0\n\t" + "decl %0\n" + "2:\ttestb %%al,%%al\n\t" + "jne 1b" + :"=d" (__res):"0" (0),"S" (s),"a" (c):); +return __res; +} + +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) + :"dx","di"); +return __res-cs; +} + +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) + :"dx","di"); +return __res-cs; +} + +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) + :"dx","di"); +return __res; +} + +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" + "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" + "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) + :"dx","di"); +return __res; +} + +inline int strlen(const char * s) +{ + const char* p = s; + while (*p) p++; + return p - s; +} + + +inline void * memcpy(void * dest,const void * src, int n) +{ +__asm__("cld\n\t" + "rep\n\t" + "movsb" + ::"c" (n),"S" (src),"D" (dest) + :); +return dest; +} + +inline void * memmove(void * dest,const void * src, int n) +{ +if (dest +#include + +_syscall3(int,write,int,fd,const char *,buf,off_t,count) +_syscall1(int,exit,int,fd); +_syscall3(int,read,int,fd,const char *,buf,off_t,count) +_syscall2(int, mkdir, const char *, pathname, mode_t, mode) +_syscall1(int, rmdir, const char *, pathname) +_syscall1(int, chdir, const char *, filename) +_syscall3(int,execve,const char *,file,char **,argv,char **,envp) +_syscall0(int,fork); +_syscall1(int, pipe, unsigned int *, filedes) + +_syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options) + +pid_t wait(int * wait_stat) { + return waitpid(-1,wait_stat,0); +} + +int open(const char * filename, int flag, ...) { + register int res; + va_list arg; + + va_start(arg,flag); + __asm__("int $0x80" + :"=a" (res) + :"0" (__NR_open),"b" (filename),"c" (flag), + "d" (va_arg(arg,int))); + if (res>=0) + return res; + errno = -res; + return -1; +} diff --git a/tools/tcc/runtime/vsprintf.c b/tools/tcc/runtime/vsprintf.c new file mode 100644 index 0000000000000000000000000000000000000000..64aa7bc6266d70fc36d4e0458ad849001ecd5dab --- /dev/null +++ b/tools/tcc/runtime/vsprintf.c @@ -0,0 +1,243 @@ +#include +#include + +#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 = 0; + + 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--; + } + + if (num==0) + tmp[i++]='0'; + else { + while (num!=0) { + tmp[i++]=digits[do_div(num,base)]; + } + } + + if (i>precision) precision=i; + size -= precision; + + if (!(type&(ZEROPAD+LEFT))) { + while(size-->0) + *str++ = ' '; + } + + if (sign) + *str++ = sign; + + if (type&SPECIAL) { + if (base==8) + *str++ = '0'; + else if (base==16) { + *str++ = '0'; + *str++ = digits[33]; + } + } + + if (!(type&LEFT)) { + while(size-->0) + *str++ = c; + } + + while(i0) + *str++ = tmp[i]; + + while(size-->0) + *str++ = ' '; + + return str; +} + +int vsprintf(char *buf, const char *fmt, va_list args) { + int len; + int i; + char * str; + char *s; + int *ip; + + int flags; /* flags to number() */ + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier; /* 'h', 'l', or 'L' for integer fields */ + + for (str = buf; *fmt; fmt++) { + if (*fmt != '%') { + *str++ = *fmt; + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case '-': flags |= LEFT; goto repeat; + case '+': flags |= PLUS; goto repeat; + case ' ': flags |= SPACE; goto repeat; + case '#': flags |= SPECIAL; goto repeat; + case '0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if (is_digit(*fmt)) { + field_width = skip_atoi(&fmt); + } + else if (*fmt == '*') { + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == '.') { + ++fmt; + if (is_digit(*fmt)) + precision = skip_atoi(&fmt); + else if (*fmt == '*') { + /* it's the next argument */ + precision = va_arg(args, int); + } + + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { + qualifier = *fmt; + ++fmt; + } + + switch (*fmt) { + case 'c': + if (!(flags & LEFT)) + while (--field_width > 0) + *str++ = ' '; + *str++ = (unsigned char) va_arg(args, int); + while (--field_width > 0) + *str++ = ' '; + break; + case 's': + s = va_arg(args, char *); + len = strlen(s); + + if (precision < 0) + precision = len; + else if (len > precision) + len = precision; + + if (!(flags & LEFT)) + while (len < field_width--) + *str++ = ' '; + for (i = 0; i < len; ++i) + *str++ = *s++; + while (len < field_width--) + *str++ = ' '; + break; + + case 'o': + str = number(str, va_arg(args, unsigned long), 8, + field_width, precision, flags); + break; + + case 'p': + if (field_width == -1) { + field_width = 8; + flags |= ZEROPAD; + } + str = number(str, + (unsigned long) va_arg(args, void *), 16, + field_width, precision, flags); + break; + + case 'x': + flags |= SMALL; + case 'X': + str = number(str, va_arg(args, unsigned long), 16, + field_width, precision, flags); + break; + + case 'd': + case 'i': + flags |= SIGN; + case 'u': + str = number(str, va_arg(args, unsigned long), 10, + field_width, precision, flags); + break; + + case 'n': + ip = va_arg(args, int *); + *ip = (str - buf); + break; + + default: + if (*fmt != '%') + *str++ = '%'; + + if (*fmt) + *str++ = *fmt; + else + --fmt; + break; + } + } + + *str = '\0'; + return str-buf; +} + diff --git a/tools/tcc/tcc b/tools/tcc/tcc new file mode 100644 index 0000000000000000000000000000000000000000..ec4bd261f67aa9fed4eb25ba7d105ddce16b095f --- /dev/null +++ b/tools/tcc/tcc @@ -0,0 +1,7 @@ +#!/bin/bash +export LDEMULATION=elf_i386 +filename=$1 +objfile=${filename/".c"/".o"} +echo ${filename/".c"/".o"} +gcc -c -fno-pic -m32 -ffreestanding -I./include -o $objfile $filename +ld -e _start -M -T linkerscript/a.out.lds linkerscript/a.out.header $objfile runtime/libc.a -o $2 > test.map diff --git a/tools/tcc/test/hello.c b/tools/tcc/test/hello.c new file mode 100644 index 0000000000000000000000000000000000000000..deccabdf8d3c289974436f2ae3a345f69d24fb62 --- /dev/null +++ b/tools/tcc/test/hello.c @@ -0,0 +1,24 @@ +#include +#include +#include + +int main() { + char buf[128]; + + int fid = open("/root/txt", O_RDONLY); + if (fid < 0) { + printf("unable to open file\n\r"); + return 0; + } + + int n = read(fid, buf, 128); + if (n > 0) { + write(1, buf, n); + printf("\n\r"); + } + else + printf("unable to read file\n\r"); + + return 0; +} + diff --git a/tools/tcc/test/pipe.c b/tools/tcc/test/pipe.c new file mode 100644 index 0000000000000000000000000000000000000000..167b0b565b7651d07ba2fdaefa8712a5044de657 --- /dev/null +++ b/tools/tcc/test/pipe.c @@ -0,0 +1,41 @@ +#include +#include +#include + +int main() { + char buf[16]; + int fds[2]; + int pid; + int n = pipe(fds); + + if (n < 0) { + printf("unable to create pipe: %d\n\r", n); + return 0; + } + + if ((pid = fork()) == 0) { + n = write(fds[1], "hello pipe!", 11); + if (n < 0) { + printf("unable to write:%d\n\r", n); + } + else { + printf("write done\n\r"); + } + + wait(pid); + } + else { + n = read(fds[0], buf, 16); + if (n < 0) { + printf("unable to read:%d\n\r", n); + return 0; + } + else { + printf("receive: %s\n\r", buf); + return 0; + } + } + + return 0; +} + diff --git a/tools/tcc/test/test.c b/tools/tcc/test/test.c new file mode 100644 index 0000000000000000000000000000000000000000..e5d646aef04b5ddbd4f7c1a0cbe41df17213dd44 --- /dev/null +++ b/tools/tcc/test/test.c @@ -0,0 +1,57 @@ +#include +#include +#include + +#define MAX_LEN 128 + +char buf[MAX_LEN]; +char* argv[] = {"/bin", NULL}; +char* envp[] = {"HOME=/usr/root", NULL}; + +int main(int argc, char** argv, char** envp) { + int i; + pid_t pid; + + while (1) { + printf(">>>"); + i = read(0, buf, MAX_LEN); + buf[i-1] = '\0'; + if (strcmp(buf, "exit") == 0) { + break; + } + else if (strcmp(buf, "sh") == 0) { + printf("got sh\n"); + if (!(pid = fork())) { + execve("/bin/sh", argv, envp); + } + wait(pid); + } + else if (strcmp(buf, "ls") == 0) { + printf("got ls\n"); + if (!(pid = fork())) { + execve("/bin/ls", argv, envp); + } + wait(pid); + } + else if (strcmp(buf, "cat") == 0) { + printf("got cat\n"); + buf[0] = '/'; + buf[1] = 'r'; + buf[2] = 'o'; + buf[3] = 'o'; + buf[4] = 't'; + buf[5] = '/'; + i = read(0, buf + 6, MAX_LEN); + buf[i + 6] = '\0'; + argv[0] = buf; + + if (!(pid = fork())) { + printf("%s\n\r", buf); + execve("/bin/cat", argv, envp); + } + wait(pid); + } + } + + return 0; +}